/* START ************************************************************/ /* OBS måste ligga högst upp för att kunna användas längre ned i koden */ // Ungefär som PHPs sprintf funktion för att ersätta i strängar //console.log("{0} is dead, but {1} is alive! {0} {2}".sprintf("ASP", "ASP.NET")); String.prototype.sprintf = function () { var args = arguments; return this.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); }; function sprintf() { // discuss at: http://phpjs.org/functions/sprintf/ // original by: Ash Searle (http://hexmen.com/blog/) // improved by: Michael White (http://getsprink.com) // improved by: Jack // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // improved by: Dj // improved by: Allidylls // input by: Paulo Freitas // input by: Brett Zamir (http://brett-zamir.me) // example 1: sprintf("%01.2f", 123.1); // returns 1: 123.10 // example 2: sprintf("[%10s]", 'monkey'); // returns 2: '[ monkey]' // example 3: sprintf("[%'#10s]", 'monkey'); // returns 3: '[####monkey]' // example 4: sprintf("%d", 123456789012345); // returns 4: '123456789012345' // example 5: sprintf('%-03s', 'E'); // returns 5: 'E00' var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuideEfFgG])/g; var a = arguments; var i = 0; var format = a[i++]; // pad() var pad = function (str, len, chr, leftJustify) { if (!chr) { chr = ' '; } var padding = (str.length >= len) ? '' : new Array(1 + len - str.length >>> 0) .join(chr); return leftJustify ? str + padding : padding + str; }; // justify() var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) { var diff = minWidth - value.length; if (diff > 0) { if (leftJustify || !zeroPad) { value = pad(value, minWidth, customPadChar, leftJustify); } else { value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length); } } return value; }; // formatBaseX() var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) { // Note: casts negative numbers to positive ones var number = value >>> 0; prefix = prefix && number && { '2': '0b', '8': '0', '16': '0x' }[base] || ''; value = prefix + pad(number.toString(base), precision || 0, '0', false); return justify(value, prefix, leftJustify, minWidth, zeroPad); }; // formatString() var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) { if (precision != null) { value = value.slice(0, precision); } return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar); }; // doFormat() var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) { var number, prefix, method, textTransform, value; if (substring === '%%') { return '%'; } // parse flags var leftJustify = false; var positivePrefix = ''; var zeroPad = false; var prefixBaseX = false; var customPadChar = ' '; var flagsl = flags.length; for (var j = 0; flags && j < flagsl; j++) { switch (flags.charAt(j)) { case ' ': positivePrefix = ' '; break; case '+': positivePrefix = '+'; break; case '-': leftJustify = true; break; case "'": customPadChar = flags.charAt(j + 1); break; case '0': zeroPad = true; customPadChar = '0'; break; case '#': prefixBaseX = true; break; } } // parameters may be null, undefined, empty-string or real valued // we want to ignore null, undefined and empty-string values if (!minWidth) { minWidth = 0; } else if (minWidth === '*') { minWidth = +a[i++]; } else if (minWidth.charAt(0) == '*') { minWidth = +a[minWidth.slice(1, -1)]; } else { minWidth = +minWidth; } // Note: undocumented perl feature: if (minWidth < 0) { minWidth = -minWidth; leftJustify = true; } if (!isFinite(minWidth)) { throw new Error('sprintf: (minimum-)width must be finite'); } if (!precision) { precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type === 'd') ? 0 : undefined; } else if (precision === '*') { precision = +a[i++]; } else if (precision.charAt(0) == '*') { precision = +a[precision.slice(1, -1)]; } else { precision = +precision; } // grab value using valueIndex if required? value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++]; switch (type) { case 's': return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar); case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad); case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad); case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad); case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad); case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad) .toUpperCase(); case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad); case 'i': case 'd': number = +value || 0; // Plain Math.round doesn't just truncate number = Math.round(number - number % 1); prefix = number < 0 ? '-' : positivePrefix; value = prefix + pad(String(Math.abs(number)), precision, '0', false); return justify(value, prefix, leftJustify, minWidth, zeroPad); case 'e': case 'E': case 'f': // Should handle locales (as per setlocale) case 'F': case 'g': case 'G': number = +value; prefix = number < 0 ? '-' : positivePrefix; method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())]; textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2]; value = prefix + Math.abs(number)[method](precision); return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform](); default: return substring; } }; return format.replace(regex, doFormat); } function parse_url(str, component) { // http://kevin.vanzonneveld.net // + original by: Steven Levithan (http://blog.stevenlevithan.com) // + reimplemented by: Brett Zamir (http://brett-zamir.me) // + input by: Lorenzo Pisani // + input by: Tony // + improved by: Brett Zamir (http://brett-zamir.me) // % note: Based on http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js // % note: blog post at http://blog.stevenlevithan.com/archives/parseuri // % note: demo at http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js // % note: Does not replace invalid characters with '_' as in PHP, nor does it return false with // % note: a seriously malformed URL. // % note: Besides function name, is essentially the same as parseUri as well as our allowing // % note: an extra slash after the scheme/protocol (to allow file:/// as in PHP) // * example 1: parse_url('http://username:password@hostname/path?arg=value#anchor'); // * returns 1: {scheme: 'http', host: 'hostname', user: 'username', pass: 'password', path: '/path', query: 'arg=value', fragment: 'anchor'} var query, key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment' ], ini = (this.php_js && this.php_js.ini) || {}, mode = (ini['phpjs.parse_url.mode'] && ini['phpjs.parse_url.mode'].local_value) || 'php', parser = { php: /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // Added one optional slash to post-scheme to catch file:/// (should restrict this) }; var m = parser[mode].exec(str), uri = {}, i = 14; while (i--) { if (m[i]) { uri[key[i]] = m[i]; } } if (component) { return uri[component.replace('PHP_URL_', '').toLowerCase()]; } if (mode !== 'php') { var name = (ini['phpjs.parse_url.queryKey'] && ini['phpjs.parse_url.queryKey'].local_value) || 'queryKey'; parser = /(?:^|&)([^&=]*)=?([^&]*)/g; uri[name] = {}; query = uri[key[12]] || ''; query.replace(parser, function ($0, $1, $2) { if ($1) { uri[name][$1] = $2; } }); } delete uri.source; return uri; } /* Tvärtom mot jquerys param-funktion T.ex för att hämta ut en querystring var qstr = window.location.search; var q = deparam(test); console.log(q); */ deparam = (function (d, x, params, pair, i) { return function (qs) { // start bucket; can't cheat by setting it in scope declaration or it overwrites params = {}; // remove preceding non-querystring, correct spaces, and split qs = qs.substring(qs.indexOf('?') + 1).replace(x, ' ').split('&'); // march and parse for (i = qs.length; i > 0;) { pair = qs[--i].split('='); params[d(pair[0])] = d(pair[1]); } return params; }; //-- fn deparam })(decodeURIComponent, /\+/g); /* Parsar en URL och skickar tillbaka allting i ett objekt T.ex http://xpectum.localhost/edit.php?id=195#test=1 { "query": { "id": "195" }, "path": "/edit.php", "host": "xpectum.localhost", "scheme": "http", "fragment": { "test": "1" } } */ function parse_and_get_url(url) { url = parse_url(url); query = (typeof url.query != "undefined" ? deparam(url.query) : new Object()); hash = (typeof url.fragment != "undefined" ? deparam(url.fragment) : new Object()); url.query = query; url.fragment = hash; return url; } // Execute a JavaScript function by name as a string // http://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string/359910#359910 function execute_function_by_name(function_name, context /*, args */ ) { var args = Array.prototype.slice.call(arguments, 2); var namespaces = function_name.split("."); var func = namespaces.pop(); for (var i = 0; i < namespaces.length; i++) { context = context[namespaces[i]]; } if (typeof context[func] == "function") { return context[func].apply(context, args); } } // Konverterar newline (\n) till "
" function nl2br(str) { return str.replace(/\n/g, "
"); }; // Konverterar "
" till newline (\n) function br2nl(str) { return str.replace(//gi, "\n"); //return str.replace(//mg,"\n"); //return str.replace(/
/gi, "\n"); }; /* SLUT ************************************************************/ // //youtube API // //vimeo API load_js_for_page_via_getscript("https://player.vimeo.com/api/player.js"); load_js_for_page_via_getscript("jsVideoUrlParser/jsVideoUrlParser.min.js", "../../js/plugins/"); // Laddar in eventuella JS-filer function load_js_for_page_via_getscript(js_urls, path) { // Kollar om det finns js script som ska laddas if (!$.isEmptyObject(js_urls)) { var urls = js_urls.split(','); var _urls = $.map(urls, function(scr) { return $.getScript( (path||"") + scr ); }); //console.log(_urls); urls.push($.Deferred(function( deferred ){ $( deferred.resolve ); })); return $.when.apply($, _urls); } else { // Finns inga script att ladda, retunerar en solved promise $.Deferred(function( deferred ){ $( deferred.resolve ); }) return $.when.apply($, js_urls); } } // Laddar js-script, eller json osv för en sida function load_js_for_page_via_ajax(js_url, callback) { callback = typeof callback !== 'undefined' ? callback : false; var js_urls = js_url.split(','); $.each(js_urls, function (js_url_key, js_url) { $.ajax({ url: js_url }) .done(function (jqXHR, textStatus) { //console.log("scriptet '" + js_url + "' har laddats") if (callback) { callback(jqXHR, $(this)[0].dataTypes); } }) .fail(function (jqXHR, textStatus, errorThrown) { //console.log($(jqXHR.responseText).text()); // Kollar om felmeddelande innnehåller HTML och konvertar det i så fall till text if ($(jqXHR.responseText).length > 0) { var responseText = $(jqXHR.responseText).text(); } else { var responseText = jqXHR.responseText; } switch (jqXHR.status) { case 0: error_text = "Could not connect.\n Verify Network."; break; case 404: error_text = "Page not found [404]."; break; case 500: error_text = "Internal Server Error [500]."; break; default: error_text = textStatus + ". " + errorThrown + ". " + responseText; } $("#course_page_content").html("

" + error_text + "

" + errorThrown + ".
" + responseText + "

"); }); }); } // Laddar en eller flera css för en sida function load_css_for_page(css_urls, callback, nocache) { if (!$.isEmptyObject(css_urls)) { var urls = css_urls.split(","); var css_urls_existing = []; var $page_styles = $('.page_styles'); // Hömtar existrerade stylesheet som redan är laddade $.each($page_styles, function (style_key, style) { css_urls_existing.push( $(style).attr('href') ); }); // Kollar vilka stylesheet som inte redan finns och behöver ladds var urls_to_load = []; $.each(urls, function (url_key, url) { if( $.inArray(url, css_urls_existing) == -1 ) { urls_to_load.push(url); } }); if (typeof nocache=='undefined') nocache=false; // default don't refresh $.when.apply($, $.map(urls_to_load, function(url){ if (nocache) url += '?_ts=' + new Date().getTime(); // refresh? return $.get(url, function(){ $('', {rel:'stylesheet', type:'text/css', 'href':url, class:'page_styles'}).appendTo('head'); }); }) ).then(function(){ if (typeof callback=='function') callback(); }); } else { callback(); } } // Kollar vilka stylesheet som inte ska användas och tar bort dom function remove_unused_css_for_page(css_urls_to_load) { var urls = []; if (!$.isEmptyObject(css_urls_to_load)) { urls = css_urls_to_load.split(","); } var css_urls_existing = []; var $page_styles = $('.page_styles'); // Hömtar existrerade stylesheet som redan är laddade $.each($page_styles, function (style_key, style) { css_urls_existing.push( $(style).attr('href') ); }); // Tar ut skillnaden av vilka stylesheet som finns och vilka som ska vara kvar var css_urls_to_remove = $(css_urls_existing).not(urls).get(); // Tar bort de stylesheets som inte ska vara kvar $.each($page_styles, function (style_key, style) { if( $.inArray($(style).attr('href'), css_urls_to_remove) >= 0 ) { $(style).remove(); } }) } function remove_css_for_page() { $('.page_styles').remove(); } // Hämtar ut filändelse function get_extension(filename) { var lastIndex = filename.lastIndexOf('.'); var name = filename.substr(0, lastIndex).toLowerCase(); var extension = filename.split('.').pop().toLowerCase(); var file_info = { "name": name, "extension": extension }; return file_info; } // Sättar att en sida är visad och uppdaterar datumet och hur länge man varit inne på sidan, eller sätter en sida som ej visad och tar bort datumet och tiden visad /*function set_page_viewed(pagekey, viewed) { user_log.pages[pagekey].viewed = viewed; if(viewed) { user_log.pages[pagekey].date_viewed = get_and_format_date("", 3) user_log.pages[pagekey].time_visited += 0; } else { user_log.pages[pagekey].date_viewed = ""; user_log.pages[pagekey].time_visited = 0; } }*/ // Kollar om man är i kursen eller i editorn genom att se om kursstruktiuren är definierad function is_in_course_or_editor() { var is_in_course_or_editor = 'editor'; if (course.pages != undefined) { is_in_course_or_editor = 'course' } return is_in_course_or_editor; } function get_and_format_date(thedate, return_type) { var return_date; if (thedate == "") { var thedate = new Date(); } if (!is_valid_date(thedate)) { var thedate = new Date(Date.parse(thedate)); } if (is_valid_date(thedate)) { var dd = thedate.getDate(); var mm = thedate.getMonth() + 1; //Januari är 0 var hh = thedate.getHours(); var min = thedate.getMinutes(); var sec = thedate.getSeconds(); var yyyy = thedate.getFullYear(); if (dd < 10) { dd = '0' + dd } if (mm < 10) { mm = '0' + mm } if (hh < 10) { hh = '0' + hh } if (min < 10) { min = '0' + min } if (sec < 10) { sec = '0' + sec } switch (return_type) { case 1: // Datumobjekt var return_date = thedate; //new Date(yyyy, mm, dd, hh, min, sec); break; case 2: // Sträng var return_date = yyyy + "-" + mm + "-" + dd + " " + hh + ":" + min + ":" + sec; break; case 3: // ISO 8601 YYYY-MM-DDThh:mm:ssTZD var return_date = yyyy + "-" + mm + "-" + dd + "T" + hh + ":" + min + ":" + sec + "+01:00"; break; default: // Sträng var return_date = yyyy + "-" + mm + "-" + dd + " " + hh + ":" + min + ":" + sec; } } else { // ogiltigt datum return_date = -1; } return return_date; } function is_valid_date(d) { if (Object.prototype.toString.call(d) !== "[object Date]") return false; return !isNaN(d.getTime()); } // Sortera en "associative array", egentligen ett objekt function by_sorted_value(obj, callback, context) { var tuples = []; for (var key in obj) tuples.push([key, obj[key]]); tuples.sort(function (a, b) { return a[1] < b[1] ? 1 : a[1] > b[1] ? -1 : 0 }); var length = tuples.length; while (length--) callback.call(context, tuples[length][0], tuples[length][1]); } /* // Dynamic sort function that sorts objects by their value that you pass var People = [ {Name: "Name", Surname: "Surname"}, {Name:"AAA", Surname:"ZZZ"}, {Name: "Name", Surname: "AAA"} ]; ...and it will work when you do: People.sort(dynamicSort("Name")); People.sort(dynamicSort("Surname")); People.sort(dynamicSort("-Surname")); */ function dynamic_sort(property) { var sortOrder = 1; if (property[0] === "-") { sortOrder = -1; property = property.substr(1); } return function (a, b) { var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0; return result * sortOrder; } } /* // Dynamic sort function that sorts objects by their value that you pass var People = [ {Name: "Name", Surname: "Surname"}, {Name:"AAA", Surname:"ZZZ"}, {Name: "Name", Surname: "AAA"} ]; ...and it will work when you do: People.sort(dynamicSortMultiple("Name", "-Surname")) */ function dynamic_sort_multiple() { /* * save the arguments object as it will be overwritten * note that arguments object is an array-like object * consisting of the names of the properties to sort by */ var props = arguments; return function (obj1, obj2) { var i = 0, result = 0, numberOfProperties = props.length; /* try getting a different result from 0 (equal) * as long as we have extra properties to compare */ while (result === 0 && i < numberOfProperties) { result = dynamicSort(props[i])(obj1, obj2); i++; } return result; } } /* function date_diff(date1, date2) { return date1.getTime() - date2.getTime(); } */ // Hämtar en sida i kursen function get_page_for_course(page) { var counter = 0; var return_page = -1; // Loopar igenom kursstrukturen $.each(course.pages, function (key, value) { //console.log(key + ": " + value); if (counter == page || value.name == page) { return_page = value; return false; } counter++; }); return return_page; } /*console.log(myself(10)); function myself (n) { if (n <= 1) { return 1; } return n * myself(n-1); }*/ // Skapar en ny kurslogg function set_new_user_log(user_log) { if (!preview) { var course_id = course_info.published_info.course_id_kursstart; var exam_id = course_info.published_info.course_id_kursstart; ajax_load("../../courses_shared/set_user_log.php?course_id=" + course_id + "&exam_id=" + exam_id, { type: "insert", user_log: user_log, total_course_time: 0 }, function (data) { //console.log(data); }); } else { // Kollar om webbläsaren stödjer localStorage if (Modernizr.localstorage) { localStorage["user_log_course_" + course_info.course_id] = JSON.stringify(user_log); } } } var ajax_loader_delay = 1000; var ajax_loader_message_timer = false; // Visar ajaxloader med eller utan fördröjning. Med fördröjning kan vara bra för snabb uppkoppling då den bara visas om det tar lång tid function ajax_loader(enable, no_delay) { var no_delay = typeof no_delay !== 'undefined' ? no_delay : false; clearTimeout(ajax_loader_message_timer); if (enable) { if( no_delay ) { // Utan fördröjning $("#ajax_loader_container").fadeIn("fast"); } else { // Med fördröjning ajax_loader_message_timer = setTimeout(function () { $("#ajax_loader_container").fadeIn("fast"); clearTimeout(ajax_loader_message_timer); ajax_loader_message_timer = false; }, ajax_loader_delay); } } else { if (ajax_loader_message_timer) clearTimeout(ajax_loader_message_timer); ajax_loader_message_timer = false; $("#ajax_loader_container").fadeOut("fast"); } } // En generell ajax funktion. Retunerar eventuellt data eller true om det gick bra och false vid fel function ajax_load(url, post_data, callback) { ajax_loader(true); $.post(url, post_data) .done(function (data, textStatus, jqXHR) { ajax_loader(false); // Testar om det går att parsa det retunerade datat try { data = $.parseJSON(data); } catch (err) { // Kollar om felmeddelande innnehåller HTML och konvertar det i så fall till text if ($(jqXHR.responseText).length > 0) { var data = { status: err + '\n' + $(jqXHR.responseText).text() }; } else { var data = { status: err + '\n' + jqXHR.responseText }; } }; switch (data.status) { case "success": // Allt gick bra $('#course_content #page_error').remove(); callback(data); break; case "logged_out": // Användaren har blivit utloggad var url = parse_and_get_url(window.location); window.location = 'https://www.kursstart.se/?session_end=true'; break; default: // Error, something went wrong. Shows error message. var error_message = { title: i18next.t('theme.error.error'), text: i18next.t('theme.error.error_occured') + '\n' + i18next.t("theme.error.error_help_text") + '\n\n' }; // Klonar orginalobjektet så att inte det ändras. Funkar inte att klona med $.extend. var page_position = JSON.parse(JSON.stringify(course.pages[current_page_key].position)); var separator = ' > '; var nr_of_submenus = page_position.length - 1; var breadcrumbs_trail = []; //breadcrumbs_trail.push( '' + $element.find('a').first().text().replace('•','') + '' ); for (i = 0; i <= nr_of_submenus; i++) { $element = $(escape_for_jquery("#menu" + JSON.stringify(page_position))) page_name = $element.find('a').first().text().replace('•', ''); breadcrumbs_trail.push(page_name); page_position.pop(); } // Huvudnivå breadcrumbs_trail.push(i18next.t("theme.menu.contents")); // Vänder på arrayen så att det visas från huvudmeny och framåt breadcrumbs_trail.reverse(); var post_data = { subject: 'Make My Course - Felmeddelande', body: nl2br('

' + error_message.title + '

Användare: ' + JSON.stringify(user_info, null, 2) + '

Kurs: ' + course_info.course_id + ': ' + course_info.name + '

Inträffade här: ' + breadcrumbs_trail.join(separator) + '

' + error_message.text + i18next.t('theme.error.error_occured') + '\n\n' + data.status + i18next.t("theme.error.error_help_text") + $(jqXHR.responseText).text() + '

'), from: 'support@makemycourse.com', to: 'peter@xpectum.se' }; $.post('../../ajax.log-errors.php', post_data) var $page_error = $('#course_content #page_error'); if ($page_error.length == 0) { $('#course_content').prepend('

' + error_message.title + '

' + nl2br(error_message.text) + '
'); } else { $('#course_content #page_error').html('

' + error_message.title + '

' + nl2br(error_message.text) + '
'); } $('#course_content #page_error h3').off('click').on('click', function () { $(this).parent().remove(); }); return false; } }) .fail(function (jqXHR, textStatus, errorThrown) { ajax_loader(false); var error_message = { title: i18next.t('theme.error.error') }; switch (jqXHR.status) { case 0: error_message.text = i18next.t("theme.error.network") + ' ' + i18next.t("theme.error.error_help_text") + $(jqXHR.responseText).text(); break; case 404: error_message.text = i18next.t("theme.error.404") + ' ' + i18next.t("theme.error.error_help_text") + $(jqXHR.responseText).text(); break; case 500: error_message.text = i18next.t("theme.error.500") + ' ' + i18next.t("theme.error.error_help_text") + $(jqXHR.responseText).text(); break; default: error_message.text = i18next.t("theme.error.unknown") + ' ' + i18next.t("theme.error.error_help_text") + $(jqXHR.responseText).text(); } var $page_error = $('#course_content #page_error'); if ($page_error.length == 0) { $('#course_content').prepend('

' + error_message.title + '

' + nl2br(error_message.text) + '
'); } else { $('#course_content #page_error').html('

' + error_message.title + '

' + nl2br(error_message.text) + '
'); } $('#course_content #page_error h3').off('click').on('click', function () { $(this).parent().remove(); }); return false; }); } function play_video(video) { // Check for flashcard, in that case don't autoplay HTML5 video. if($('#page_contents .flashcards_container').length == 0) { if (video !== undefined ) { // Funkar inte för t.ex youtube // Autospelar om det inte är mobil if (!is_ipad()) { video.play(); }; } // Bugg på iPad som gör att bilden i videon fryser och bara ljudet fortsätter, om man inte pausar och kör igång igen. /*if(is_ipad()){ video.pause(); setTimeout(function(){ video.play(); }, 1000); }*/ } } function pause_video(video) { video.pause(); } function stop_video(video) { video.stop(); } // Uppdaterar kursloggen function set_user_log(auto_continue_to_next_page, auto_continue_play_video, course_finished, user_points_for_course) { uto_continue_to_next_page = typeof auto_continue_to_next_page !== 'undefined' ? auto_continue_to_next_page : false; auto_continue_play_video = typeof auto_continue_play_video !== 'undefined' ? auto_continue_play_video : false; course_finished = typeof course_finished !== 'undefined' ? course_finished : false; user_points_for_course = typeof user_points_for_course !== 'undefined' ? user_points_for_course : 0; ajax_loader(true); if (!$.isEmptyObject($("video")[0])) { $("video")[0].pause(); } if (course_finished) { update_type = "update_and_set_as_finished"; } else { update_type = "update"; } //preview = false if (!preview) { var course_id = course_info.published_info.course_id_kursstart; var exam_id = course_info.published_info.course_id_kursstart; ajax_load("../../courses_shared/set_user_log.php?course_id=" + course_id + "&exam_id=" + exam_id, { type: update_type, user_log: user_log, total_course_time: total_course_time, user_points_for_course: user_points_for_course }, function (data) { ajax_loader(false); //console.log(data); if (auto_continue_to_next_page) { get_page(1); } if (auto_continue_play_video) { if (!$.isEmptyObject($("video")[0])) { hide_event_container($("#event_container")); if (is_ipad()) $("video").css({ visibility: "visible" }); play_video($("video")[0]); } } }, "json"); } else { // Kollar om webbläsaren stödjer localStorage if (Modernizr.localstorage) { ajax_loader(false); localStorage["user_log_course_" + course_info.course_id] = JSON.stringify(user_log); if (auto_continue_to_next_page) { get_page(1); } if (auto_continue_play_video) { if (!$.isEmptyObject($("video")[0])) { hide_event_container($("#event_container")); if (is_ipad()) $("video").css({ visibility: "visible" }); play_video($("video")[0]); } } show_page_info(); } } /*if(show_only_debug_buttons) { show_page_info(); }*/ //console.log(user_log); } // Koll så att man inte kan gå bakåt om man är på första sidan eller fortsätta om man är på sista sidan // Skickar man in tomt så försöker den hämta från course_log. Skicka in "none" eller "tomt" eller nåt för att gömma alla knappar function show_control_buttons(buttons_to_show) { buttons_to_show = typeof buttons_to_show !== 'undefined' ? buttons_to_show : ""; // Börjar med att gömma alla knappar och kontrollpanelen var view_control_buttons = false; // OBS! GÅR EJ ATT FEJDE UT KNAPPARNA HÄR! <--- Blir nån slags bugg. Kanske att den inte hinner med att fejda ut. $("#control_buttons").hide(); $("#control_buttons .button").hide(); $("#control_buttons .button").removeClass("button_disabled"); // Kollar om det är sidans inställningar för vilka knappar som ska synas som ska användas eller om det är det man skickar in i funktionen // Lägger vilka knappar som ska synas i en array var control_buttons_to_show = ""; if (buttons_to_show != "") { control_buttons_to_show = buttons_to_show.split(","); } else { if (!$.isEmptyObject(course.pages[current_page_key].show_control_buttons)) { control_buttons_to_show = course.pages[current_page_key].show_control_buttons.split(","); } } if (control_buttons_to_show.length != 0) { // Kollar om knapparna ska synas först när en film är klar var control_buttons_to_show_when_movie_finished = false; if ($.inArray("movie_finished", control_buttons_to_show) != -1) { control_buttons_to_show_when_movie_finished = true; } $.each(control_buttons_to_show, function (control_button_key, control_button) { switch ($.trim(control_button)) { case "all": $("#control_buttons .button").fadeIn("fast"); view_control_buttons = true; break; case "next": //console.log("Visa framåt"); $("#next_button").fadeIn("fast"); view_control_buttons = true; break; case "previous": //console.log("Visa bakåt"); $("#prev_button").fadeIn("fast"); view_control_buttons = true; break; case "course_menu": //console.log("Visa snabbmeny"); $("#show_course_menu_button").fadeIn("fast"); view_control_buttons = true; break; case "return": //console.log("Visa snabbmeny"); $("#return_button").fadeIn("fast"); view_control_buttons = true; break; } }); if (view_control_buttons) { if (control_buttons_to_show_when_movie_finished) { $("video").bind("ended", function () { $("#control_buttons").fadeIn("fast"); check_course_postition_for_buttons(); }); } else { $("#control_buttons").fadeIn("fast"); check_course_postition_for_buttons(); } } } // Kod för debugknapparna if (preview) { $("#debug_next_button").fadeOut("fast"); $("#debug_prev_button").fadeOut("fast"); $('#debug_select_page').fadeOut("fast"); if (current_page_key == course.pages.length - 1) { $("#debug_next_button").fadeOut("fast"); } else { $("#debug_next_button").fadeIn("fast"); } if (current_page_key == 0) { $("#debug_prev_button").fadeOut("fast"); } else { $("#debug_prev_button").fadeIn("fast"); } $('#debug_select_page').fadeIn("fast"); } } $(function () { // Kör en timer för att behålla referensen till parent-fönstret, ifall det laddas om. if (typeof preview !== 'undefined') { if (preview) { childTimer = window.setInterval(function () { try { if (window.opener != null) { // Kollar om den är öppnad från en parent, annars tas timern bort window.opener.preview_window = window; } else { window.clearInterval(childTimer); } } catch (e) {} }, 1000); window.onUnload = function () { try { window.clearInterval(childTimer); window.opener.preview_window = null; } catch (e) {} } } } }); function check_course_postition_for_buttons() { // Loopar igenom alla kontrollknappar och tar bort alla förutom prev_button och next. För att rensa upp i bottombar om det skapats extraknappar för t.ex övningar och övningsgenomgångar $control_buttons = $('#control_buttons #control_buttons_left, #control_buttons #control_buttons_right').children(); $.each($control_buttons, function (control_button_key, control_button) { switch ($(control_button).attr('id')) { case 'prev_button': case 'next_button': case 'show_course_menu_button': break; default: $(control_button).remove(); } }); // Om kursen inte är linjär så ska snabbvals-knappen också rensas bort. Den ska bara synas i linjära kurser if (course_info.course_linear == 0) { $('#control_buttons #control_buttons_left #show_course_menu_button').remove(); } $('#control_buttons_left, #control_buttons_right').show(); // Kollar om man är på första eller sista sidan för då ska inte bakåt respektive framåt-knappen inte synas if (current_page_key == course.pages.length - 1) { $("#next_button").fadeOut("fast"); } else { //$("#next_button").fadeIn("fast"); } if (current_page_key == 0) { $("#prev_button").fadeOut("fast"); } else { //$("#prev_button").fadeIn("fast"); } } /** * Hämtar numret på nuvarande sida och antalet sidor i kursen */ function get_course_pos() { var course_pos = new Object(); course_pos.current = user_log.pages.length; //current_page_key + 1; course_pos.total = course.pages.length; course_pos.percent = Math.floor(100 * (course_pos.current) / course_pos.total) course_pos.latest_viewed_page = get_latest_viewed_page(); course_pos.latest_viewed_page++; return course_pos; } /** * Uppdaterar info om var kursdeltagaren är i kursen */ function update_course_pos() { var course_pos = get_course_pos(); $('#course-pos .current').html(course_pos.current); $('#course-pos .total').html(course_pos.total); } function get_latest_viewed_page() { var latest_pagekey = -1; var timestamps = new Object(); var sorted_timestamps = new Object(); //console.log(get_and_format_date("", 1).toLocaleString()); // Loopar igenom användarloggen $.each(user_log.pages, function (key, value) { if (!!value) { //console.log(key + ': ' + value.name + ' : ' + value.date_viewed + ' : ' + get_and_format_date(value.date_viewed,1) ); // Check if the date is valid if (get_and_format_date(value.date_viewed,1) == -1) { // The date isn't valid, set it to todays date and current time timestamps[key] = get_and_format_date("", 3); user_log.pages[key].date_viewed = get_and_format_date("", 3); } timestamps[key] = get_and_format_date(value.date_viewed, 1).getTime(); } }); // Sorterar arrayen numeriskt och stigande, dvs högst värdet sist mao sidan där man var sist by_sorted_value(timestamps, function (key, value) { sorted_timestamps[key] = value; latest_pagekey = key; }); return parseInt(latest_pagekey); } // Skriver ut information om sidan function show_page_info() { var view_once = false; var view_in_menu = true; if (typeof course.pages[current_page_key].view_once != 'undefined') view_once = boolean_check_and_convert(course.pages[current_page_key].view_once); if (typeof course.pages[current_page_key].view_in_menu != 'undefined') view_in_menu = boolean_check_and_convert(course.pages[current_page_key].view_in_menu); // Tömmer debug-infon så att det inte ligger kvar gammal info där när man byter sida debug_page_info = $('#debug_page_info .debug_page_info_name').next('td'); $.each(debug_page_info, function (key, value) { if (!$(value).has('textarea').length) { $(value).empty(); } else { $(value).val(''); } }); debug_page_info = $("#debug_page_info table td") $.each(debug_page_info, function (key, value) { if (typeof $(value).attr('class') != 'undefined') { class_name = $(value).attr('class'); switch (class_name) { case "done": // Förutsätter att sidan är klar var done = true; // Annar hämtar statusen från course_log if (course.pages[current_page_key][class_name] != undefined) { done = course.pages[current_page_key][class_name]; } $(value).html(String(done)); break; case "type": $(value).html(pagetypes[Number(course.pages[current_page_key][class_name])] + " (" + course.pages[current_page_key][class_name] + ")"); break; case "view_once": $(value).html(view_once.toString()); break; case "view_in_menu": $(value).html(view_in_menu.toString()); break; case "description": $(debug_page_info).children("#description_text").val(course.pages[current_page_key][class_name]); break; case "todo": $(debug_page_info).children("#todo_text").val(course.pages[current_page_key][class_name]); break; case "user_log": $(debug_page_info).children("#user_log_text").val(JSON.stringify(user_log.pages[current_page_key], null, '\t')); break; case "position": $(value).html(JSON.stringify(course.pages[current_page_key][class_name])); break; default: $(value).html(course.pages[current_page_key][class_name]); } } }); } // Hämtar eventuella undertexter function get_subtitles(movie_url) { // Vilka språk som finns sätts i kursstrukturen, course.js.php /*var languages = [{ "label": "Svensk undertext", "srclang": "sv" },{ "label": "English subtitle", "srclang": "en" },{ "label": "Norske undertekst", "srclang": "no" }];*/ // Sätter standard filformat var subtitle_formats = ["vtt", "srt", "sbv", "lrc", "ttml"]; var subtitle_file_extension = "." + subtitle_formats[0]; // Hämtar defaultspråket var querystring = window.location.search; var querystring = deparam(querystring); // Hämtar ut filnamnet på filmen, exklusive sökvägen var str = movie_url; var regex = /([^/]+$)/i; var movie_url_filname = str.match(regex); if (movie_url_filname != null) { movie_url_filname = movie_url_filname[0]; var subtitles = []; var index = 0; load_language(subtitles, index, languages, movie_url, subtitle_file_extension, language_settings.language, false); } } use_captionator = false; // Kollar vilka undertexter som finns och lägger dom i en array. Lägger sedan till dom tiil video-elementet function load_language(subtitles, index, languages, movie_url, subtitle_file_extension, language, found_subtitle) { if (index < languages.length) { $.get(movie_url + "." + languages[index].srclang + subtitle_file_extension) .done(function (data) { //console.log(data); subtitles.push(""); index++; found_subtitle = true; load_language(subtitles, index, languages, movie_url, subtitle_file_extension, language, found_subtitle); }) .fail(function (jqXHR, textStatus, errorThrown) { //console.log($(jqXHR.responseText).text()); switch (jqXHR.status) { case 0: error_text = "Could not connect.\n Verify Network."; break; case 404: error_text = "Page not found [404]."; break; case 500: error_text = "Internal Server Error [500]."; break; default: error_text = "Unknown error. " + $(jqXHR.responseText).text(); } //$("#course_page_content").html("

" + error_text + "

"); //console.log(error_text); index++; load_language(subtitles, index, languages, movie_url, subtitle_file_extension, language, found_subtitle); }); } else { if (found_subtitle) { var video_object = $("video")[0]; $(video_object).append(subtitles.join("")); use_captionator = captionator.captionify(); } set_language(); } } // Växlar mellan undertexter function switch_subtitles() { if (typeof $("video")[0] !== 'undefined') { // Hämtar undertexterna var texttracks = $("video")[0].textTracks; if (typeof texttracks == "object") { if (use_captionator) { // Firefox //OFF, HIDDEN eller SHOWING $.each(texttracks, function (texttrack_key, texttrack) { texttracks[texttrack_key].mode = captionator.TextTrack.OFF; if (texttracks[texttrack_key].language == language_settings.language && language_settings.subtitle == true) { texttracks[texttrack_key].mode = captionator.TextTrack.SHOWING; } }); } else { // Safari, Chrome // hidden eller showing. disabled verkar inte funka $.each(texttracks, function (texttrack_key, texttrack) { texttracks[texttrack_key].mode = "hidden"; if (texttracks[texttrack_key].language == language_settings.language && language_settings.subtitle == true) { texttracks[texttrack_key].mode = "showing"; } }); } } } } // Visar / gömmer undertexter function toggle_subtitles(show) { language_settings.subtitle = show; $.cookie("language_settings", JSON.stringify(language_settings)); switch_subtitles(); } // Byter språk function set_language() { if (typeof languages !== 'undefined') { if (languages instanceof Array) { if (languages.length != 0) { $("*[lang]").hide(); $("*[lang='" + language_settings.language + "']").show(); switch_subtitles(); } } } } // Måste även gömma elemnten som skapats annars ligger dom i vägen t.ex när man byter sida. function hide_captionator() { if (use_captionator) { $(".captionator-cue-canvas").remove(); window.addEventListener("resize", function (eventData) { $(".captionator-cue-canvas").remove(); }); } } // Loopar igenom alla språk och skapar olika typer av knappar function init_change_language_buttons(type) { var language_buttons = [""); return language_buttons; } // Lägger in knapparna där man kan välja språk function show_languages() { if (typeof languages !== 'undefined') { if (languages instanceof Array) { if (languages.length != 0) { language_buttons = init_change_language_buttons("flags"); if ($("#course_tools #language_settings").length == 0) { $("#course_tools").append("
") } $("#course_tools #language_settings").html(language_buttons.join("")); $("#course_tools #language_settings li span").click(function () { language_settings.language = $(this).data("language"); $.cookie("language_settings", JSON.stringify(language_settings)); set_language(); }); if (preview) { //$("#change_language").show() } } } } } // Hitta en sida med ett visst databas id. Används främst för förhandsgranskning från publiceringsverktyget function find_page_with_page_id(page_id) { var found_page_key = 0; $.each(course.pages, function (page_key, page) { if (page.id == page_id) { found_page_key = page_key; return false; } }); return found_page_key; } // Hämatr en sida från orginal kursstrukturen, den som inte är "tillplattad". Retunerar sidan med eventuella childpages function get_page_by_position(position) { // Sträng '0,4' eller array [0,4] // Om ingen postion skickats in hämtas nuvarande sida if (arguments.length == 0) { position = course.pages[current_page_key].position; } else { // Kollar om det inte är en array och konverterar det i så fall och gör om till int if (!Array.isArray(position)) { position = position.split(',').map(Number); } } var str = ""; for (var i = 0; i < position.length; i++) { if (i == 0) { str = "original_course.pages[" + position[i] + "]"; } else { str += ".children[" + position[i] + "]"; } } str += ";"; return eval(str); } // Hämtar parent sidan function get_parent_page(page_index_or_position) { // Om ingen index eller position skickats in hämtas nuvarande sida if (arguments.length == 0) page_index_or_position = current_page_key; // Hämtar positionen om det är index som skickats in var parent_page_position = ""; if ($.isArray(page_index_or_position)) { // Klonar orginalobjektet så att inte det ändras. Funkar inte att klona med $.extend. parent_page_position = JSON.parse(JSON.stringify(page_index_or_position)); } else { // Klonar orginalobjektet så att inte det ändras parent_page_position = $.extend(true, {}, course.pages[page_index_or_position].position); //Gör om det från ett object till array parent_page_position = $.map(parent_page_position, function (el) { return el }); } // Tar bort sista elementet i arrayen parent_page_position.pop(); if (parent_page_position != "") { parent_page = get_page_by_position(parent_page_position); } else { parent_page = ""; } return parent_page; } /********************************************************* Escape all needed characters for jQuery. Because jQuery uses CSS syntax for selecting elements, some characters are interpreted as CSS notation. For example, ID attributes, after an initial letter (a-z or A-Z), may also use periods and colons, in addition to letters, numbers, hyphens, and underscores (see W3C Basic HTML Data Types). The colon (":") and period (".") are problematic within the context of a jQuery selector because they indicate a pseudo-class and class, respectively. In order to tell jQuery to treat these characters literally rather than as CSS notation, they must be "escaped" by placing two backslashes in front of them. https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/ */ function escape_for_jquery(str) { return str.replace(/(:|\.|\[|\]|,)/g, "\\$1"); } /*********************************************************/ // Lägger till/ändrar querystringen till rätt ID för sidan function add_page_querystring() { url = parse_and_get_url(window.location); // Standard värden query_keys = new Object(); query_keys.course_id = url.query.course_id; query_keys.page_id = course.pages[current_page_key].id; query_keys.lng = url.query.lng; if (url.query.preview != undefined) { query_keys.preview = url.query.preview; } if (url.query.demo_token != undefined) { query_keys.demo_token = url.query.demo_token; } if (url.query.responsive_preview != undefined) { query_keys.responsive_preview = url.query.responsive_preview; } if (url.query.hash != undefined) { query_keys.hash = url.query.hash if(query_keys.hash.slice(-1) != '='){ // Add "=" (if missing) at the end of encrypted hash since it gets removed when parsing the url query_keys.hash += '='; } } // Om sidan övning eller övningsgenomgång så utökas querystringen med ytterligare id för att hålla koll på vilken sidan man är på och ibland att man bara ska kunna se ett visst span av sidor i övningsgenomgånar. I annat fall sätt querystringen till defaultvärden. switch (course.pages[current_page_key].type) { case 13: // Övning if (url.query.debug != undefined) { query_keys.debug = url.query.debug; } break; case 15: // Övningsgenomgång query_keys.question_page_key = url.query.question_page_key; query_keys.review_page_key = url.query.review_page_key; if (url.query.review_pages_span != undefined) { query_keys.review_pages_span = url.query.review_pages_span; } break; } url.query = query_keys; new_url = url.scheme + '://' + url.host + url.path + (!$.isEmptyObject(url.query) ? '?' + $.param(url.query) : "") + (!$.isEmptyObject(url.hash) ? '#' + $.param(url.hash) : ""); window.history.replaceState({}, document.title, new_url); } events = ""; current_event_key = ""; function get_page(offset) { var animate_page_change_speed = "medium"; // Kollar om sidan finns eller om någonting blivit galet, sätter i så fall så att man hamnar på första sidan. if (course.pages[current_page_key] == undefined) { current_page_key = 0; } if (course.pages[current_page_key].type == 14) { // Minskar ner när det är övningsexempel-sidor för att man ska se skillnaderna mellan sidorna bättre. animate_page_change_speed = 'none'; } show_hide_page_contents(animate_page_change_speed, 'opacity', 'hide', function(){ hide_captionator(); // Rensar och sätter variabler events = ""; current_event_key = ""; var current_time = 0; // När man klickat i menyn så sätts variabler tillbaka för att kolleb om man är på samlingssidan för alla övningar och kunskapstester. if ($('#course_menu_pages').multilevelpushmenu) { if (multilevelpushmenu_clicked) { multilevelpushmenu_dont_change = false; got_here_from_exercises_or_knowledge_tests = false; // Nollställer querystringen från question_page_key så att man inte kan hamna mitt i en sida i en övning, t.ex övningsprovet url = parse_and_get_url(window.location); if (url.query.question_page_key != undefined) { url.query.question_page_key = 0; new_url = url.scheme + '://' + url.host + url.path + (!$.isEmptyObject(url.query) ? '?' + $.param(url.query) : "") + (!$.isEmptyObject(url.hash) ? '#' + $.param(url.hash) : ""); window.history.replaceState({}, document.title, new_url); } } } // Rensar eventuella test-timers för säkerhets skull. for (var i = test_timers.length; i--;) { clearInterval(test_timers[i]); test_timers.splice(i, 1); } // Om sidan är "välj övning" så hoppa till nästa sida/kapitel, istället för nästa undersida. Mao det ska inte gå att stega in i övningsexempel/övning med framåtknappen /* Sidtyper: 12: Välj övning 13: Övning 14: Övningsexempel 15: Övningsgenomgång 16: Övningar och Kunskapstester */ if (course.pages[current_page_key].type == 12 && offset == 1) { var page_position = JSON.parse(JSON.stringify(course.pages[current_page_key].position)); // Klonar page_position så att man inte ändrar i orginalet var last_page_pos = page_position[page_position.length - 1]; last_page_pos += 1; page_position[page_position.length - 1] = last_page_pos; var page = get_page_by_position(page_position); current_page_key = page.page_index; offset = 0; } //Om sidan är en övning, övningsgenomgång eller övningsexempel och man har backat dit från en annan sida så ska man hamna på "Välj övning"-sidan var exercise_page_types = [13, 14, 15]; if ($.inArray(course.pages[current_page_key].type, exercise_page_types) == -1 && offset == -1) { // Kollar om sidan man kommer till är en övning, övningsgenomgång eller övningsexempel för i så fall ska man hamna på "Välj övning"-sidan if ($.inArray(course.pages[current_page_key + offset].type, exercise_page_types) !== -1) { var page_position = JSON.parse(JSON.stringify(course.pages[current_page_key].position)); // Klonar page_position så att man inte ändrar i orginalet var last_page_pos = page_position[page_position.length - 1]; last_page_pos -= 1; page_position[page_position.length - 1] = last_page_pos; var page = get_page_by_position(page_position); current_page_key = page.page_index; offset = 0; } } // Aktuellt sid-ID current_page_key = current_page_key + offset; if (current_page_key > course.pages.length - 1) { current_page_key = 0; } if (preview) { //$('#debug_select_page').val(current_page_key); debug_show_page_list(); } add_page_querystring(); // Om kursen inte är linjär så sparar inte kunskapstester; quiz, sant eller falskt och jeopardy if (!course_info.course_linear) { var dont_save_page_types = [3, 7, 9]; if ($.inArray(course.pages[current_page_key].type, dont_save_page_types) > -1) { // Tar bort eventuella svar på sidan if (!$.isEmptyObject(user_log.pages[current_page_key])) { if (!$.isEmptyObject(user_log.pages[current_page_key].answers)) { delete user_log.pages[current_page_key].answers; delete user_log.pages[current_page_key].points; } } } } // Tar bort allting som eventuellt lagts till utöver sidinnheållet, t.ex explanation_container för övningsexempel // Bara #course_guide, course_page_content ska finnas under #course_content $content_to_remove = $('#course_content').children().not('#course_guide, #page_name, #course_page_content, #video_controllers, .bottom_bar_dummy, #bottom_bar'); $content_to_remove.remove(); // Containern var course_page_content = $("#course_page_content"); // Kollar om sidan är visad förut och om den bara ska visas en gång view_once = false; if (typeof course.pages[current_page_key].view_once != 'undefined') view_once = boolean_check_and_convert(course.pages[current_page_key].view_once); if (!$.isEmptyObject(user_log.pages[current_page_key]) && boolean_check_and_convert(view_once)) { get_page(1); } else { // Sidans innehåll var content = course.pages[current_page_key].content; // Sidas rubrik // Finns även kategori, vet inte om det behövs // course.pages[current_page_key].category var theme_page_name = $('#course_content > #page_name'); var page_name_and_content = content; if (!theme_page_name.length) { page_name_and_content = "

" + course.pages[current_page_key].name + "

" + page_name_and_content; } else { $('#course_content > #page_name h2').html(course.pages[current_page_key].name); } content = '
' + page_name_and_content + '
' // Sätter standardvärden för videoprogress och gömmer den tills videon kommer igång var video_progress_percent = 0; $("#video_progress").width(video_progress_percent + "%"); /*$("#video_controllers").fadeOut("fast"); // Bugg i WebKit, controllerna fejdas inte bort*/ $("#video_controllers").hide(); show_control_buttons(); if ($('#course_menu_pages').multilevelpushmenu) { if (multilevelpushmenu_clicked) { set_active_menu_page(offset); } } // Kollar om det finns css som ska laddas load_css_for_page(course.pages[current_page_key].css_url, function(){ ajax_loader(true); // Eventuell CSS laddad remove_unused_css_for_page(course.pages[current_page_key].css_url); insert_page_contents(course_page_content, content, function(){ //$('#course_content #page_name h2').html('Lägger in innehållet') // Lägger in innehållet set_readmore_button(); // Sätter poster-bild set_video_poster_image(course_page_content); // Lägger till undertext set_video_subtitle(course_page_content); // Lägger till attributet target="_blank" på alla länkar i elementen .text. $('#page_contents .text a').attr('target', '_blank'); //load_js_for_page2(course.pages[current_page_key].js_url); load_js_for_page_via_getscript(course.pages[current_page_key].js_url).done(function() { // All eventuella script laddade show_hide_page_contents(animate_page_change_speed, 'opacity', 'show', function(){ // Visar innehållet ajax_loader(false); if ($('#course_menu_pages').multilevelpushmenu) { if (multilevelpushmenu_dont_change == false) { if (!multilevelpushmenu_clicked) { set_active_menu_page(offset); } else { multilevelpushmenu_clicked = false; } } }; }); }).fail(function(error) { // one or more scripts failed to load //console.log('one or more scripts failed to load'); }).always(function() { // always called, both on success and error //console.log('always called, both on success and error'); }); }); }); //countup_start(); //create_breadcrumbs_trail(); //show_control_buttons(); show_languages(); // Uppdaterar info om sidposition //update_course_pos(); // Uppdaterar guiden sida x av y $("#course_guide_text").fadeOut("fast", function () { var dont_show_on_page_types = [12, 13, 15]; if ($.inArray(course.pages[current_page_key].type, dont_show_on_page_types) == -1) { page_nr = course.pages[current_page_key].position[course.pages[current_page_key].position.length - 1] + 1; page_nr_of = original_course.pages.length; // Kollar sidan är ett kapitel och börjar i så fall räkna från 1 //if( course.pages[current_page_key].children_nr_of !== undefined ) { if (current_page_is_chapter()) { page_nr = 1; page_nr_of = course.pages[current_page_key].children_nr_of + 1; } // Kollar om man är inuti ett kapitel //if( course.pages[current_page_key].position.length > 1 && course.pages[current_page_key].children_nr_of == undefined ) { if (course.pages[current_page_key].position.length > 1 && !current_page_is_chapter()) { page_nr++; // Plussar på ett eftersom huvudsidan i kapitlet är nr 1 page_nr_of = get_parent_page(current_page_key).children_nr_of + 1; // Hämtar huvudsidan i kapitle och kollar hur många sidor det innehåller } // Kollar om det är en ensam övningsexempel mall utan några undersidor och fixar till sidnumreringen if(course.pages[current_page_key].type == 14 && !current_page_is_chapter()){ parent_page = get_parent_page(current_page_key); if(parent_page.type != 14){ page_nr = 1; page_nr_of = 1; $("#prev_button").fadeOut("fast"); $("#next_button").fadeOut("fast"); } } /* Byter ut och formaterar strängen beroende på hur det ska visas upp. Utseendet och vad som ska skrivas ut ställs in i respektive tema. %1$s : Sida %2$s : x %3$s : av %4$s : y %1$s %2$s %3$s %4$s = Sida x av y %2$s / %4$s = x / y show_in_root: true // Visas även i huvudnivån/rootnivån i kursen och inte bara inuti kapitel show_with_content: true // Flyttar in sidvisningen inuti kursinehållet */ var page_nr_settings = $.parseJSON($('#course_guide_text').attr('data-settings')); $("#course_guide_text").html(sprintf(page_nr_settings.formatting, i18next.t("theme.text.page"), page_nr, i18next.t("theme.text.of"), page_nr_of)); // Flyttar in course_guide in tillsammans med innehållet if (page_nr_settings.show_with_content) { // Kollar om den redan är flyttad if ($('#course_content > #course_guide').length == 0) { var $course_guide = $("#course_tools #course_guide"); var $course_guide = $course_guide.detach().prependTo('#course_content'); } } // Visar inte antalet sidor om man är i huvudnivån if (page_nr_settings.show_in_root == true) { $('#course_guide_text').fadeIn("fast"); //}else if( page_nr_settings.show_in_root == false && course.pages[current_page_key].position.length > 1 || course.pages[current_page_key].children_nr_of !== undefined ) { } else if (page_nr_settings.show_in_root == false && course.pages[current_page_key].position.length > 1 || current_page_is_chapter()) { $('#course_guide_text').fadeIn("fast"); } } }); // Uppdaterar progressbaren var progress_percent = Math.floor(100 * (current_page_key + 1) / course.pages.length); $("#progress").width(progress_percent + "%"); // Om kursen är linjär så ska snabbvals-menyn uppdateras varje gång man byter sida. if (typeof set_course_menu_pages === "function") { // Kollar så att funktionen finns för säkerhets skull if (course_info.course_linear == 1) { set_course_menu_pages(); } } // Kollar om sidan redan finns i användarloggen och uppdaterar isf den if (!$.isEmptyObject(user_log.pages[current_page_key]) && user_log.pages[current_page_key] != "") { //console.log("Uppdaterar tidigare besökt sida"); user_log.pages[current_page_key].name = course.pages[current_page_key].name; user_log.pages[current_page_key].viewed = true; user_log.pages[current_page_key].date_viewed = get_and_format_date("", 3); user_log.pages[current_page_key].time_visited = (user_log.pages[current_page_key].time_visited == undefined ? 1 : user_log.pages[current_page_key].time_visited += 1); } else { // Annars lägger till sidan i användarloggen //console.log("Lägger till ny ej tidigare besökt sida"); if(user_log.pages == ""){ user_log.pages = []; } new_page = { "name": course.pages[current_page_key].name, "viewed": true, "date_viewed": get_and_format_date("", 3), "time_visited": 1 }; user_log.pages[current_page_key] = new_page; } //console.log( JSON.stringify(user_log.pages[current_page_key], null, 2)); // Sparar hur länge man var inne på föregående sida och totaltiden //user_log.pages[current_page_key-offset].time_visited = $('#countup_seconds').countdown('getTimes')[6]; //total_course_time = $('#countup_total_seconds').countdown('getTimes')[6]; // Sparar användarloggen set_user_log(false, true, false); } }); } /// Lägger in innehållet function insert_page_contents(course_page_content, content, callback){ switch (course.pages[current_page_key].type) { case 1: // text/html // Lägger till sidinnehållet i containern course_page_content.html(content); set_language(); break; case 10: // text/html fullskärm, täcker hela ytan // Lägger till sidinnehållet i containern course_page_content.html(content); set_language(); break; case 2: // video /*$("#course_page_content").html(content); set_language(); break;*/ case 11: // video med kontrollfrågor case 6: // film med frågor och respons // All denna kod för video borde läggas i en funktion så att man kan ladda filmer med event dynamiskt, tex olika filmer beroende på om man är godkänd eller inte. Se sortabel.js och true_false_result.js // Skapar eventkontainern för video content += "
"; //course.pages[current_page_key].movie_url = "inledning_jonas_lundin"; //autoplay=\"autoplay\" controls=\"controls\" // Skapar videokontainer // Hmm vilken codecs ska man använda för mp4? Verkar som man ska använda avc1.42E01E, mp4a.40.2 istället för H.264, AAC, // Firefox och Chrome kör .webm // Safari och IE kör .mp4 // För att undvika buffring rnd = "?rnd=" + Math.floor(Math.random() * 10000); content += ""; //\ // Lägger till sidinnehållet i containern course_page_content.html(content); if (typeof languages !== 'undefined') { if (languages instanceof Array) { if (languages.length != 0) { // Hämtar eventuella undertexter get_subtitles(course.pages[current_page_key].movie_url); $("video").bind("ended", function () { hide_captionator(); }); } } } // Visar controllern på iPad eftersom det inte går att autostarta video // Visar även controllern på alla filmer förutom filmer med frågor och respons if (is_ipad() || preview || course.pages[current_page_key].type == 2) { toggleControls($("video")[0]); } $("#video_controllers").fadeIn("fast"); // Kollar om det finns några events if (!$.isEmptyObject(course.pages[current_page_key].events)) { // Hämtar events för video events = course.pages[current_page_key].events; } $("#course_page_content video").bind("timeupdate", function () { // Tiden som spelats // I hela sekunder current_time = parseInt(this.currentTime); total_time = parseInt(this.duration); //console.log(current_time + " / " + total_time); // Uppdaterar video progressbaren video_progress_percent = Math.floor(100 * (current_time) / total_time); $("#video_progress").width(video_progress_percent + "%"); // Kollar om det finns några events if (!$.isEmptyObject(course.pages[current_page_key].events)) { // Rensar alla triggade event förutom de som bara får visas en gång vid start/omstart av en film if (current_time == 0) { $.each(events, function (key, value) { if (value.repeatable) { value.triggered = false; } }); } // Föregående tid (används för att "throttla" antalet anrop till eventfunktionen) old_time = 0; // Hämtar nästa event från eventlistan (movie_properties) if (current_time > old_time) get_next_movie_event(events, current_time, $(this), $("#event_container")); old_time = current_time; } }); // Kollar om filmen ska kunna spelas upp igen direkt när den slutat movie_buttons_container = ($("#course_page_content #movie_buttons_container")); if (movie_buttons_container.length > 0) { $("video").bind("ended", function () { if (is_ipad()) $("video").css({ visibility: "hidden" }); $("#movie_buttons_container").fadeIn("fast"); }); $("#watch_movie_again_button").off('click').click(function () { $("#movie_buttons_container").fadeOut("fast"); if (is_ipad()) $("video").css({ visibility: "visible" }); play_video($("video")[0]); }); } break; case 3: // sant eller falskt // Lägger till sidinnehållet i containern course_page_content.html(content); set_language(); break; case 4: // rangordna // Lägger till sidinnehållet i containern course_page_content.html(content); set_language(); break; case 5: // utvärdering // Lägger till sidinnehållet i containern course_page_content.html(content); set_language(); break; case 7: // Quiz checkbox, radio fritext // Lägger till sidinnehållet i containern course_page_content.html(content); set_language(); break; case 8: // Dra och släpp Quiz // Lägger till sidinnehållet i containern course_page_content.html(content); set_language(); break; case 9: // Jeopardy // Lägger till sidinnehållet i containern course_page_content.html(content); set_language(); break; default: // Lägger till sidinnehållet i containern course_page_content.html(content); set_language(); break; } var $has_attached_files = $(course_page_content).find('#attached_files'); if ($has_attached_files.length != 0) { if( $(course_page_content).find('.gen_sound_index').length != 0 ) { $($has_attached_files).insertBefore( $(course_page_content).find('.gen_sound_index') ); } load_css_for_page('../../js/plugins/fine-uploader-all-5.16.2/fine-uploader-mmc-course.css', function(){ var attached_files = $.parseJSON( $has_attached_files.attr('data-attached_files') ); var header = attached_files.length > 1 ? i18next.t('files:text.attached_files') : i18next.t('files:text.attached_file'); var html = ['

' + header + '

'); $has_attached_files.html( html.join('') ); setTimeout(function() { $has_attached_files.addClass('show'); $has_attached_files.off("click").click(function () { $has_attached_files.focus(); }); }, 2000); //$("#course_content #attached_files").draggable({handle: "#course_content #attached_files h3", containment: '#course_wrapper'}); //$('#page_contents').css('padding'); }); } callback(); } function attached_file_icon(contentType){ var icon = ""; var icon_fallback = ""; switch (contentType) { case 'image/jpeg': icon = '../../js/plugins/fine-uploader-all-5.16.2/placeholders/if_jpgs_774688.svg'; icon_fallback = '../../js/plugins/fine-uploader-all-5.16.2/placeholders/if_jpgs_774688.png'; break; case 'image/png': icon = '../../js/plugins/fine-uploader-all-5.16.2/placeholders/if_pngs_774683.svg'; icon_fallback = '../../js/plugins/fine-uploader-all-5.16.2/placeholders/if_pngs_774683.png'; break; case 'application/pdf': icon = '../../js/plugins/fine-uploader-all-5.16.2/placeholders/if_pdfs_774684.svg'; icon_fallback = '../../js/plugins/fine-uploader-all-5.16.2/placeholders/if_pdfs_774684.png'; break; } return '\ \ \ '; } // Visar eller döljer innehållet function show_hide_page_contents(animate_page_change_speed, type, state, callback) { switch (type) { case 'opacity': if($('#page_transition').length == 0) { $('').appendTo('head'); } $("#course_page_content").removeClass('fade-transition-fast fade-transition-medium'); switch (animate_page_change_speed) { case 'medium': $("#course_page_content").addClass('fade-transition-medium'); break; case 'fast': $("#course_page_content").addClass('fade-transition-fast'); break; case 'none': break; default: $("#course_page_content").addClass('fade-transition-medium'); break; } if (state === 'show' && animate_page_change_speed !== 'none' ) { // fejd in $("#course_page_content").removeClass('do-fade').one('transitionend', function () { callback(); scroll_to_top_of_page(); }); } else if (animate_page_change_speed === 'none') { callback(); } else { // fejd ut $("#course_page_content").addClass('do-fade').one('transitionend', function () { callback(); }); } break; } } function scroll_to_top_of_page(){ // Scrollar högst upp på sidan $('html,body').animate({ scrollTop: 0 }, 800); } // Kollar om en fil finns och kör i så fall callback med jqXHR och datatyp // does_file_exist("http://www.xpectum.se/kurser/vid/FAR/intervjuer_intern_extern_redovisning.vtt"); // does_file_exist("http://www.xpectum.se/kurser/vid/bokforing1/4_typer_av_konton.vtt"); // does_file_exist('../../../kurser/vid/bokforing1/4_typer_av_konton2.vtt', function (jqXHR, dataTypes) { // if (dataTypes[0] === "text" && dataTypes[1] !== "html") { // console.log( 'Funkar!' ); // } // }) // does_file_exist("../../../images/xpectum_logotype.png"); function does_file_exist(url_to_file, callback) { $.ajax({ url: url_to_file }) .done(function (jqXHR, textStatus) { //console.log("scriptet '" + js_url + "' har laddats") //console.log( $(this)[0].dataTypes ); if (callback) { callback(jqXHR, $(this)[0].dataTypes); } else { return true; } }) .fail(function (jqXHR, textStatus, errorThrown) { return false; }); } /* Kollar och konverterar, om det behövs, strängar till riktiga boolean-värden Exempel: console.log( boolean_check_and_convert('false') ); // False console.log( boolean_check_and_convert(false) ); // False console.log( boolean_check_and_convert('true') ); // True console.log( boolean_check_and_convert(true) ); // True console.log( boolean_check_and_convert('abc') ); // False console.log( boolean_check_and_convert(123) ); // False */ function boolean_check_and_convert(bool_string) { switch (typeof bool_string) { case 'string': switch (bool_string.toLowerCase().trim()) { case "true": case "yes": case "1": return true; case "false": case "no": case "0": case null: return false; default: return false; } break; case 'boolean': return bool_string; break; default: return false; } } // Hämtar alla videoelement och sätter en poster bild utifrån samma filnamn som filmen function set_video_poster_image($element) { var $video_elements = $element.find('video'); if ($video_elements.length > 0) { $.each($video_elements, function (video_key, $video_element) { var poster_img = get_extension($($video_element).find('source').attr("src")); $($video_element).attr("poster", poster_img.name + ".jpg"); }); } } // Hämtar alla videoelement och sätter en subtitle utifrån samma filnamn som filmen function set_video_subtitle($element) { user_video_subtitle_settings = { show: false, language: '' }; /* Saves it in localStorage for all courses Change to this localStorage_key, if it is to be saved per course: 'user_video_subtitle_settings_course_' + course_info.course_id] */ var localStorage_key = 'user_video_subtitle_settings_course'; if (Modernizr.localstorage) { if( localStorage[localStorage_key] != undefined ){ user_video_subtitle_settings = JSON.parse(localStorage[localStorage_key]); } } // Alla språk. Om undertext-filen inte har någon suffix (_sv, _en, _no) så utgår vi från att det är en svensk undertext var languages = { "" : "Svenska", "sv" : "Svenska", "no" : "Norsk", "en" : "English" }; var $video_elements = $element.find('video'); if ($video_elements.length > 0) { // Loops through all videos $.each($video_elements, function (video_key, $video_element) { var subtitle = get_extension($($video_element).find('source').attr("src")); var subtitle_files = []; // Loops through all available languages and collect info $.each(languages, function (language_key, language_name) { var language_suffix = ''; var language = 'sv'; if(language_key !== ''){ var language_suffix = '_' + language_key; var language = language_key; } var subtitle_file = subtitle.name + language_suffix + '.vtt'; subtitle_files.push({"src": subtitle_file.toLowerCase(), "language_name": language_name, "language": language}); }); // Check for subtitle files and adds them as tracks get_subtitle_tracks(subtitle_files, $video_element, function () { }); // Check for user changes of subtitle and which language is choosen. To be saved in localStorage $($video_element)[0].textTracks.onchange = function(event) { user_video_subtitle_settings.show = false; user_video_subtitle_settings.language = ''; $.each(this, function (texttrack_key, texttrack) { if(texttrack.mode == 'showing'){ user_video_subtitle_settings.show = true user_video_subtitle_settings.language = texttrack.language } }) // TODO: change language/subtitle settings for all videos on page (video carousels) // Cant do it here because it triggers onchange again on all videos and it becomes an infinite loop (?) // Save the subtitle settings (is subitle showing and in what langugae) for current course in localStorage. // TODO: save settings in database, so it works everywhere ? if (Modernizr.localstorage) { localStorage[localStorage_key] = JSON.stringify(user_video_subtitle_settings); } }; }); } } // Check for subtitle files and adds them as tracks function get_subtitle_tracks(subtitle_files, $video_element, callback) { var progress = 0; $.each(subtitle_files, function (subtitle_file_key, subtitle_file) { $.ajax({ url: subtitle_file.src }) .done(function (jqXHR, textStatus) { default_language = ''; // If localStorage setting exist set chosen language if(user_video_subtitle_settings.language == subtitle_file.language){ default_language = ' default'; } $($video_element).append(''); if (++progress == subtitle_files.length) callback(); }) .fail(function (jqXHR, textStatus, errorThrown) { if (++progress == subtitle_files.length) callback(); }); }); } // Ändrar class på nuvarande sida i menyn så att man ser att den är aktiv. function set_active_menu_page(offset) { // Kollar om multilevelpushmenu finns //if ($('#course_menu_pages').multilevelpushmenu) { /* Position: [0] -> Nuvarande sida eller "kapitel". Dvs första sidan, eller första sidan i första kapitlet i kursen [0][1] -> Andra sidan i första kapitlet: [0] -> Kapitel [1] -> Nuvarande sida [0][1][2] -> Tredje sidan i andra underkapitlet i första kapitlet: [0] -> Kapitel [1] -> Kapitel [2] -> Nuvarande sida */ /* console.clear(); console.log('position: ' + course.pages[current_page_key].position + ' : previous_position: ' + multilevelpushmenu_previous_position ); console.log("children_nr_of: " + course.pages[current_page_key].children_nr_of); console.log(course.pages[current_page_key].position.length + ' > ' + multilevelpushmenu_previous_position.length); console.log("Är kapitel: " + current_page_is_chapter() ); console.log("Klickat i menyn: " + multilevelpushmenu_clicked ); */ var $parent_menu, parent_id, active_menu; var page_position, nr_of_submenus; var $active_menu = $(escape_for_jquery("#menu" + JSON.stringify(course.pages[current_page_key].position))); var current_page = get_page_by_position($active_menu.attr('data-position')) var dont_change_to_submenu = false; // Kollar om sidan är av en viss typ där man menyn inte ska ändra sig och förhindrar att menyn går in i det kapitlet switch (current_page.type) { case 12: // Välj övning case 13: // Övning case 14: // Övningsexempel case 15: // Övningsgenomgång //case 16: // Övningar och Kunskapstester dont_change_to_submenu = true; // Leta upp närmaste "välj övning"-sida och markerar den i menyn. $page = get_closest_page_of_type(12); $page = $page.closest('div.levelHolderClass'); /* if( current_page.type == 12 ) { // Om sidan man är på redan är "välj övning"-sidan, välj bara den $page = $active_menu.closest('div.levelHolderClass'); } else { // Annars så leta upp närmaste "välj övning"-sida och markera den i menyn. page_position = JSON.parse(JSON.stringify(course.pages[current_page_key].position)); nr_of_submenus = page_position.length-2; for (i = 0; i <= nr_of_submenus; i++) { page_position.pop(); page = get_page_by_position( page_position ); //console.log('page.type: ' + page.type); if( page.type == 12 ) { break; } } $page = $(escape_for_jquery( '#course_menu_pages #menu[' + page.position + ']')).closest('div.levelHolderClass'); } */ break; } if (!multilevelpushmenu_clicked) { // Koll om man gått till en sidan på något annat sätt än genom att klicka i menyn. Ändrar i så fall till rätt kapitel. if (current_page_is_chapter()) { // Om sidan man är på har undersidor, dvs är ett kapitel, så gå in i det kapitlet. $parent_menu = $(escape_for_jquery('#course_menu_pages #header[' + course.pages[current_page_key].position + ']')).parent("div"); } else { // Annars kolla vilket som är "parent"-kapitel och gå in i det $parent_id = $(escape_for_jquery('#course_menu_pages #menu[' + course.pages[current_page_key].position + ']')).parent("ul").attr('data-parent-id'); $parent_menu = $(escape_for_jquery('#course_menu_pages #' + $parent_id)).parent("div.levelHolderClass"); } if (dont_change_to_submenu) { //if( !$('#course_menu_pages').multilevelpushmenu('menuexpanded', $page) ) { $('#course_menu_pages').multilevelpushmenu('expand', $page); // collapse //} } else { //if( !$('#course_menu_pages').multilevelpushmenu('menuexpanded', $parent_menu) ) { $('#course_menu_pages').multilevelpushmenu('expand', $parent_menu); //} } } // Sätter menyn så att den är lika hög som containern //$parent_ul.css('height',$('.course_mid_section').outerHeight()-5); //console.log($parent_ul.css('height')); //console.log("active_pos: " + $active_menu.position().top); //console.log("ul_height: " + $parent_ul.height()); // Kollar om man klickar på en sida och markerar sidan direkt eller // om man bläddrar sig framåt/bakåt och ser isf till att sidan i menyn scrollas fram så att den syns if (!multilevelpushmenu_clicked) { // Scrollar bara ifall aktuell sida inte syns. Funkar inte när sidan laddas första gången. //if (!$active_menu.visibleInScroll().isContained) { setTimeout(function() { scroll_to_active_page(); multilevelpushmenu_clicked = false; }, 1000); } else { select_current_page($active_menu); } } function scroll_to_active_page() { //console.log( 'scroll_to_active_page' ); var $parent_ul = $(escape_for_jquery('#course_menu_pages #menu[' + course.pages[current_page_key].position + ']')).closest('div.levelHolderClass'); var $active_menu = $(escape_for_jquery("#menu" + JSON.stringify(course.pages[current_page_key].position))); var current_page = get_page_by_position($active_menu.attr('data-position')) /* $parent_id = $(escape_for_jquery('#course_menu_pages #menu[' + course.pages[current_page_key].position + ']')).parent("ul").attr('data-parent-id'); $parent_menu = $(escape_for_jquery('#course_menu_pages #' + $parent_id)).parent("div.levelHolderClass"); */ var dont_change_to_submenu = false; // Kollar om sidan är av en viss typ där man menyn inte ska ändra sig och förhindrar att menyn går in i det kapitlet switch (current_page.type) { case 12: // Välj övning case 13: // Övning case 14: // Övningsexempel case 15: // Övningsgenomgång //case 16: // Övningar och Kunskapstester dont_change_to_submenu = true; break; } // var visibleInScroll = $active_menu.visibleInScroll(); // Räkanr ut postition för att scrolla till aktiell sida //var scroll_to = Math.round( $parent_ul.scrollTop() - $parent_ul.offset().top + ( $active_menu.offset().top - 145 ) ); // Koll om det är en huvudmeny/kapitle med undersidor, men inte pagetype 12,13,14,15. Scrollar i så fall högst upp, annars scrolla till aktuell sida // TODO: Den scrollar inte till aktuell sida om man befinner sig inuti en övning (dvs i ett gömt underkapitel) och laddar kursen eftersom if-satsen nedan blir true if (current_page_is_chapter() && !dont_change_to_submenu) { //console.log( 'scroll to top' ); //$active_menu.find('div.levelHolderClass').first().scrollTo( 0, 1000 ); $active_menu.find('div.levelHolderClass').first().scrollTop( 0 ); select_current_page($active_menu); } else { $parent_ul.stop(true).scrollTo($active_menu, {duration:500, offset: -100, interrupt:true, onAfter: function() { requestAnimationFrame(function() { select_current_page($active_menu); }); } }); } } // Ändrar class på nuvarande sida i menyn så att man ser att den är aktiv. function select_current_page($element) { $('#course_menu_pages li').removeClass("active"); $element.addClass("active"); /********************************************************************************************/ // Loopar igenom alla kapitelsidor upptill huvudnivån och markerar dom // Klonar course.pages[current_page_key].position så att inte det ändras. page_position = JSON.parse(JSON.stringify(course.pages[current_page_key].position)); //console.log( page_positions ); var nr_of_submenus = page_position.length - 2; for (i = 0; i <= nr_of_submenus; i++) { page_position.pop(); $(escape_for_jquery("#menu" + JSON.stringify(page_position))).addClass("active"); } /********************************************************************************************/ } /** * Determines whether an element is contained in the visible viewport of its scrolled parents * * @param goDeep If false or undefined, just check the immediate scroll parent. * If truthy, check all scroll parents up to the Document. * @return Object A bounding box representing the element's visible portion: * left: left edge of the visible portion of the element relative to the screen * top: top edge of the visible portion of the element relative to the screen * right: right edge of the visible portion of the element relative to the screen * bottom: bottom edge of the visible portion of the element relative to the screen * width: width of the element * height: height of the element * isVisible: whether any part of the element can be seen * isContained: whether all of the element can be seen * visibleWidth: width of the visible portion of the element * visibleHeight: height of the visible portion of the element */ jQuery.fn.visibleInScroll = function (goDeep) { var parent = $(this[0]).scrollParent()[0], elRect = this[0].getBoundingClientRect(), rects = [parent.getBoundingClientRect()]; elRect = { left: elRect.left, top: elRect.top, right: elRect.right, bottom: elRect.bottom, width: elRect.width, height: elRect.height, visibleWidth: elRect.width, visibleHeight: elRect.height, isVisible: true, isContained: true }; var elWidth = elRect.width, elHeight = elRect.height; if (parent === this[0].ownerDocument) { return elRect; } while (parent !== this[0].ownerDocument && parent !== null) { if (parent.scrollWidth > parent.clientWidth || parent.scrollHeight > parent.clientHeight) { rects.push(parent.getBoundingClientRect()); } if (rects.length && goDeep) { break; } parent = $(parent).scrollParent()[0]; } if (!goDeep) { rects.length = 1; } for (var i = 0; i < rects.length; i += 1) { var rect = rects[i]; elRect.left = Math.max(elRect.left, rect.left); elRect.top = Math.max(elRect.top, rect.top); elRect.right = Math.min(elRect.right, rect.right); elRect.bottom = Math.min(elRect.bottom, rect.bottom); } elRect.visibleWidth = Math.max(0, elRect.right - elRect.left); elRect.visibleHeight = elRect.visibleWidth && Math.max(0, elRect.bottom - elRect.top); if (!elRect.visibleHeight) { elRect.visibleWidth = 0; } elRect.isVisible = elRect.visibleWidth > 0 && elRect.visibleHeight > 0; elRect.isContained = elRect.visibleWidth === elRect.width && elRect.visibleHeight === elRect.height; return elRect; }; // Hittar närmste parent-sida av en viss typ utfrån sidan man är på. T.ex för att hitta närmaste "Välj övning"-sida när man är inne i en övning function get_closest_page_of_type(page_type) { var $active_menu = $(escape_for_jquery("#menu" + JSON.stringify(course.pages[current_page_key].position))); var current_page = get_page_by_position($active_menu.attr('data-position')) var found_page = false; if (current_page.type == 12) { // Om sidan man är på redan är av den typen, välj bara den $page = $active_menu; } else { // Annars så leta upp närmaste sida av typen och markera den i menyn. page_position = JSON.parse(JSON.stringify(course.pages[current_page_key].position)); // Klonar page_position så att man inte ändrar i orginalet if (page_position.length > 1) { // Kollar om sidan har några undersidor, annars används nuvarande sida nr_of_submenus = page_position.length - 2; for (i = 0; i <= nr_of_submenus; i++) { page_position.pop(); page = get_page_by_position(page_position); if (page.type == 12) { found_page = true; break; } } } else { page = get_page_by_position(page_position); } if (!found_page) { // Om inte sidan med vald page_type hittats, välj nuvarande sida. $page = $active_menu } else { $page = $(escape_for_jquery('#course_menu_pages #menu[' + page.position + ']')); //.closest('div.levelHolderClass'); } } return $page; } // Loopar igenom alla kapitelsidor upptill huvudnivån och skapar breadcrumbs_trail function create_breadcrumbs_trail() { // kollar om breadcrumbs_trail elementet finns if ($("#course_guide_breadcrumbs_trail").length != 0) { $("#course_guide_breadcrumbs_trail").fadeIn('fast'); var separator = ' > '; // Klonar orginalobjektet så att inte det ändras. Funkar inte att klona med $.extend. var page_position = JSON.parse(JSON.stringify(course.pages[current_page_key].position)); //console.log( page_position ); var nr_of_submenus = page_position.length - 1; var breadcrumbs_trail = []; var $element, href, page_name; //breadcrumbs_trail.push( '' + $element.find('a').first().text().replace('•','') + '' ); for (i = 0; i <= nr_of_submenus; i++) { $element = $(escape_for_jquery("#menu" + JSON.stringify(page_position))) page_name = $element.find('a').first().text().replace('•', ''); breadcrumbs_trail.push('' + page_name + ''); page_position.pop(); } // Huvudnivå breadcrumbs_trail.push('' + i18next.t("theme.menu.contents") + ''); // Vänder på arrayen så att det visas från huvudmeny och framåt breadcrumbs_trail.reverse(); $("#course_guide_breadcrumbs_trail").html('Du är här: ' + breadcrumbs_trail.join(separator)); $("#course_guide_breadcrumbs_trail a").off('click').click(function () { page_id = parseInt($(this).attr("data-page-id")); if (page_id === -1) { $('#course_menu_pages').multilevelpushmenu('collapse', 0); } else { current_page_key = 0; get_page(page_id); } return false; }) } } // Kollar om ett element ligger utanför en scrollbar yta // t.ex jQuery('#parent').isChildOverflowing('#child'); jQuery.fn.isChildOverflowing = function (child) { var p = jQuery(this).get(0); var el = jQuery(child).get(0); return (el.offsetTop < p.offsetTop || el.offsetLeft < p.offsetLeft) || (el.offsetTop + el.offsetHeight > p.offsetTop + p.offsetHeight || el.offsetLeft + el.offsetWidth > p.offsetLeft + p.offsetWidth); }; function current_page_is_chapter() { return typeof course.pages[current_page_key].children_nr_of != 'undefined'; } // Lägger till ett antal tecken framför sidnamnet beroende på hur lång ner i strukturen den ligger function add_depth(depth, limiter) { var str = ""; for (i = 1; i <= depth; i++) { str += limiter; } return str; } // För debug, listar alla sidor function debug_show_page_list() { var url = parse_and_get_url(window.location); var url_path = url.host; // Check if under xpectum-domain and add subfolder // TODO: can be removed when moved to makemycourse.com-domain if(url.host.indexOf('.xpectum.') > 0){ url_path = url.host + '/make_my_course'; } $('#debug_edit_page a').attr('href', 'https://' + url_path + '/edit.php?id=' + course.pages[current_page_key]["id"]); var done = true; var debug_missing_movie_css = ""; var debug_not_done_css = ""; var page_name = ""; var category_name = ""; var debug_select_page_list = []; $.each(course.pages, function (key, value) { debug_missing_movie_css = ""; debug_not_done_css = ""; page_name = value.name; if (value.movie_url != undefined) { if (value.movie_url == "") { debug_missing_movie_css = "missing_movie"; //page_name += " (SAKNAR FILM) "; } } // Kollar om sidan är klar eller inte. Förutsätter att den är klar, annars hämta status från course_log done = true; if (value.done != undefined) { done = value.done; if (!done) { debug_not_done_css = "not_done"; } } // Skriver ut eventuella kategorier som sidorna ligger under if (typeof course_has_categories !== 'undefined') { if (course_has_categories) { if (category_name != value.category && value.category != undefined && value.category != "") { category_name = value.category debug_select_page_list.push("
" + category_name + "
"); } } } if (current_page_key == key) { debug_select_page_list.push("
" + page_name + "
"); } else { debug_select_page_list.push("
" + page_name + "
"); } }); $('#debug_select_page #debug_select_page_list').html(debug_select_page_list.join("")); // Sätter klickevent på varje sida i debug_menyn $("#debug_select_page #debug_select_page_list .debug_select_page_list_page").click(function () { //page_id = parseInt($(this).data().page); page_id = parseInt($(this).attr("data-page")); current_page_key = 0; get_page(page_id); }); } // Funktionen hämtar nästa film-event function get_next_movie_event(events, time, video, container) { // Eventets innehåll event_content = ""; // Loopar igenom eventlistan $.each(events, function (key, value) { //console.log(key + ": time:" + time + ", start: " + value.start_time + ", dur: " + value.duration); // Kollar om eventet ska gömmas efter en viss tid if (time >= (value.start_time + value.duration) && value.triggered == true && current_event_key == key) { if (value.duration != 0) { hide_event_container(container); current_event_key = -1; } } if (time >= value.start_time && value.triggered == false) { // Sparar unden vilken event som visas så att man kan gömma det sen current_event_key = key; // Innehållet i eventet event_content = value.content; // Flaggar eventet när det triggas value.triggered = true; current_page_event_key = key; // Pausar video if (value.pause) $("video")[0].pause(); // Gömmer video om kursen körs på iPad och är pausad if (is_ipad() && value.pause) $("video").css({ visibility: "hidden" }); // Visar eventet container.html(event_content); set_language(); // Kollar om eventen innehåller en fortsätt-knapp och fixar så att filmen fortsätter spela om man trycker på den continue_button = ($("#" + $(container).attr("id") + " #event-continue_button")); if (continue_button.length > 0) { $(continue_button).off('click').click(function () { hide_event_container(container); current_event_key = -1; if (is_ipad()) $("video").css({ visibility: "visible" }); play_video($("video")[0]); }); } // Kollar om eventen innehåller en "se filmen igen"-knapp watch_movie_again_button = ($("#" + $(container).attr("id") + " #watch_movie_again_button")); if (watch_movie_again_button.length > 0) { $(watch_movie_again_button).off('click').click(function () { hide_event_container(container); current_event_key = -1; if (is_ipad()) $("video").css({ visibility: "visible" }); $("video")[0].currentTime = 0; play_video($("video")[0]); }); } show_event_container(container); // Om det är en fråge sida, kolla om användaren redan har svarat på eventet och visar vad man svarat //console.log(user_log); //console.log(current_page_key); switch (course.pages[current_page_key].type) { case 6: if (!$.isEmptyObject(user_log.pages[current_page_key].answers)) { if (!$.isEmptyObject(user_log.pages[current_page_key].answers.question_answers[current_event_key])) { // Kollar om det är ett fritextsvar if ($("#free_text").length != 0) { var free_text = user_log.pages[current_page_key].answers.question_answers[current_event_key].answer.replace(//gi, "\n"); $("#free_text").val(free_text); } else { question_click($("#questions #" + user_log.pages[current_page_key].answers.question_answers[current_event_key].clicked_button), false); } } } break; } // Avslutar loopen efter triggat event return false; } }); } // Nollställer alla kommande events i listan function reset_upcoming_events(current_time) { // Loopar igenom alla events $.each(events, function (key, value) { // Kontrollerar om starttiden för kommande events är högre än den spolade tiden // Kollar även om eventetn är "repeatable" if (value.start_time >= current_time && value.repeatable) { // Nollställer trigger-flaggan value.triggered = false; } }); } function toggleControls(video) { if (video.hasAttribute("controls")) { video.removeAttribute("controls") } else { video.setAttribute("controls", "controls") } } // Funktionen kollar om kursen körs på mobil function is_ipad() { var isMobile = { Windows: function () { // Must be checked first since Microsoft also put "Android" and "iPhone" into the userAgent String return /IEMobile/i.test(navigator.userAgent); }, Android: function () { return /Android/i.test(navigator.userAgent); }, BlackBerry: function () { return /BlackBerry/i.test(navigator.userAgent); }, iOS: function () { return /iPhone|iPad|iPod/i.test(navigator.userAgent); }, any: function () { return (isMobile.Windows() || isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS()); } }; //return !! navigator.userAgent.match(/iPad/i); return isMobile.any(); } // Visar event-containern function show_event_container(container) { container.fadeIn("fast"); } // Gömmer event-containern function hide_event_container(container) { container.fadeOut("fast"); } // EJ TESTAD Konverterar sträng (True/False) till boolean function convert_string_to_boolean(str) { if (typeof str === 'string') { if (str == "false") { bool = false; } else if (str == "true") { bool = true; } else { bool = false; } return bool; } else { return str; } } var countdown_time = 0; /*$.countdown.regional['sv'] = { labels: ['år', 'månader', 'veckor', 'dagar', 'timmar', 'minuter', 'sekunder'], labels1: ['år', 'månad', 'vecka', 'dag', 'timme', 'minut', 'sekund'], compactLabels: ['Å', 'M', 'V', 'D'], whichLabels: null, timeSeparator: ':', isRTL: false, format: 'dHMS'}; $.countdown.setDefaults($.countdown.regional['sv']); */ function countup_start() { // Stannar och tar bort alla timers $('#countup_seconds').countdown('destroy'); $('#countup_total_seconds').countdown('destroy'); //console.log("page_time: " + user_log.pages[current_page_key].time_visited); //console.log("total_time: " + total_course_time); $('#countup_seconds').countdown({ since: -user_log.pages[current_page_key].time_visited, layout: '{sn} {sl}', format: "S" }); $('#countup_total_seconds').countdown({ since: -total_course_time, layout: '{sn} {sl}', format: "S" }); } // Shuffle array function fisher_yates(my_array) { var i = my_array.length; if (i == 0) return false; while (--i) { var j = Math.floor(Math.random() * (i + 1)); var tempi = my_array[i]; var tempj = my_array[j]; my_array[i] = tempj; my_array[j] = tempi; } } function set_readmore_button() { $(".read-more-button").off("click").on("click", function () { the_button = $(this); // Read more-innehållet read_more_content = $(this).parent().parent().find(".read-more-content"); // Visar och gömmer innehållet i "Läs mer" read_more_content.fadeToggle("fast", function () { // Ändrar CSS-klassen på knappen if (read_more_content.css("display") == "block") { the_button.addClass("selected"); } else { the_button.removeClass("selected"); handle_bottom_bar(); } }); }); $(".read-more-button").localize(); } /** * Fixerar bottom_bar när kursfönstret förminskas i höjdled */ function handle_bottom_bar() { /* window_height = $(window).scrollTop() + $(window).height() - $('#bottom_bar').outerHeight(); course_height = $('#course_content').offset().top + $('#course_content').height() - $('#bottom_bar').outerHeight(); // console.log('Window height: ' + window_height); // console.log('Course height: ' + course_height); if(course_height > window_height) { // Visar en dummy-div som tar upp lika stor plats som bottom_bar så att det inte blir ett "hopp" i scrollningen. $('.bottom_bar_dummy').show(); // Fäster bottom_bar i fönstrets nederkant. $('#bottom_bar').addClass('sticky'); } else { $('#bottom_bar').removeClass('sticky'); $('.bottom_bar_dummy').hide(); } */ } function is_last_page_in_course(){ if(current_page_key == course.pages.length-1){ return true; } else { return false; } } // Hämtar totalpoängen för kursen function get_totalt_points_for_course() { var total_course_points = 0; $.each(course.pages, function(page_key, page) { var points = 0; switch(page.type) { case 3: // sant eller falskt // console.log("--> " + page_key + " : " + page.name + ", type: " + page.type + " <---" ); if(page.page_content != null){ if (page.page_content.questions == undefined) { // Hittar positionen i json-strukturen vart frågorna finns var questions_content_key = 0; $.each(page.page_content.page_contents, function(content_key, content) { if ( content.true_or_false != undefined ) { questions_content_key = content_key; } }); questions = page.page_content.page_contents[questions_content_key].true_or_false.questions; } else { questions = page.page_content.questions } $.each(questions, function(question_key, question) { total_course_points += question.points; }); } break; case 6: // film med frågor och respons. Utgår från att maxpoängen är 300 på varje // console.log("--> " + page_key + " : " + page.name + ", type: " + page.type + " <---" ); /* total_course_points += 300; */ break; case 7: // Quiz checkbox, radio fritext //console.log("--> " + page_key + " : " + page.name + ", type: " + page.type + " <---" ); if(page.page_content != null){ if (page.page_content.questions == undefined) { // Hittar positionen i json-strukturen vart frågorna finns var questions_content_key = 0; $.each(page.page_content.page_contents, function(content_key, content) { if ( content.questions != undefined ) { questions_content_key = content_key; } }); questions = page.page_content.page_contents[questions_content_key].questions.questions; } else { questions = page.page_content.questions } $.each(questions, function(question_key, question) { total_course_points += question.points; }); } break; case 8: // Dra och släpp test // console.log("--> " + page_key + " : " + page.name + ", type: " + page.type + " <---" ); /* points_per_item = page.dragndrop.points_per_item; $.each(page.page_content.items, function(item_key, item) { if(item.targets != undefined) { total_course_points += item.targets.length*points_per_item; points += item.targets.length*points_per_item; } }); */ break; case 9: // Jeopardy // console.log("--> " + page_key + " : " + page.name + ", type: " + page.type + " <---" ); var jeopardy_points = 0; if (page.page_content.percent_pass == undefined) { // Hittar positionen i json-strukturen vart frågorna finns var questions_content_key = 0; $.each(page.page_content.page_contents, function(content_key, content) { if ( content.jeopardy != undefined ) { questions_content_key = content_key; } }); jeopardy = page.page_content.page_contents[questions_content_key].jeopardy; } else { jeopardy = page.page_content } $.each(jeopardy.categories, function(category_key, category) { $.each(category.questions, function(question_key, question) { jeopardy_points += question.points; }); }); total_course_points += jeopardy_points; break; /*case 17: // Supermall, HTML, CSS och JavaScript. Går det ens att få ut nåt vetigt, typ poäng, från en sån? // console.log("--> " + page_key + " : " + page.name + ", type: " + page.type + " <---" ); //var content = $($.parseHTML(page.content)).filter('#dragndrop'); var content = $('#dragndrop', $(page.content)); if (content.length != 0 ) { console.log( content ); } break;*/ case 19: // "Matcha ord", // console.log("--> " + page_key + " : " + page.name + ", type: " + page.type + " <---" ); var content = $(page.content).find('.check_check'); total_course_points += (content.length * 50); break; case 20: // "Fritextfråga" - Alltid bara ett svar med 50 poäng // console.log("--> " + page_key + " : " + page.name + ", type: " + page.type + " <---" ); //console.log( JSON.stringify(user_log.pages[page_key], null, 2)); total_course_points += 50; break; } /*if(points != 0) { debug(page_key, page, points); }*/ }); return total_course_points; } function collect_user_answers_and_report_for_course (page_number, name, type, quesitions_and_user_answers, user_page_points, page_points) { template_names = { "3" : i18next.t('page_type.true_or_false'), "4" : i18next.t('page_type.rank'), "5" : i18next.t('page_type.evaluation'), "6" : i18next.t('page_type.movie_with_questions_and_response'), "7" : i18next.t('page_type.quiz'), "8" : i18next.t('page_type.drag_and_drop'), "9" : i18next.t('page_type.jeopardy'), "18" : i18next.t('page_type.gallup'), "19" : i18next.t('page_type.match_words'), "20" : i18next.t('page_type.freetext_answer') }; answers_and_user_report = {}; answers_and_user_report.page_number = page_number+1; answers_and_user_report.name = name; answers_and_user_report.type = type; answers_and_user_report.template_name = template_names[type]; answers_and_user_report.quesitions_and_user_answers = quesitions_and_user_answers; if (user_page_points !== "" && user_page_points !== "") { answers_and_user_report.user_page_points = user_page_points; answers_and_user_report.page_points = page_points; } //console.log( JSON.stringify(answers_and_user_report, null, 2)); return answers_and_user_report; } // Hämtar totalpoängen för kursen function get_user_answers_and_report_for_course() { /* 3: "Sant/falskt", 4: "Rangordna", 5: "Utvärdering", 6: "Film med frågor och respons", 7: "Radio - Checkbox - Fritext", 8: "Dra och släpp test", 9: "Jeopardy", 18: "Gallup - Radio - Checkbox - Fritext", 19: "Matcha ord", 20: "Fritextfråga" */ var page; var user_page_points = 0; var page_points = 0; var page_number = 0; var user_report = []; if ( user_log.pages.length > course.pages.length ) { /* Användarloggen och kursloggen stämmer inte överens */ user_report = { "error": { "code": -1, "message": "The user log and course log do not match" } } } else { $.each(user_log.pages, function(page_key, user_log_page) { page = course.pages[page_key]; user_page_points = 0; page_points = 0; page_number = page_key+1; switch(page.type) { case 3: // sant eller falskt // console.log("--> " + page_number + " : " + page.name + ", type: " + page.type + " <---" ); if (page.page_content.questions == undefined) { // Hittar positionen i json-strukturen vart frågorna finns var questions_content_key = 0; $.each(page.page_content.page_contents, function(content_key, content) { if ( content.true_or_false != undefined ) { questions_content_key = content_key; } }); questions = page.page_content.page_contents[questions_content_key].true_or_false.questions; } else { questions = page.page_content.questions } // console.log( JSON.stringify(questions, null, 2)); // console.log( JSON.stringify(user_log_page, null, 2)); user_page_points = user_log_page.points; $.each(questions, function(question_key, question) { page_points += question.points; }); user_report.push(collect_user_answers_and_report_for_course(page_key, page.name, page.type,'', user_page_points, page_points)); break; case 5: // Utvärdering //console.log("--> " + page_number + " : " + page.name + ", type: " + page.type + " <---" ); break; case 6: // film med frågor och respons. Utgår från att maxpoängen är 300 på varje // console.log("--> " + page_number + " : " + page.name + ", type: " + page.type + " <---" ); /* total_course_points += 300; points = 300; */ break; case 7: // Quiz checkbox, radio fritext // console.log("--> " + page_number + " : " + page.name + ", type: " + page.type + " <---" ); if (page.page_content.questions == undefined) { // Hittar positionen i json-strukturen vart frågorna finns var questions_content_key = 0; $.each(page.page_content.page_contents, function(content_key, content) { if ( content.questions != undefined ) { questions_content_key = content_key; } }); questions = page.page_content.page_contents[questions_content_key].questions.questions; } else { questions = page.page_content.questions } user_page_points = user_log_page.points; $.each(questions, function(question_key, question) { page_points += question.points; }); user_report.push(collect_user_answers_and_report_for_course(page_key, page.name, page.type,'', user_page_points, page_points)); break; case 8: // Dra och släpp test // console.log("--> " + page_number + " : " + page.name + ", type: " + page.type + " <---" ); /* points_per_item = page.dragndrop.points_per_item; $.each(page.page_content.items, function(item_key, item) { if(item.targets != undefined) { total_course_points += item.targets.length*points_per_item; points += item.targets.length*points_per_item; } }); */ break; case 9: // Jeopardy // console.log("--> " + page_number + " : " + page.name + ", type: " + page.type + " <---" ); var jeopardy_points = 0; if (page.page_content.percent_pass == undefined) { // Hittar positionen i json-strukturen vart frågorna finns var questions_content_key = 0; $.each(page.page_content.page_contents, function(content_key, content) { if ( content.jeopardy != undefined ) { questions_content_key = content_key; } }); jeopardy = page.page_content.page_contents[questions_content_key].jeopardy; } else { jeopardy = page.page_content } user_page_points = user_log_page.points; $.each(jeopardy.categories, function(category_key, category) { $.each(category.questions, function(question_key, question) { jeopardy_points += question.points; }); }); page_points = jeopardy_points; user_report.push(collect_user_answers_and_report_for_course(page_key, page.name, page.type,'', user_page_points, page_points)); break; /*case 17: // Supermall, HTML, CSS och JavaScript. Går det ens att få ut nåt vetigt, typ poäng, från en sån? // console.log("--> " + page_number + " : " + page.name + ", type: " + page.type + " <---" ); //var content = $($.parseHTML(page.content)).filter('#dragndrop'); var content = $('#dragndrop', $(page.content)); if (content.length != 0 ) { console.log( content ); } break;*/ case 18: // "Gallup - Radio - Checkbox - Fritext", //console.log("--> " + page_number + " : " + page.name + ", type: " + page.type + " <--" ); // Gör en deep copy på objektet och loopar igenom det och för att kunna ta bort sånt som inte ska vara med i orginalobjectet. // Det matchar då användarens svar i användarloggen och man kan visa fråga/svar, fråga/svar osv var page_content = JSON.parse(JSON.stringify(page.page_content.page_contents)) var question_counter = 0; var questions_and_answers = []; var user_questions_and_answers = {}; $.each(page_content, function(question_key, question) { keys = Object.keys(question); switch (keys[0]) { case "text": user_questions_and_answers = { text : '', answer : ''} //questions_and_answers.question = $(question.text).text(); //questions_and_answers.question.push({ "question" : $(question.text).text() }); /* var HMTLtexts = ''; $.each($(question.text), function(HMTLtext_key, HMTLtext) { HMTLtexts += $(HMTLtext).html(); }); user_questions_and_answers.text = remove_tags(HMTLtexts); */ user_questions_and_answers.text = question.text.replace("

", "").replace("

", "

").replace("

", "").replace("

", ""); questions_and_answers[question_counter] = user_questions_and_answers; break; case "freetext_answer": //questions_and_answers.answer = nl2br(user_log_page.answers[question_counter].answer); //questions_and_answers.answer.push({ "answer" : nl2br(user_log_page.answers[question_counter].answer) }); if (user_log_page.answers != undefined) { user_questions_and_answers.answer = nl2br(user_log_page.answers[question_counter].answer); questions_and_answers[question_counter] = user_questions_and_answers; } question_counter++; break; case "gallup_questions": questions_and_answers = []; var user_log_quiz_answer = ""; $.each(question.gallup_questions.questions, function(gallup_question_key, gallup_question) { user_log_quiz_answer = ""; if(user_log_page.answers != undefined){ if(user_log_page.answers.quiz_answers != undefined){ user_log_quiz_answer = user_log_page.answers.quiz_answers[gallup_question_key] } } questions_and_answers.push({ "type" : gallup_question.type, "question" : gallup_question.question, "answers" : gallup_question.answers, "user_answers" : user_log_quiz_answer }) }); break; } }); user_report.push(collect_user_answers_and_report_for_course(page_key, page.name, page.type,questions_and_answers, "", "")); break; case 19: // "Matcha ord", // console.log("--> " + page_number + " : " + page.name + ", type: " + page.type + " <---" ); var content = $(page.content).find('.check_check'); page_points += (content.length * 50); if(user_log_page.points !== undefined) { user_page_points = user_log_page.points; } else { user_page_points = page_points; } user_report.push(collect_user_answers_and_report_for_course(page_key, page.name, page.type,'', user_page_points, page_points)); break; case 20: // "Fritextfråga" - Alltid bara ett svar med 50 poäng // console.log("--> " + page_number + " : " + page.name + ", type: " + page.type + " <---" ); user_page_points = 50; page_points = 50; user_report.push(collect_user_answers_and_report_for_course(page_key, page.name, page.type,'', user_page_points, page_points)); break; } }); } return user_report; } // remove html tags but keeps newline function remove_tags(html) { html = html.replace(//g, "$br$"); html = html.replace(/(?:\r\n|\r|\n)/g, '$br$'); var tmp = document.createElement("DIV"); tmp.innerHTML = html; html = tmp.textContent || tmp.innerText; html = html.replace(/\$br\$/g, "
"); return html; } function show_user_answers_and_report_for_course(user_report) { //console.log( JSON.stringify(user_report, null, 2)); var html_report = []; user_course_current_position = get_course_pos(); //console.log( user_course_current_position.current == report.page_number ); $.each(user_report, function(report_key, report) { if(user_course_current_position.current == report.page_number){ user_position_icon = ''; } else { user_position_icon = ''; } html_report.push('
' + user_position_icon + '

' + i18next.t('text.page') + ' ' + report.page_number + ' - ' + report.name + '

'); html_report.push('

' + report.template_name + '

'); switch (report.type) { case 18: // Gallup - visa frågor och svar $.each(report.quesitions_and_user_answers, function(question_key, question) { if(question.answer == undefined) { // Kollar om det är quiz eller fritextsvar var user_answers = ""; // Om det är envals sparas det som ett number. Är det flervalsfråga sparas det som en kommaseparerad sträng //console.log( question ); if(question.user_answers.clicked_answer != undefined){ switch (question.type) { case "radio": case "checkbox": user_answers = question.user_answers.clicked_answer.toString().split(','); user_answers == undefined ? question.user_answers.clicked_answer : [user_answers]; break; case "textarea": user_answers = [question.user_answers.clicked_answer]; break; } } if(user_answers.length != 0){ var answers = '
    '; switch (question.type) { case "radio": case "checkbox": for (var i = 0; i < user_answers.length; i++) { answers += '
  • ' + question.answers[user_answers[i]-1] + '
  • '; } break; case "textarea": answers += '
  • ' + nl2br(user_answers[0]) + '
  • '; break; } answers += '
' } else { answers = i18next.t('text.no_answer'); } html_report.push('
\
' + i18next.t('text.question') + ':
' + question.question + '
\
' + i18next.t('text.answer') + ':
' + answers + '
\
'); } else { html_report.push('
\
' + i18next.t('text.question') + ':
' + question.text + '
\
' + i18next.t('text.answer') + ':
' + (question.answer == "" ? i18next.t('text.no_answer') : question.answer) + '
\
'); } }); break; default: // Annars visa bara resultat/poäng html_report.push('

' + report.user_page_points + ' ' + i18next.t('text.of') + ' ' + report.page_points + ' ' + i18next.t('text.points') + '

'); break; } html_report.push('

') //console.log( JSON.stringify(report, null, 2)); }); return html_report.join(''); } function get_html_user_report_for_course() { var user_report = get_user_answers_and_report_for_course(); var html_report = ''; if ( user_report.error == undefined ) { if (user_report.length != 0 ){ html_report = show_user_answers_and_report_for_course(user_report); } } else { html_report = user_report; } return html_report; } /*function countup_pause() { $('#countup_total_seconds').countdown('pause'); $('#countup_seconds').countdown('pause'); } function countup_resume() { $('#countup_total_seconds').countdown('resume'); $('#countup_seconds').countdown('resume'); } function countup_stop() { $('#countup_seconds').countdown('destroy'); }*/ // OVERRIDE fortsätt-knapp /*$("#event_container").live("click", function() { hide_event_container($("#event_container")); if(is_ipad()) $("video").css({visibility:"visible"}); play_video($("video")[0]); });*/ // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. If `immediate` is passed, trigger the function on the // leading edge, instead of the trailing. function debounce(func, wait, immediate) { var timeout; return function () { var context = this, args = arguments; var later = function () { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; // If an event doesn't exist, check for your desired state at intervals: // Usage: /* poll( function () { // Condition return that.value.length; }, // Success function () { // ... }, // Error function () { // ... }, 3000, // Poll timeout 50 // Poll interval ); */ function poll(fn, callback, errback, timeout, interval) { var endTime = Number(new Date()) + (timeout || 2000); interval = interval || 100; (function p() { // If the condition is met, we're done! if(fn()) { callback(); } // If the condition isn't met but the timeout hasn't elapsed, go again else if (Number(new Date()) < endTime) { setTimeout(p, interval); } // Didn't match and too much time, reject! else { errback(new Error('timed out for ' + fn + ': ' + arguments)); } })(); } // Chunks an array into arrays with size elements. The last chunk may contain less than size elements. function array_chunk(arr, len) { var chunks = [], i = 0, n = arr.length; while (i < n) { chunks.push(arr.slice(i, i += len)); } return chunks; } function pnotify_show(title, text, type, delay, modal, hide, remove_all, maxonscreen){ // Kollar först så att PNotify finns, måste finns i temat för att det ska fungera. if(typeof PNotify == 'function'){ /* var context = $('#pnotify_context'); if(context.length === 0){ $('body').append('
'); } */ type = typeof type !== 'undefined' ? type : 'sucess'; delay = typeof delay !== 'undefined' ? delay : 4000; modal = typeof modal !== 'undefined' ? modal : false; hide = typeof hide !== 'undefined' ? hide : true; remove_all = typeof remove_all !== 'undefined' ? remove_all : false; maxonscreen = typeof maxonscreen !== 'undefined' ? maxonscreen : 3; modal = modal === 'modal' ? true : false; hide = hide === 'hide' ? true : false; remove_all = remove_all === 'remove_all' ? true : false; if (typeof pnotify_stack_top_right === "undefined") pnotify_stack_top_right = {"dir1": "down", "dir2": "right", "push": "bottom", "spacing1": 15, "spacing2": 15, "modal": modal, "overlay_close": true/* , context: $('#pnotify_context') */}; //{"dir1": "down", "dir2": "right", "push": "bottom", "modal": modal, "overlay_close": true}; var pnotify_opts = { // cornerclass: "", // width: "70%", hide: hide, destroy: true, buttons: { closer_hover: false, sticker: false, labels: { close: i18next.t('theme.pnotify.load.close'), stick: i18next.t('theme.pnotify.load.stick'), unstick: i18next.t('theme.pnotify.load.unstick') } }, history: { history: false, maxonscreen: maxonscreen }, stack: pnotify_stack_top_right/* , after_close: function(notice, timer_hide) { console.log('I\'m called after the notice closes. I\'m passed the PNotify object for the current notice: ' + notice); console.log('I also have an argument called timer_hide, which is true if the notice was closed because the timer ran down. Value: ' + timer_hide); } */ }; PNotify.prototype.options.delay = delay; pnotify_opts.title = title; pnotify_opts.text = text; pnotify_opts.type = type; if(remove_all && PNotify.notices.length > 0) { PNotify.removeAll(); // Kollar så att alla PNotify är borta innan nästa visas poll( function () { // console.log( 'ui-pnotify:' + $('.ui-pnotify').length ); // console.log( 'PNotify.notices:' + PNotify.notices.length ); return $('.ui-pnotify').length == 0; }, // Success function () { var notice = new PNotify(pnotify_opts); notice.get().click(function() { notice.remove(); }) }, // Error function () { }, 5000, // Poll timeout 100 // Poll interval ); } else { var notice = new PNotify(pnotify_opts); notice.get().click(function() { notice.remove(); }) } } } function new_pnotify(pnotify_opts){ var notice = new PNotify(pnotify_opts); notice.get().click(function() { notice.remove(); }) } // Slår ihop en array till en sträng med komma mellan förutom i slutet där man kan lägga in en bindeord, t.ex och/eller. /* Exempel: $array = array("1 år", "2 månader", "3 dagar"); console.log( conjunction_array($array, "och")); Output: 1 år, 2 månader och 3 dagar" */ function conjunction_array(array, conjunction, end_conjunction) { if (array.length <= 1) { return array.join(""); } ll = array.pop(); return array.join(conjunction + ' ') + ' ' + end_conjunction + ' ' + ll; } /* Try to keep the session alive if the user is doing a difficult exercise, or test exam */ // Not during preview if(typeof preview != 'undefined'){ if (!preview) { var setIntervalTime = 600000; // 600000 ms = 10 minutes, 900000 ms = 15 minutes, 60000 ms = 1 minute setInterval(function(){ // Post current user info and course info post_data = "&user_info=" + JSON.stringify(user_info); post_data += "&course_info=" + '{"course_id":' + course_info["course_id"] + ', "kursLanguage":"' + course_info["kursLanguage"] + '"}'; $.post('../../ajax.keep-alive.php', post_data) .done(function(data, textStatus, jqXHR) { //console.log( data, textStatus, jqXHR ); // Tests if it is possible to parse the returned data try { data = $.parseJSON(data); } catch(err) { var data = { status: "failed", message: err + '\n' + jqXHR.responseText }; }; switch(data.status) { case "success": // Everything went well //console.log( data ); break; default: // Something went wrong. Displays error message //console.log( data ); break; } }) .fail(function(jqXHR, textStatus, errorThrown) { console.log( jqXHR, textStatus, errorThrown ); }) }, setIntervalTime); } }