/* dialog.js */ 
﻿/*
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
*/

var dlg_parent;
var dialogh_ref;
var device_dpi;
var dialog2_html;
var modal_dialog;
var dlg_width;
var dlg_height;
var dlg_autosizeheight = false;
var callback_end = "";
var isopened = false;

function setParent(parentDialog) {
    dlg_parent = parentDialog;
}

function Click1() {
    closeDialog();
    $("#graydiv").remove();
}

function getDPI() {
    return device_dpi;
}

function setWidth(dlg, width) {
    $(dlg).css("width", width);
}

function setHeight(dlg, height) {
    $(dlg).css("height", height);
}

function getFullWidth() {
    return IsIE7() ? $(window).width() : document.body.scrollWidth;
}

function getFullHeight() {
    return IsIE7() ? $(window).height() : document.body.scrollHeight;
}

function setPadding(content, padding, classvalue) {
    s = "<div style='padding:" + padding + "px'";
    if (classvalue && classvalue != "")
        s += " class='" + classvalue + "'";
    s += ">" + content + "</div>";
    return s;
}

function getContentSize(html) {
    var size = { width: 0, height: 0 };
    o = $("<div style='display:visible;position:absolute;top:0px;left:0px;' id='04A98DB973UPK'>" + html + "</div>");
    $('body').append(o);
    size.width = $("#04A98DB973UPK").outerWidth(true);
    size.height = $("#04A98DB973UPK").outerHeight(true);
    $("#04A98DB973UPK").remove();
    return size;
}

function showDialog3(html, xpos, ypos, width, height, modal, dpi, noborder, outcontent) {

    showDialog2(html, xpos, ypos, width, height, modal, dpi, noborder);
    outcontent = "<div id='04A98DB974UPK'>" + outcontent + "</div>";
    $('body').append(outcontent);
}

function showDialog2(html, xpos, ypos, width, height, modal, dpi, noborder) {
    if (height == -1) {
        dlg_autosizeheight = true;
    }
    else dlg_autosizeheight = false;
    dialog2_html = html;
    showDialog("", xpos, ypos, width, height, modal, dpi, "", noborder);
}

function showDialog(href, xpos, ypos, width, height, modal, dpi, dialog1_path, noborder) {
    isopened = true;
    if (dpi == 0) dpi = 96;

    if (xpos != -1) xpos = PtToPx(xpos, dpi);
    if (ypos != -1) ypos = PtToPx(ypos, dpi);
    width = PtToPx(width, dpi);
    height = PtToPx(height, dpi);

    dlg_width = width;
    dlg_height = height;
    device_dpi = dpi;
    dialogh_ref = href;
    modal_dialog = modal;

    var wpx, hpx;
    wpx = width;
    hpx = height;

    if (xpos == -1 || ypos == -1) {
        // if the browser is IE then we can use pixel positioning
        centerx = $(window).width() / 2 - (wpx / 2) + $(document).scrollLeft();
        centery = $(window).height() / 2 - (hpx / 2) + $(document).scrollTop();
    }
    else {
        //do we need scroll adjustment here too???
        centerx = xpos;
        centery = ypos;
    }
    if (noborder)
        mainref = dialogh_ref;
    else
        if (dialog1_path && dialog1_path != "")
            mainref = dialog1_path + "dialog1.html";
        else
            mainref = "../dialog1.html"

        if (href == "") mainref = "../dialog2.html";

        var bodyWidth = getFullWidth();
        var bodyHeight = getFullHeight();

        // scrollarea ////////////////////////////////////////////////
        if (modal) $(document.body).append('<div id="scrollarea" scrolling="no" style="display:visible;position:absolute; top:0px; left: 0px; overflow:auto; z-index: 100;width:' + bodyWidth + 'px;height:' + bodyHeight + 'px;"></div>');
        else $(document.body).append('<div id="scrollarea" scrolling="yes"  style="overflow:auto; z-index: 99;" onclick="Click1();"></div>');
        //////////////////////////////////////////////////////////////

        if (bodyHeight < hpx) centery = 0;

        $(document.body).append('<div id="ehandlerdiv" style="display:none;position:absolute; top:0px; left: 0px; width:100%; height:100%; display:none; z-index: 999;"></div>');

        if (modal) $(document.body).append('<div id="graydiv" scrolling="yes" class="pointerdiv" style="display:none;z-index: 99;width:' + bodyWidth + 'px;height:' + bodyHeight + 'px;"></div>');
        else $(document.body).append('<div id="graydiv" scrolling="yes" class="pointerdiv2" style="display:none;z-index: 99;" onclick="Click1();"></div>');
        $("#graydiv").show();

        if (noborder) $("#scrollarea").append('<div id="draggable" style="visibility:hidden;position:absolute; left:' + centerx + 'px; top:' + centery + 'px; width: ' + wpx + 'px; height: ' + hpx + 'px;z-index: 998; overflow:hidden;">');
        else $("#scrollarea").append('<div id="draggable" style="visibility:hidden;position:absolute; left:' + centerx + 'px; top:' + centery + 'px; width: ' + wpx + 'px; height: ' + hpx + 'px;z-index: 998; overflow:hidden;">');

        $('#draggable').append('<iframe id="if1" scrolling="no" src="' + mainref + '" frameborder="0" style="width: 100%; height: 100%; margin:0px; padding:0px; position: absolute;top: 0px; left: 0px; background-color: white;"></iframe>');
    }

    function isOpenDialog() {
        return isopened;
    }

    function removeDiv(dlgName) {
        $(dlgName).remove();
    }

    function appendDiv(div) {
        $(document.body).append(div);
    }

    function resizeDialog() {
        var bodyWidth = getFullWidth();
        var bodyHeight = getFullHeight();
        $("#graydiv").css("width", bodyWidth + "px");
        $("#graydiv").css("height", bodyHeight + "px");

        $("#scrollarea").css("width", bodyWidth + "px");
        $("#scrollarea").css("height", bodyHeight + "px");
    }

    function closeDialog() {
        $("#ehandlerdiv").remove();
        $("#draggable").remove();
        $("#04A98DB974UPK").remove();
        $("#graydiv").remove();
        $("#scrollarea").remove();
        isopened = false;
        if (dlg_parent) {
            if (callback_end) dlg_parent.eval(callback_end);
        }
        else
            if (callback_end) eval(callback_end);
    }

    function setOnCloseEvent(functionname) {
        callback_end = functionname;
    }

    function getOnCloseEvent() {
        return callback_end;
    }

    function getDialog2Content() {
        return dialog2_html;
    }/* common.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

// Common functions between toc and lms

function filterHTML(s) {
    s = replaceString("&", "&amp;", s);
    s = replaceString("<", "&lt;", s);
    s = replaceString(">", "&gt;", s);
    return s;
}

function replaceString(oldString, newString, fullS) {
    if (fullS == null) return;
    var cReg = new RegExp(oldString, "g");
    var nString = fullS.replace(cReg, newString);
    return nString;
}

function PtToPx(pt, dpi) {
    return (pt * dpi) / 72;
}

function PxToPt(px, dpi) {
    return (px / dpi) * 72;
}

/*****************************************************************************/

function getDPICookie() {
    var cookie = new Cookie(document, "UPKDpiDailyWarning", "today", "/");
    cookie.Load();
    if (cookie.DPIdailyWarning == 1) {
        return true;
    }
    cookie.DPIdailyWarning = 1;
    cookie.Store();
    return false;
}
/* loader.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

var loader_dontclose = false;

function EscEvent() {
    if (loader_dontclose == false)
        top.close();
};

document.onstop = EscEvent
/* cookie.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

/** @constructor */
function Cookie(doc, name, exp, path, domain, secure) {
    this.$document = doc;
    this.$name = name;
    if (exp == "today") {
        var d = new Date();
        d.setHours(23);
        d.setMinutes(59);
        d.setSeconds(59);
        this.$exp = d;
    }
    else if (exp)
        this.$exp = new Date((new Date()).getTime() + exp * 3600000 * 24);
    else
        this.$exp = null;
    if (path) this.$path = path; else this.$path = null;
    if (domain) this.$domain = domain; else this.$domain = null;
    if (secure) this.$secure = true; else this.$secure = false;
}

Cookie.prototype.Store = function() {
    if (!PlayerConfig.EnableCookies)
        return;

    var cookieval = "";
    for (var prop in this) {
        if ((prop.charAt(0) == "$") || ((typeof this[prop]) == 'function'))
            continue;
        if (cookieval != "") cookieval += "&";
        cookieval += prop + ":" + escape(this[prop]);
    }

    var cookie = this.$name + "=" + cookieval;
    if (this.$exp)
        cookie += "; expires=" + this.$exp.toGMTString();
    if (this.$path) cookie += "; path=" + this.$path;
    if (this.$domain) cookie += "; domain=" + this.$domain;
    if (this.$secure) cookie += "; secure=";

    this.$document.cookie = cookie;
}

Cookie.prototype.Load = function() {
    if (!PlayerConfig.EnableCookies)
        return false;

    var allcookies = this.$document.cookie;
    if (allcookies == "") return false;

    var start = allcookies.indexOf(this.$name + "=");
    if (start == -1) return false;
    start += this.$name.length + 1;

    var end = allcookies.indexOf(";", start);
    if (end == -1)
        end = allcookies.length;

    var cookieval = allcookies.substring(start, end);

    var a = cookieval.split("&");
    for (var i = 0; i < a.length; i++) {
        var p = a[i].split(":");
        this[p[0]] = unescape(p[1]);
    }

    return true;
}

Cookie.prototype.Remove = function() {
    if (!PlayerConfig.EnableCookies)
        return;

    var cookie = this.$name + '=';
    if (this.$path) cookie += '; path=' + this.$path;
    if (this.$domain) cookie += '; domain=' + this.$domain;
    cookie += '; expires=Fri, 02-Jan-1970 00:00:00 GMT';

    this.$document.cookie = cookie;
}
/* preferences.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

function UserPreferences() {
    this.EnablePreferences = true;
    this.TimeStamp = "000000000000";
    this.PlayAudio = "all";
    this.ShowLeadIn = "all";
    this.MarqueeColor = "red";
    this.TryIt = new Object;
    this.TryIt.EnableSkipping = true;
    this.DoIt = new Object
    this.DoIt.HotKey = new Object;
    this.DoIt.HotKey.Ctrl = "L";
    this.DoIt.HotKey.Shift = "N";
    this.DoIt.HotKey.Alt = "L";
    this.DefaultPlayMode = "S";
    this.WebPageAutoPlayback = true;
    this.NavbarVolume = 100;
}

UserPreferences.prototype.Copy = function (src) {
    this.TimeStamp = src.TimeStamp;
    this.PlayAudio = src.PlayAudio;
    this.ShowLeadIn = src.ShowLeadIn;
    this.MarqueeColor = src.MarqueeColor;
    this.TryIt.EnableSkipping = src.TryIt.EnableSkipping;
    this.DoIt.HotKey.Ctrl = src.DoIt.HotKey.Ctrl;
    this.DoIt.HotKey.Shift = src.DoIt.HotKey.Shift;
    this.DoIt.HotKey.Alt = src.DoIt.HotKey.Alt;
    this.DefaultPlayMode = src.DefaultPlayMode;
    this.WebPageAutoPlayback = src.WebPageAutoPlayback;
    this.NavbarVolume = src.NavbarVolume;
}

UserPreferences.prototype.Compare = function (src) {
    if (this.PlayAudio != src.PlayAudio) return true;
    if (this.ShowLeadIn != src.ShowLeadIn) return true;
    if (this.MarqueeColor != src.MarqueeColor) return true;
    if (this.TryIt.EnableSkipping != src.TryIt.EnableSkipping) return true;
    if (this.DoIt.HotKey.Ctrl != src.DoIt.HotKey.Ctrl) return true;
    if (this.DoIt.HotKey.Shift != src.DoIt.HotKey.Shift) return true;
    if (this.DoIt.HotKey.Alt != src.DoIt.HotKey.Alt) return true;
    if (this.DefaultPlayMode != src.DefaultPlayMode) return true;
    if (this.WebPageAutoPlayback != src.WebPageAutoPlayback) return true;
    if (this.NavbarVolume != src.NavbarVolume) return true;
    return false;
}

UserPreferences.prototype.GetCookie = function () {
    return new Cookie(document, "OnDemandPlayer", 365, "/");
}

UserPreferences.prototype.LoadCookie = function () {
    var cookie = this.GetCookie();
    cookie.Load();
    //    if (IsTouchDevice())
    //        this.PlayAudio = "none";

    if (UserPrefs.TimeStamp != "000000000000" && (!cookie.TimeStamp || UserPrefs.TimeStamp > cookie.TimeStamp))
        return;

    if (cookie.PlayAudio)
        this.PlayAudio = cookie.PlayAudio;
    if (cookie.ShowLeadIn)
        this.ShowLeadIn = cookie.ShowLeadIn;
    if (cookie.MarqueeColor)
        this.MarqueeColor = cookie.MarqueeColor;
    if (cookie.TryIt_EnableSkipping)
        this.TryIt.EnableSkipping = (cookie.TryIt_EnableSkipping == "true");
    if (cookie.DoIt_HotKey_Ctrl)
        this.DoIt.HotKey.Ctrl = cookie.DoIt_HotKey_Ctrl;
    if (cookie.DoIt_HotKey_Shift)
        this.DoIt.HotKey.Shift = cookie.DoIt_HotKey_Shift;
    if (cookie.DoIt_HotKey_Alt)
        this.DoIt.HotKey.Alt = cookie.DoIt_HotKey_Alt;
    if (cookie.DefaultPlayMode)
        this.DefaultPlayMode = cookie.DefaultPlayMode;
    if (cookie.WebPageAutoPlayback)
        this.WebPageAutoPlayback = cookie.WebPageAutoPlayback;
    if (cookie.NavbarVolume)
        this.NavbarVolume = cookie.NavbarVolume;
}

UserPreferences.prototype.StoreCookie = function () {
    var cookie = this.GetCookie();
    cookie.TimeStamp = this.TimeStamp;
    cookie.PlayAudio = this.PlayAudio;
    cookie.ShowLeadIn = this.ShowLeadIn;
    cookie.MarqueeColor = this.MarqueeColor;
    cookie.TryIt_EnableSkipping = this.TryIt.EnableSkipping;
    cookie.DoIt_HotKey_Ctrl = this.DoIt.HotKey.Ctrl;
    cookie.DoIt_HotKey_Shift = this.DoIt.HotKey.Shift;
    cookie.DoIt_HotKey_Alt = this.DoIt.HotKey.Alt;
    cookie.DefaultPlayMode = this.DefaultPlayMode;
    cookie.WebPageAutoPlayback = this.WebPageAutoPlayback;
    cookie.NavbarVolume = this.NavbarVolume;
    cookie.Store();
}

UserPreferences.prototype.GetUrlParamString = function () {
    return "PP_SOUND=" + this.PlayAudio +
		"&PP_LEADIN=" + this.ShowLeadIn +
		"&PP_SKIP=" + (this.TryIt.EnableSkipping ? "true" : "false") +
		"&PP_MARQUEE=" + this.MarqueeColor +
		"&PP_ENABLE=" + (this.EnablePreferences ? "true" : "false") +
		"&PP_HOTKEY=" + this.DoIt.HotKey.Ctrl + this.DoIt.HotKey.Shift + this.DoIt.HotKey.Alt;
}

UserPreferences.prototype.ParseUrlParamString = function (param_str) {
    var params = param_str.split('&');
    for (var p = 0; p < params.length; p++) {
        var paritem = params[p].split("=");
        if (paritem[0].toUpperCase() == "PP_SOUND")
            this.PlayAudio = paritem[1];
        else if (paritem[0].toUpperCase() == "PP_LEADIN")
            this.ShowLeadIn = paritem[1];
        else if (paritem[0].toUpperCase() == "PP_MARQUEE")
            this.MarqueeColor = paritem[1];
        else if (paritem[0].toUpperCase() == "PP_SKIP")
            this.TryIt.EnableSkipping = (paritem[1] == "true");
        else if (paritem[0].toUpperCase() == "PP_ENABLE")
            this.EnablePreferences = (paritem[1] == "true");
        else if (paritem[0].toUpperCase() == "PP_HOTKEY") {
            this.DoIt.HotKey.Ctrl = paritem[1].charAt(0);
            this.DoIt.HotKey.Shift = paritem[1].charAt(1);
            this.DoIt.HotKey.Alt = paritem[1].charAt(2);
        }
    }
}

var UserPrefs = new UserPreferences();

if (window.SetDefaultPreferences)
    SetDefaultPreferences();
if (UserPrefs.EnablePreferences)
    UserPrefs.LoadCookie();

var paramstr = unescape(document.location.hash.substring(1));
if (paramstr == "")
    paramstr = unescape(document.location.search.substring(1));

if (UserPrefs.EnablePreferences)
    UserPrefs.LoadCookie();

UserPrefs.ParseUrlParamString(paramstr);

function OpenPreferencesDialog(path, nosound, seeitonly) {
    if (!UserPrefs.EnablePreferences)
        alert(R_preferences_disabled);
    else {
        var p = path + "/preferences/preferences.html";
        h = 412;
        var params = new Array();
        try {
            if (lms_IsUserProfileAvailable()) {
                var url = lms_GetUserProfileUrl();
                if (url != "")
                    params[params.length] = "UserProfileUrl=" + Escape.MyEscape(url);
            }
        }
        catch (e) { };
        if (nosound) {
            params[params.length] = "nosound";
        }
        if (seeitonly) {
            params[params.length] = "seeitonly";
            h = 412;
        }
        for (var i = 0; i < params.length; i++) {
            p += (i == 0) ? "?" : "&";
            p += params[i];
        }
        window.open(p, "prefwin", "width=550,height=" + h + ",resizable=1,scrollbars=0,top=" + (screen.availHeight - 290) / 2 + ",left=" + (screen.availWidth - 550) / 2);
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////

function SessionPreferences() {
    this.swipeInstructionShowed = false;
}

SessionPreferences.prototype.GetCookie = function () {
    return new Cookie(document, "OnDemandPlayerSession", null, "/");
}

SessionPreferences.prototype.LoadCookie = function () {
    var cookie = this.GetCookie();
    cookie.Load();
    if (cookie.swipeInstructionShowed)
        this.swipeInstructionShowed = cookie.swipeInstructionShowed;
}

SessionPreferences.prototype.StoreCookie = function () {
    var cookie = this.GetCookie();
    cookie.swipeInstructionShowed = this.swipeInstructionShowed;
    cookie.Store();
}

var SessionPrefs = new SessionPreferences();

///////////////////////////////////////////////////////////////////////////////////////////////

function UserRolesClass() {
    this.Filtering = false;
    this.Roles = new Array;
}

UserRolesClass.prototype.Copy = function (src) {
    this.Filtering = src.Filtering;
    this.Roles = new Array;
    for (var r = 0; r < src.Roles.length; r++)
        this.Roles[r] = src.Roles[r];
}

UserRolesClass.prototype.Compare = function (src) {
    if (this.Filtering != src.Filtering) return true;
    if (this.Roles.length != src.Roles.length) return true;
    for (var r = 0; r < this.Roles.length; r++) {
        if (this.Roles[r] != src.Roles[r]) return true;
    }
    return false;
}

UserRolesClass.prototype.GetCookie = function () {
    return new Cookie(document, "OnDemandPlayerRoles", 365, "/");
}

UserRolesClass.prototype.LoadCookie = function () {
    var cookie = this.GetCookie();
    cookie.Load();
    this.Filtering = false;
    if (cookie.Filtering)
        this.Filtering = (cookie.Filtering == "true");
    this.Roles = new Array();
    if (cookie.Roles)
        this.Roles = cookie.Roles.split("+");
}

UserRolesClass.prototype.StoreCookie = function () {
    var cookie = this.GetCookie();
    cookie.Filtering = this.Filtering ? "true" : "false";
    cookie.Roles = this.Roles.join("+");
    cookie.Store();
}

UserRolesClass.prototype.GetUrlParamString = function () {
    return "PP_ROLEFILTERING=" + (this.Filtering ? "true" : "false") + "&PP_ROLES=" + encodeURIComponent(this.Roles.join('+'));
}

UserRolesClass.prototype.ParseUrlParamString = function (param_str) {
    var params = param_str.split('&');
    for (var p = 0; p < params.length; p++) {
        var paritem = params[p].split("=");
        if (paritem[0].toUpperCase() == "PP_ROLEFILTERING")
            this.Filtering = (paritem[1] == "true");
        else if (paritem[0].toUpperCase() == "PP_ROLES") {
            this.Roles = new Array;
            if (paritem[1])
                this.Roles = paritem[1].split('+');
        }
    }
}

var UserRoles = new UserRolesClass();
UserRoles.LoadCookie();
UserRoles.ParseUrlParamString(paramstr);

function OpenRolesDialog(path) {
    window.open(path + "/preferences/roles.html", "roleswin", "width=500,height=318,resizable=1,scrollbars=0,top=" + (screen.availHeight - 286) / 2 + ",left=" + (screen.availWidth - 500) / 2);
}
/* soundobj.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

var sounds = new Array();

function SoundObj(id, filelist, duration) {
    _flist = filelist.split("+");
    _fct = _flist.length;
    this.flist = new Array();
    this.fct = 0;
    this.duration = duration;
    for (var i = 0; i < _fct; i++) {
        s = _flist[i];
        if (s.substr(0, 5) != "TEMP:") {
            this.flist[this.fct] = s;
            this.fct++;
        }
    }
};

function Sound(id, filelist, duration) {
    if (id.indexOf('.') < 0)
        id += ".ASX";
    sounds[id.substr(1)] = new SoundObj(id, filelist, duration);
};
/* help.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

function onHelp(url)
{
	if (url.charAt(url.length - 1) == '/')
	    url = url.substr(0, url.length - 1);
	if (url.length > 0)
	    url += "/";
	_left=screen.availWidth/17;
	_top=_left;
	_height=screen.availHeight-3*_top;
	if (_height>500)
		_height=500;
	_width=_height*4.5/3;
	_height=390;
	_width=637;
	var strFeatures = "width="+_width+",height="+_height+",left="+_left+",top="+_top + 
				",resizable=1,toolbar=1,scrollbars=1,location=0,menubar=0";
	w=window.open(url+"../help/toc.html", "odhelp", strFeatures)
	w.focus();
}
/* template.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

var template_leadin = "";
var template_leadout = "";
var template_explanation = "";
var template_pauselink = "";

var template_knowit_leadin = "";
var template_knowit_leadout = "";
var template_knowit_nextstep = "";
var template_knowit_explanation = "";

var template_knowit_leadin_score = "";

var template_knowit_warningL1 = "";
var template_knowit_warningL2 = "";
var template_knowit_warningL3_0 = "";
var template_knowit_warningL3_H = "";
var template_knowit_warningL4 = "";

var template_scoring = "";

var template_scoring_YES = "";
var template_scoring_NO = "";

var template_knowit_continue = "";
var template_knowit_confirmdemo = "";
var template_typingcomplete = "";

var template_knowit_dragwarning = ""

var template_knowit_finish_close = "";
var template_knowit_finish_close_inassessment = "";

var template_strinp_suppress_example = 0;

//***********************************************************************************************

var _template_arr = new Array();
var _template_retfv = "";

function LoadTemplates(guid, retfv) {
    _template_retfv = retfv;
    if (document.implementation && document.implementation.createDocument) {
        xmlDoc = document.implementation.createDocument("", "", null);
        xmlDoc.onload = LoadTemplates_Returned0;
    }
    else if (window.ActiveXObject) {
        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.onreadystatechange = function () {
            if (xmlDoc.readyState == 4) LoadTemplates_Returned0();
        };
    }
    else {
        LoadTemplates_Error();
        return;
    }

    try {
        xmlDoc.load("../../template/" + guid + "/template.xml");
    }
    catch (e) {
        LoadXMLDocArray("../../template/" + guid + "/template.xml", "LoadTemplates_Returned", "LoadTemplates_Error", "Item", true)
    }
}

function LoadTemplates_Returned0() {
    _nodesArray = new Array();
    var _nodes = xmlDoc.getElementsByTagName('Item');
    for (var i = 0; i < _nodes.length; i++) {
        n = _nodes[i];
        xmlname = n.attributes[0].nodeValue;
        xmltext = "";
        for (var j = 0; j < n.childNodes.length; j++) {
            if (n.childNodes[j].xml) {
                xmltext += n.childNodes[j].xml;
            } else {
                var oSerializer = new XMLSerializer;
                xmltext += oSerializer.serializeToString(n.childNodes[j]);
            }
        }
        _nodesArray[_nodesArray.length] = xmlname + "=" + xmltext;
    }
    LoadTemplates_Returned(_nodesArray);
}

function LoadTemplates_Error() {
    alert("Common template loading error ...");
}

function LoadTemplates_Returned(a) {
    _template_arr = new Array();
    for (var i = 0; i < a.length; i++) {
        k = a[i].indexOf("=");
        key = a[i].substr(0, k);
        value = a[i].substr(k + 1);
        _template_arr[key] = value;
    }
    LoadAll();
    setTimeout(_template_retfv, 100);
}

function GetTemp(id) {
    if (_template_arr[id])
        return _template_arr[id];
    return "";
}

function Insert(s1, s2, k) {
    return s1.substr(0, k) + s2 + s1.substr(k);
}

function LoadAll() {
    template_leadin = GetTemp('leadin');
    template_leadout = GetTemp('leadout');
    template_explanation = GetTemp('continue');
    //var p = GetTemp('pauselink');
    //var p1 = ReplaceAll(p, '<br></br>', '<br/>');
    //template_pauselink = ReplaceAll(p1, '<BR></BR>', '<br/>');

    template_knowit_leadin = GetTemp('knowit_leadin');
    template_knowit_leadout = GetTemp('knowit_leadout');
    template_knowit_nextstep = GetTemp('knowit_nextstep');
    template_knowit_explanation = GetTemp('knowit_explanation');

    if (IsTouchDevice()) {
        var attr = ' style="color:#0033cc;font-weight:bold;" href="javascript:HLink(0)"';
        template_leadin = R_swipe_start;
        var k = template_leadin.indexOf("<a");
        template_leadin = Insert(template_leadin, attr, k + 2);
        attr = ' style="color:#0033cc;font-weight:bold;" href="javascript:HLink(2)"';
        template_explanation = R_swipe_continue;
        k = template_explanation.indexOf("<a");
        template_explanation = Insert(template_explanation, attr, k + 2);
        attr = ' style="color:#0033cc;font-weight:bold;" href="javascript:HLink(2)"';
        template_leadout = R_swipe_finish;
        k = template_leadout.indexOf("<a");
        template_leadout = Insert(template_leadout, attr, k + 2);
    }

    template_knowit_leadin_score = GetTemp('leadin_score');

    template_knowit_warningL1 = GetTemp('knowit_warningL1');
    template_knowit_warningL2 = GetTemp('knowit_warningL2');
    template_knowit_warningL3_0 = GetTemp('knowit_warningL3_0');
    template_knowit_warningL3_H = GetTemp('knowit_warningL3_H');
    template_knowit_warningL4 = GetTemp('knowit_warningL4');

    template_scoring = GetTemp('scoring');
    template_scoring = template_scoring.substr(0, 6) + ' width="100%" ' + template_scoring.substr(6);

    template_scoring_YES = GetTemp('scoring_YES');
    template_scoring_NO = GetTemp('scoring_NO');

    template_knowit_continue = GetTemp('knowit_continue');
    template_knowit_confirmdemo = GetTemp('knowit_confirmdemo');
    template_typingcomplete = GetTemp('typingcomplete');

    template_knowit_dragwarning = GetTemp('knowit_dragwarning')

    template_knowit_finish_close = GetTemp('knowit_finish_close');
    template_knowit_finish_close_inassessment = GetTemp('knowit_finish_close_inassessment');

    template_strinp_suppress_example = GetTemp('strinp_suppress_example');

    s = GetTemplate_knowit_leadin_score("168");
}

function ReplaceAll(sourcestr, sourceexpr, newexpr) {
    var ret = sourcestr;
    var k = ret.indexOf(sourceexpr);
    while (k >= 0) {
        ret = Template_Replace(ret, sourceexpr, newexpr);
        var k = ret.indexOf(sourceexpr);
    }
    return ret;
}

function Template_Replace(sourcestr, sourceexpr, newexpr) {
    var k = sourcestr.indexOf(sourceexpr);
    if (k < 0)
        return sourcestr;
    var s1 = sourcestr.substr(0, k);
    var s2 = sourcestr.substr(k + sourceexpr.length);
    return s1 + newexpr + s2;
}

function GetTemplate_knowit_leadin_score(score) {
    return Template_Replace(template_knowit_leadin_score, "$score$", score);
}

function GetTemplate_scoring(good, needed, result) {
    s = Replace(template_scoring, "$good$", good);
    ss = Replace(s, "$needed$", needed);
    return Replace(ss, "$result$", result);
}

/* browser.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

var _simulate_120_dpi = false;

function IsTouchDevice() {
    return (window.Touch);
}

function IsMacOs() {
    k = (navigator.userAgent.indexOf("Macintosh") >= 0);
    return k;
}

function IsFF3() {
    if (this.navigator) {
        if (this.navigator.userAgent) {
            if (this.navigator.userAgent.indexOf("Firefox/3") > 0) {
                return true;
            }
        }
    }
    return false;
}

function IsFF() {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    return (bi.name == "Firefox");
}

function IsFF4() {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    if (bi.name != "Firefox")
        return false;
    return (bi.version == 4);
}

function checkFFVersion(i) {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    if (bi.name != "Firefox")
        return false;
    return (bi.version == i);
}

function IsSafari() {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    return (bi.name == "Safari" || bi.name == "Chrome");
}

function IsExplorer() {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    return (bi.name == "MSIE");
}

function IsIE7() {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    if (bi.name != "MSIE")
        return false;
    return (bi.version == 7);
}

function IsIE8() {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    if (bi.name != "MSIE")
        return false;
    return (bi.version == 8 || (bi.trident && bi.tridentVersion == 4));
}

function IsIE9() {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    if (bi.name != "MSIE")
        return false;
    return (bi.version == 9 || (bi.trident && bi.tridentVersion == 5));
}

function IsIE10() {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    if (bi.name != "MSIE")
        return false;
    return (bi.version == 10 || (bi.trident && bi.tridentVersion == 6));
}

function IsActiveXEnabled() {
    var supported = null;
    try {
        supported = !!new ActiveXObject("htmlfile");
    }
    catch (e) {
        supported = false;
    }
    return supported;
}

function IsIE10Modern() {
    if (IsIE10() == false)
        return false;
    return !IsActiveXEnabled();
}

function IsiOS() {
    p = navigator.platform;
    if (p === 'iPad' || p === 'iPad Simulator' || p === 'iPhone' || p === 'iPod')
        return true;
    return false;
}

function IsiOS5() {
    p = navigator.userAgent;
    return (p.indexOf("CPU OS 5_") >= 0);
}

function IsiOS6() {
    p = navigator.userAgent;
    return (p.indexOf("CPU OS 6_") >= 0);
}

function IsSoundSupported() {
    if (IsiOS())
        return false;
    if (swfobject.getFlashPlayerVersion().major > 0)
        return true;
    return true;
}

function BrowserInfo() {
    this.name = "";
    this.version = 0;
    this.subversion = 0;
    this.trident = false;
    this.tridentVersion = 0;
}

function GetBrowserInfo(bi) {
    s = navigator.userAgent;
    k = 0 - 1;
    if (s.indexOf("Chrome") >= 0) {
        bi.name = "Chrome";
        k = s.indexOf("Chrome") + 7;
    }
    else if (s.indexOf("Opera") >= 0) {
        bi.name = "Opera";
        k = s.indexOf("Opera") + 6;
    }
    else if (s.indexOf("Firefox") >= 0) {
        bi.name = "Firefox";
        k = s.indexOf("Firefox") + 8;
    }
    else if (s.indexOf("Safari") >= 0) {
        bi.name = "Safari";
        k = s.indexOf("Version") + 8;
    }
    else if (s.indexOf("MSIE") >= 0) {
        bi.name = "MSIE";
        k = s.indexOf("MSIE") + 5;
        var ti = s.indexOf("Trident/");
        if (ti >= 0) {
            bi.trident = true;
            bi.tridentVersion = parseInt(s.substr(ti + 8));
        }
    }
    else {
        bi.name = "other";
        bi.version = 0;
        return;
    }
    bi.version = parseInt(s.substr(k));
    bi.subversion = parseInt(s.substr(k + 2, 1));
}

function IsSupportedBrowser() {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    k = false;
    if (bi.name == "MSIE" && bi.version >= 7)
        k = true;
    if (bi.name == "Firefox" && ((bi.version >= 3 && bi.subversion >= 5) || bi.version >= 4))
        k = true;
    if (bi.name == "Safari" && bi.version >= 4)
        k = true;
    if (bi.name == "Chrome" && bi.version >= 18)
        k = true;
    return k;
}

//
// Browser-independent object access (NS4, IE5+, Mozilla)
//

function getDIV(id) {
    try {
        if (document.all) {
            return document.all(id);
        }
        else if (document.getElementById) {
            return document.getElementById(id);
        }
        else if (document.layers) {
            var obj = document.layers.screen.document.layers[id];
            if (!obj) {
                obj = document.layers[id];
            }
            return obj;
        }
        return 0;
    }
    catch (error) {
        return (null);
    }
}

function getDIVstyle(id) {
    try {
        if (document.all) {
            return (document.all(id).style);
        }
        else if (document.getElementById) {
            if (document.getElementById(id).style != null) {
                return (document.getElementById(id).style);
            }
        }
        else if (document.layers) {
            var obj = document.layers.screen.document.layers[id];
            if (!obj) {
                obj = document.layers[id];
            }
            return (obj);
        }
        return 0;
    }
    catch (error) {
        //alert ("##### ERROR #####:\n" + error + "\n\n##### CALLER #####" + getDIVstyle.caller);
        return (null);
    }
}

function shiftTo(id, x, y) {
    var obj = getDIVstyle(id);
    if (obj.moveTo) {
        obj.moveTo(x, y);
    }
    else {
        obj.left = x + "px";
        obj.top = y + "px";
    }
}

/**
* #####################
* # START NEW CONTENT #
* #####################
*/

function getUniWidth(id) {
    try {
        var cObj = getDIV(id);
        var w;
        if (id.style.width) {
            w = parseInt(id.style.width);
        }
        else if (id.style.pixelWidth) {
            w = id.style.pixelWidth;
        }
        else if (id.offsetWidth) {
            w = id.offsetWidth;
        }
        else if (document.defaultView && document.defaultView.getComputedStyle) {
            w = document.defaultView.getComputedStyle(cObj, '').getPropertyValue('width');
        }
        if (typeof w == "string") {
            w = parseInt(w);
        }
        return w;
    }
    catch (error) {
        return (null);
    }
}

function getUniHeight(id) {
    try {
        var cObj = getDIV(id);
        var w;
        if (id.style.height) {
            w = parseInt(id.style.height);
        }
        else if (id.style.pixelHeight) {
            w = id.style.pixelHeight;
        }
        else if (id.offsetHeight) {
            w = id.offsetHeight;
        }
        else if (document.defaultView && document.defaultView.getComputedStyle) {
            w = document.defaultView.getComputedStyle(cObj, '').getPropertyValue('height');
        }
        if (typeof w == "string") {
            w = parseInt(w);
        }
        return w;
    }
    catch (error) {
        return (null);
    }
}

function getClientWidth(id) {
    try {
        var cObj = getDIV(id);
        if (cObj.clientWidth) {
            return cObj.clientWidth
        }
        else {
            return parseInt(cObj.width);
        }
    }
    catch (error) {
        return id.offsetWidth;
    }
}

function getClientHeight(id) {
    try {
        var cObj = getDIV(id);
        if (cObj.clientHeight) {
            return cObj.clientHeight
        }
        else {
            return parseInt(cObj.height);
        }
    }
    catch (error) {
        return id.offsetHeight;
    }
}

/**
* ###################
* # END NEW CONTENT #
* ###################
*/

function getObjHeight(id) {
    var obj = getDIV(id);
    if (obj.clip) {
        return obj.clip.height;
    }
    else {
        return obj.offsetHeight;
    }
}

function getObjWidth(id) {
    var obj = getDIV(id);
    if (obj.clip) {
        return obj.clip.width;
    }
    else {
        return obj.offsetWidth;
    }
}

function getObjLeft(id) {
    try {
        var obj = getDIVstyle(id);
        if (obj.pixelLeft) {
            return obj.pixelLeft;
        }
        else {
            return parseInt(obj.left);
        }
    }
    catch (error) {
        return parseInt(id.offsetLeft);
    }
}

function getObjTop(id) {
    try {
        var obj = getDIVstyle(id);
        if (obj.pixelTop) {
            return obj.pixelTop;
        }
        else {
            return parseInt(obj.top);
        }
    }
    catch (error) {
        return parseInt(id.offsetTop);
    }
}


function getInsideWindowWidth() {
    if (window.innerWidth) {
        return window.innerWidth;
    }
    else {
        return document.body.clientWidth;
    }
}

function getInsideWindowHeight() {
    if (window.innerHeight) {
        return window.innerHeight;
    }
    else {
        return document.body.clientHeight;
    }
}

function getScrollLeft() {
    if (window.pageXOffset || window.pageXOffset == 0) {
        return window.pageXOffset;
    }
    else {
        return document.body.scrollLeft;
    }
}

function getScrollTop() {
    if (window.pageYOffset || window.pageYOffset == 0) {
        return window.pageYOffset;
    }
    else {
        return document.body.scrollTop;
    }
}

function show(id, strinput) {
    var obj = getDIVstyle(id);
    obj.visibility = "visible";
    if (strinput && IsiOS()) {
        try {
            if (playMode == "S") {
                if (showActObj.type == "Input") {
                    $("#" + id + " input").attr('readonly', true);
                }
            }
        }
        catch (e) { };
    }
}

function hide(id, strinput) {
    var obj = getDIVstyle(id);
    obj.visibility = "hidden";
}

var __DPIwidth = 0;

function getDpiInfo() {
    var d = document.getElementById("DPIInfoDiv");
    if (d != null) {
        __DPIwidth = d.clientWidth;
        if (__DPIwidth != 0)
            document.getElementsByTagName("body")[0].removeChild(d);
    }
    return _simulate_120_dpi == true ? 120 : __DPIwidth;
}

function initDpiInfo() {
    document.write('<div id="DPIInfoDiv" style="visibility:hidden; width: 72pt; height: 1pt;">DPIINFODIV</div>');
}

function checkIEDPI() {
    return true;
}
/* infoblock.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

var isOnLink = false;

function ShowInfoBlock(s) {
    try {
        if (playMode != null) {
            if (playMode != "") {
                PlayStop();
            }
        }
    }
    catch (e) { };
    var webpage = false;
    var su = Escape.MyUnEscape(s);

    if (su.indexOf('odrel://') == 0)
        su = resolve(su);

    var ss = su;

    while (ss.substr(0, 3) == "../") {
        ss = ss.substr(3);
    }
    if (ss.substr(36) == '/index.html') {
        webpage = true;
    }

    if (webpage) {
        var w = screen.availWidth;
        var left = (w - PlayerConfig.InfoWidth) / 2;

        var h = screen.availHeight;
        var top = (h - PlayerConfig.InfoHeight) / 2;

        var features = "toolbar=1,scrollbars=1,statusbar=1,resizable=1,fullscreen=0";
        id = window.open(su, "", "top=" + top + ",left=" + left + ",width=" + PlayerConfig.InfoWidth + ",height=" + PlayerConfig.InfoHeight + features);
        var s = "Center(" + left + "," + top + ")";
        setTimeout(s, 500);

    }
    else {
        iw = PlayerConfig.InfoWidth;
        ih = PlayerConfig.InfoHeight;
        if (PlayerConfig.InfoWidth2) {
            if (PlayerConfig.InfoWidth2.length > 0) {
                iw = PlayerConfig.InfoWidth2;
            }
        }
        if (PlayerConfig.InfoHeight2) {
            if (PlayerConfig.InfoHeight2.length > 0) {
                ih = PlayerConfig.InfoHeight2;
            }
        }

        var w = screen.availWidth;
        var left = (w - iw) / 2;

        var h = screen.availHeight;
        var top = (h - ih) / 2;

        var features = "toolbar=1,scrollbars=1,location=1,statusbar=1,menubar=1,resizable=1,fullscreen=0";
        id = window.open(su, "", "top=" + top + ",left=" + left + ",width=" + iw + ",height=" + ih + features);
        var s = "Center(" + left + "," + top + ")";
        setTimeout(s, 500);
    }
}

function OnLink() {
    isOnLink = true
}

function OffLink() {
    isOnLink = false
}

var globalloc = "";

function MakeAbsolute(URL) {
    var s = URL.toLowerCase();
    if (s.substr(0, 7) == "mailto:")
        return URL;
    var loc = "";
    if (globalloc.length == 0) {
        globalloc = location.href;
        while (globalloc.indexOf('\\') != -1)
            globalloc = globalloc.replace('\\', '/');
    };
    loc = globalloc;
    var k = loc.indexOf('#');
    if (k < 0)
        k = loc.indexOf('?');
    if (k >= 0)
        loc = loc.substr(0, k);
    var end
    end = loc.lastIndexOf('/')
    if (end != -1 && URL.indexOf('//') == -1) {
        return loc.substr(0, end + 1) + URL
    }
    else
        return URL
}

var id;

function Center(x, y) {
    try {
        id.focus();
        id.moveTo(x, y);
    }
    catch (e) {
    }
};

/* escape.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

var Escape = {};

//*****************************************************************
//Safe Escape/UnEscape support

Escape.SafeUri_EscapeCharacter = '/';

Escape.SafeUri_UnsafeCharacters = ['<', '>', '"', '\'', '%', ';', '(', ')', '&', '+'];

Escape.SafeUriEscape = function(s) {
    return Escape.__Escape(s, 1);
}

Escape.SafeUriUnEscape = function(s) {
    return Escape.__UnEscape(s, 1);
}


//*****************************************************************
// Simple Escape/UnEscape support

Escape.MyEscape = function(s) {
    return Escape.__Escape(s, 0);
}

Escape.MyUnEscape = function(s) {
    return Escape.__UnEscape(s, 0);
}

//*****************************************************************
// private

Escape.__Escape = function(s, safe) {
    var snew = "";
    for (var i = 0; i < s.length; i++) {
        ss = s.substr(i, 1);
        if (safe == 0 ? Escape.__Normal_Contains(ss) : !Escape.__SafeUri_Contains(ss)) {
            snew += ss;
        }
        else {
            ss = s.charCodeAt(i);
            a = "0000" + ss.toString(16).toUpperCase();
            snew += (safe == 0 ? "$" : Escape.SafeUri_EscapeCharacter) + a.substr(a.length - 4);
        }
    }
    return snew;
}

Escape.__UnEscape = function(s, safe) {
    var snew = "";
    var bEscape = false;
    for (var i = 0; i < s.length; i++) {
        if (bEscape) {
            ss = s.substr(i, 4);
            snew += String.fromCharCode(parseInt("0x" + ss));
            i += 3;
            bEscape = false;
        }
        else {
            ss = s.substr(i, 1);
            if (ss == (safe == 0 ? '$' : Escape.SafeUri_EscapeCharacter))
                bEscape = true;
            else
                snew += ss;
        }
    }
    return snew;
}

Escape.__Normal_Contains = function(s) {
    return ((s >= '0' && s <= '9') || (s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z'));
}

Escape.__SafeUri_Contains = function(s) {
    var l = Escape.SafeUri_UnsafeCharacters.length;
    for (var i = 0; i < l; i++) {
        if (s == Escape.SafeUri_UnsafeCharacters[i])
            return true;
    }
    if (s == Escape.SafeUri_EscapeCharacter)
        return true;
    return false;
}

////////////////////////////////////////////////////////////////////////////////////////
// UrlParser object

/** @constructor */
function UrlParser() {
    this.params = new Array();
    this.safemode = false;
}

UrlParser.prototype.Clone = function() {
    var url = new UrlParser();
    url.params = new Array();
    url.safemode = this.safemode;
    for (var k in this.params) {
        var v = this.params[k];
        if (v == null)
            continue;
        url.params[k] = this.params[k];
    }
    return url;
}

UrlParser.prototype.Parse = function() {
    var strArgs;
    var strArg;
    var ss = document.location.hash.substring(1);
    strArgs = ss.split("&");
    if (strArgs.length == 0 || strArgs[0] == "") {
        ss = document.location.search.substring(1);
        strArgs = ss.split("&");
    };
    if (strArgs.length > 0) {
        if (strArgs[0].toLowerCase().substr(0, 3) == "su=") {
            this.safemode = true;
            strArgs = strArgs[0].substr(3);
            strArgs = Escape.SafeUriUnEscape(strArgs);
            strArgs = strArgs.split("&");
        }
    }
    for (var i = 0; i < strArgs.length; i++) {
        strArg = (strArgs[i]);
        if (strArg.length == 0)
            continue;
        var param = strArg.split("=");
        if (param.length == 2) {
            this.params[param[0].toLowerCase()] = param[1];
        }
        else if (param.length < 2) {
            this.params[param[0].toLowerCase()] = "";
        }
        else {
            this.params[param[0].toLowerCase()] = strArg.substr(param[0].length + 1);
        }
    }
}

UrlParser.prototype.GetSafeMode = function() {
    return this.safemode;
}

UrlParser.prototype.SetSafeMode = function(k) {
    this.safemode = k;
}

UrlParser.prototype.GetParameter = function(s) {
    return this.params[s.toLowerCase()];
}

UrlParser.prototype.AddParameter = function(s, v) {
    this.params[s.toLowerCase()] = v;
}

UrlParser.prototype.RemoveParameter = function(s) {
    this.params[s.toLowerCase()] = null;
}

UrlParser.prototype.ClearParameterList = function(s) {
    this.params = null;
    this.params = new Array();
}

UrlParser.prototype.BuildParameterList = function(s) {
    var s = "";
    var first = true;
    for (var k in this.params) {
        var v = this.params[k];
        if (v == null) {
            continue;
        }
        if (first == false) {
            s += "&";
        }
        first = false;
        if (v.length == 0) {
            s += k;
        }
        else {
            s += k + "=" + this.params[k];
        }
    }
    if (this.safemode) {
        s = "su=" + Escape.MyEscape(s);
    }
    return s;
}

UrlParser.prototype.GetCorrectUrl = function(url, nosu) {
    if (!this.safemode) { return url; }
    var strArgs;
    var k = url.indexOf("#");
    if (k == -1) { k = url.indexOf("?") }
    if (k >= 0) {
        var paramss = url.substring(k + 1);
        strArgs = paramss.split("&");
        if (strArgs[0].toLowerCase().substr(0, 3) == "su=") {
            return url;
        }
        var ss = url.substring(0, k + 1) + "su=" + Escape.SafeUriEscape(paramss);
        return ss;
    }
    else {
        return url + (nosu ? "" : "?su=");
    }
}

/* splash.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

function SplashWindow() {
    //	var x=window.screen.availWidth;
    //	var y=window.screen.availHeight;

    var x = document.documentElement.offsetWidth;
    var y = document.documentElement.offsetHeight;

    document.open();

    document.writeln("<script>var splash_hidden=false;");
    document.writeln("function ShowSplash()");
    document.writeln("{if (splash_hidden==false)");
    document.writeln("document.getElementById('splash').style.display='block';}");
    document.writeln("function HideSplash()");
    document.writeln("{splash_hidden=true; document.getElementById('splash').style.display='none';}");
    document.writeln("</script>");

    document.writeln("<DIV id='splash' style='display:none;position:absolute;left:0;top:" + (y / 2 - 50) + ";width:" + x + ";height:200'>");
    document.writeln("<p align='center'><font color='#FF0000' face='Arial' style='font-size:11pt'>");
    document.writeln(R_splashtext);
    document.writeln("</font></p>");
    document.writeln("</DIV>");
    document.writeln("<script>setTimeout('ShowSplash()',2000);</script>");
    document.close();
};

SplashWindow();




/* binterface.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

//file version 2.82

function getElementsByAttribute(attribute, attributeValue) {
    var elementArray = new Array();
    var matchedArray = new Array();

    if (attribute == "id" && document.all && !IsFF3()) {
        var oObject = document.all.item(attributeValue);
        if (oObject != null) {
            if (oObject.length != null) {
                for (i = 0; i < oObject.length; i++) {
                    matchedArray[matchedArray.length] = oObject(i);
                }
            } else {
                matchedArray[matchedArray.length] = oObject;
            }
        }
        return matchedArray;
    }

    if (document.all && !IsFF3()) {
        elementArray = document.all;
    }
    else {
        elementArray = document.getElementsByTagName("*");
    }

    for (var i = 0; i < elementArray.length; i++) {
        if (attribute == "class") {
            var pattern = new RegExp("(^| )" +
         attributeValue + "( |$)");

            if (pattern.test(elementArray[i].className)) {
                matchedArray[matchedArray.length] = elementArray[i];
            }
        }
        else if (attribute == "for") {
            if (elementArray[i].getAttribute("htmlFor") ||
         elementArray[i].getAttribute("for")) {
                if (elementArray[i].htmlFor == attributeValue) {
                    matchedArray[matchedArray.length] = elementArray[i];
                }
            }
        }
        else if (elementArray[i].getAttribute(attribute) ==
       attributeValue) {
            matchedArray[matchedArray.length] = elementArray[i];
        }
    }

    return matchedArray;
}

function getElementOfObject(attributeValue, objectId) {
    var cNode = '';
    var elements = getElementsByAttribute('id', attributeValue);
    for (var i in elements) {
        cNode = elements[i];
        while (cNode.parentNode != null) {
            if (cNode.parentNode == objectId) { return elements[i]; }
            cNode = cNode.parentNode;
        }
    }
    return false;
}

//////////////////////////////////////////////////////////////////

var objIcon02Img;
var objYesImg0;
var objNoImg0;
var objDoneTypingImg0;
var objYesImg1;
var objNoImg1;
var objDoneTypingImg1;
var spanE;
var spanEYes;
var spanENo;

var mobjBubble = 0;
var mobjContent = 0;
var mobjPointer = 0;
var mblnShowPointer = false;

var mAct;

// outer bubble padding from content
var topPadding = 38;
var leftPadding = 14;
var rightPadding = 14;
var bottomPadding = 3;

var m_Pointed;
var m_PointerXpos = 0;
var m_PointerYpos = 0;
var m_PointerDirection = BUBB07_NOPOINTER;
var m_bWidth = 0;
var m_bHeight = 0;
var m_scrOffLeft = 0;
var m_scrOffTop = 0;

//	<xsl:variable name="BUBBLE_DIR_TOP_LEFT" select="3" />
//	<xsl:variable name="BUBBLE_DIR_TOP_RIGHT" select="4" />
//	<xsl:variable name="BUBBLE_DIR_BOTTOM_LEFT" select="1" />
//	<xsl:variable name="BUBBLE_DIR_BOTTOM_RIGHT" select="2" />
//	<xsl:variable name="BUBBLE_DIR_LEFT_TOP" select="7" />
//	<xsl:variable name="BUBBLE_DIR_RIGHT_TOP" select="8" />
//	<xsl:variable name="BUBBLE_DIR_LEFT_BOTTOM" select="5" />
//	<xsl:variable name="BUBBLE_DIR_RIGHT_BOTTOM" select="6" />
//	<xsl:variable name="BUBBLE_DIR_NONE" select="0" />


var BUBB07_NULL = 0;
var BUBB07_NOPOINTER = 0;

var BUBB07_TOPLEFT = 3; 	// 1
var BUBB07_TOPRIGHT = 4; 	// 2
var BUBB07_BOTTOMLEFT = 1; 	// 3
var BUBB07_BOTTOMRIGHT = 2; 	// 4
var BUBB07_LEFTTOP = 7;
var BUBB07_RIGHTTOP = 8; 	// 2
var BUBB07_LEFTBOTTOM = 5;
var BUBB07_RIGHTBOTTOM = 6;

var BUBB07_DEFAULTWIDTH = 200 - leftPadding - rightPadding;

// +++ defines
var BUBB07_LEFTAREA = 37;
var m_BubblePath = "../../../img/";
var ash = false;
var abubbv02_bubbcolor = 0;
var tID = 0;
var setpos = true;

//var img1on,img1off,
var img2on, img2off;

var imagesArr = new Array();
var imagesXref = new Array();

function cached_image(color) {
    var bubbc;
    bubbc = convert(String(color), 10, 16);
    while (bubbc.length < 6) bubbc = "0" + bubbc;

    bubbc = bubbc.toLowerCase();
    //alert("cached_image - " + bubbc)

    var m_BubbleImgs;
    m_BubbleImgs =
		[m_BubblePath + 'giftrk1.gif', //0
			m_BubblePath + 'b' + bubbc + '_03.gif',
			m_BubblePath + 'b' + bubbc + '_03over.gif',
			m_BubblePath + 'b' + bubbc + '_01.gif',
			m_BubblePath + 'b' + bubbc + '_02.gif',
			m_BubblePath + 'b' + bubbc + '_04.gif', 	//10
			m_BubblePath + 'b' + bubbc + '_06.gif',
			m_BubblePath + 'b' + bubbc + '_07.gif',
			m_BubblePath + 'b' + bubbc + '_08.gif',
			m_BubblePath + 'b' + bubbc + '_09.gif',
			m_BubblePath + 'b' + bubbc + '_anch_tl.gif', // upper left
			m_BubblePath + 'b' + bubbc + '_anch_tr.gif', // upper right
			m_BubblePath + 'b' + bubbc + '_anch_lthigh.gif', // left high
			m_BubblePath + 'b' + bubbc + '_anch_ltlow.gif', // left low
			m_BubblePath + 'b' + bubbc + '_anch_rthigh.gif', // right high
			m_BubblePath + 'b' + bubbc + '_anch_rtlow.gif', // right low
			m_BubblePath + 'b' + bubbc + '_anch_bl.gif', // bottom left
			m_BubblePath + 'b' + bubbc + '_anch_br.gif',
			m_BubblePath + 'b' + bubbc + '_03disab.gif', // bottom right
			m_BubblePath + 'b' + bubbc + '_03empty.gif'] // no bottom

    this.imageNames = m_BubbleImgs;
    this.color = color;

    var imgon = document.createElement("img");
    imgon.width = 23;
    imgon.height = 21;
    imgon.src = m_BubbleImgs[2];

    var imgoff = document.createElement("img");
    imgoff.width = 23;
    imgoff.height = 21;
    imgoff.src = m_BubbleImgs[1];

    this.imgon = imgon;
    this.imgoff = imgoff;

}


function cached_images(bubcolor) {
    abubbv02_bubbcolor = bubcolor;
    if (!imagesArr["c_" + bubcolor]) {
        imagesArr["c_" + bubcolor] = new cached_image(bubcolor);
        imagesXref[imagesXref.length] = "c_" + bubcolor;
    }
}

function load_buttons() {
    if (document.images) {
        img2on = imagesArr["c_" + abubbv02_bubbcolor].imgon;
        img2off = imagesArr["c_" + abubbv02_bubbcolor].imgoff;
    }
}

function GetScrName(fileName) {
    k = fileName.lastIndexOf('/');
    s = fileName.substr(k + 1);
    return "../../img/" + s;
}

function BubbleimgOn(imgName, img2) {

    if (img2) {
        //mobjBubble.all[imgName].style.display = "none"
        //mobjBubble.all[img2].style.display = "block"
        var cimg = getElementOfObject(imgName, mobjBubble);
        cimg.style.display = "none";
        var cimg2 = getElementOfObject(img2, mobjBubble);
        cimg2.style.display = "block";
    }
    else {
        var blnInBox = false;
        // on highlight if in box otherwise do not highlight
        if (document.images) {
            if ((event.offsetX >= 3 && event.offsetX <= 26) && (event.offsetY >= 7 && event.offsetX <= 27)) {
                mobjBubble.all[imgName].src = GetScrName(eval(imgName + "on.src"));
            }
            else {
                mobjBubble.all[imgName].src = GetScrName(eval(imgName + "off.src"));
            }
        }
    }
}

function BubbleimgOff(imgName, img2) {
    if (img2) {
        //mobjBubble.all[imgName].style.display = "block"
        //mobjBubble.all[img2].style.display = "none"
        var cimg = getElementOfObject(imgName, mobjBubble);
        cimg.style.display = "block";
        var cimg2 = getElementOfObject(img2, mobjBubble);
        cimg2.style.display = "none";
    }
    else {
        if (document.images)
            mobjBubble.all[imgName].src = GetScrName(eval(imgName + "off.src"));
    }
}

function BubbleClose() {
    /*	if ((event.offsetX >= 3 && event.offsetX <= 26) && (event.offsetY >= 7 && event.offsetX <= 27)) {*/
    OnClose();
    /*}*/
}

function InAnchor(event) {

    var inAnchor = false;
    var xCoord = event.offsetX;
    var yCoord = event.offsetY;
    switch (abubbv02_Pointer) {
        case BUBB07_TOPLEFT:
            if ((xCoord >= 3) && (yCoord <= 38)) {
                // in triangle range

                //slop = (y2 - y1) / (x2 - x1)
                var Slope = (38 - 1) / (18 - 4);

                // CoordPos = y1 = slope * (x2 - x1) - y2
                var CoordPos = (Slope * (18 - xCoord)) + yCoord;

                // if CoordPos < y1
                if (CoordPos > 38) {
                    inAnchor = true;
                }
            }
            break;
        case BUBB07_TOPRIGHT:
            if ((xCoord <= 15) && (yCoord <= 38)) {
                // in triangle range

                //slop = (y2 - y1) / (x2 - x1)
                var Slope = (1 - 35) / (13 - 1);

                // CoordPos = y1 = slope * (x2 - x1) - y2
                var CoordPos = (Slope * (13 - xCoord)) + yCoord;

                // if CoordPos < y1
                if (CoordPos > 1) {
                    inAnchor = true;
                }
                //alert(inAnchor);
            }
            break;
        case BUBB07_BOTTOMLEFT:
            if (xCoord >= 3) {
                // in triangle range

                //slop = (y2 - y1) / (x2 - x1)
                var Slope = (41 - 5) / (5 - 17);

                // CoordPos = y1 = slope * (x2 - x1) - y2
                var CoordPos = (Slope * (5 - xCoord)) + yCoord;

                // if CoordPos < y1
                if (CoordPos < 41) {
                    inAnchor = true;
                }
                //alert(inAnchor);
            }
            break;
        case BUBB07_BOTTOMRIGHT:
            if (xCoord <= 15) {
                // in triangle range

                //slop = (y2 - y1) / (x2 - x1)
                var Slope = (41 - 4) / (14 - 1);

                // CoordPos = y1 = slope * (x2 - x1) - y2
                var CoordPos = (Slope * (14 - xCoord)) + yCoord;

                // if CoordPos < y1
                if (CoordPos < 41) {
                    inAnchor = true;
                }
                //alert(inAnchor);
            }
            break;
        case BUBB07_LEFTTOP:
            if (yCoord >= 3) {
                // in triangle range

                //slop = (y2 - y1) / (x2 - x1)
                var Slope = (15 - 3) / (38 - 1);

                // CoordPos = y1 = slope * (x2 - x1) - y2
                var CoordPos = (Slope * (38 - xCoord)) + yCoord;

                // if CoordPos < y1
                if (CoordPos < 15) {
                    inAnchor = true;
                }
            }
            break;
        case BUBB07_LEFTBOTTOM:
            if (yCoord <= 15) {
                // in triangle range

                //slop = (y2 - y1) / (x2 - x1)
                var Slope = (3 - 15) / (38 - 1);

                // CoordPos = y1 = slope * (x2 - x1) - y2
                var CoordPos = (Slope * (38 - xCoord)) + yCoord;

                // if CoordPos < y1
                if (CoordPos > 3) {
                    inAnchor = true;
                }
            }
            break;
        case BUBB07_RIGHTTOP:
            if (yCoord >= 3) {
                // in triangle range

                //slop = (y2 - y1) / (x2 - x1)
                var Slope = (15 - 3) / (1 - 38);

                // CoordPos = y1 = slope * (x2 - x1) - y2
                var CoordPos = (Slope * (1 - xCoord)) + yCoord;

                // if CoordPos < y1
                if (CoordPos < 15) {
                    inAnchor = true;
                }
            }
            break;
        case BUBB07_RIGHTBOTTOM:
            if (yCoord >= 3) {
                // in triangle range

                //slop = (y2 - y1) / (x2 - x1)
                var Slope = (3 - 15) / (1 - 38);

                // CoordPos = y1 = slope * (x2 - x1) - y2
                var CoordPos = (Slope * (1 - xCoord)) + yCoord;

                // if CoordPos < y1
                if (CoordPos > 3) {
                    inAnchor = true;
                }
            }
            break;

    }
    return inAnchor;
}

function AnchorMouseDown() {
    // this function is to determine if the mousedown event was in the pointer. If not pass event
    // through

    if (!InAnchor(event)) {
        EventMouseDown(event);
    }
}

function AnchorMouseUp() {
    // this function is to determine if the mousedown event was in the pointer. If not pass event
    // through
    if (!InAnchor(event)) {
        EventMouseUp(event);
    }
}


function convert(input, origin, dest) {
    base = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    c = 0; Result = "";
    for (t = 1; t <= input.length; t++) {
        b = base.indexOf(input.substring(t - 1, t));
        n = b * (Math.pow(origin, input.length - t));
        c += n;
    }
    a = 100;
    while (c < Math.pow(dest, a)) { a--; }

    while (a > -1) {
        e = Math.pow(dest, a);
        a--;
        d = ((c - (c % e)) / e) + 1;
        c = c % e; Ciffer = base.substring(d - 1, d); Result = Result + Ciffer;
    }
    return Result;
}


//<!--hide from old browsers

N = (document.all && !IsFF3()) ? 0 : 1;
var ob = false;
var xi, yi, X, Y;
var global_moveable = true;


// +++ mouse down event
function bubb07_global_MD(e) {
    if (!global_moveable) return;
    if (N) {
        ob = e.target;

        if (e.target.id == "blink" || e.target.id == "m_Caption" || e.target.id == "m_StaticCaption") {
            if (e.target.id == "blink" || e.target.id == "m_StaticCaption") {
                xi = document.getElementById("bubb_cap").offsetWidth;
            }
            else {
                xi = 0
            }

            ob = true;

            X = e.layerX;
            Y = e.layerY;
        };

        return false;
    }
    else {
        if (event.srcElement.id == "blink" || event.srcElement.id == "m_Caption" || event.srcElement.id == "m_StaticCaption") {
            if (event.srcElement.id == "blink" || event.srcElement.id == "m_StaticCaption") {
                xi = mobjBubble.all.bubb_cap.clientWidth;
            }
            else {
                xi = 0;
            }
            ob = true;

            X = window.event.offsetX;
            Y = window.event.offsetY;
        }
    }
}


// +++ mouse move event
function bubb07_global_MM(e) {
    if (ob) {
        if (IsTouchDevice()) {
            if (ob == true) {
                leftarea = 0;
                rightarea = 0;

                var xMovement = e.clientX - X;
                var yMovement = e.clientY - Y;

                var xp = getObjLeft(mobjBubble) + xMovement;
                var yp = getObjTop(mobjBubble) + yMovement;

                X = e.clientX;
                Y = e.clientY;

                mobjBubble.style.left = xp + "px";
                mobjBubble.style.top = yp + "px";

                mobjContent.style.left = Number(xp + leftPadding) + "px";
                mobjContent.style.top = Number(yp + topPadding) + "px";
            }
        }
        else if (N) {
            if (ob == true) {
                leftarea = 0;
                rightarea = 0;

                var xMovement = e.pageX - X	//-14-xi + document.body.scrollLeft-leftarea;
                var yMovement = e.pageY - Y	// + document.body.scrollTop-rightarea;

                mobjBubble.style.left = xMovement + "px";
                mobjBubble.style.top = yMovement + "px";

                mobjContent.style.left = Number(xMovement + leftPadding) + "px";
                mobjContent.style.top = Number(yMovement + topPadding) + "px";

                document.getElementById('blink').focus();
            }
        }
        else {
            if (ob == true) {
                leftarea = 0;
                rightarea = 0;

                var xMovement = event.clientX - X - 14 - xi + document.body.scrollLeft - leftarea;
                var yMovement = event.clientY - Y + document.body.scrollTop - rightarea;

                mobjBubble.style.left = xMovement + "px";
                mobjBubble.style.top = yMovement + "px";

                mobjContent.style.left = Number(xMovement + leftPadding) + "px";
                mobjContent.style.top = Number(yMovement + topPadding) + "px";
            }
            return false;
        }
    }
}


// +++ mouse up event
function bubb07_global_MU() {
    if (ob) OnBubbleMoved();
    ob = false;
}

if (N) {
    document.captureEvents(Event.MOUSEDOWN | Event.MOUSEMOVE | Event.MOUSEUP);
}

function touch(e) {
    if (e.originalEvent.touches && e.originalEvent.touches.length) {
        return e.originalEvent.touches[0];
    } else if (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length) {
        return e.originalEvent.changedTouches[0];
    }
};
if (IsTouchDevice()) {
    $(document).bind("touchend", function (e) {
        bubb07_global_MM(touch(e));
        if (ob) {
            e.preventDefault();
        }
        ob = false;
    });
    $(document).bind("touchmove", function (e) {
        bubb07_global_MM(touch(e));
        if (ob) {
            e.preventDefault();
        }
    });
    $(document).bind("touchstart", function (e) {
        if (!global_moveable) return;
        var f = touch(e);
        if (f.target.id == "blink" || f.target.id == "m_Caption" || f.target.id == "m_StaticCaption") {
            e.preventDefault();
            ob = true;
        };
        X = f.clientX;
        Y = f.clientY;
    });
} else {
    if (document.attachEvent) {
        document.attachEvent("onmousedown", bubb07_global_MD);
        document.attachEvent("onmousemove", bubb07_global_MM);
        document.attachEvent("onmouseup", bubb07_global_MU);
    }
    else {
        document.addEventListener("mousedown", bubb07_global_MD, true);
        document.addEventListener("mousemove", bubb07_global_MM, true);
        document.addEventListener("mouseup", bubb07_global_MU, true);
    }
}

function JSRect(left, top, right, bottom) {
    this.m_Left = left;
    this.m_Top = top;
    this.m_Right = right;
    this.m_Bottom = bottom;
}

///////////////////////////////////
//  +++ class JSBubbleInterface  //
///////////////////////////////////
function JSBubbleInterface(name) {
    abubbv02_bVisible = false;
    abubbv02_show = true;
    abubbv02_Text = "";
    abubbv02_CaptionText = "";
    abubbv02_ActionText = "";
    abubbv02_IconName = '';
    abubbv02_Pointer = BUBB07_NULL;
    abubbv02_infos = "";
    abubbv02_enableclose = 1;
    m_Pointed = true;
    //abubbv02_bubbcolor=0;
    _ax = 0;
    _ay = 0;

    // +++ bubble position
    m_rect = new JSRect(-1, -1, -1, -1);

    //alert(name);
    // +++ knowit bubble position
    this.m_knrect = new JSRect(-1, -1, -1, -1)

    //if(document.all) this.m_Object=document.all[this.m_BubbleID];
    this.m_bFFClearHeight = false;
    this.m_Name = name;
    this.m_Text = "";
    this.m_Caption = "";
    this.lastbubbstyle = "";
    this.m_ShowAction = false;
    this.EnabledAction = false;
    this.m_bMoveDefPos = false;
    this.savedPos = null;
};

///////////////////////////////////////////////
JSBubbleInterface.prototype.SetMode = function (text) {
    //alert(text);
    abubbv02_CaptionText = text;
}


JSBubbleInterface.prototype.ShowMode = function () {
    if (abubbv02_show == true) {
        if (document.all && !IsFF3()) {
            mobjBubble.all.m_Caption.innerText = abubbv02_CaptionText;
        } else {
            var mCap = getElementsByAttribute('id', 'm_Caption');
            for (var i in mCap) {
                mCap[i].textContent = abubbv02_CaptionText;
            };
        };
    }
}

JSBubbleInterface.prototype.StartBlink = function (color) {
    BlinkTxt();
}

JSBubbleInterface.prototype.EndBlink = function (color) {
    clearTimeout(tID);
    var prdiv = document.getElementById("prdiv"); // instead of mobjContent.all (works only in IE)
    prdiv.style.color = "blue"
}

JSBubbleInterface.prototype.SetColor = function (color) {

    abubbv02_bubbcolor = color;
}

function BlinkTxt() {

    if (mobjContent) {
        var prdiv = getElementOfObject("prdiv", mobjContent); // instead of mobjContent.all (works only in IE)
        if (prdiv) {
        	if (prdiv.style.color == "#ccffff" || prdiv.style.color == "rgb(204, 255, 255)" || prdiv.style.color == "#7dc1db" || prdiv.style.color == "rgb(125, 193, 219)")
                prdiv.style.color = "#003366"
            else
            	prdiv.style.color = grayBubbles ? "#7dc1db" : "#ccffff";
        }
    }
    tID = setTimeout('BlinkTxt()', 750);
}

JSBubbleInterface.prototype.SetEnableCloseButton = function (bValue) {

    //    if (abubbv02_enableclose != bValue)
    if (abubbv02_show == true) {
        var closebtn = document.getElementById("closebtn_" + abubbv02_bubbcolor); // instead of mobjBubble.all["closebtn"] (works only in IE)
        str = "";
        if (bValue == 1) {
            str = "<div id='closebtn_" + abubbv02_bubbcolor + "' style='position:relative'><div><img id='img2' name='img2' src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[1] + "' style='display:block' width='32' height='27' border='0'><img id='img2o' name='img2o' src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[2] + "' style='display:none' width='32' height='27' border='0'></div><div style='position:absolute; left:3px; top:7px'><a onclick='BubbleClose();return false'"
				+ (IsTouchDevice() ? "" : " onMouseMove='BubbleimgOn(\"img2\",\"img2o\")' onMouseOut='BubbleimgOff(\"img2\",\"img2o\")'")
				+ "><img alt='" + R_bubble_closeondemand + "' id='imghandler' name='imghandler' src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[0] + "' style='display:block' width='23' height='20' border='0'></a></div></div></td>";
            //closebtn.detachEvent("onmousemove",BubbleimgOn2);
            //closebtn.detachEvent("onmouseout",BubbleimgOff2);
            //closebtn.attachEvent("onmousemove",BubbleimgOn2);
            //closebtn.attachEvent("onmouseout",BubbleimgOff2);
            //closebtn.href="javascript:OnClose()";
            //closebtn.all["img2"].src=imagesArr["c_" + abubbv02_bubbcolor].imageNames[2];
            //closebtn.detachEvent("onclick",BubbleClose);
            //closebtn.attachEvent("onclick",BubbleClose);
        }
        else if (bValue == 0) {
            str = '<a id="closebtn_' + abubbv02_bubbcolor + '" onclick=""><img name="img2" src="' + imagesArr["c_" + abubbv02_bubbcolor].imageNames[18] + '" width="32" height="27" border="0" alt="' + R_bubble_closeondemand + '"></td>';
        }
        else {      // bValue == 2 -> nem kell gomb: bxxxxxx_03empty.gif
            str = '<a id="closebtn_' + abubbv02_bubbcolor + '" onclick=""><img name="img2" src="' + imagesArr["c_" + abubbv02_bubbcolor].imageNames[19] + '" width="32" height="27" border="0" alt=""></td>';
        }

        if (document.all && !IsFF3()) {
            closebtn.outerHTML = str;
        } else {
            var r = closebtn.ownerDocument.createRange();
            r.setStartBefore(closebtn);
            var df = r.createContextualFragment(str);
            closebtn.parentNode.replaceChild(df, closebtn);
        }
    }
    abubbv02_enableclose = bValue;
}

JSBubbleInterface.prototype.GetActionLink = function () {
    return getElementOfObject('m_ActionText', mobjBubble);
}

JSBubbleInterface.prototype.SetPRText = function (text) {
    if (mobjContent) {
        var cElem = document.getElementById('prdiv');
        if (cElem != null) //if(mobjContent.all["prdiv"])
        {
            if (document.all && !IsFF3()) {
                cElem.innerText = text; //mobjContent.all["prdiv"].innerText=text;
            } else {
                cElem.textContent = text;
            }
        }
    }
}

var noactionstitle = false;
JSBubbleInterface.prototype.SetActionText = function (text, notitle) {
    //alert(text);
    abubbv02_ActionText = text;
    //this.ShowActionText();
    noactionstitle = notitle;
    this.ShowActionText();
}

JSBubbleInterface.prototype.ShowActionText = function () {
    //alert("huha");
    if (mobjBubble)
        if (abubbv02_show == true) {
            if (document.all && !IsFF3()) {
                if (!noactionstitle) mobjBubble.all.m_ActionText.title = R_interface_action_alt;
                mobjBubble.all.m_ActionText.innerText = abubbv02_ActionText;
            } else {
                mAct = getElementOfObject('m_ActionText', mobjBubble);
                if (!noactionstitle) mAct.title = R_interface_action_alt;
                mAct.textContent = abubbv02_ActionText;
            }
        }
}

JSBubbleInterface.prototype.Show = function () {
    this.ShowActionText();
    abubbv02_bVisible = true;
    if (mobjBubble) {
        mobjBubble.style.visibility = "visible";
        mobjBubble.style.zIndex = 2;
        mobjBubble.style.left = Math.abs(getObjLeft(mobjBubble)) + "px";
        mobjContent.style.visibility = "visible";
        mobjContent.style.zIndex = 3;
        if (mblnShowPointer) {
            mobjPointer.style.visibility = "visible";
            mobjPointer.style.zIndex = 4;
        }
        mAct = getElementOfObject('m_ActionText', mobjBubble);
        mAct.style.visibility = "visible";
    }
}

JSBubbleInterface.prototype.Hide = function () {
    if (mobjBubble) {
        abubbv02_bVisible = false;

        //		_ax=mobjContent.style.pixelLeft;
        //		_ay=mobjContent.style.pixelTop;

        _ax = getObjLeft(mobjContent);
        _ay = getObjTop(mobjContent);

        //here what is this for??
        mobjBubble.style.visibility = "hidden";
        mobjBubble.style.left = "-" + Math.abs(getObjLeft(mobjBubble)) + "px";
        mobjContent.style.visibility = "hidden";
        if (mblnShowPointer)
            mobjPointer.style.visibility = "hidden";
        mAct = getElementOfObject('m_ActionText', mobjBubble);
        mAct.style.visibility = "hidden";
    }
}

JSBubbleInterface.prototype.IsVisible = function () {
    if (mobjBubble)
        return abubbv02_bVisible;
    return false;
}

JSBubbleInterface.prototype.SetErrorMessage = function (text) {
    //alert(text);
    this.m_bFFClearHeight = true;
    var checkobj;
    checkobj = getElementOfObject("errortext", mobjContent);
    if (abubbv02_show == true) {
        var intObjHeight = 0;
        if (text == '') {
            //no error message - regenerate the bubble text using the appropriate function.
            this.Hide();
            this.ShowText();
            kmbdefpos = false;
            RepositionBubble(this);
            this.Show();
        }
        else {
            this.SetEnableCloseButton(true);
            if (!checkobj) {

                this.Hide();
                this.ShowText();

                var objContent = mobjContent;
                var objSpan = document.createElement("span");
                objSpan.ID = "errortext";
                var objB = document.createElement("b");
                var objFont = document.createElement("font");
                objFont.color = "#FF0000";
                objFont.face = "Arial";
                objFont.size = "2";
                objFont.setAttribute("style", "font-family:Arial; font-size:10pt;");

                if (document.all && !IsFF3()) {
                    objFont.innerText = text;
                } else {
                    objFont.textContent = text;
                }
                objB.appendChild(objFont);
                objSpan.appendChild(objB);

                var objHR = document.createElement("hr");
                objSpan.appendChild(objHR);
                if (document.all && !IsFF3()) objContent.insertBefore(objSpan, objContent.children(0))
                else objContent.insertBefore(objSpan, objContent.firstChild);

                this.RefreshBubble();
                kmbdefpos = false;
                RepositionBubble(this);
                this.Show();
            }
        }
    }
}
JSBubbleInterface.prototype.SetIcon = function (iconfilename) {
    if (iconfilename != "") {
        abubbv02_IconName = iconfilename;
    }
}

JSBubbleInterface.prototype.SetMoveable = function (bValue) {
    global_moveable = bValue;
};

JSBubbleInterface.prototype.RefreshBubble = function () {
    // reset the width. Otherwise the width will just grow
    mobjContent.style.pixelWidth = BUBB07_DEFAULTWIDTH;
    //	mobjContent.style.pixelHeight = 30;
    mobjContent.style.width = BUBB07_DEFAULTWIDTH + 'px';
    //	mobjContent.style.height = '30px';

    //	if((mobjContent.clientHeight + topPadding + bottomPadding) > BUBB07_DEFAULTWIDTH)
    //	{	
    //	    //bubble height exceeds predefined bubble width - adjust width to a (4:3) width-to-height ratio...
    //		var avgSize = Math.round((((mobjContent.clientHeight + topPadding + bottomPadding) + (mobjContent.clientWidth + leftPadding + rightPadding))*4)/7) - leftPadding - rightPadding;
    //		
    //		mobjContent.style.width = avgSize;
    //		
    //	}
    //	
}

JSBubbleInterface.prototype.SetText = function (text) {
    abubbv02_Text = text;
}


JSBubbleInterface.prototype.ResetContent = function () {
    abubbv02_IconName = "";
    m_ShowAction = "false";
    abubbv02_infos = "";
}

JSBubbleInterface.prototype.ShowText = function () {
    text = abubbv02_Text;


    if (abubbv02_show == true) {
        var objContent = mobjContent;

        if (text == '') {
            text = '<DIV style="visibility: hidden">longtextlongtextlongtext</DIV>';
            //alert(text);
        }

        objContent.innerHTML = text;

        if (abubbv02_IconName != '') {
            //iconarea='<IMG alt="" width="32" height="32" align="left" src="'+abubbv02_IconName+'"/>';
            var objImg = document.createElement("img");
            objImg.width = 32;
            objImg.height = 32;
            objImg.border = 0;
            objImg.align = "left";
            objImg.src = m_BubblePath + abubbv02_IconName;
            if (document.all && !IsFF3())
                objContent.insertBefore(objImg, objContent.children(0))
            else
                objContent.firstChild.insertBefore(objImg, objContent.firstChild.firstChild);
        }
        var objTable = document.createElement("table");
        objTable.cellspacing = 0;
        objTable.cellpadding = 0;
        objTable.style.marginBottom = "8px";
        var objTableBody = document.createElement("tbody");

        var objTR = document.createElement("tr");

        var objTD = document.createElement("td");
        objTD.height = 5;
        objTR.appendChild(objTD);
        objTableBody.appendChild(objTR);

        if (this.m_ShowAction || abubbv02_infos) {
            objTR = document.createElement("tr");

            if (this.m_ShowAction) {
                //action=+separator+"</td>"
                objTD = document.createElement("td");
                objTD.align = "right";

                var objAnchor = document.createElement("a");
                objAnchor.href = "javascript:OnAlternative();";

                var objImg = document.createElement("img");
                objImg.width = 22;
                objImg.height = 22;
                objImg.border = 0;
                objImg.alt = R_menu_alternatives;
                objImg.src = m_BubblePath + "alternatives.gif"
                objAnchor.appendChild(objImg);

                objTD.appendChild(objAnchor);


                if (screens[showScreen].infoblocks.length > 0) {
                    //separator="<img src='icondivide.gif' width='16' height='19' border='0' alt=''></img>";
                    var objImgSep = document.createElement("img");
                    objImgSep.width = 16;
                    objImgSep.height = 19;
                    objImgSep.border = 0;
                    objImgSep.src = m_BubblePath + "icondivide.gif"
                    objTD.appendChild(objImgSep);
                }

                objTR.appendChild(objTD)
            }

            if (screens[showScreen].infoblocks.length > 0) {
                // process infoblocks
                for (var i = 0; i < screens[showScreen].infoblocks.length; i++) {
                    var ib = screens[showScreen].infoblocks[i];

                    var objInfoBlock = document.createElement("td");
                    objInfoBlock.width = 25;
                    objInfoBlock.border = 0;

                    var objAnchor = document.createElement("a");
                    objAnchor.href = ib.url;
                    objAnchor.title = ib.tooltip;

                    var objActionImg = document.createElement("img");
                    objActionImg.src = ib.buttonfile;
                    objActionImg.width = 22;
                    objActionImg.height = 22
                    objActionImg.border = 0;
                    objActionImg.alt = ib.tooltip;
                    objAnchor.appendChild(objActionImg);

                    objInfoBlock.appendChild(objAnchor);
                    objTR.appendChild(objInfoBlock);
                };
            }
            objTableBody.appendChild(objTR);
        }
        objTable.appendChild(objTableBody);
        objContent.appendChild(objTable);

        if (playMode == "K") {
            // insert images using DOM. Currently three instances of images will be processed
            // through the DOM. These images are only available for Know It
            //var objIcon02 = mobjContent.all["img_icon02"];
            var objIcon02 = document.getElementById("img_icon02");
            if (objIcon02) {
                // if icon exists
                var objImg = objIcon02Img.cloneNode(null);
                objIcon02.appendChild(objImg);
            }

            UpdateYesNo(false, false);
        }
        UpdateDoneTyping(false);
    }
}

function UpdateDoneTyping(HighLighted) {

    //var objDoneTyping = mobjContent.all["img_DoneTyping"];
    //var objDoneTyping = mobjContent.img_DoneTyping;
    var a_objDoneTyping = getElementsByAttribute('id', 'img_DoneTyping');
    for (var i = 0; i < a_objDoneTyping.length; i++) {
        objDoneTyping = a_objDoneTyping[i];
        if (objDoneTyping) {
            // if yes No object exists
            if ((document.all && !IsFF3() && objDoneTyping.childNodes.length == 0) || (!document.all && objDoneTyping.nodeType == 1)) {
                // if the object is empty then populate using appenchild		

                spanE.innerHTML = R_tcbutton_title;

                objDoneTyping.appendChild(objDoneTypingA);
                objDoneTypingA.appendChild(objDoneTypingImg0);
                objDoneTypingImg0.appendChild(spanE);
                if (playMode == "K") {
                    br = document.createElement("P");
                    br.innerHTML = "&nbsp;";
                    br2 = document.createElement("P");
                    br2.innerHTML = "&nbsp;";
                    objDoneTyping.appendChild(br);
                    objDoneTyping.appendChild(br2);
                    objDoneTypingImg0.style.marginTop = "0px";
                    objDoneTypingImg0.style.marginBottom = "15px";
                }
                else {
                    // bottom line
                    br = document.createElement("p");
                    br.style.height = "42px";
                    objDoneTyping.appendChild(br);
                    objDoneTypingImg0.style.marginTop = "10px";
                    objDoneTypingImg0.style.marginBottom = "15px";
                }


            }
        }
    }
}

function UpdateYesNo(YesHighLighted, NoHighlighted) {
    //var objYesNo = mobjContent.all["img_YesNo"];
    var objYesNo = document.getElementById("img_YesNo");
    if (objYesNo) {
        // if yes No object exists

        if (objYesNo.childNodes.length == 0 || !mobjContent.all) {
            // if the object is empty then populate using appenchild
            spanENo.innerHTML = R_nobutton_title;
            objNoA.appendChild(spanENo);
            objYesNo.appendChild(objNoA);
            var objTextNode = document.createTextNode("  ");
            objYesNo.appendChild(objTextNode);

            spanEYes.innerHTML = R_yesbutton_title;
            objYesA.appendChild(spanEYes);
            objYesNo.appendChild(objYesA);
            yesnobr = document.createElement("P");
            yesnobr.innerHTML = "&nbsp;";
            objYesNo.appendChild(yesnobr);
        }
    }
}

function YesOnClick() {
    HLink(11);
}

function YesOnMouseOver() {
    HLink(111);
}

function YesOnMouseOut() {
    HLink(110);
}

function NoOnClick() {
    HLink(12);
}

function NoOnMouseOver() {
    HLink(121);
}

function NoOnMouseOut() {
    HLink(120);
}

function DTOnClick() {
    HLink(13);
}

function DTOnMouseOver() {
    HLink(131);
}

function DTOnMouseOut() {
    HLink(130);
}

JSBubbleInterface.prototype.SetAlternative = function (bShow, bEnabled) {
    this.m_ShowAction = bShow;
    this.EnabledAction = bEnabled;
}

JSBubbleInterface.prototype.AddInfoBlock = function (bitmapname, urltext, tooltip) {
    //if(abubbv02_show==true)
    {
        var EncodedTooltip = fixHTMLString(tooltip)
        abubbv02_infos += "<td width='25' border='0'><a target='_blank' href='" + urltext + "'><img src='" + bitmapname + "' width='22' height='22' border='0' alt='" + EncodedTooltip + "'></img></a></td>";
    }
}

var kmbdefpos = false;
var FirstBubble = true;

JSBubbleInterface.prototype.HandleRepos = function () {
    try {
        var sScreen = getDIV("screen");
        var sx = sScreen.offsetLeft;
        var sy = sScreen.offsetTop;
        var xdiff = m_scrOffLeft - sx;
        var ydiff = m_scrOffTop - sy;
        if (xdiff != 0) {
            mobjContent.style.left = Number(getObjLeft(mobjContent) - xdiff) + "px";
            mobjContent.style.top = Number(getObjTop(mobjContent) - ydiff) + "px";
            mobjBubble.style.left = Number(getObjLeft(mobjBubble) - xdiff) + "px";
            mobjBubble.style.top = Number(getObjTop(mobjBubble) - ydiff) + "px";
            if (mobjPointer) {
                mobjPointer.style.left = Number(getObjLeft(mobjPointer) - xdiff) + "px";
                mobjPointer.style.top = Number(getObjTop(mobjPointer) - ydiff) + "px";
            }
        }
        m_scrOffLeft = sScreen.offsetLeft;
        m_scrOffTop = sScreen.offsetTop;
    }
    catch (e) { };
}

JSBubbleInterface.prototype.GetBubbleLeft = function (full) {
    if (!full)
        return getObjLeft(mobjBubble);
    switch (m_PointerDirection) {
        case BUBB07_LEFTTOP:
        case BUBB07_LEFTBOTTOM:
            return getObjLeft(mobjPointer)
        default:
            return getObjLeft(mobjBubble);
    }
}

JSBubbleInterface.prototype.GetBubbleTop = function (full) {
    if (!full)
        return getObjTop(mobjBubble);
    switch (m_PointerDirection) {

        case BUBB07_TOPLEFT:
        case BUBB07_TOPRIGHT:
            return getObjTop(mobjPointer)
        default:
            return getObjTop(mobjBubble);
    }
}

JSBubbleInterface.prototype.GetBubbleWidth = function (full) {
    if (!full)
        return getClientWidth(mobjBubble);
    switch (m_PointerDirection) {
        case BUBB07_LEFTTOP:
        case BUBB07_RIGHTTOP:
        case BUBB07_LEFTBOTTOM:
        case BUBB07_RIGHTBOTTOM:
            return getClientWidth(mobjBubble) + getClientWidth(mobjPointer);
        default:
            return getClientWidth(mobjBubble);
    }
}

JSBubbleInterface.prototype.GetBubbleHeight = function (full) {
    if (!full)
        return getClientHeight(mobjBubble);
    switch (m_PointerDirection) {
        case BUBB07_TOPLEFT:
        case BUBB07_TOPRIGHT:
        case BUBB07_BOTTOMLEFT:
        case BUBB07_BOTTOMRIGHT:
            return getClientHeight(mobjBubble) + getClientHeight(mobjPointer);
        default:
            return getClientHeight(mobjBubble);
    }
}

JSBubbleInterface.prototype.GetBubblePointer = function () {
    return m_PointerDirection;
}

function SavedPosition(left, top, right, bottom, pointed, pointerDirection, pointerXpos, pointerYpos, bwidth, bheight) {
    this.left = left;
    this.top = top;
    this.right = right;
    this.bottom = bottom;
    this.pointed = pointed;
    this.pointerDirection = pointerDirection;
    this.pointerXpos = pointerXpos;
    this.pointerYpos = pointerYpos;
    this.bwidth = bwidth;
    this.bheight = bheight;
}

JSBubbleInterface.prototype.RefreshPosition = function () {
    if (this.savedPos == null)
        return;
    if (this.IsVisible() == false)
        return;
    this.SetPosition(this.savedPos.left, this.savedPos.top, this.savedPos.right, this.savedPos.bottom, this.savedPos.pointed, this.savedPos.pointerDirection, this.savedPos.pointerXpos, this.savedPos.pointerYpos, this.savedPos.bwidth, this.savedPos.bheight);
    this.Show();
}


JSBubbleInterface.prototype.SetPosition = function (left, top, right, bottom, pointed, pointerDirection, pointerXpos, pointerYpos, bwidth, bheight) {

    this.savedPos = new SavedPosition(left, top, right, bottom, pointed, pointerDirection, pointerXpos, pointerYpos, bwidth, bheight);

    // +++ check & set knowit mode move default position flag 
    //mobjContent = document.all["content"];
    mobjContent = document.getElementById('content');
    this.Hide();
    this.ShowText();
    this.RefreshBubble();


    //	kmbdefpos=false;
    if (m_rect.m_Left == -1 && this.m_bMoveDefPos) kmbdefpos = true;
    if (FirstBubble) {
        this.m_bMoveDefPos = true;
        FirstBubble = false;
    }

    m_rect.m_Left = left;
    m_rect.m_Top = top;
    m_rect.m_Right = right;
    m_rect.m_Bottom = bottom;

    m_Pointed = pointed;
    m_PointerDirection = pointerDirection;
    m_PointerXpos = pointerXpos;
    m_PointerYpos = pointerYpos;
    m_bWidth = bwidth;
    m_bHeight = bheight;

    mblnShowPointer = m_Pointed;

    RepositionBubble(this);
    this.ShowMode();
    //	alert(pointerXpos + " X,W " + bwidth);

}

function RepositionBubble(thisItem) {

    // Note that we should probably incorperate
    // the screen object (infoblocks) in the interface as well.

    // set dimensions of hotspot location
    thisItem.SetEnableCloseButton(abubbv02_enableclose);

    var right = m_rect.m_Right;
    var left = m_rect.m_Left;
    var bottom = m_rect.m_Bottom;
    var top = m_rect.m_Top;
    var pointed = m_Pointed;

    var contentLeft = 0;
    var contentTop = 0;

    // width and height of hotspot location
    var _w = right - left;
    var _h = bottom - top;

    var addwidth = 0;

    var sScreen = getDIV("screen");
    if (m_bWidth > sScreen.style.pixelWidth) m_bWidth = sScreen.style.pixelWidth;
    var sx = sScreen.offsetLeft;
    var sy = sScreen.offsetTop;
    m_scrOffLeft = sScreen.offsetLeft;
    m_scrOffTop = sScreen.offsetTop;

    // if hotspot width is less that 40 and greater that 0 then added width is half of 
    // hotspot width, otherwise add width is 20	
    if (_w < 40 & _w > 0) addwidth = (_w) / 2;
    else addwidth = 20;

    if (abubbv02_show == true) {
        var cw = document.body.clientWidth; // client width
        var ch = document.body.clientHeight; // client height
        var w = mobjContent.clientWidth; 	// bubble width
        var h = mobjContent.clientHeight; 	// bubble height
        var x, y;
        var st01, st02;

        x = right + w;
        y = bottom + h;

        var right_over = false;
        var left_over = false;
        var top_over = false;
        var bottom_over = false;

        //alert("bubborék valós1 = "+m_Object.style.pixelLeft+","+m_Object.style.pixelTop+",");

        if (setpos) {
            //			thisItem.m_knrect.left=mobjContent.style.pixelLeft;
            //			thisItem.m_knrect.top=mobjContent.style.pixelTop;

            thisItem.m_knrect.left = getObjLeft(mobjContent);
            thisItem.m_knrect.top = getObjTop(mobjContent);
        }
        if (left == -1 && pointed && m_PointerDirection == 0) {
            //			thisItem.m_knrect.left=_ax;//m_Object.style.pixelLeft;
            //			thisItem.m_knrect.top=_ay;//m_Object.style.pixelTop;
            //alert("bubborék valós0 = "+this.m_knrect.left+","+this.m_knrect.top+",");
            setpos = false;

        }
        if (!pointed) {
            if (m_bWidth) setpos = false;
            else setpos = true;
            if (thisItem.m_knrect.left) {
                //alert("bubborék valós2 = "+this.m_knrect.left+","+this.m_knrect.top+",");
                //mobjContent.style.pixelLeft=thisItem.m_knrect.left;
                //mobjContent.style.pixelTop=thisItem.m_knrect.top;

                mobjContent.style.left = thisItem.m_knrect.left + "px";
                mobjContent.style.top = thisItem.m_knrect.top + "px";
            }
        }
        if (pointed) {
            setpos = false;
            if (mobjContent && m_PointerDirection > 0) {
                abubbv02_Pointer = m_PointerDirection;

                mobjContent.style.pixelWidth = m_bWidth - 28;
                mobjContent.style.pixelHeight = m_bHeight - 41;
                if (m_bWidth) mobjContent.style.width = (m_bWidth - 28) + 'px';
                mobjContent.style.height = '';
                if (!thisItem.m_bFFClearHeight && mobjContent.clientHeight < (m_bHeight - 41)) mobjContent.style.height = (m_bHeight - 41) + 'px';

                var pointerdir = 0;
                var inScreen = false;
                while (!inScreen) {
                    if (abubbv02_Pointer == BUBB07_TOPLEFT) {
                        //alert("TopLeft");

                        GetBubble("bubbTLp", abubbv02_bubbcolor);
                        contentLeft = sx + m_PointerXpos - 4;
                        contentTop = sy + m_PointerYpos;
                        // place the pointer

                        //						mobjPointer.style.pixelTop = contentTop;
                        //						mobjPointer.style.pixelLeft = contentLeft;

                        mobjPointer.style.left = contentLeft + "px";
                        mobjPointer.style.top = contentTop + "px";

                        // place the bubble over top of pointer

                        //						mobjBubble.style.pixelLeft = contentLeft - leftPadding;
                        //						mobjBubble.style.pixelTop=contentTop + 38;

                        mobjBubble.style.left = Number(contentLeft - leftPadding) + "px";
                        mobjBubble.style.top = Number(contentTop + 38) + "px";

                        // place the content in the bubble

                        //						mobjContent.style.pixelLeft = contentLeft;
                        //						mobjContent.style.pixelTop = contentTop + 37 + topPadding;

                        mobjContent.style.left = contentLeft + "px";
                        mobjContent.style.top = Number(contentTop + 37 + topPadding) + "px";

                        mobjBubble.style.zIndex = 2
                        mobjContent.style.zIndex = 3
                        mobjPointer.style.zIndex = 4
                    }

                    if (abubbv02_Pointer == BUBB07_TOPRIGHT) {
                        //alert("TopRight");

                        GetBubble("bubbTRp", abubbv02_bubbcolor);
                        contentLeft = sx + m_PointerXpos - 10;
                        contentTop = sy + m_PointerYpos;
                        // place the pointer

                        //						mobjPointer.style.pixelTop = contentTop;
                        //						mobjPointer.style.pixelLeft = contentLeft - 5;

                        mobjPointer.style.left = Number(contentLeft - 5) + "px";
                        mobjPointer.style.top = contentTop + "px";

                        // place the bubble over top of pointer

                        //						mobjBubble.style.pixelLeft = (contentLeft+ leftPadding + rightPadding) - mobjBubble.clientWidth;
                        //						mobjBubble.style.pixelTop=contentTop + 38;

                        mobjBubble.style.left = Number((contentLeft + leftPadding + rightPadding) - mobjBubble.clientWidth) + "px";
                        mobjBubble.style.top = Number(contentTop + 38) + "px";

                        // place the content in the bubble

                        //						mobjContent.style.pixelLeft = (contentLeft+ leftPadding + rightPadding) - mobjBubble.clientWidth + leftPadding;
                        //						mobjContent.style.pixelTop = contentTop + 37 + topPadding;

                        mobjContent.style.left = Number((contentLeft + leftPadding + rightPadding) - mobjBubble.clientWidth + leftPadding) + "px";
                        mobjContent.style.top = Number(contentTop + 37 + topPadding) + "px";

                        mobjBubble.style.zIndex = 2;
                        mobjContent.style.zIndex = 3;
                        mobjPointer.style.zIndex = 4;
                    }

                    if (abubbv02_Pointer == BUBB07_BOTTOMRIGHT) {
                        //alert("BottomRight");
                        GetBubble("bubbBRp", abubbv02_bubbcolor);
                        contentLeft = sx + m_PointerXpos - 10;
                        contentTop = sy + m_PointerYpos - 41;
                        //contentTop = top-41;
                        // place the pointer

                        //						mobjPointer.style.pixelTop = contentTop;
                        //						mobjPointer.style.pixelLeft = contentLeft - 5;

                        mobjPointer.style.left = Number(contentLeft - 5) + "px";
                        mobjPointer.style.top = contentTop + "px";

                        // place the bubble over top of pointer

                        //						mobjBubble.style.pixelLeft = (contentLeft+ leftPadding + rightPadding) - mobjBubble.clientWidth;
                        //						mobjBubble.style.pixelTop=contentTop - mobjBubble.clientHeight + 3;

                        mobjBubble.style.left = Number((contentLeft + leftPadding + rightPadding) - mobjBubble.clientWidth) + "px";
                        mobjBubble.style.top = Number(contentTop - mobjBubble.clientHeight + 3) + "px";

                        // place the content in the bubble

                        //						mobjContent.style.pixelLeft = (contentLeft+ leftPadding + rightPadding) - mobjBubble.clientWidth + leftPadding;
                        //						mobjContent.style.pixelTop = contentTop - mobjBubble.clientHeight + 2 + topPadding;

                        mobjContent.style.left = Number((contentLeft + leftPadding + rightPadding) - mobjBubble.clientWidth + leftPadding) + "px";
                        mobjContent.style.top = Number(contentTop - mobjBubble.clientHeight + 2 + topPadding) + "px";

                        mobjBubble.style.zIndex = 2;
                        mobjContent.style.zIndex = 3;
                        mobjPointer.style.zIndex = 4;
                    }

                    if (abubbv02_Pointer == BUBB07_BOTTOMLEFT) {
                        //alert("BottomRight");
                        GetBubble("bubbBLp", abubbv02_bubbcolor);
                        contentLeft = sx + m_PointerXpos - 4;
                        contentTop = sy + m_PointerYpos - 41;
                        //alert("h=" + h + "\nObject Height = " + m_Object.clientHeight);
                        //contentTop = top - 41;

                        //						mobjPointer.style.pixelTop = contentTop;
                        //						mobjPointer.style.pixelLeft = contentLeft;

                        mobjPointer.style.left = contentLeft + "px";
                        mobjPointer.style.top = contentTop + "px";

                        // place the bubble over top of pointer

                        //						mobjBubble.style.pixelLeft = contentLeft - leftPadding;
                        //						mobjBubble.style.pixelTop=contentTop - mobjBubble.clientHeight + 3;

                        mobjBubble.style.left = Number(contentLeft - leftPadding) + "px";
                        mobjBubble.style.top = Number(contentTop - mobjBubble.clientHeight + 3) + "px";

                        // place the content in the bubble

                        //						mobjContent.style.pixelLeft = contentLeft;
                        //						mobjContent.style.pixelTop = contentTop - mobjBubble.clientHeight + 2 + topPadding;

                        mobjContent.style.left = contentLeft + "px";
                        mobjContent.style.top = Number(contentTop - mobjBubble.clientHeight + 2 + topPadding) + "px";

                        mobjBubble.style.zIndex = 2;
                        mobjContent.style.zIndex = 3;
                        mobjPointer.style.zIndex = 4;
                    }

                    if (abubbv02_Pointer == BUBB07_LEFTTOP) {
                        //alert("TopLeft");

                        GetBubble("bubbLTp", abubbv02_bubbcolor);
                        contentLeft = sx + m_PointerXpos;
                        contentTop = sy + m_PointerYpos - 3;
                        // place the pointer

                        //						mobjPointer.style.pixelTop = contentTop;
                        //						mobjPointer.style.pixelLeft = contentLeft;

                        mobjPointer.style.left = contentLeft + "px";
                        mobjPointer.style.top = contentTop + "px";

                        // place the bubble over top of pointer

                        //						mobjBubble.style.pixelLeft = contentLeft - leftPadding + 52;
                        //						mobjBubble.style.pixelTop=contentTop - 15;

                        mobjBubble.style.left = Number(contentLeft - leftPadding + 52) + "px";
                        mobjBubble.style.top = Number(contentTop - 15) + "px";

                        // place the content in the bubble

                        //						mobjContent.style.pixelLeft = contentLeft + 52;
                        //						mobjContent.style.pixelTop = contentTop + topPadding - 16;

                        mobjContent.style.left = Number(contentLeft + 52) + "px";
                        mobjContent.style.top = Number(contentTop + topPadding - 16) + "px";

                        mobjBubble.style.zIndex = 2;
                        mobjContent.style.zIndex = 3;
                        mobjPointer.style.zIndex = 4;
                    }

                    if (abubbv02_Pointer == BUBB07_RIGHTTOP) {
                        //alert("TopRight");

                        GetBubble("bubbRTp", abubbv02_bubbcolor);
                        contentLeft = sx + m_PointerXpos - 41;
                        contentTop = sy + m_PointerYpos - 3;
                        // place the pointer

                        //						mobjPointer.style.pixelTop = contentTop;
                        //						mobjPointer.style.pixelLeft = contentLeft;

                        mobjPointer.style.left = contentLeft + "px";
                        mobjPointer.style.top = contentTop + "px";

                        // place the bubble over top of pointer

                        //						mobjBubble.style.pixelLeft = (contentLeft - leftPadding) - mobjBubble.clientWidth + 17;
                        //						mobjBubble.style.pixelTop=contentTop - 15;

                        mobjBubble.style.left = Number((contentLeft - leftPadding) - mobjBubble.clientWidth + 17) + "px";
                        mobjBubble.style.top = Number(contentTop - 15) + "px";

                        // place the content in the bubble

                        //						mobjContent.style.pixelLeft = (contentLeft - leftPadding) - mobjBubble.clientWidth + leftPadding + 17;
                        //						mobjContent.style.pixelTop = contentTop + topPadding - 16;

                        mobjContent.style.left = Number((contentLeft - leftPadding) - mobjBubble.clientWidth + leftPadding + 17) + "px";
                        mobjContent.style.top = Number(contentTop + topPadding - 16) + "px";

                        mobjBubble.style.zIndex = 2;
                        mobjContent.style.zIndex = 3;
                        mobjPointer.style.zIndex = 4;
                    }

                    if (abubbv02_Pointer == BUBB07_RIGHTBOTTOM) {
                        //alert("BottomRight");
                        GetBubble("bubbRBp", abubbv02_bubbcolor);
                        contentLeft = sx + m_PointerXpos - 41;
                        contentTop = sy + m_PointerYpos - 15;
                        // place the pointer

                        //						mobjPointer.style.pixelTop = contentTop;
                        //						mobjPointer.style.pixelLeft = contentLeft;

                        mobjPointer.style.left = contentLeft + "px";
                        mobjPointer.style.top = contentTop + "px";

                        // place the bubble over top of pointer

                        //						mobjBubble.style.pixelLeft = (contentLeft - leftPadding) - mobjBubble.clientWidth + 17;
                        //						mobjBubble.style.pixelTop=contentTop - mobjBubble.clientHeight + 33;

                        mobjBubble.style.left = Number((contentLeft - leftPadding) - mobjBubble.clientWidth + 17) + "px";
                        mobjBubble.style.top = Number(contentTop - mobjBubble.clientHeight + 33) + "px";

                        // place the content in the bubble

                        //						mobjContent.style.pixelLeft = (contentLeft - leftPadding) - mobjBubble.clientWidth + leftPadding + 17;
                        //						mobjContent.style.pixelTop = contentTop - mobjBubble.clientHeight + 32 + topPadding;

                        mobjContent.style.left = Number((contentLeft - leftPadding) - mobjBubble.clientWidth + leftPadding + 17) + "px";
                        mobjContent.style.top = Number(contentTop - mobjBubble.clientHeight + 32 + topPadding) + "px";

                        mobjBubble.style.zIndex = 2;
                        mobjContent.style.zIndex = 3;
                        mobjPointer.style.zIndex = 4;
                    }

                    if (abubbv02_Pointer == BUBB07_LEFTBOTTOM) {
                        //alert("BottomRight");
                        GetBubble("bubbLBp", abubbv02_bubbcolor);
                        contentLeft = sx + m_PointerXpos;
                        contentTop = sy + m_PointerYpos - 15;
                        //alert("h=" + h + "\nObject Height = " + m_Object.clientHeight);
                        //contentTop = top;

                        //						mobjPointer.style.pixelTop = contentTop;
                        //						mobjPointer.style.pixelLeft = contentLeft;

                        mobjPointer.style.left = contentLeft + "px";
                        mobjPointer.style.top = contentTop + "px";

                        // place the bubble over top of pointer

                        //						mobjBubble.style.pixelLeft = contentLeft - leftPadding + 52;
                        //						mobjBubble.style.pixelTop=contentTop - mobjBubble.clientHeight + 33;

                        mobjBubble.style.left = Number(contentLeft - leftPadding + 52) + "px";
                        mobjBubble.style.top = Number(contentTop - mobjBubble.clientHeight + 33) + "px";

                        // place the content in the bubble

                        //						mobjContent.style.pixelLeft = contentLeft + 52;
                        //						mobjContent.style.pixelTop = contentTop - mobjBubble.clientHeight + 32 + topPadding;

                        mobjContent.style.left = Number(contentLeft + 52) + "px";
                        mobjContent.style.top = Number(contentTop - mobjBubble.clientHeight + 32 + topPadding) + "px";

                        mobjBubble.style.zIndex = 2;
                        mobjContent.style.zIndex = 3;
                        mobjPointer.style.zIndex = 4;
                    }
                    if (abubbv02_Pointer == 9) {
                        //alert("BottomRight");
                        GetBubble("bubbLBp", abubbv02_bubbcolor);
                        m_PointerXpos = getUniWidth(sScreen) / 2;
                        m_PointerYpos = getUniHeight(sScreen) / 2;
                        contentLeft = sx + m_PointerXpos;
                        contentTop = sy + m_PointerYpos - 15;

                        mobjPointer.style.left = contentLeft + "px";
                        mobjPointer.style.top = contentTop + "px";


                        mobjBubble.style.left = Number(contentLeft - leftPadding + 52) + "px";
                        mobjBubble.style.top = Number(contentTop - mobjBubble.clientHeight + 33) + "px";


                        mobjContent.style.left = Number(contentLeft + 52) + "px";
                        mobjContent.style.top = Number(contentTop - mobjBubble.clientHeight + 32 + topPadding) + "px";

                        mobjBubble.style.zIndex = 2;
                        mobjContent.style.zIndex = 3;
                        mobjPointer.style.zIndex = 4;
                        pointed = false;

                    }
                    //					if(mobjBubble.style.pixelTop - sy < 0 || mobjBubble.style.pixelTop - sy + mobjBubble.clientHeight > sScreen.style.pixelHeight ||
                    //						mobjBubble.style.pixelLeft - sx < 0 ||  mobjBubble.style.pixelLeft - sx + mobjBubble.clientWidth > sScreen.style.pixelWidth)
                    if
					(
						getObjTop(mobjBubble) - sy < 0 ||
						getObjTop(mobjBubble) - sy + getClientHeight(mobjBubble) > getUniHeight(sScreen) ||
						getObjLeft(mobjBubble) - sx < 0 ||
						getObjLeft(mobjBubble) - sx + getClientWidth(mobjBubble) > getUniWidth(sScreen)
					) {
                        pointerdir++;
                        abubbv02_Pointer = pointerdir;
                        inScreen = false;
                        switch (abubbv02_Pointer) {
                            case 1:
                                m_PointerXpos = right - sx;
                                m_PointerYpos = top - sy;
                                break;
                            case 2:
                                m_PointerXpos = left - sx;
                                m_PointerYpos = top - sy;
                                break;
                            case 3:
                                m_PointerXpos = right - sx;
                                m_PointerYpos = bottom - sy;
                                break;
                            case 4:
                                m_PointerXpos = left - sx;
                                m_PointerYpos = bottom - sy;
                                break;
                            case 5:
                                m_PointerXpos = right - sx;
                                m_PointerYpos = top - sy;
                                break;
                            case 6:
                                m_PointerXpos = left - sx;
                                m_PointerYpos = top - sy;
                                break;
                            case 7:
                                m_PointerXpos = right - sx;
                                m_PointerYpos = bottom - sy;
                                break;
                            case 8:
                                m_PointerXpos = left - sx;
                                m_PointerYpos = bottom - sy;
                                break;
                            case 9:
                                //								abubbv02_Pointer = BUBB07_TOPLEFT;
                                m_PointerXpos = getUniWidth(sScreen) / 2;
                                m_PointerYpos = getUniHeight(sScreen) / 2;
                                pointed = false;
                                inScreen = true;
                                break;
                        }
                    }
                    else {
                        thisItem.m_bFFClearHeight = false;
                        inScreen = true;
                    }
                    m_PointerDirection = abubbv02_Pointer;
                    thisItem.lastbubbstyle = abubbv02_Pointer;
                }
            }
        }
        if (!pointed) {
            thisItem.m_bMoveDefPos = false;

            brect = new JSRect();

            //			brect.left = mobjContent.style.pixelLeft - leftPadding;
            //			brect.top = mobjContent.style.pixelTop - topPadding;
            //			brect.right = mobjContent.style.pixelLeft + w + rightPadding;
            //			brect.bottom = mobjContent.style.pixelTop + h + bottomPadding;

            brect.left = getObjLeft(mobjContent) - leftPadding;
            brect.top = getObjTop(mobjContent) - topPadding;
            brect.right = getObjLeft(mobjContent) + w + rightPadding;
            brect.bottom = getObjTop(mobjContent) + h + bottomPadding;

            if (m_bWidth) mobjContent.style.pixelWidth = m_bWidth - 28;
            mobjContent.style.pixelHeight = m_bHeight - 41;
            if (m_bWidth) mobjContent.style.width = (m_bWidth - 28) + 'px';
            mobjContent.style.height = '';
            if (!thisItem.m_bFFClearHeight && mobjContent.clientHeight < (m_bHeight - 41)) mobjContent.style.height = (m_bHeight - 41) + 'px';

            setBubbleWidthToNowrapElements('getNode:NOBR', 'size:maxWidth');

            if (m_PointerXpos != 0) {
                mobjContent.style.pixelWidth = m_bWidth - 28;
                mobjContent.style.pixelHeight = m_bHeight - 41;
                if (m_bWidth) mobjContent.style.width = (m_bWidth - 28) + 'px';
                mobjContent.style.height = '';
                if (!thisItem.m_bFFClearHeight && mobjContent.clientHeight < (m_bHeight - 41)) {
                    mobjContent.style.height = (m_bHeight - 41) + 'px';
                    thisItem.m_bFFClearHeight = false;
                }
            }

            GetBubble("bubbNp", abubbv02_bubbcolor);
            abubbv02_Pointer = BUBB07_NOPOINTER;

            contentLeft = sx + m_PointerXpos - (mobjBubble.clientWidth / 2);
            contentTop = sy + m_PointerYpos - (mobjBubble.clientHeight / 2);
            //-------------Bubble Out--------------------------------------------------
            if (m_PointerXpos == 0) {
                contentLeft = brect.left;
                contentTop = brect.top;
            }
            //-------------------------------------------------------------------------
            //contentLeft = brect.left;
            //contentTop = brect.top;
            // check bubble position
            if ((brect.right > cw) && (m_PointerXpos == 0)) {
                contentLeft = cw - mobjContent.clientWidth - 10 - leftPadding - rightPadding;
            }
            if ((brect.bottom > ch) && (m_PointerXpos == 0)) {
                contentTop = ch - mobjContent.clientHeight - 10 - topPadding - bottomPadding;
            }

            // +++ check default position flag
            if ((kmbdefpos) && (m_PointerXpos == 0)) {
                // +++ set deafult position
                contentLeft = (cw - mobjContent.clientWidth - 10 - leftPadding - rightPadding);
                contentTop = ((ch / 2) - mobjContent.clientHeight / 2) - topPadding - bottomPadding;
                // +++ actualize bubble position
                brect.left = contentLeft;
                brect.top = contentTop;
            }
            //alert('contentLeft='+contentLeft+'; sx='+sx);
            if (contentLeft - sx < 0) contentLeft = 0 + sx;
            if (contentLeft - sx + mobjBubble.clientWidth > getUniWidth(sScreen)) contentLeft = getUniWidth(sScreen) - mobjBubble.clientWidth + sx;
            if (contentTop - sy < 0) contentTop = 0 + sy;
            if (contentTop - sy + mobjBubble.clientHeight > getUniHeight(sScreen)) contentTop = getUniHeight(sScreen) - mobjBubble.clientHeight + sy;

            // place the bubble over top of pointer

            //			mobjBubble.style.pixelLeft = contentLeft;
            //			mobjBubble.style.pixelTop=contentTop;

            mobjBubble.style.left = contentLeft + "px";
            mobjBubble.style.top = contentTop + "px";

            // place the content in the bubble

            //			mobjContent.style.pixelLeft = contentLeft + leftPadding;
            //			mobjContent.style.pixelTop = contentTop + topPadding;

            mobjContent.style.left = Number(contentLeft + leftPadding) + "px";
            mobjContent.style.top = Number(contentTop + topPadding) + "px";

            mobjBubble.style.zIndex = 2
            mobjContent.style.zIndex = 3
            if
			(
				getObjTop(mobjBubble) < top &&
				getObjTop(mobjBubble) + getClientHeight(mobjBubble) > bottom &&
				getObjLeft(mobjBubble) < left &&
				getObjLeft(mobjBubble) + getClientWidth(mobjBubble) > right
			) {
                if (left > (cw - right)) {
                    contentLeft = left - getClientWidth(mobjBubble) - 10;
                    if (contentLeft - sx < 0) contentLeft = 0;
                }
                else {
                    contentLeft = right + 10;
                    if (contentLeft - sx + mobjBubble.clientWidth > getUniWidth(sScreen)) contentLeft = sx + getUniWidth(sScreen) - mobjBubble.clientWidth;
                }
                mobjBubble.style.left = contentLeft + "px";
                mobjContent.style.left = Number(contentLeft + leftPadding) + "px";
            }
        }

        if (mobjContent && left == -1 && right == -1 && top == -1 && bottom == -1 && pointed && m_PointerDirection == 0) {
            //			if(m_bWidth && m_PointerXpos > 0) mobjContent.style.width = m_bWidth - 28;
            //			if(m_bHeight && m_PointerXpos > 0) mobjContent.style.height = m_bHeight - 52;
            if (m_bWidth) mobjContent.style.pixelWidth = m_bWidth - 28;
            if (m_bHeight) mobjContent.style.pixelHeight = m_bHeight - 41;
            if (m_bWidth) mobjContent.style.width = (m_bWidth - 28) + 'px';
            mobjContent.style.height = '';
            if (!thisItem.m_bFFClearHeight && mobjContent.clientHeight < (m_bHeight - 41)) {
                mobjContent.style.height = (m_bHeight - 41) + 'px';
                thisItem.m_bFFClearHeight = false;
            }

            mobjContent.style.width = queryContentWidth()

            GetBubble("bubbNp", abubbv02_bubbcolor);
            abubbv02_Pointer = BUBB07_NOPOINTER;

            cw = IsTouchDevice() ? $(document.body).width() : document.body.clientWidth;
            ch = document.body.clientHeight;
            if (m_PointerXpos > 0 && m_PointerYpos > 0) {
                contentLeft = (sx + m_PointerXpos - mobjBubble.clientWidth / 2); //right;//-(right-left);
                contentTop = sy + m_PointerYpos - mobjBubble.clientHeight / 2;
            }
            else {
                contentLeft = ((cw / 2) - mobjBubble.clientWidth / 2); //right;//-(right-left);
                contentTop = (ch / 2) - mobjBubble.clientHeight / 2;
            }
            //if(abubbv02_Pointer!=BUBB07_NOPOINTER) 
            //{
            //this.SetColor(abubbv02_bubbcolor);
            //}

            if (contentLeft - sx < 0) contentLeft = 0 + sx;
            if (contentLeft - sx + mobjBubble.clientWidth > getUniWidth(sScreen)) contentLeft = getUniWidth(sScreen) - mobjBubble.clientWidth + sx;
            if (contentTop - sy < 0) contentTop = 0 + sy;
            if (contentTop - sy + mobjBubble.clientHeight > getUniHeight(sScreen)) contentTop = getUniHeight(sScreen) - mobjBubble.clientHeight + sy;

            //			mobjBubble.style.pixelLeft = contentLeft;
            //			mobjBubble.style.pixelTop = contentTop;

            mobjBubble.style.left = contentLeft + "px";
            mobjBubble.style.top = contentTop + "px";

            // place the content in the bubble

            //			mobjContent.style.pixelLeft = contentLeft + leftPadding;
            //			mobjContent.style.pixelTop = contentTop + topPadding;

            mobjContent.style.left = Number(contentLeft + leftPadding) + "px";
            mobjContent.style.top = Number(contentTop + topPadding) + "px";

            mobjBubble.style.zIndex = 2;
            mobjContent.style.zIndex = 3;
        }
    }
}

var imgCntr = 0;

function buildBubble(color) {

    var bubble = "";
    var bubID;

    var bubbc;
    bubbc = convert(String(color), 10, 16);
    while (bubbc.length < 6) bubbc = "0" + bubbc;
    bubbc = "#" + bubbc;

    bubID = "bubble_" + color;

    bubble += "<div id='" + bubID + "' name='" + bubID + "' style='position:absolute; left:100; top:100;zIndex:2;visibility:hidden'>";

    if (IsiOS())
        bubble += "<div style=' position: absolute; top:1px; z-index:-1; left:10px; background-color:" + bubbc + "; right: 10px; bottom: 1px;'></div>"

    bubble += "<table ID='BubbleTable' width='266' border='0' cellspacing='0' cellpadding='0'>";
    bubble += "<tr>"
    bubble += "<td valign='top'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[3] + "' width='14' height='27' border='0' alt=''></td>";
    bubble += "<td valign='top' bgcolor='" + (grayBubbles ? "#F4F2F1" : "#003166") + "' width='100%' background=" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[4] + ">";
    //	bubble += "<div style='position:absolute;'>";
    bubble += "<table border='0' cellspacing='0' cellpadding='0' height='27' width='100%'>";
    bubble += "<tr>"
    bubble += "<td id='bubb_cap' valign='" + (grayBubbles ? "center" : "bottom") + "' nowrap><a style='cursor:default' id='m_Caption' class='CurvedBoxText'></a></td>";
    bubble += "<td id='m_StaticCaption' valign='" + (grayBubbles ? "center" : "bottom") + "' width='100%' align='right'><div id='blink' style='white-space:nowrap; VISIBILITY: visible'><a id='m_ActionText' style='white-space:nowrap; cursor:pointer; text-decoration:underline;' onclick='setAOpener(event)' class='CurvedBoxNav'></a></div></td>";
    bubble += "<td>&nbsp;&nbsp;</td>";
    bubble += "</tr>";
    bubble += "<tr height='" + (grayBubbles ? "0" : "3") +"'>";
    bubble += "<td colspan='3'></td>";
    bubble += "</tr>";
    bubble += "</table>";
    //	bubble += "</div>";
    //	bubble += "<img src='"+imagesArr["c_" + abubbv02_bubbcolor].imageNames[4]+"' width='100%' height='27' border='0' alt=''>";
    bubble += "</td>";
    bubble += "<td valign='top'><div id='closebtn_" + color + "' style='position:relative'><div><img id='img2' name='img2' src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[1] + "' style='display:block' width='32' height='27' border='0'><img id='img2o' name='img2o' src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[2] + "' style='display:none' width='32' height='27' border='0'></div><div style='position:absolute; left:3px; top:7px'><a onclick='BubbleClose();return false'"
	 + (IsTouchDevice() ? "" : "onMouseMove='BubbleimgOn(\"img2\",\"img2o\")' onMouseOut='BubbleimgOff(\"img2\",\"img2o\")'")
	 + "><img alt='" + R_bubble_closeondemand + "' id='imghandler' name='imghandler' src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[0] + "' style='display:block' width='23' height='20' border='0'></a></div></div></td>";
    bubble += "</tr>";
    bubble += "<tr>";
    if (IsiOS()) {
        bubble += "<td> <img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[5] + "' style='height:100%; width: 14px'/></td>";
    }
    else {
        bubble += "<td style='background-image:url(" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[5] + ")'></td>";
    }
    bubble += "<td ID='BubbleSides' bgcolor='" + bubbc + "' height='116'>&nbsp;</td>";
    if (IsiOS()) {
        bubble += "<td> <img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[6] + "' style='height:100%; width: 32px'/></td>";
    }
    else {
        bubble += "<td style='background-image:url(" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[6] + ")'></td>";
    }
    bubble += "</tr>";
    bubble += "<tr>"
    bubble += "<td valign='top'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[7] + "' width='14' height='14' border='0' alt=''></td>";
    bubble += "<td valign='top' width='100%'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[8] + "' width='100%' height='14px'></td>";
    bubble += "<td valign='top'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[9] + "' width='32' height='14' border='0' alt=''></td>";
    bubble += "</tr>";
    bubble += "</table>"
    bubble += "</div>"

    document.write(bubble);

    //<!-- anchor upper left -->
    bubID = "ulPointer_" + color;
    ul = "<div id='" + bubID + "' name='" + bubID + "' style='position:absolute; left:114; top:62;zIndex:2;visibility:hidden' onMouseDown='AnchorMouseDown(); return false' onMouseUp='AnchorMouseUp(); return false'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[10] + "' width='18' height='41' border='0' alt=''></div>";
    //<!-- anchor upper right -->
    bubID = "urPointer_" + color;
    ur = "<div id='" + bubID + "' name='" + bubID + "' style='position:absolute; left:334; top:62;zIndex:2;visibility:hidden' onMouseDown='AnchorMouseDown(); return false' onMouseUp='AnchorMouseUp(); return false'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[11] + "' width='18' height='41' border='0' alt=''></div>";
    //<!-- anchor left high -->
    bubID = "lhPointer_" + color;
    lh = "<div id='" + bubID + "' name='" + bubID + "' style='position:absolute; left:62; top:114;zIndex:2;visibility:hidden' onMouseDown='AnchorMouseDown(); return false' onMouseUp='AnchorMouseUp(); return false'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[12] + "' width='41' height='18' border='0' alt=''></div>";
    //<!-- anchor left low -->
    bubID = "llPointer_" + color;
    ll = "<div id='" + bubID + "' name='" + bubID + "' style='position:absolute; left:62; top:225;zIndex:2;visibility:hidden' onMouseDown='AnchorMouseDown(); return false' onMouseUp='AnchorMouseUp(); return false'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[13] + "' width='41' height='18' border='0' alt=''></div>";
    //<!-- anchor right high -->
    bubID = "rhPointer_" + color;
    rh = "<div id='" + bubID + "' name='" + bubID + "' style='position:absolute; left:363; top:114;zIndex:2;visibility:hidden' onMouseDown='AnchorMouseDown(); return false' onMouseUp='AnchorMouseUp(); return false'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[14] + "' width='41' height='18' border='0' alt=''></div>";
    //<!-- anchor right low -->
    bubID = "rlPointer_" + color;
    rl = "<div id='" + bubID + "' name='" + bubID + "' style='position:absolute; left:363; top:225;zIndex:2;visibility:hidden' onMouseDown='AnchorMouseDown(); return false' onMouseUp='AnchorMouseUp(); return false'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[15] + "' width='41' height='18' border='0' alt=''></div>";
    //<!-- anchor lower left -->
    bubID = "btPointer_" + color;
    bt = "<div id='" + bubID + "' name='" + bubID + "' style='position:absolute; left:114; top:254;zIndex:2;visibility:hidden' onMouseDown='AnchorMouseDown(); return false' onMouseUp='AnchorMouseUp(); return false'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[16] + "' width='18' height='41' border='0' alt=''></div>";
    //<!-- anchor lower right -->
    bubID = "brPointer_" + color;
    br = "<div id='" + bubID + "' name='" + bubID + "' style='position:absolute; left:334; top:254;zIndex:2;visibility:hidden' onMouseDown='AnchorMouseDown(); return false' onMouseUp='AnchorMouseUp(); return false'><img src='" + imagesArr["c_" + abubbv02_bubbcolor].imageNames[17] + "' width='18' height='41' border='0' alt=''></div>";

    document.write(ul);
    document.write(ur);
    document.write(lh);
    document.write(ll);
    document.write(rh);
    document.write(rl);
    document.write(bt);
    document.write(br);

}

function LoadAllBubbles() {
    for (var c = 0; c < imagesXref.length; c++) {
        var color = imagesArr[imagesXref[c]].color;
        abubbv02_bubbcolor = color;
        buildBubble(color);
    }

    document.write("<div id='content' name='content' style='position:absolute; left:114; top:138;zIndex:10;visibility:hidden'></div>");

    objDoneTypingA = document.createElement("SPAN");
    objDoneTypingA.id = "bbdta";
    objDoneTypingA.onclick = function () { document.getElementById("bbdt0").className = 'button'; DTOnClick(); };
    objDoneTypingA.style.position = "absolute";
    objDoneTypingA.style.right = 0;
    objDoneTypingA.style.marginTop = "16px";

    objDoneTypingImg0 = document.createElement("A");
    objDoneTypingImg0.id = "bbdt0";
    objDoneTypingImg0.className = "button";
    objDoneTypingImg0.onmousemove = function () { this.className = 'buttonhover'; };
    objDoneTypingImg0.onmouseout = function () { this.className = 'button'; };
    objDoneTypingImg0.style.display = "block";

    spanE = document.createElement("SPAN");
    spanE.innerHTML = R_tcbutton_title;
    if (R_tcbutton_title.length >= 18) {
        objDoneTypingImg0.style.letterSpacing = "-1px";
        objDoneTypingImg0.style.font = "bold 7pt Arial";
    }

    if (playMode == "K") {
        // know it needs to have additional images

        // icon imape
        objIcon02Img = document.createElement("img");
        objIcon02Img.src = m_BubblePath + template_knowit_icon02;

        spanEYes = document.createElement("SPAN");
        spanEYes.innerHTML = R_yesbutton_title;
        spanEYes.onclick = function () { document.getElementById("bbyesa").className = 'button' };

        spanENo = document.createElement("SPAN");
        spanENo.innerHTML = R_nobutton_title;
        spanENo.onclick = function () { document.getElementById("bbnoa").className = 'button' };

        // yes button images	
        objYesA = document.createElement("A");
        objYesA.id = "bbyesa";
        objYesA.className = "button";
        objYesA.onmousemove = function () { this.className = 'buttonhover'; };
        objYesA.onmouseout = function () { this.className = 'button'; };
        objYesA.onclick = YesOnClick;
        objYesA.style.styleFloat = "right";
        objYesA.style.cssFloat = "right";

        // no button images	
        objNoA = document.createElement("A");
        objNoA.id = "bbnoa";
        objNoA.className = "button";
        objNoA.onmousemove = function () { this.className = 'buttonhover'; };
        objNoA.onmouseout = function () { this.className = 'button'; };
        objNoA.style.styleFloat = "right";
        objNoA.style.cssFloat = "right";
        objNoA.onclick = NoOnClick;
    }
}

function GetBubble(type, color) {
    //mobjBubble = document.all["bubble_" + color];
    mobjBubble = document.getElementById('bubble_' + color);
    //mobjBubble = document.getElementById('bubble_16777152');
    if (mblnShowPointer) {
        mblnShowPointer = true;
        switch (type) {
            case "bubbTLp":
                mobjPointer = document.getElementById("ulPointer_" + color);
                break;
            case "bubbTRp":
                mobjPointer = document.getElementById("urPointer_" + color);
                break;
            case "bubbBLp":
                mobjPointer = document.getElementById("btPointer_" + color);
                break;
            case "bubbBRp":
                mobjPointer = document.getElementById("brPointer_" + color);
                break;
            case "bubbLTp":
                mobjPointer = document.getElementById("lhPointer_" + color);
                break;
            case "bubbRTp":
                mobjPointer = document.getElementById("rhPointer_" + color);
                break;
            case "bubbLBp":
                mobjPointer = document.getElementById("llPointer_" + color);
                break;
            case "bubbRBp":
                mobjPointer = document.getElementById("rlPointer_" + color);
                break;
            case "bubbNp":
                mblnShowPointer = false;
        }
    }
    //mobjContent.style.backgroundColor = color;
    //mobjBubble.style.backgroundColor = color;

    //alert(mobjBubble.all["BubbleSides"]);
    //mobjBubble.all["BubbleSides"].height = mobjContent.clientHeight + topPadding + bottomPadding;
    //mobjBubble.all["BubbleSides"].height = mobjContent.clientHeight //+ bottomPadding;
    //document.getElementById('BubbleSides').height = mobjContent.clientHeight //+ bottomPadding;
    var cBS = getElementsByAttribute('id', 'BubbleSides');
    for (var i in cBS) {
        cBS[i].height = mobjContent.clientHeight;
    };

    //mobjBubble.all["BubbleTable"].width = mobjContent.clientWidth + leftPadding + rightPadding;
    //document.getElementById('BubbleTable').width = mobjContent.clientWidth + leftPadding + rightPadding;
    var cBT = getElementsByAttribute('id', 'BubbleTable');
    for (var i in cBT) {
        cBT[i].width = mobjContent.clientWidth + leftPadding + rightPadding;
    };

    load_buttons();
}

function setBubbleWidthToNowrapElements(getNode, getBy) {
    try {
        var getNode = getNode.split(':')[1];
        var cParts = mobjContent.getElementsByTagName('*');
        var KCmaxWidth = 0;

        //get left
        for (var i = 0; i < cParts.length; i++) {
            if (cParts[i].nodeName == getNode) {
                var nodeLeft = cParts[i].offsetLeft;
                break;
            }
        }

        //get by size
        if (getBy.indexOf('size') != -1) {
            for (var i = 0; i < cParts.length; i++) {
                if (cParts[i].nodeName == getNode) {
                    if (cParts[i].offsetWidth > KCmaxWidth) {
                        KCmaxWidth = cParts[i].offsetWidth;
                    }
                }
            }
            if (KCmaxWidth + nodeLeft > mobjContent.clientWidth) mobjContent.style.width = KCmaxWidth + nodeLeft + 'px';
        }

        //get by id
        if (getBy.indexOf('id') != -1) {
            var nodeId = getBy.split(':')[1];
            for (var i = 0; i < cParts.length; i++) {
                if (cParts[i].id == nodeId) {
                    mobjContent.style.width = cParts[i].offsetWidth + nodeLeft + 'px';
                    break;
                }
            }
        }
    } catch (e) { }
}

function queryContentWidth() {
    try {
        var cParts = mobjContent.getElementsByTagName('*');
        var KCmaxWidth = 0;

        //get left
        for (var i = 0; i < cParts.length; i++) {
            if (cParts[i].nodeName.toUpperCase() == 'P' || cParts[i].nodeName.toUpperCase() == 'NOBR' || cParts[i].nodeName.toUpperCase() == 'SPAN' || cParts[i].nodeName.toUpperCase() == 'DIV' || cParts[i].nodeName.toUpperCase() == 'TABLE') {
                var w = cParts[i].offsetWidth + cParts[i].offsetLeft;
                if (w > KCmaxWidth) KCmaxWidth = w;
            }
        }
        return KCmaxWidth;
    } catch (e) { }
}
/* menu.js */ 
/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

var popupMenu = 0;
showAttachments = false;
var fullength = 0;

function ActionMenu() {
    this.Open = _AOpen;
    this.Close = _AClose;
    this.Refresh = _ARefresh;
    this.IsOnScreen = _AIsOnScreen;
    this.PopupIsOpened = _APopupIsOpened;
    this.onScreen = false;
};


function setAOpener(e) {
    if (document.all) {
        popupOpener = event.srcElement;
    }
    else {
        event = e;
        popupOpener = event.target;
    }
    OnAction();
}

function _AOpen() {

    /*	IE FÜGGŐ HÍVÁS	

    if (!popupMenu)
    {
    popupMenu=createPopup();
    };
    */

    //HELYETTE DIV

    if (!popupMenu) {
        popupMenu = document.createElement('DIV');
        document.body.appendChild(popupMenu);
        myspan = document.createElement('SPAN');
        myspan.setAttribute("id", "_myspan_");
        myspan.setAttribute("style", "font:8pt Arial;");
        document.body.appendChild(myspan);
    };

    //LEKÉRDEZZÜK A NYITÓ POZÍCIÓJÁT
    nextNode = popupOpener;
    popupOpener.positionTop = 0;
    popupOpener.positionLeft = 0;
    while (nextNode.nodeName != 'BODY') {
        popupOpener.positionTop += nextNode.offsetTop;
        popupOpener.positionLeft += nextNode.offsetLeft;
        nextNode = nextNode.parentNode;
    }

    popupOpenerHeight = popupOpener.offsetHeight;

    //BELŐJÜK A MENÜ POZÍCIÓJÁT	
    popupMenu.style.zIndex = 10000;
    popupMenu.style.position = "absolute";

    var _top_correction = (IsFF3() || IsFF4() || checkFFVersion(7) || checkFFVersion(8) ||
        checkFFVersion(9) || IsSafari() ? 16 : 0);

    if (IsIE10()) {
        _top_correction += 20;
    }

    popupMenu.style.top = (popupOpener.positionTop + popupOpenerHeight) - _top_correction - 6 + 'px';
    if (document.all) {
        popupMenu.style.left = (popupOpener.positionLeft - 65) + 'px';
        popupMenu.style.width = "140px";
    }
    else {
        popupMenu.style.left = (popupOpener.positionLeft - 80) + 'px';
        popupMenu.style.width = "125px";
    }

    //aPopBody = popupMenu.document.body;	NEM KELL

    //NEM KELLENEK A DOCUMENT.BODY -K, margin, helyett padding

    //EZ KAPCSOLJA BE A MENÜ MEGJELENÍTÉSÉT
    popupMenu.style.display = "block";
    popupMenu.className = "AMenu";

    popupMenu.style.borderStyle = "solid";
    popupMenu.style.borderWidth = "1px";
    popupMenu.style.borderColor = "gray";
    popupMenu.style.paddingTop = "8px";
    popupMenu.style.paddingBottom = "8px";
    popupMenu.style.paddingLeft = "8px";
    popupMenu.style.paddingRight = "8px";

    popupMenu.aLink = "0000FF";
    popupMenu.link = "0000FF";
    popupMenu.vLink = "0000FF";
    popupMenu.text = "black";

    //aPopBody.ondragstart = EventCancel ;
    //aPopBody.oncontextmenu = EventCancel ;

    this.onScreen = true;
};

function _APopupIsOpened() {
    if (popupMenu == 0) {
        return false;
    }
    return popupMenu.isOpen;
}

function _AClose() {
    //popupMenu.hide();
    window.setTimeout("popupMenuHide()", 200);
    this.onScreen = false;
};

function OnActionSelection(v1, v2) {
    //popupMenu.hide();
    this.onScreen = false;
    if (v1 == "Next") {
        OnMenuAlternative("TeacherForward(false)");
    };
    if (v1 == "Prev") {
        OnMenuAlternative("TeacherBack()");
    };
    if (v1 == "Start") {
        OnMenuAlternative("TeacherFastBack()");
    };
    if (v1 == "Alt") {
        OnMenuAlternative("TeacherAlter()");
    };
    if (v1 == "Conc") {
        OnMenuAlternative(concepts[v2].url,
							concepts[v2].width,
							concepts[v2].height,
							concepts[v2].infotype,
							concepts[v2].infokey);
    };
    if (v1 == "Info") {
        OnMenuAlternative(screens[showScreen].infoblocks[v2].simpleurl,
							screens[showScreen].infoblocks[v2].width,
							screens[showScreen].infoblocks[v2].height,
							screens[showScreen].infoblocks[v2].infotype,
							screens[showScreen].infoblocks[v2].infokey);
    };
    if (v1 == "Prefs") {
        OnMenuAlternative("OpenPreferences()");
    };
    if (v1 == "Help") {
        OnMenuAlternative("LaunchHelp()", "../../");
    };
    if (v1 == "LogOut") {
        OnMenuAlternative("LogOut()");
    };
    if (v1 == "CloseT") {
        OnClose();
    };
    if (v1 == "CloseW") {
        CloseAction();
    };
    if (v1 == "Resume") {
        OnMenuAlternative("Menu_Resume()");
    }
    if (v1 == "Printit") {
        OnMenuAlternative("ShowPrintit()");
    }
    if (v1 == "AskAnExpert") {
        OnMenuAlternative("AskAnExpert()");
    }
    if (v1 == "ProvideFeedback") {
        OnMenuAlternative("ProvideFeedback()");
    }
};


function CorrectPopup() {
    try {
        obj = binterf.GetActionLink();
        h = obj.offsetHeight;
        popupMenu.show(0, h, 0, 0, obj);
        sp = popupMenu.getElementById('actionspan');
        hsp = sp.offsetHeight;
        wsp = sp.offsetWidth;
        popupMenu.show(0, h, wsp + 20, hsp + 20, obj);
    } catch (e) { };
    this.onScreen = true;

}

function IsNotIE() {
    var bi = new BrowserInfo();
    GetBrowserInfo(bi);
    return bi.name != "MSIE";
}

function PopupToggle(div) {
    if (popupMenu.getElementsByTagName('DIV')[1].style.display == "none") {
        if (IsNotIE()) {
            if (fullength > 100)
                popupMenu.style.width = "" + (fullength + 40) + "px";
        }
        popupMenu.getElementsByTagName('DIV')[1].style.display = "block";
        showAttachments = true;
    }
    else {
        if (IsNotIE()) {
            popupMenu.style.width = "140px";
        }
        popupMenu.getElementsByTagName('DIV')[1].style.display = "none";
        showAttachments = true;
    }

    CorrectPopup();
};

/////////////////////////////////////////////////////////////////////////////////////////////////
//KPATH PORTAL SUPPORT

var _topLevelLmsMode = "";

function CheckKPTMode() {
    if (_topLevelLmsMode == "")
        _topLevelLmsMode = GetTopLevelLmsMode();
    return (_topLevelLmsMode == "KPT");
}

// lms_IsKPathPortalAvailable()
function lms_IsKPathPortalAvailable() {
    __alert("lms_IsKPathPortalAvailable() called");
    if (CheckKPTMode() == false)
        return false;
    if (parent.urlParser.GetParameter("launchFromKPath") == null)
        return "";
    return (lms_GetKPathPortalUrl().length > 0);
}

// lms_GetKPathPortalUrl()
function lms_GetKPathPortalUrl() {
    __alert("lms_GetKPathPortalUrl() called");
    if (Kpath_launch == false)
        return "";
    var s = "";
    try {
        s = Kpath_home_URL;
    }
    catch (e) { };
    return s;
}

function AskAnExpert() {
    var dpi = 96;
    var url = lms_GetMentoringUrl(parent.topicID)
    parent.showDialog(url, -1, -1, 500, 430, true, dpi, "../../../");
}

// 2011/09/20, Zsolt
function ProvideFeedback() {
    var dpi = 96;
    var url = lms_GetFeedbackUrl(parent.topicID)
    parent.showDialog(url, -1, -1, 500, 430, true, dpi, "../../../");
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// NOTES AND MENTORING SUPPORT

// lms_IsMentoringAvailable
function lms_IsMentoringAvailable() {
    __alert("lms_IsMentoringAvailable() called");
    return document.LmsCom.doGetUPKValue("upk.mentoring_available") && document.LmsCom.doGetUPKValue("upk.anonymous") == "0";
}

// lms_GetMentoringUrl
function lms_GetMentoringUrl() {
    __alert("lms_GetMentoringUrl() called");
    // _feedbackUrlArgs in lms_topic.js
    return Kpath_base_URL + "/Mentoring/NewMentQuest.aspx?Path=" +
        window.location.href.split("?")[0] + "&GUID=" + lms_store.cguid + "&FeedbackType=1" + _feedbackUrlArgs;
}

// lms_IsFeedbackAvailable
// 2011/09/20, Zsolt 
function lms_IsFeedbackAvailable() {
    __alert("lms_IsFeedbackAvailable() called");
    return document.LmsCom.doGetUPKValue("upk.feedback_available") && document.LmsCom.doGetUPKValue("upk.anonymous") == "0";
}

// lms_GetFeedbackUrl
// 2011/09/20, Zsolt 
function lms_GetFeedbackUrl() {
    __alert("lms_GetFeedbackUrl() called");
    // _feedbackUrlArgs in lms_topic.js
    return Kpath_base_URL + "/Mentoring/NewMentQuest.aspx?Path=" +
        window.location.href.split("?")[0] + "&GUID=" + lms_store.cguid + "&FeedbackType=2" + _feedbackUrlArgs;
}

function _ARefresh(next, prev, first, alt, changeconcept, changeinfo, frompref, printit) {
    if (!this.onScreen)
        return;

    var s = "";
    s += "<div id='actionspan' style='font:8pt Arial; width:100%;' nowrap=yes>";
    s += "<a href='#'></a>";
    if (playMode == "T") {
        if (next) {
            s += "<li><a href='#' onclick='OnActionSelection(\"Next\");return false;'>";
            s += R_menu_nextstep;
            s += "</a></li>";
        };
        if (prev) {
            s += "<li><a href='#' onclick='OnActionSelection(\"Prev\");return false;'>";
            s += R_menu_prevstep;
            s += "</a></li>";
        };
        if (first) {
            s += "<li><a href='#' onclick='OnActionSelection(\"Start\");return false;'>";
            s += R_menu_start;
            s += "</a></li>";
        };
        if (alt) {
            s += "<li><a href='#' onclick='OnActionSelection(\"Alt\");return false;'>";
            s += R_menu_alternatives;
            s += "</a></li>";
            popupMenu.style.width = "170px";
        };

        var i = 0;
        if (concepts.length > 0) {
            s += "<li>";
            s += "<a href='#' onclick='OnActionSelection(\"Conc\",\"0\");return false;'>";
            s += R_menu_concepts;
            s += "</a></li>";
        };

        if (screens[showScreen].infoblocks.length > 0) {
            s += "<li><a href='javascript:EmptyFunction()' onclick='PopupToggle(\"infodiv\")'>";
            s += R_menu_infoblocks;
            s += "</a></li>";
            s += "<div id='infodiv' style='display:none'>";
            if (IsNotIE()) {
                for (i = 0; i < screens[showScreen].infoblocks.length; i++) {
                    document.getElementById("_myspan_").innerHTML = fixHTMLString(screens[showScreen].infoblocks[i].tooltip);
                    var fw = document.getElementById("_myspan_").offsetWidth;
                    if (fullength < fw) {
                        fullength = fw;
                    }
                    document.getElementById("_myspan_").innerHTML = "";
                }
            }
            for (i = 0; i < screens[showScreen].infoblocks.length; i++) {
                if (IsNotIE())
                    s += "<li style='list-style-type:circle;text-indent:18px; width: " + (fullength + 40) + "px;'>";
                else
                    s += "<li style='list-style-type:circle;text-indent:18px; width: 140px;'>";
                s += "<a href='#' onclick='OnActionSelection(\"Info\",";
                s += "" + i;
                s += ");return false;'>";
                s += fixHTMLString(screens[showScreen].infoblocks[i].tooltip);
                s += "</a></li>";
            };
            s += "</div>";
        };
    };

    ///// works in seeit only

    if (playMode == "S") {
        s += "<li><a href='#' onclick='OnActionSelection(\"Resume\");return false;'>";
        s += R_interface_resume;
        s += "</a></li>";
    }

    if (playMode == "T" || playMode == "S") {
        if (printit) {
            s += "<li><a href='#' onclick='OnActionSelection(\"Printit\");return false;'>";
            s += R_interface_printit;
            s += "</a></li>";
        }
    }

    ///// works in tryit and knowit and seeit
    ///// AskAnExpert
    if (lms_IsMentoringAvailable() == true) {
        s += "<li><a href='#' onclick='OnActionSelection(\"AskAnExpert\");return false;'>";
        s += R_interface_askexpert;
        s += "</a></li>";
    }

    ///// ProvideFeedback
    if (lms_IsFeedbackAvailable() == true) {
        s += "<li><a href='#' onclick='OnActionSelection(\"ProvideFeedback\");return false;'>";
        s += R_interface_providefeedback;
        s += "</a></li>";
    }

    if (PlayerConfig.EnableCookies && UserPrefs.EnablePreferences) {
        s += "<li><a href='#' onclick='OnActionSelection(\"Prefs\");return false;'>";
        s += R_menu_preferences;
        s += "</a></li>";
    };

    if (UIComponents.TopicHelp == true && IsTouchDevice() == null) {
        s += "<li><a href='#' onclick='OnActionSelection(\"Help\");return false;'>";
        s += R_menu_help;
        s += "</a></li>";
    }

    try {
        if ((GetTopLevelLmsMode() == "KPT" || Kpath_launch == true) && lms_IsKPathLogoutAvailable()) {
            s += "<li><a href='#' onclick='OnActionSelection(\"LogOut\");return false;'>";
            s += R_toctooltip_kpathlogout;
            s += "</a></li>";
        }
    }
    catch (e) { }

    s += "<li><a href='#' onclick='OnActionSelection(\"CloseT\");return false;'>";
    s += R_menu_Close;
    s += "</a></li>";

    s += "</span>";


    //popupMenu.document.body.innerHTML=s;
    popupMenu.innerHTML = s;

    //    sH = document["screenshot"].clientHeight;
    sH = document.getElementsByTagName("body")[0].clientHeight + getScrollTop();
    if (popupMenu.offsetTop + popupMenu.clientHeight > sH) {
        popupMenu.style.top = "" + (sH - popupMenu.clientHeight) + "px";
    }

    //    sW = document["screenshot"].clientWidth;
    sW = document.getElementsByTagName("body")[0].clientWidth + getScrollLeft();
    if (popupMenu.offsetLeft + popupMenu.clientWidth > sW) {
        popupMenu.style.left = "" + (sW - popupMenu.clientWidth) + "px";
    }

    setTimeout('try{popupMenu.document.all["actfocus"].focus();}catch(e){};', 100);
    //	obj=document.all('screen');
    //	popupMenu.show(100,150,230,360,obj);

    CorrectPopup();
};

function popupMenuHide() {
    if (showAttachments == true) {
        showAttachments = false
        actionMenu.onScreen = true;
    }
    else {
        popupMenu.style.display = 'none';
    }
}

function _AIsOnScreen() {
    return this.onScreen;
};

function EmptyFunction() {
}/* query.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

// OnDemand query parser

datasourceroot = "querydb/";
ConvertDbSelector = { t: "text", u: "ctxod", e: "ctxex", r: "role", g: "genctx" };

var q_search_and = " and ";
var q_search_or = " or ";

function ToHalfWidth(str)
{
  var halfKatakanaSet = "ｦｧｨｩｪｫｬｭｮｯｰｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜﾝ";
  var fullKatakanaSet = "ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン";
  
  var result="";
  
  for (var i=0; i<str.length; i++)
  {
	var k = fullKatakanaSet.indexOf(str.charAt(i));
	if (k!=-1)
		result += halfKatakanaSet.charAt(k);
	else if (str.charCodeAt(i)>=0xff01 && str.charCodeAt(i)<=0xff5f)
		result += String.fromCharCode(str.charCodeAt(i)-0xfee0);
	else
		result += str.charAt(i);
  }
  
  return result;
}

var QueryParser = { 
	PS: null, // stack
	PT: [ 0,
//     e   (   )   &|  !  EOT q
	[  2,  3,  0,  0,  0,  0, 4 ],
	[ -1, -1, -1, -1,  5, -1, 0 ],
	[  2,  3,  0,  0,  0,  0, 6 ],
	[  0,  0,  0,  7,  0, 10, 0 ],
	[ -2, -2, -2, -2, -2, -2, 0 ],
	[  0,  0,  8,  7,  0,  0, 0 ],
	[  2,  3,  0,  0,  0,  0, 9 ],
	[ -4, -4, -4, -4, -4, -4, 0 ],
	[ -3, -3, -3, -3, -3, -3, 0 ]],

Parse: function(query_type, query_expression)
{
	if (window.R_search_AND)
		q_search_and = " " + R_search_AND.toLowerCase() + " ";
	if (window.R_search_OR)
		q_search_or = " " + R_search_OR.toLowerCase() + " ";

	var lexer;
	var keyws;
	if ("URI" == query_type) {
		lexer = /\(|\)|\+|-|[u,e,k,r,g]|!|\d|'[^']+'/g;
		keyws = ["(",")","+","-","u","e","t","r","g","!","0","1","2","3","4","5","6","7","8","9"];
	} else {
		lexer = new RegExp('\\(|\\)|'+q_search_and+'|'+q_search_or+'|"[^"]+"|[^ \\(\\)]+(?=\\(|\\)|\\s|$)','gi'); //doesn't support db|!|\d
		keyws = ["(",")",q_search_and,q_search_or];
	}
	var codem = [1,2,3,3,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4];
	var semvm = [0,0,"&","|",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];


	if (query_type!='URI')
	{
		query_expression = ToHalfWidth(query_expression);
		query_expression = query_expression.toLowerCase();
	}
	
	this.ev = null;
	this.pr = null;
	this.PS = new Array()
	this.PS.push({st: 1, se: 0});
	
	var result;
	var i;
	var opm = 0; // operator missing
	var cdb = "t"; // current database
	while ((result = lexer.exec(query_expression)) != null) {
		var sem = result[0]; // semantic value
		var sym = 0; // symbol value
		for (i in keyws) {
			if (sem == keyws[i]) {
				sym = codem[i];
				if (semvm[i])
					sem = semvm[i];
				break;
			}
		}

		// lexical preprocessor
		// 1) implicit db settings
		// 2) implicit operator '&'
		if (sym == 5) { // db change is stored but not passed
			cdb = sem;
			continue;
		}
		if (sym == 3) // operator
			opm = 0;
		if ((sym == 0 || sym == 1) && opm) { 
			if (this.SM(3, "&")) // insert missing '&'
				return;
			opm = 0;
		}
		if (sym == 0) { // condition
			if (sem.charAt(0) == '"' || sem.charAt(0) == "'")
				sem = sem.slice(1, sem.length - 1);
			if ("URI" != query_type) 
			{
				// remove trailing % or *
				if (sem.length > 1) {
					var lc = sem[sem.length - 1];
					if (lc == '%' || lc == '*')
						sem = sem.slice(0, -1);
				}
				sem = Escape.MyEscape(sem.toLowerCase());
			}
			sem = cdb + sem;
			opm = 1;
		}
		if (this.SM(sym, sem))
			return;
	}
	if (!this.SM(5, "$")) {
		this.ev = this.PS[1].se.ev;
		this.pr = this.PS[1].se.pr;
	}
//	alert(this.ev + "\n" + this.pr);
},

SM: function(sym, sem)
{
//	alert(sym + ", " + sem);
	while (1) {
		var sp = this.PS[this.PS.length - 1];
		var ptv = this.PT[sp.st][sym];
		if (ptv == 10) {
//			alert("accept");
			return false;
		}
		if (ptv == 0) {
//			alert("error");
			return true; // error
		}
		if (ptv > 0) { // shift
			this.PS.push({st: ptv, se: sem});
			return false;
		}
		if (ptv < 0) {
			var nsem;
			var p = this.PS.length;
			var p1 = this.PS[p - 1];
			var p2 = this.PS[p - 2];
			var p3 = this.PS[p - 3];
			switch (-ptv) {
				case 1: 
					nsem = { 
					ev: "{a:'s', d:'" + p1.se.charAt(0) + "', p:'" + p1.se.slice(1) + "'}", 
					pr: p1.se.slice(1) }; 
					break;
				case 2:	
					if (p1.se == "!") {
						nsem = { ev: "{a:'s', d:'" + p2.se.charAt(0) + "', p:'" + p2.se.slice(1) + "', m:'" + p1.se + "'}" };
					} else {
						var ss = p2.se.slice(1, parseInt(p1.se) + 1) + "$002A";
						nsem = {
						ev: "{a:'s', d:'" + p2.se.charAt(0) + "', p:'" + p2.se.slice(1) +
						"'}, {a:'s', d:'" + p2.se.charAt(0) + "', p:'" + ss + 
						"'}, {a:'o', p:'|'}" };
					}
					nsem.pr = p2.se.slice(1);
					break;
				case 3: nsem = {
					ev: p3.se.ev + ", " + p1.se.ev + ", {a:'o', p:'" + p2.se + "'}",
					pr: p3.se.pr + (p2.se == "|" ? " or " : " ") + p1.se.pr };
					break;
				case 4: nsem = {
					ev: p2.se.ev,
					pr: "(" + p2.se.pr + ")" };	
					ptv = -3;
					break;
			}
			if (ptv == -1 || ptv == -2) {
				nsem.pr = decodeURIComponent(nsem.pr);
				if (nsem.pr.search(/\s/) != -1)
					nsem.pr = '"' + nsem.pr + '"';
			}
			this.PS.length += ptv;
			this.PS.push({st: this.PT[this.PS[this.PS.length - 1].st][6], se: nsem});
		}
	}
},

o: function(op, op1, op2)
{
	debug.insertAdjacentHTML("beforeEnd", "<div>" + op + ", " + op1 + ", " + op2 + "</div>");
	return op1 + op + op2;
},

e: function(db, se, st)
{
	if (!st)
		st = "";
	se = decodeURIComponent(se);
	debug.insertAdjacentHTML("beforeEnd", "<div>" + db + ", " + se + ", " + st + "</div>");
	
	return db + "=" + se + st;
}
};

var QueryProcessor = {
	rr: null,
Start: function(q, r)
{
	this.rr = r;
	eval("this.qa = [" + q + "]");
	this.qp = 0;
	this.Eval();
},

Eval: function()
{
	var n = this.qa[this.qp];
	if (n.a == "s") {
		var m = n.d == "t" ? false : true;
		if (n.m == "!")
			m = !m;
		SearchDBs[n.d].Search(decodeURIComponent(n.p), m);
	} else if (n.a == "o") {
		if (n.p == "&")
			this.qa[this.qp - 2].And(this.qa[this.qp - 1]);
		else
			this.qa[this.qp - 2].Or(this.qa[this.qp - 1]);
		this.qp -= 2;
		this.qa.splice(this.qp + 1, 2);
		this.Next();
	}
},

Next: function()
{
	if (this.qa.length == 1) {
		this.rr(this.qa[0].rs);
		return;
	}
	this.qp++;
	this.Eval();
},

ReportResult: function(r)
{
	this.qa[this.qp] = r;
	this.Next();
}
};

function ReadBase64_6(i)
{
	if (i == 43)
		return 62;
	if (i == 45)
		return 63;
	if (i < 58)
		return i - 48;
	if (i < 91)
		return i - 55;
	else
		return i - 61;
}

function ReadBase64_32(s)
{
	var i, j;
	j = 0;
	i = 0x20;
	while (i & 0x20) {
		i = ReadBase64_6(s.s.charCodeAt(s.p));
		j <<= 5;
		j |= (i & 0x1f);
		s.p++;
	}
	return j;
}

function ReadBase64_ITP(s, ctr)
{
	var r = new Array();
	var c, n, l = 0;
	while (s.p < s.s.length) {
		n = ReadBase64_32(s);
		c = 1 == n ? ReadBase64_32(s) : 1;
		while (c) {
			l += n;
			r.push(new ctr(l));
			c--;
		}
	}
	return r;
}

function SearchDB(dbid)
{
	this.db_id = dbid;
	this.ResetIndex();
	this.request_total = 0;
	this.request_count = 0;
}

SearchDB.prototype.ResetIndex = function()
{
	this.index = new Array();
	this.index.push({ key: null, node: "1" });
}

SearchDB.prototype.k = function(args)
{
	var prev = "";
	for (var i = 0; i < args.length; i++) {
		var s = { s: args[i], p: 0 };
		var l;
		var w = "";
		l = ReadBase64_32(s);
		var nk;
		nk = i == args.length - 1 ? this.index[this.index_insert_position]: new Object;
		nk.node = l > 0 ? s.s.slice(s.p, s.p + l): 0;
		s.p += l;
		l = ReadBase64_32(s);
		w += prev.slice(0, l);
		l = ReadBase64_32(s);
		w += s.s.slice(s.p, s.p + l);
		s.p += l;
		if (w.length > 0) {
			nk.key = w;
		}
		prev = w;
		while (s.p < s.s.length) {
			nk.values = new Array();
			l = ReadBase64_32(s);
			nk.values.push(s.s.slice(s.p, s.p + l));
			s.p += l;
		}
		if (i < args.length - 1) {
			this.index.splice(this.index_insert_position, 0, nk);
			this.index_insert_position++;
		}
	}
	this.d();
}

SearchDB.prototype.LoadScript = function(f)
{
	CDB=this;
	var dbPath = ConvertDbSelector[this.db_id];
//	setTimeout("jsdbfile.src='" + datasourceroot + dbPath + "/" + f + ".js'", 1);
	var s="SearchDBs."+this.db_id+".LoadScript_Callback";
	LoadXMLDocArray(datasourceroot+dbPath+"/"+f+".xml",s,"","N");
	this.request_total++;
	this.request_count++;
}

SearchDB.prototype.LoadScript_Callback = function(a)
{
	CDB=this;
	CDB.k(a);	
}

SearchDB.prototype.Search = function(s, m)
{
	this.RequestCount = 0;
	this.search = s;
	this.exact_match = m;
	this.results = new SearchResultSet();
	if (this.search.length == 0)
		return;
	this.index_match = 0;
	this.d = this.d1;
	this.d();
}

SearchDB.prototype.IndexSearch = function()
{
	var i;
	for (i = this.index_match; i < this.index.length; i++)
		if (null == this.index[i].key || this.search <= this.index[i].key)
			break;

	this.index_match = i;
}

SearchDB.prototype.d1 = function()
{
	this.IndexSearch();
	if (null != this.index[this.index_match].key && this.search == this.index[this.index_match].key) {
		if (!this.exact_match && this.index[this.index_match].values.length < 2) {
			this.d = this.d2;
			this.d();
		} else {
			var v = this.index[this.index_match].values;
			for (var j in v) {
				this.results.Or(new SearchResultSet(v[j]));
				if (this.exact_match)
					break;
			}			
			QueryProcessor.ReportResult(this.results);
		}
	} else {
		if (this.index[this.index_match].node != 0) {
			this.index_insert_position = this.index_match;
			this.LoadScript(this.index[this.index_match].node);
		} else {
			if (!this.exact_match) {
				this.d = this.d2;
				this.d();
			}
			else {
				QueryProcessor.ReportResult(this.results);
			}
		}
	}
}

SearchDB.prototype.d2 = function()
{
	if (null == this.index[this.index_match].key || (this.index[this.index_match].key.substring(0, this.search.length) != this.search && this.index[this.index_match].node == 0)) {
		QueryProcessor.ReportResult(this.results);
		return;
	}
	if (this.index[this.index_match].node == 0) {
		this.results.Or(new SearchResultSet(this.index[this.index_match].values[0]));
		this.index_match++;
		this.d2();
	} else {
		this.index_insert_position = this.index_match;
		this.LoadScript(this.index[this.index_match].node);
	} 
}

SearchDBs = { t: new SearchDB("t"), u: new SearchDB("u"), e: new SearchDB("e"), r: new SearchDB("r"), g: new SearchDB("g") };
CDB = null;

function SearchResult(index)
{
    this.index = index;
    this.weight = 1.0;
}

function SearchResultSet(s)
{
	if (s) {
		var ss = { s: s, p: 0 };
		this.rs = ReadBase64_ITP(ss, SearchResult);
	} else
		this.rs = new Array();
}

SearchResultSet.prototype.Or = function(srs)
{
    this.AOR(srs, true);
}

SearchResultSet.prototype.AOR = function(srs, or, weight)
{
	var i, j;
	for (i = 0, j = 0; i < srs.rs.length; i++) {
		while (j < this.rs.length && this.rs[j].index < srs.rs[i].index)
			j++;
		if (j == this.rs.length || this.rs[j].index != srs.rs[i].index)
			this.rs.splice(j, 0, srs.rs[i]);
		else {
		    var w1 = this.rs[j].weight;
		    var w2 = srs.rs[i].weight;
            this.rs[j].weight = or ? Math.max(w1, w2) : w1 + w2 * weight;
		}
	}
}

SearchResultSet.prototype.And = function(srs)
{
	var i, j;
	for (i = 0, j = 0; i < srs.rs.length && j < this.rs.length; i++) {
		while (j < this.rs.length && this.rs[j].index < srs.rs[i].index)
			this.rs.splice(j, 1);
		if (j < this.rs.length && srs.rs[i].index == this.rs[j].index) {
		    var w1 = this.rs[j].weight;
		    var w2 = srs.rs[i].weight;
	        this.rs[j].weight = Math.min(w1, w2);
			j++;
	    }
	}
	this.rs.splice(j, this.rs.length - j);
}

/* ecidcomp.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	EcidComparer:
//	------------
//	void Init(expressionstr)	-> Initializes the object variable with expression string, got the player 
//										as ECID parameter in command line
//	BOOL Compare(ecidarray)		-> EcidArray contains ECID-s, got the player in an Action function
//										If the return value is true, the player has to start from frame, that
//										contain the given action, as "forward" action.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Using:	You have to initialize the object variable, and you can use the compare function for every action.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Important:	Include with "query.js"!!!
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

var EcidComparer =
{
	expstr: "",
	
Init:
function(expressionstr)
{
	if (expressionstr && expressionstr.length > 0)
	{
		QueryParser.Parse("URI", expressionstr);
	}
	else
	{
		this.expstr="";
		return;
	};

	if (QueryParser.ev)
		this.expstr=QueryParser.ev;
},






Compare:
function(ecidarray)
{
	if (this.expstr.length==0)
		return false;
	if (!ecidarray)
		return false;
	eval("exparray = [" + this.expstr + "]");
	for (var i=0;i<exparray.length;i++)
	{
		exparray[i].l=false;
		if (exparray[i].a.toLowerCase()=="s")
		{
			for (var j=0;j<ecidarray.length;j++)
			{
				if (matchString(ecidarray[j],exparray[i].p))
				{
					exparray[i].l=true;
				};
			};
		};
	};
	EcidCompareStack.Init();
	for (var i=0;i<exparray.length;i++)
	{
		if (exparray[i].a.toLowerCase()=="s")
		{
			EcidCompareStack.Push(exparray[i]);
		}
		else
		{
			var a=EcidCompareStack.Pop();
			var b=EcidCompareStack.Pop();
			if (exparray[i].p=="|")
				a.l=a.l || b.l;
			else
				a.l=a.l && b.l;
			EcidCompareStack.Push(a);
		};
	};
	return EcidCompareStack.Pop().l;
}
};

function StackItem(a,p,l)
{
	this.a=a;
	this.p=p;
	this.l=l;
};

var EcidCompareStack =
{
Init:
function()
{
	this.stArray=new Array();
	this.pTop=(-1);
},

Push:
function(element)
{
	if (this.stArray.length-this.pTop==1)
	{
		this.stArray[this.stArray.length]=new StackItem(element.a,element.p,element.l);
		this.pTop++;
	}
	else
	{
		this.pTop++;
		this.stArray[this.pTop]=new StackItem(element.a,element.p,element.l);
	};
},

Pop:
function()
{
	if (this.pTop!=(-1))
	{
		return this.stArray[this.pTop--];
	};
}
};

/////////////////////////////////////////////////////////////////////////////////////

function matchCharacter(char1, char2) 
{
    var halfKatakanaSet = " ｦｧｨｩｪｫｬｭｮｯｰｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜﾝ";
    var fullKatakanaSet = "　ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン";
    
    if (char1 == char2) {
        return true;
    }
    else if (halfKatakanaSet.indexOf(char1) > -1 && halfKatakanaSet.indexOf(char2) > -1) {
        return false;
    }
    else if (fullKatakanaSet.indexOf(char1) > -1 && fullKatakanaSet.indexOf(char2) > -1) {
        return false;
    }
    else if (halfKatakanaSet.indexOf(char1) > -1 || halfKatakanaSet.indexOf(char2) > -1) {
        return halfKatakanaSet.indexOf(char1) == fullKatakanaSet.indexOf(char2) || halfKatakanaSet.indexOf(char2) == fullKatakanaSet.indexOf(char1);
    }
    else {
        var diff = "Ａ".charCodeAt(0) - "A".charCodeAt(0);
        var charCode1 = char1.charCodeAt(0);
        var charCode2 = char2.charCodeAt(0);
        
        return (charCode1 - diff == charCode2) || (charCode2 - diff == charCode1);
    }
}

function replaceDotAndCircle(str)
{
    var fullKatakanaSet1 = "ガギグゲゴザジズゼゾダヂヅデドバビブベボ";
    var newFullKatakanaSet1 = "カキクケコサシスセソタチツテトハヒフヘホ";
    var fullKatakanaSet2 = "パピプペポ"
    var newFullKatakanaSet2 = "ハヒフヘホ";
    var newStr = null;
    
    newStr = str.replace(new RegExp("ﾞ", "g"), "#");
    newStr = newStr.replace(new RegExp("ﾟ", "g"), "*");
    
    for (var i = 0; i < fullKatakanaSet1.length; i++) {
        newStr = newStr.replace(new RegExp(fullKatakanaSet1.charAt(i), "g"), newFullKatakanaSet1.charAt(i) + "#");
    }
    for (var i = 0; i < fullKatakanaSet2.length; i++) {
        newStr = newStr.replace(new RegExp(fullKatakanaSet2.charAt(i), "g"), newFullKatakanaSet2.charAt(i) + "*");
    }
    return newStr;
}

function matchString(s1,s2,casesensitive)
{
	if (!s1)
		return false;
	if (!casesensitive)
		casesensitive=false;
	var sl1=s1.length;
	var sl2=s2.length;
	if (sl1==0 && sl2==0)
		return true;
	if (sl1==0 && sl2!=0)
		return false;
	if (sl1!=0 && sl2==0)
		return false;
	if (sl1!=sl2)
		return false;

	var ss1=(casesensitive ? s1 : s1.toLowerCase());
	var ss2=(casesensitive ? s2 : s2.toLowerCase());
	
    var newStr1 = replaceDotAndCircle(ss1);
    var newStr2 = replaceDotAndCircle(ss2);
    if (newStr1.length!=newStr2.length)
		return false;	

	for (var i=0;i<newStr1.length;i++)
	{
		if (!matchCharacter(newStr1.substr(i,1),newStr2.substr(i,1)))
			return false;
	}
	return true;
}

//////////////////////////////////////////////////////////////////////////////////////* xmlloader.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

//////////////////////////////////////////////////////////////////////////////
// Simple function for load XML file by HTTPRequest
// Parameters:
//	url				url of xml file
//	workerFunction	name of callback function will be called with request in the following form:
//					workerFunction(req,extraInfo);
//	extraInfo		extra information for user will be give back with callback function

var _workerFunction = "";
var _errorFunction = "";
var _extraInfo = "";
var _req;
var _url;

function AbsUrl(url) {
    for (var i = 0; i < url.length; i++) {
        c = url.substr(i, 1);
        if (c == ':')
            return url;
    }
    base = window.location.href;

    var k1 = base.indexOf('?');
    var k2 = base.indexOf('#');
    if (k1 >= 0 || k2 >= 0) {
        if (k1 >= 0 && k2 >= 0) {
            base = base.substr(0, (k1 < k2 ? k1 : k2));
        }
        else if (k1 >= 0) {
            base = base.substr(0, k1);
        }
        else {
            base = base.substr(0, k2);
        }
    }

    if (url.substr(0, 3) == "../") {
        var k = base.lastIndexOf('/');
        base = base.substr(0, k);
        while (url.substr(0, 3) == "../") {
            k = base.lastIndexOf('/');
            base = base.substr(0, k);
            url = url.substr(3);
        }
        base = base + "/" + url;
    }
    else {
        if (url.substr(0, 1) == "/")
            url = url.substr(1);
        k = base.lastIndexOf('/');
        base = base.substr(0, k);
        base = base + "/" + url;
    }
    return (base);
}

function LoadXMLDoc(url, workerFunction, errorFunction, extraInfo) {
    _workerFunction = workerFunction;
    _errorFunction = errorFunction;
    _extraInfo = extraInfo;
    _url = AbsUrl(url);

    _req = null;
    try {
        if (window.location.href.substr(0, 7).toLowerCase() == "http://" ||
            window.location.href.substr(0, 8).toLowerCase() == "https://") {
            _req = new XMLHttpRequest();
        }
    }
    catch (e) { }
    finally {
        if (_req == null)
            _req = new ActiveXObject("Microsoft.XMLHTTP");
    }

    _req.onreadystatechange = state_Change;
    _req.open("GET", _url, true);
    _req.send(null);
}

function state_Change() {
    if (_req.readyState == 4) {
        if (_req.status == 200) {
            eval(_workerFunction + "(_req,_extraInfo)");
        }
        else if (_req.status == 0) {
            if (_req.responseXML.documentElement == null) {
                var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
                xmlDoc.async = false;
                xmlDoc.loadXML(_req.responseText);
                _req = new Object();
                _req.responseXML = xmlDoc;
            }
            eval(_workerFunction + "(_req,_extraInfo)");

        }
        else {
            if (_url.substr(0, 3) == "../") {
                LoadXMLDoc(_url.substr(3), _workerFunction, _errorFunction, _extraInfo);
            }
            else if (_errorFunction.length > 0) {
                alert(_url + " not found. Logged...");
                eval(_errorFunction + "(_extraInfo)");
            }
            else
                alert("Problem retrieving data: " + _req.statusText);
        }
    }
}

//////////////////////////////////////////////////////////////////////////////
// Function to load XML files contain simple arrays
// Parameters:
//	url				url of xml file
//	returnFunction	function will be call back with a simple array loaded from xml file
//	nodeName		name of node for load

var _returnFunction = "";
var _nodes;
var _nodesArray = new Array();

function LoadXMLDocArray(url, returnFunction, errorFunction, nodeName, xmlmode) {
    _returnFunction = returnFunction;
    _nodeName = nodeName;
    if (!xmlmode)
        LoadXMLDoc(url, "XMLDocArrayWorker", errorFunction, nodeName);
    else
        LoadXMLDoc(url, "XMLDocArrayWorker2", errorFunction, nodeName);
}

function XMLDocArrayWorker(req, extraInfo) {
    _nodesArray = new Array();
    _nodes = req.responseXML.getElementsByTagName(extraInfo);
    for (var i = 0; i < _nodes.length; i++) {
        n = _nodes[i];
        s = (n.textContent ? n.textContent : n.text);
        if (!s)
            s = "";
        k = s.length;
        if (k >= 2) {
            if ((s.substr(0, 1) == '\"') && (s.substr(k - 1, 1) == '\"')) {
                ss = s.substr(1, k - 2);
                s = ss;
            }
        }
        _nodesArray[_nodesArray.length] = s;
    }
    sfn = _returnFunction + "(_nodesArray)";
    setTimeout(sfn, 1);
}

function XMLDocArrayWorker2(req, extraInfo) {
    _nodesArray = new Array();
    _nodes = req.responseXML.getElementsByTagName(extraInfo);
    for (var i = 0; i < _nodes.length; i++) {
        n = _nodes[i];
        xmlname = n.attributes[0].nodeValue;
        xmltext = "";
        for (var j = 0; j < n.childNodes.length; j++) {
            if (n.childNodes[j].xml) {
                xmltext += n.childNodes[j].xml;
            } else {
                var oSerializer = new XMLSerializer;
                xmltext += oSerializer.serializeToString(n.childNodes[j]);
            }
        }
        _nodesArray[_nodesArray.length] = xmlname + "=" + xmltext;
    }
    sfn = _returnFunction + "(_nodesArray)";
    setTimeout(sfn, 1);
}

/* lmsapplet.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

// the following code must exist for AICC
// Only add the java applet to the page when running a course through HACP.

var intPos = window.location.search.toLowerCase().indexOf("aicc_url");
var intPos2 = window.location.search.toLowerCase().indexOf("aicc_sid");
function getOnlyPath(s) {
    while (s.indexOf('\\') != -1)
        s = s.replace('\\', '/');
    return s.substr(0, s.lastIndexOf("/"));
}
if ((intPos>-1) && (intPos2>-1)) {
	//running in AICC mode
	if (LmsConfig.AiccAppletPath == "") {
		//using applet from package
        var currentPgPath = window.location.protocol + "//" + window.location.host + getOnlyPath(window.location.pathname);
		fullPath = currentPgPath + "/" + lms_path + "js";
	}
	else {
		//using applet from predeifned location
	    fullPath = LmsConfig.AiccAppletPath;
	}

	document.write("<div style='position: absolute;'><applet NAME='GetHTTPPostData' codebase='" + fullPath + "' code='GetHTTPPostData.class' width='1' height='1' MAYSCRIPT></applet></div>");
}
/* lmscomfactory.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

// This function is reposible for inserting
// the KPath API into the environment if
// the asset is running under KPath and 
// no API can currently be found. 
//
// This call inserts an invisible iframe and 
// sets its source to a HTML page that will 
// contains the KPATH Scorm API adaptor when
// the page is configured to run under Kpath UT.
//
// Since invisible iframe page will load asyncronously
// we have to tie the LmsCom creation with the 
// onload of the iframe.
function InsertRuntimeAPI(loadcallback) {

    /* If we are not running with Kpath we do not have
       to insert the API so just directly call the
       load callback. */ 
    if (Kpath_launch == false) {
        setTimeout(loadcallback, 1);
        return;
    }

    /* We are running under KPath, check to see if
    the frame hosting the low level KPath
    API adaptor has been loaded somewhere.
    If so, do nothing else but directly
    call the load call back.
       
    Else we have to asynchronously load the
    API frame into the environment */
    var apiframe = findKPathAPIFrame(window);

    if (apiframe == null) {
        apiframe = document.createElement("iframe");
        apiframe.id = "KPATH_API_FRAME";
        apiframe.style.display = 'none';

        document.body.appendChild(apiframe);

        if (loadcallback) {
            if (navigator.appName == "Microsoft Internet Explorer")
                apiframe.attachEvent("onload", loadcallback);
            else
                apiframe.onload = loadcallback;

        }

        apiframe.src = Kpath_Runtime_API;
    }
    else
        setTimeout(loadcallback, 1);
}

function findKPathAPIFrame(win) {
    var apiframe = null;
    var depth = 0;
    var w = win;

    try {
        while (w != null) {
            apiframe = w.document.getElementById("KPATH_API_FRAME");
    
            if (apiframe != null)
                return apiframe.contentWindow;
    
            depth++;
            // Note: 7 is an arbitrary number, but should
            // be more than sufficient
            if (depth > 7) {
                break;
            }
    
            if (w === w.parent) break;
            w = w.parent;
        }
    
        if (win.top.opener != null)
            return findKPathAPIFrame(win.top.opener);
    } catch (e) {
        return null;
    }


    return null;
}

var _GlobalLmsComFactory = null; 

function GetLmsComFactory() {

    if (_GlobalLmsComFactory == null)
        alert(R_initializelmscom_not_called);
        
    return _GlobalLmsComFactory;
}


function CheckForLMSAPI() {
    if (_lmsMode == "LMS" &&
            !(_GlobalLmsComFactory.api_type == "scorm2004" ||
              _GlobalLmsComFactory.api_type == "scorm12" ||
              _GlobalLmsComFactory.api_type == "aicc" ||
              (_GlobalLmsComFactory.api_type == "kpath" && findKPathAPIFrame(window))
            )
        )
            alert(R_scorm_noapi);
    if (_lmsMode == "KPT" && !findKPathAPIFrame(window))
        alert(R_scorm_noapi);
}


function InitializeLmsCom() {
    _GlobalLmsComFactory = new LmsComFactory(window.location.search);
}

/* LmsComFactory uses environmental information like URL  parameters
   and runtime variables to determine which type of LmsCom object
   it should instantiated.  Note that code outside of the JS file 
   should use GetLmsCom instead since GetLmsCom has logic in it 
   that allows the parent page to provide the LmsCom object if 
   it wants to. */ 
function LmsComFactory(launcharg) {
    var fname = "LmsComFactory";

    this.api_type = "none";
    
    this.launch_arg = launcharg;
    this.aicc_url = "";
    this.aicc_sid = "";

    //maintain the api pointer if found so that lmscomscorm constructors can use it
    this.scorm_api_12 = null;
    this.scorm_api_2004 = null; 

    if (launcharg == null)
        launcharg = "";
        
    var strArgs = this.launch_arg.substring(1).split("&");

    lmslog.addEntry(0, fname, "strArgs", strArgs);
    for (var i = 0; i < strArgs.length; i++) {
        strArg = strArgs[i];

        var val;

        val = this.CheckParam(strArg, "aicc_url=");
        if (val != "") {
            // this is aicc Hacp, set flag to indicate this
            if (val.substr(0, 4).toLowerCase() != "http") {
                this.aicc_url = LmsConfig.AiccUrlProtocol + val;
            }
            else
                this.aicc_url = val;

            continue;
        } 
        
        val = this.CheckParam(strArg, "aicc_sid=");
        if (val != "") {
            this.aicc_sid = val;
            continue;
        }
    }

    //maintain the api pointer if found so that lmscomscorm constructors can use it
    if (LmsConfig.ScormVersion !== "1.2")
        this.scorm_api_2004 = this.FindScorm2004API();
    if (this.scorm_api_2004 == null && LmsConfig.ScormVersion !== "2004")
        this.scorm_api_12 = this.FindScorm12API();

    if ((this.aicc_url != "") && (this.aicc_sid != "")) {
        this.api_type = "aicc";
    }
    else if (Kpath_launch == true) {
        this.api_type = "kpath"; 
    }
    else if (this.scorm_api_2004 != null) {
        this.api_type = "scorm2004";
    }
    else if (this.scorm_api_12 != null) {
        this.api_type = "scorm12";
    }
}


/* The factory method for LmsCom. */
// LZ: LmsComKPath added
LmsComFactory.prototype.CreateLmsCom = function() {

    if (this.api_type == "aicc") {
        return new LmsComAICC(this.aicc_url, this.aicc_sid);
    }
    else if (this.api_type == "scorm2004") {
        return new LmsComScorm2004();
    }
    // If portal launch, there will be an adapter to be found and top level SCO
    // should use it rather than calling LoadRuntime.
    else if (this.api_type == "kpath") {
        var lmscom = new LmsComKPath();
        lmscom.API = this.scorm_api_2004;
        return lmscom;
    }
    else if (this.api_type == "scorm12") {
        return new LmsComScorm12();
    }

    if (PlayerConfig.EnableCookies)
        return new LmsComCookie();
    else
        return new LmsComBase(); 
}

LmsComFactory.prototype.FindScorm12API = function () {
    try {
        var theAPI = this.FindWindowScorm12API(window);
    
        if ((theAPI == null) && (top.window.opener != null) && (!top.window.opener.closed)) {
            theAPI = this.FindWindowScorm12API(top.window.opener);
        }
    
        return theAPI;
    } catch (e) {
        return null;
    }
}

LmsComFactory.prototype.FindWindowScorm12API = function(win) {
   var findAPITries = 0;
   while ((win.API == null) && (win.parent != null) && (win.parent != win))
   {
      findAPITries++;
      // Note: 500 is an arbitrary number, but should be more than sufficient
      if (findAPITries > 500) 
      {
        lmslog.addEntry(0, "FindScorm12API", "", R_scorm_apideep);
        return null;
      }
      
      win = win.parent;
  }
   
   return win.API;
}

LmsComFactory.prototype.FindScorm2004API = function() {
    try {
        var theAPI = this.FindWindowScorm2004API(window);

        if ((theAPI == null) && (top.window.opener != null) && (!top.window.opener.closed)) {
            theAPI = this.FindWindowScorm2004API(top.window.opener);
        }

        return theAPI;
    } catch (e) {
        return null;
    }
}

LmsComFactory.prototype.FindWindowScorm2004API = function(win) {
    var findAPITries = 0;
 
    while ((win.API_1484_11 == null) && (win.parent != null) && (win.parent != win)) {
        findAPITries++;

        if (findAPITries > 500) {
            lmslog.addEntry(0, "FindScorm2004API", "", R_scorm_apideep);
            return null;
        }
        win = win.parent;
    }

    return win.API_1484_11;
}

LmsComFactory.prototype.CheckParam = function(strArg, param) {
    var len = param.length;
    var val = "";

    if (strArg.substr(0, len).toLowerCase() == param) {
        val = strArg.substring(len);
    }

    return val;
}

/* lmscom.js */ 
/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

/* Constant for the different statuses that a coarse may have.  
   These ID corresponsed to the values used by both SCORM and 
   AICC. */ 
var LMS_PASSED = "passed";
var LMS_FAILED = "failed";
var LMS_COMPLETED = "completed";
var LMS_INCOMPLETE = "incomplete";
var LMS_NOT_ATTEMPTED = "not attempted";

/* Extend internal Date object to format for SCORM 2004 */
Date.prototype.toSCORM = function() {
    return this.getFullYear() + "-" + ("0"+(this.getMonth()+1)).slice(-2) + "-" + ("0"+this.getDate()).slice(-2)
        + "T" + ("0"+this.getHours()).slice(-2) + ":" + ("0"+this.getMinutes()).slice(-2) + ":" + ("0"+this.getSeconds()).slice(-2);
}

///////////////////////////////////////
//
// LmsCom object defintions
//
///////////////////////////////////////

///////////////////////////////////////
// Base LmsCom object defintion
///////////////////////////////////////
function LmsComBase(parent) {
    this.status_obj = null;
    this.ordinal_number = 0; 
    
    this.start_date = "";
    this.end_date = "";
    this.student_id = "";
    this.student_name = "";
    this.credit = "";
    this.lesson_status = LMS_NOT_ATTEMPTED;
    this.lesson_flag = "";
    this.lesson_location = "";
    this.lesson_data = "";
    this.original_lesson_data = "";
    this.core_vendor = "";
    this.score = "";
    this.time = "";
    this.idle_time = 0; // idle time only computed for lmscomkpath
    
    this.owner = null;  // owner window of this lmscom
    this.guid = null;   // guid of associated asset

    this.session_active = false;
    this.bigsco = false;    // executing in a big sco, so asset status stored differently

    if (parent != null) {
        this.Copy(parent);
        this.ParentLmsCom = parent; 
    } 

    this.object_type_name = "LmsComBase";
}

LmsComBase.prototype.GetOrdinalNumber = function() {
    return this.ordinal_number;
}

LmsComBase.prototype.SetOrdinalNumber = function(ordnum) {
    this.ordinal_number = ordnum;
}

/* Copies just that invarient information.  Allows child 
   pages to report on student info if they need to. */ 
LmsComBase.prototype.Copy = function(from) {

    this.student_id = from.student_id;
    this.student_name = from.student_name;
    this.credit = from.credit;
    this.lesson_status = from.lesson_status;
    this.bigsco = from.bigsco;
    this.lesson_data = from.lesson_data;
    this.lesson_location = from.lesson_location;
}

/* Starts a session.  For LmsComBase, all this does is
   records the start time. */ 
LmsComBase.prototype.Begin = function() {
    this.start_date = new Date().getTime();

    if (this.session_active)
        alert(R_lmscom_already_active);

    this.session_active = true; 
       
    return true;
}

/* Ends a session.  For LmsComBase, all this does is
   records the end time. */ 
LmsComBase.prototype.End = function() {

    if (!this.session_active)
        alert(R_lmscom_inactive);

    this.end_date = new Date().getTime();
    this.session_active = false;
 
    return true;
}

/* Load the SCORM API adapter if needed and save reference to it. */
LmsComBase.prototype.LoadAPIAdapter = function (callback) {
    //setTimeout(callback,1);
    // Above timeout caused mode launches to hang on ipad. Apparently it isn't cross-tab
    // execution that is blocked, but only the timer thread in inactive tabs.
    callback();
}

/* Sends completion status to the LMS. This is factored out of LmsCom.End() so
    that completion information may be sent immediately to allow the LMS to
    update any visual feedback. */
LmsComBase.prototype.SendCompletionInfo = function() {}

/* Notifies parent lmscom to roll up the status of this lmscom */
LmsComBase.prototype.NotifyParent = function() {
    var parentlmscom = this.ParentLmsCom;
    if (parentlmscom && !parentlmscom.owner.closed && parentlmscom.owner.ListenChildClose)
        parentlmscom.owner.ListenChildClose();
}

LmsComBase.prototype.getReportedLessonStatus = function() {
    if (this.lesson_status === LMS_PASSED)
        return LmsConfig.ReportOnPass;
    else if (this.lesson_status === LMS_FAILED)
        return LmsConfig.ReportOnFail;
    else
        return this.lesson_status;
}
/* Internal helper method that computes elapse time in 
   seconds. */
LmsComBase.prototype.computeTime = function(bdate, edate) {
    var elapsedSeconds = ((edate - bdate - this.idle_time) / 1000);
    return this.convertTotalSeconds(elapsedSeconds);
}

/* Internal helper method that converts date/time into
   seconds. */
LmsComBase.prototype.convertTotalSeconds = function(ts) {
    var sec = (ts % 60);
    ts -= sec;
    var tmp = (ts % 3600);  //# of seconds in the total # of minutes
    ts -= tmp;              //# of seconds in the total # of hours
    // convert seconds to conform to CMITimespan type (e.g. SS.00)
    sec = Math.round(sec * 100) / 100;
    var strSec = new String(sec);
    var strWholeSec = strSec;
    var strFractionSec = "";
    if (strSec.indexOf(".") != -1) {
        strWholeSec = strSec.substring(0, strSec.indexOf("."));
        strFractionSec = strSec.substring(strSec.indexOf(".") + 1, strSec.length);
    }
    if (strWholeSec.length < 2) {
        strWholeSec = "0" + strWholeSec;
    }
    strSec = strWholeSec;
    if ((ts % 3600) != 0)
        var hour = 0;
    else var hour = (ts / 3600);
    if ((tmp % 60) != 0)
        var min = 0;
    else var min = (tmp / 60);
    if ((new String(hour)).length < 2)
        hour = "0" + hour;
    if ((new String(min)).length < 2)
        min = "0" + min;
    var rtnVal = hour + ":" + min + ":" + strSec;
    return rtnVal;
}

// Get current bookmark. This is only needed for a TOC that is called via lmstart
// but not from an LMS. If you open a Big SCO's concept from kp.html and launch
// it, the Big SCO toc will get an lmscombase from the lmstart, but the lmstart
// page doesn't have the toc_hash, so it can't get the bookmark.
// Note that "view outline" from a normal concept does not need this. It replaces
// the lmstart page with the toc, so the toc will end up with an lmscomcookie of
// its own.
LmsComBase.prototype.GetBookmark = function(toc_hash) {
    if (this.ParentLmsCom)
        return this.ParentLmsCom.GetBookmark(toc_hash);
    return 0;
}

// Support for UPK specific functionality. Delegate to parent until an lmscomkpath is found
LmsComBase.prototype.doGetUPKValue = function(name) {
    if (this.ParentLmsCom)
        return this.ParentLmsCom.doGetUPKValue(name);
    return "";
}

LmsComBase.prototype.doSetUPKValue = function(name, value) {
    if (this.ParentLmsCom)
        this.ParentLmsCom.doSetUPKValue(name, value);
}

LmsComBase.prototype.doUPKCommit = function() {
    if (this.ParentLmsCom)
        this.ParentLmsCom.doUPKCommit();
}

/* Record an interaction completion. Only an lmscomkpath will actually do this, so
   a question in the outline will delegate to its parent lmscom (from lmstart). */
LmsComBase.prototype.setInteraction = function(index,qlmscom) {
    if (this.ParentLmsCom)
        return this.ParentLmsCom.setInteraction(index,qlmscom);
}
LmsComBase.prototype.getAnsweredQuestions = function() {
    if (this.ParentLmsCom)
        return this.ParentLmsCom.getAnsweredQuestions();
    return {};
}

LmsComBase.prototype.setObjective = function(index, objective) {
    if (this.ParentLmsCom)
        this.ParentLmsCom.setObjective(index, objective);
}

// sequencing at end of pre/post assessment
LmsComBase.prototype.requestContinue = function() {
    if (this.ParentLmsCom)
        this.ParentLmsCom.requestContinue();
}

/* Indicate if LMS connection is live */
LmsComBase.prototype.IsConnected = function() {
    if (this.ParentLmsCom)
        return this.ParentLmsCom.IsConnected();
    return false;
}

/* This method reads persisted data from LmsCom 
  (primary from lesson_data) and creates a LmsBasicStatus
  object from that. */ 
LmsComBase.prototype.OpenBasicStatus = function() {
    this.status_obj = new LmsBasicStatus();
    this.status_obj.status = this.lesson_status;

    return this.status_obj;
}

/* This method reads persisted data from LmsCom 
   (primary from lesson_data) and creates a LmsTopicStatus
   object from that. */ 
LmsComBase.prototype.OpenTopicStatus = function(lmsModes, playerModes) {
    var fname = "OpenTopicStatus";
    this.status_obj = new LmsTopicStatus();
    this.status_obj.setRequiredMode(lmsModes, playerModes);
    lmslog.addEntry(0,fname,"RequiredMode",this.status_obj.requiredMode);
    this.status_obj.isScored = !!lmsModes["K"];
    
    var availableModes;
    if (GetTopLevelLmsMode() == "LMS")
        availableModes = lmsModes;
    else
        availableModes = playerModes;
    this.status_obj.setModeavail("S", availableModes["S"]);
    this.status_obj.setModeavail("T", availableModes["T"]);
    this.status_obj.setModeavail("K", availableModes["K"]);
    this.status_obj.setModeavail("D", availableModes["D"]);
    this.status_obj.setModeavail("P", availableModes["P"]);
    this.status_obj.setModeavail("E", availableModes["E"]);
    lmslog.addEntry(0, fname, "SeeIt", this.status_obj.getModeavail("S"));
    lmslog.addEntry(0, fname, "TryIt", this.status_obj.getModeavail("T"));
    lmslog.addEntry(0, fname, "KnowIt", this.status_obj.getModeavail("K"));
    lmslog.addEntry(0, fname, "DoIt", this.status_obj.getModeavail("D"));
    lmslog.addEntry(0, fname, "PrintIt", this.status_obj.getModeavail("P"));
    lmslog.addEntry(0, fname, "TestIt", this.status_obj.getModeavail("E"));

    if (this.bigsco) {
        this.status_obj.savedStatus = this.lesson_data.charAt(0);
        this.lesson_data = this.lesson_data.substring(1);
    }
    this.status_obj.initTopicstat(this.lesson_data);
        
    return this.status_obj;
}

// duplicates code for TopicStatus, except available modes are stored differently in
// topic.html than in lmstart.html
LmsComBase.prototype.OpenTopicLaunchStatus = function(mode, lmsModes, playerModes) {
    var fname = "OpenTopicLaunchStatus";

    this.status_obj = new LmsTopicLaunchStatus(mode);
    this.status_obj.setRequiredMode(lmsModes, playerModes);
    lmslog.addEntry(0,fname,"RequiredMode",this.status_obj.requiredMode);
    this.status_obj.isScored = lmsModes.indexOf("K")!=-1;

    var availableModes;
    if (GetTopLevelLmsMode() == "LMS")
        availableModes = lmsModes;
    else
        availableModes = playerModes;
    this.status_obj.setModeavail("S", availableModes.indexOf("S")!=-1);
    this.status_obj.setModeavail("T", availableModes.indexOf("T")!=-1);
    this.status_obj.setModeavail("K", availableModes.indexOf("K")!=-1);
    this.status_obj.setModeavail("D", availableModes.indexOf("D")!=-1);
    this.status_obj.setModeavail("P", availableModes.indexOf("P")!=-1);
    this.status_obj.setModeavail("E", availableModes.indexOf("E")!=-1);
    lmslog.addEntry(0, fname, "SeeIt", this.status_obj.getModeavail("S"));
    lmslog.addEntry(0, fname, "TryIt", this.status_obj.getModeavail("T"));
    lmslog.addEntry(0, fname, "KnowIt", this.status_obj.getModeavail("K"));
    lmslog.addEntry(0, fname, "DoIt", this.status_obj.getModeavail("D"));
    lmslog.addEntry(0, fname, "PrintIt", this.status_obj.getModeavail("P"));
    lmslog.addEntry(0, fname, "TestIt", this.status_obj.getModeavail("E"));

    this.status_obj.initTopicstat(this.lesson_data);
        
    return this.status_obj;
}

/* This method reads persisted data from LmsCom 
   (primary from lesson_data) and creates a 
   LmsQuestionStatus object from that. */ 
LmsComBase.prototype.OpenQuestionStatus = function() {
    this.status_obj = new LmsQuestionStatus();
    this.status_obj.status = LMS_NOT_ATTEMPTED;
    this.status_obj.savedStatus = this.lesson_data ? Stat2Lms(this.lesson_data) : LMS_NOT_ATTEMPTED;
    
    return this.status_obj;
}

/* This method reads persisted data from LmsCom 
   (primary from lesson_data) and creates a 
   LmsAssessmentStatus object from that. */
LmsComBase.prototype.OpenAssessmentStatus = function(itemCount, hash) {
    this.status_obj = new LmsAssessmentStatus();
    this.status_obj.hash = hash;    // save hash for when saving

    var str = this.lesson_data;
    var count;
    var savedhash = null;
    
    if (str) {
        if (!this.bigsco) {
            var index = str.indexOf("@");
            if (index > 0) {
                count = parseInt(str.substring(0, index));
                // if aicc lms (moodle) replaced "+" in hash with " ", put "+" back
                savedhash = str.substring(index+1, index+count+1).replace(/ /g,"+");
                str = str.substring(index+count+1);
            }
        } else
            savedhash = hash;   // to satisfy test below
    }
    
    if (hash === savedhash && str.length === itemCount+1) {         
        this.status_obj.savedStatus = str.charAt(0);
        this.status_obj.status = str.charAt(0) === "I" ? LMS_INCOMPLETE : LMS_NOT_ATTEMPTED;
        for (var i=0; i<itemCount; i++)
            this.status_obj.questionstatus[i] = str.charAt(i+1);
    } else {
        if (str && !this.bigsco) {  // there was data but we need to invalidate
            this.status_obj.stateDiscarded = true;
            this.status_obj.savedStatus = str.charAt(0);
        } else
            this.status_obj.savedStatus = "N";
        this.status_obj.status = LMS_NOT_ATTEMPTED;
        for (var i=0; i<itemCount; i++)
            this.status_obj.questionstatus[i] = "N";
    }    

    return this.status_obj;
}

/* This method reads persisted data from LmsCom 
  (primary from lesson_data) and creates a 
  LmsTOCStatus object from that. */
LmsComBase.prototype.OpenTOCStatus = function(nodecount, tocversion) {
    var tc = new LmsTOCStatus();
    this.status_obj = tc;

    var tocstate = new TOCState(nodecount, tocversion);
    tc.setTocState(tocstate);

    if (this.lesson_data != null && this.lesson_data.length > 0)
        tocstate.DeserializeTOC(this.lesson_data);
    return tc;
}

LmsComBase.prototype.SaveStatus = function() {
    if (this.status_obj)
        this.status_obj.Save(this);
}

// Add methods for communicating to UT (Kpath lite)
LmsComBase.prototype.utGetModeIndex = function() {
    if (this.ParentLmsCom)
        this.ParentLmsCom.utGetModeIndex();
}
LmsComBase.prototype.utPushModeIndex = function() {
    if (this.ParentLmsCom)
        this.ParentLmsCom.utPushModeIndex();
}
LmsComBase.prototype.utPopModeIndex = function() {
    if (this.ParentLmsCom)
        this.ParentLmsCom.utPopModeIndex();
}
LmsComBase.prototype.utRecordType = function(type) {
    if (this.ParentLmsCom)
        this.ParentLmsCom.utRecordType(type);
}
LmsComBase.prototype.utRecordStartTime = function(time) {
    if (this.ParentLmsCom)
        this.ParentLmsCom.utRecordStartTime(time);
}
LmsComBase.prototype.utRecordEndTime = function(time) {
    if (this.ParentLmsCom)
        this.ParentLmsCom.utRecordEndTime(time);
}
LmsComBase.prototype.utRecordCompletionStatus = function(status) {
    if (this.ParentLmsCom)
        this.ParentLmsCom.utRecordCompletionStatus(status);
}
LmsComBase.prototype.utRecordSuccessStatus = function(status) {
    if (this.ParentLmsCom)
        this.ParentLmsCom.utRecordSuccessStatus(status);
}
LmsComBase.prototype.utRecordScoreScaled = function(score) {
    if (this.ParentLmsCom)
        this.ParentLmsCom.utRecordScoreScaled(score);
}
LmsComBase.prototype.utRecordFrameViewed = function(frame) {
    if (this.ParentLmsCom)
        this.ParentLmsCom.utRecordFrameViewed(frame);
}

///////////////////////////////////////
// SCORM 1.2 LmsCom object defintion
///////////////////////////////////////
function LmsComScorm12() {
    this.allow_launch = false;

    this.object_type_name = "LmsComScorm12";
}

LmsComScorm12.prototype = new LmsComBase(); 
LmsComScorm12.prototype.constructor = LmsComScorm12;
LmsComScorm12.prototype.BaseClass = LmsComBase.prototype;

LmsComScorm12.prototype.Begin = function() {
    LmsComScorm12.prototype.BaseClass.Begin.call(this);

    //Initalizes communication with the LMS.
    var fname = "LmsComScorm12.Begin"
    lmslog.addEntry(0, fname, "", "Start");

    //SCORM - Gets all startup parameters from the LMS
    if (this.API == null) {
        this.allow_launch = true;
        return false;
    }
    
    if (this.API.LMSInitialize("") == "false"){
        var err = this.API.LMSGetLastError();
        var errDesc = this.API.LMSGetErrorString(err) + "\n" + this.API.LMSGetDiagnostic("");
        this.API = null;   // flag as disconnected
        lms_ConnectionLost(err + " " + errDesc);
        lmslog.addEntry(0, fname, "", errDesc);
        return false;        
    }

    this.lesson_status = this.original_lesson_status = this.doLMSGetValue("cmi.core.lesson_status");
    this.lesson_data = this.doLMSGetValue("cmi.suspend_data");
    this.lesson_location = this.doLMSGetValue("cmi.core.lesson_location");
    this.student_id = this.doLMSGetValue("cmi.core.student_id");
    this.student_name = this.doLMSGetValue("cmi.core.student_name");
    this.allow_launch = true;

    lmslog.addEntry(0, fname, "", "LMS session started");

    return true;
}

LmsComScorm12.prototype.End = function() {
    LmsComScorm12.prototype.BaseClass.End.call(this);

    //SCORM - Calls LMS to indicate that course session has ended
    var fname = "LmsComScorm12.End";
    lmslog.addEntry(0, fname, "", "Start");

    if (!this.allow_launch)
        return false;

    this.allow_launch = false;
    
    if (this.API == null) {
        return false;
    }

    if (this.lesson_status == LMS_INCOMPLETE)
        this.doLMSSetValue("cmi.core.exit", "suspend");
    else
        this.doLMSSetValue("cmi.core.exit", "");    // GS set this to suspend, too
        
    var sesstime = this.computeTime(this.start_date, this.end_date);
    this.doLMSSetValue("cmi.core.session_time", sesstime);
    // SCORM compliance suite dies if you send it an empty string (like, say, if you
    // wanted to clear out the value)
    if (this.lesson_data)
        this.doLMSSetValue("cmi.suspend_data", this.lesson_data);
    if (this.lesson_location)
        this.doLMSSetValue("cmi.core.lesson_location", this.lesson_location);

    this.SendCompletionInfo(true);
        
    if (this.API && this.API.LMSFinish("") == "false") {
        var err = this.API.LMSGetLastError();
        var errDesc = this.API.LMSGetErrorString(err) + "\n" + this.API.LMSGetDiagnostic("");
        this.API = null;   // flag as disconnected
        lms_ConnectionLost(err + " " + errDesc);
        lmslog.addEntry(0, fname, "", errDesc);
        return false;        
    }
    
    this.API = null;  // 13102364 - prevents errors from get/set if window close occurs before page callback
    
    lmslog.addEntry(0, fname, "", "LMS session terminated");

    return true;
}

/* Sends completion status to the LMS. This is factored out of LmsCom.End() so
    that completion information may be sent immediately to allow the LMS to
    update any visual feedback. "not attempted" is sent as "incomplete" because
    the SCORM1.2 spec can be interpreted to make "not attempted" an illegal value
    to set */
LmsComScorm12.prototype.SendCompletionInfo = function(isEnding) {
    if (this.lesson_status === LMS_NOT_ATTEMPTED) {
        if (this.original_lesson_status === LMS_NOT_ATTEMPTED)
            this.doLMSSetValue("cmi.core.lesson_status", LMS_INCOMPLETE);
        else
            this.doLMSSetValue("cmi.core.lesson_status", this.original_lesson_status);
    } else
        this.doLMSSetValue("cmi.core.lesson_status", this.getReportedLessonStatus());
    
    if (this.score !== "") {
        this.doLMSSetValue("cmi.core.score.raw", this.score);
        this.doLMSSetValue("cmi.core.score.min", "0");
        this.doLMSSetValue("cmi.core.score.max", "100");
    }
    if (!isEnding)
        this.doLMSCommit();
}

/* Load the SCORM API adapter if needed and save reference to it. */
LmsComScorm12.prototype.LoadAPIAdapter = function(callback) {
    this.API = null
    if (GetLmsComFactory())
        this.API = GetLmsComFactory().scorm_api_12;
    callback();
}

/* Indicate if LMS connection is live */
LmsComScorm12.prototype.IsConnected = function() {
    return this.API != null;
}

// SCORM adapter definitions

LmsComScorm12.prototype.ErrorCodes = {
        NoError : 0,
        GeneralException : 101,
        ElementCannotHaveChildren : 202,
        ElementNotAnArray : 203,
        NotInitialized : 301,
        NotImplemented : 401,
        InvalidSetValue : 402,
        ElementIsReadOnly : 403,
        ElementIsWriteOnly : 404,
        IncorrectDataType : 405
    };

LmsComScorm12.prototype.doLMSGetValue = function(name) {
    var fname = "doLMSGetValue";
    if (this.API == null) {
        return "";
    }
    
    var value = this.API.LMSGetValue(name);
    var err = this.API.LMSGetLastError();
    if (err != this.ErrorCodes.NoError) {
        var errDesc = this.API.LMSGetErrorString(err);
        lms_ConnectionLost(err + " " + errDesc + ", " + name);
        lmslog.addEntry(0,fname,"",R_scorm_getvalfail + name + " " + errDesc);
        return "";
    }
    
    lmslog.addEntry(1,fname,name,value);
    return value;
}

LmsComScorm12.prototype.doLMSSetValue = function(name, value) {
    var fname = "doLMSSetValue";
    if (this.API == null) {
        return "false";
    }
    
    if (this.API.LMSSetValue(name, value) == "false") {
        var err = this.API.LMSGetLastError();
        if (err != this.ErrorCodes.NoError && err != this.ErrorCodes.NotImplemented) {
            var errDesc = this.API.LMSGetErrorString(err);
            lms_ConnectionLost(err + " " + errDesc + ", " + name + ", " + value);
            lmslog.addEntry(0,fname,"",R_scorm_setvalfail + name + ":" + value + " " + errDesc);
            return "false";
        }
    }
    
    lmslog.addEntry(1,fname,name,value);
    return "true";
}

LmsComScorm12.prototype.doLMSCommit = function() {
    var fname = "doLMSCommit";
    if (this.API == null) {
        return "false";
    }
    
    if (this.API.LMSCommit("") == "false") {    // is commit failure a drop?
        var err = this.API.LMSGetLastError();
        var errDesc = this.API.LMSGetErrorString(err);
        lms_ConnectionLost(err + " " + errDesc);
        lmslog.addEntry(0, fname, "", errDesc);
        this.API = null;
        return "false";        
    }
    
    lmslog.addEntry(1,fname,"","");
    return "true";
}

///////////////////////////////////////
// SCORM 1.3 (SCORM2004) LmsCom object defintion
///////////////////////////////////////
function LmsComScorm2004() {
    this.allow_launch = false;
    this.object_type_name = "LmsComScorm2004";
    this.lesson_data_location = "cmi.suspend_data"; 
}

LmsComScorm2004.prototype = new LmsComBase();
LmsComScorm2004.prototype.constructor = LmsComScorm2004;
LmsComScorm2004.prototype.BaseClass = LmsComBase.prototype;

LmsComScorm2004.prototype.Begin = function() {
    LmsComScorm2004.prototype.BaseClass.Begin.call(this);

    //Initalizes communication with the LMS.
    var fname = "LmsComScorm2004.Begin"
    lmslog.addEntry(0, fname, "", "Start");

    //SCORM - Gets all startup parameters from the LMS
    if (this.API == null) {
        this.allow_launch = true;
        return false;
    }
    
    if (this.API.Initialize("") == "false"){
        var err = this.API.GetLastError();
        var errDesc = this.API.GetErrorString(err) + "\n" + this.API.GetDiagnostic("");
        this.API = null;   // flag as disconnected
        lms_ConnectionLost(err + " " + errDesc);
        lmslog.addEntry(0, fname, "", errDesc);
        return false;        
    }

    this.lesson_status = this.doGetValue("cmi.completion_status");
    if (this.lesson_status === "unknown") {
        this.lesson_status = LMS_NOT_ATTEMPTED;
    } else if (this.lesson_status === LMS_COMPLETED) {
        var success_status = this.doGetValue("cmi.success_status");
        if (success_status === LMS_PASSED || success_status === LMS_FAILED)
            this.lesson_status = success_status;
    }
    this.original_lesson_status = this.lesson_status;
    this.lesson_data = this.doGetValue(this.lesson_data_location);
    this.lesson_location = this.doGetValue("cmi.location");
    this.student_id = this.doGetValue("cmi.learner_id");
    this.student_name = this.doGetValue("cmi.learner_name");
    this.allow_launch = true;

    lmslog.addEntry(0, fname, "", "LMS session started");

    return true;
}

LmsComScorm2004.prototype.End = function() {
    LmsComScorm2004.prototype.BaseClass.End.call(this);

    //SCORM - Calls LMS to indicate that course session has ended
    var fname = "LmsComScorm2004.End";
    lmslog.addEntry(0, fname, "", "Start");

    if (!this.allow_launch)
        return false;

    this.allow_launch = false;

    if (this.API == null) {
        return false;
    }
    
    if (this.lesson_status == LMS_INCOMPLETE)
        this.doSetValue("cmi.exit", "suspend");
    else
        this.doSetValue("cmi.exit", "normal");

    var sesstime = this.computeTime(this.start_date, this.end_date);
    this.doSetValue("cmi.session_time", sesstime);
    // SCORM compliance suite dies if you send it an empty string (like, say, if you
    // wanted to clear out the value)
    if (this.lesson_data)
        this.doSetValue(this.lesson_data_location, this.lesson_data);
    if (this.lesson_location)
        this.doSetValue("cmi.location", this.lesson_location);

    this.SendCompletionInfo(true);
     
    if (this.API && this.API.Terminate("") == "false") {
        var err = this.API.GetLastError();
        var errDesc = this.API.GetErrorString(err) + "\n" + this.API.GetDiagnostic("");
        this.API = null;   // flag as disconnected
        lms_ConnectionLost(err + " " + errDesc);
        lmslog.addEntry(0, fname, "", errDesc);
        return false;        
    }
    
    this.API = null;  // 13102364 - prevents errors from get/set if window close occurs before page callback
    
    lmslog.addEntry(0, fname, "", "LMS session terminated");

    return true;
}

/* Load the SCORM API adapter if needed and save reference to it. */
LmsComScorm2004.prototype.LoadAPIAdapter = function(callback) {
    this.API = null
    if (GetLmsComFactory())
        this.API = GetLmsComFactory().scorm_api_2004;
    callback();
}

/* Sends completion status to the LMS. This is factored out of LmsCom.End() so
    that completion information may be sent immediately to allow the LMS to
    update any visual feedback. */
LmsComScorm2004.prototype.SendCompletionInfo = function(isEnding) {
    var lesson_status = this.getReportedLessonStatus();
    if (lesson_status === LMS_NOT_ATTEMPTED)
        lesson_status = this.original_lesson_status;
    // split scorm1.2/aicc completion into scorm2004 values
    // maybe it would be better to hold them in the scorm2004 manner and join
    // for aicc/scorm1.2
    if (lesson_status == LMS_PASSED || lesson_status == LMS_FAILED) {
        this.doSetValue("cmi.success_status", lesson_status);
        this.doSetValue("cmi.completion_status", LMS_COMPLETED);
    } else
        this.doSetValue("cmi.completion_status", lesson_status);

    if (this.score !== "") {
        this.doSetValue("cmi.score.raw", this.score);
        this.doSetValue("cmi.score.scaled", this.score / 100);
        this.doSetValue("cmi.score.min", "0");
        this.doSetValue("cmi.score.max", "100");
    }
    if (!isEnding)
        this.doCommit();
}

/* Internal helper method that converts date/time into
   seconds. This version generates a 1.3 compliant (second,10,2) result */
LmsComScorm2004.prototype.convertTotalSeconds = function(ts) {
    var sec = (ts % 60);
    ts -= sec;
    var tmp = (ts % 3600);  //# of seconds in the total # of minutes
    ts -= tmp;              //# of seconds in the total # of hours
    // convert seconds to conform to CMITimespan type (e.g. SS.00)
    sec = Math.round(sec * 100) / 100;
    var strSec = new String(sec);
    var strWholeSec = strSec;
    var strFractionSec = "";
    if (strSec.indexOf(".") != -1) {
        strWholeSec = strSec.substring(0, strSec.indexOf("."));
        strFractionSec = strSec.substring(strSec.indexOf(".") + 1, strSec.length);
    }
    if (strWholeSec.length < 2) {
        strWholeSec = "0" + strWholeSec;
    }
    strSec = strWholeSec;
    if ((ts % 3600) != 0)
        var hour = 0;
    else var hour = (ts / 3600);
    if ((tmp % 60) != 0)
        var min = 0;
    else var min = (tmp / 60);
    if ((new String(hour)).length < 2)
        hour = "0" + hour;
    if ((new String(min)).length < 2)
        min = "0" + min;
    var rtnVal = "PT" + hour + "H" + min + "M" + strSec + "S";
    return rtnVal;
}

/* Indicate if LMS connection is live */
LmsComScorm2004.prototype.IsConnected = function() {
    return this.API != null;
}

// SCORM adapter definitions

LmsComScorm2004.prototype.ErrorCodes = {
        NoError : 0,
        GeneralException : 101,
        GeneralInitializationFailure : 102,
        AlreadyInitialized : 103,
        ContentInstanceTerminated : 104,
        GeneralTerminationFailure : 111,
        TerminationBeforeInitialization : 112,
        TerminationAfterTermination : 113,
        RetrieveDataBeforeInitialization : 122,
        RetrieveDataAfterTermination : 123,
        StoreDataBeforeInitialization : 132,
        StoreDataAfterTermination : 133,
        CommitBeforeInitialization : 142,
        CommitAfterTermination : 143,
        GeneralArgumentError : 201,
        GeneralGetFailure : 301,
        GeneralSetFailure : 351,
        GeneralCommitFailure : 391,
        UndefinedDataModelElement : 401,
        UnimplementedDataModelElement : 402,
        DataModelElementValueNotInitialized : 403,
        DataModelElementIsReadOnly : 404,
        DataModelElementIsWriteOnly : 405,
        DataModelElementTypeMismatch : 406,
        DataModelElementValueOutOfRange : 407,
        DataModelDependencyNotEstablished : 408,
        
        KPathTimeout : 1501
    };

LmsComScorm2004.prototype.doGetValue = function(name) {
    var fname = "doGetValue";
    if (this.API == null) {
        return "";
    }
    
    var value = this.API.GetValue(name);
    var err = this.API.GetLastError();
    if (err != this.ErrorCodes.NoError && err != this.ErrorCodes.DataModelElementValueNotInitialized) {
        if (err == this.ErrorCodes.KPathTimeout && this.object_type_name == "LmsComKPath") {
            lmslog.addEntry(0,fname,"","KCenter timeout");
            var idle = this.API.GetValue("upk.idle_time");
            lmslog.addEntry(0,fname,"upk.idle_time",idle);
            this.idle_time += idle;
            lmslog.addEntry(0,fname,"idle_time",this.idle_time);
            return this.doGetValue(name);  // redo the call
        } else {            
            var errDesc = this.API.GetErrorString(err);
            lms_ConnectionLost(err + " " + errDesc + ", " + name);
            lmslog.addEntry(0,fname,"",R_scorm_getvalfail + name + " " + errDesc);
            return "";
        }
    }
    
    lmslog.addEntry(1,fname,name,value);
    return value;
}

LmsComScorm2004.prototype.doSetValue = function(name, value) {
    var fname = "doSetValue";
    if (this.API == null) {
        return "false";
    }
    
    if (this.API.SetValue(name, value) == "false") {
        var err = this.API.GetLastError();
        if (err != this.ErrorCodes.NoError && err != this.ErrorCodes.UnimplementedDataModelElement) {
            if (err == this.ErrorCodes.KPathTimeout && this.object_type_name == "LmsComKPath") {
                lmslog.addEntry(0,fname,"","KCenter timeout");
                var idle = this.API.GetValue("upk.idle_time");
                lmslog.addEntry(0,fname,"upk.idle_time",idle);
                this.idle_time += idle;
                lmslog.addEntry(0,fname,"idle_time",this.idle_time);
                return this.doSetValue(name, value);
            } else {          
                var errDesc = this.API.GetErrorString(err);
                lms_ConnectionLost(err + " " + errDesc + ", " + name + ", " + value);
                lmslog.addEntry(0,fname,"",R_scorm_setvalfail + name + ":" + value + " " + errDesc);
                return "false";
            }
        }
    }
//alert(fname+":"+name+":"+value);
    lmslog.addEntry(1,fname,name,value);
    return "true";
}

LmsComScorm2004.prototype.doCommit = function() {
    var fname = "doCommit";
    if (this.API == null) {
        return "false";
    }
    
    if (this.API.Commit("") == "false") {
        var err = this.API.GetLastError();
        var errDesc = this.API.GetErrorString(err);
        if (err == this.ErrorCodes.KPathTimeout && this.object_type_name == "LmsComKPath") {
            lmslog.addEntry(0,fname,"","KCenter timeout");
            var idle = this.API.GetValue("upk.idle_time");
            lmslog.addEntry(0,fname,"upk.idle_time",idle);
            this.idle_time += idle;
            lmslog.addEntry(0,fname,"idle_time",this.idle_time);
            return this.doCommit();
        } else {
            this.API = null;   // flag as disconnected
            lms_ConnectionLost(err + " " + errDesc);
            lmslog.addEntry(0, fname, "", errDesc);
            return "false";
        }        
    }
    
    lmslog.addEntry(1,fname,"","");
    return "true";
}


///////////////////////////////////////
// Knowledge Pathways LmsCom object defintion
///////////////////////////////////////
function LmsComKPath(parent) {
    this.allow_launch = false;

    if (parent != null) {
        this.Copy(parent);
        this.ParentLmsCom = parent; 
    } 

    this.object_type_name = "LmsComKPath";
    this.lesson_data_location = "upk.sco_data"; 
}

LmsComKPath.prototype = new LmsComScorm2004();
LmsComKPath.prototype.constructor = LmsComKPath;
LmsComKPath.prototype.BaseClass = LmsComScorm2004.prototype;

LmsComKPath.prototype.Begin = function() {
    var fname = "LmsComKPath.Begin"
    lmslog.addEntry(0, fname, "", "Start");
    var result = LmsComKPath.prototype.BaseClass.Begin.call(this);
    this.doSetValue("upk.launch_from", GetTopLevelLmsMode());
    lmslog.addEntry(0, fname, "", "LMS session started");
    return result;
}

/* Sends completion status to the LMS. This is factored out of LmsCom.End() so
    that completion information may be sent immediately to allow the LMS to
    update any visual feedback. Unlike the other lmscom types, we want to send
    LMS_NOT_ATTEMPTED to kpath if no new attempt is made */
LmsComKPath.prototype.SendCompletionInfo = function(isEnding) {
    var lesson_status = this.getReportedLessonStatus();
    if (lesson_status === LMS_NOT_ATTEMPTED) {
        this.doSetValue("cmi.completion_status", LMS_NOT_ATTEMPTED);
        return;
    }
    // split scorm1.2/aicc completion into scorm2004 values
    // maybe it would be better to hold them in the scorm2004 manner and join
    // for aicc/scorm1.2
    if (lesson_status == LMS_PASSED || lesson_status == LMS_FAILED) {
        this.doSetValue("cmi.success_status", lesson_status);
        this.doSetValue("cmi.completion_status", LMS_COMPLETED);
    } else
        this.doSetValue("cmi.completion_status", lesson_status);

    if (this.score !== "") {
        this.doSetValue("cmi.score.raw", this.score);
        this.doSetValue("cmi.score.scaled", this.score / 100);
        this.doSetValue("cmi.score.min", "0");
        this.doSetValue("cmi.score.max", "100");
    }
    if (!isEnding)
        this.doCommit();
}

/* Load the SCORM API adapter if needed and save reference to it. */
LmsComKPath.prototype.LoadAPIAdapter = function(callback) {
    if (!this.API) {    // don't overwrite previously set adapter
        var apiframe = findKPathAPIFrame(window);
        if (apiframe && apiframe.LoadRuntime && this.guid) {
            this.deferred_callback = callback;
            var that = this;
            apiframe.LoadRuntime(this.guid, 0, 0, 0, function(s,g,a,e){that.LoadAPIAdapterCallback(s,g,a,e)});
        } else {
            callback();
        }
    } else
        callback();
}

LmsComKPath.prototype.LoadAPIAdapterCallback = function(succeeded, guid, APIControl, ErrorMessage) {
    if (succeeded == "succeeded" && guid == this.guid) {
        this.API = APIControl.GetAPI();
        lmslog.addEntry(0, "LoadAPIAdapterCallback", "", "KPath adapter bound");
        try {
            this.deferred_callback();
        } catch (e) { } // catch case where we cycle quickly through the toc & lmscom page closed before API callback runs
    } else if (succeeded == "no SCO") {
        this.API = null;    // fall back to lmscombase functionality
        lmslog.addEntry(0,"LoadAPIAdapterCallback","",ErrorMessage);
        this.deferred_callback();
    } else {
        alert(R_scorm_noapi + " " + ErrorMessage);
        lmslog.addEntry(0,"LoadAPIAdapterCallback","",ErrorMessage);
        this.deferred_callback();
    }
}

LmsComKPath.prototype.doGetUPKValue = function(name) {
    var ret = this.doGetValue(name);
    if (ret === "")
        ret = -1;
    return ret;
}

LmsComKPath.prototype.doSetUPKValue = function(name, value) {
    this.doSetValue(name, value);
}

LmsComKPath.prototype.doUPKCommit = function() {
    this.doCommit();
}

// Record an interaction completion.
LmsComKPath.prototype.setInteraction = function(index,qlmscom) {
    if (!this.API)  // if running in "lmscombase mode"
        return;
        
    var statobj = qlmscom.status_obj;
    var count = this.doGetValue("cmi.interactions._count");
    if (index == -1) index = count;
    if (index >= count)
        this.doSetValue("cmi.interactions."+index+".id",qlmscom.guid);
    this.doSetValue("cmi.interactions."+index+".type",statobj.getQuestionType());
    this.doSetValue("cmi.interactions."+index+".timestamp",(new Date()).toSCORM());
    this.doSetValue("cmi.interactions."+index+".weighting","1");
    if (statobj.getResult()) {
        this.doSetValue("cmi.interactions."+index+".learner_response",statobj.getLearnerResponse());
        this.doSetValue("cmi.interactions."+index+".result",statobj.getResult());
    }
    this.doCommit();
    return index;
}

LmsComKPath.prototype.getAnsweredQuestions = function() {
    var answeredQuestions = {};
    if (!this.API)
        return answeredQuestions;
        
    var count = this.doGetValue("cmi.interactions._count");
    for (var i=0; i<count; i++) {
        var id = this.doGetValue("cmi.interactions." + i + ".id");
        answeredQuestions[id] = { index: i };
        answeredQuestions[id].weighting = this.doGetValue("cmi.interactions." + i + ".weighting");
        answeredQuestions[id].result = this.doGetValue("cmi.interactions." + i + ".result");
    }
    return answeredQuestions;
}

LmsComKPath.prototype.setObjective = function(index, objective) {
    if (this.API) {
        var objectiveID = objective.objectiveGuid == "PRIMARYOBJ" ? "PRIMARYOBJ" : "OBJ_" + objective.objectiveGuid; 
        this.doSetValue("cmi.objectives."+index+".id", objectiveID);
        this.doSetValue("cmi.objectives."+index+".score.scaled", objective.score/100);
        this.doSetValue("cmi.objectives."+index+".completion_status", objective.completed ? "completed" : "incomplete");
        this.doSetValue("cmi.objectives."+index+".success_status", objective.completed ? "passed" : "failed");
    }
}

// sequencing at end of pre/post assessment
LmsComKPath.prototype.requestContinue = function() {
    this.doSetValue("adl.nav.request","continue");
}

// Add methods for communicating to UT (Kpath lite)
LmsComKPath.prototype.utGetModeIndex = function() {
    this.mode_index = this.doGetValue("upk.modes._count");
}
// single entry stack for ut tracking seeit/tryit/printit from doit
LmsComKPath.prototype.utPushModeIndex = function() {
    this.saved_mode_index = this.mode_index;
    this.utGetModeIndex();
}
LmsComKPath.prototype.utPopModeIndex = function() {
    this.mode_index = this.saved_mode_index;
    delete this.saved_mode_index;
}
LmsComKPath.prototype.utRecordType = function(type) {
    this.doSetValue("upk.modes." + this.mode_index + ".type", type);
}
LmsComKPath.prototype.utRecordStartTime = function(time) {
    this.doSetValue("upk.modes." + this.mode_index + ".start_time",time.toSCORM());
}
LmsComKPath.prototype.utRecordEndTime = function(time) {
    this.doSetValue("upk.modes." + this.mode_index + ".end_time",time.toSCORM());
}
LmsComKPath.prototype.utRecordCompletionStatus = function(status) {
    this.doSetValue("upk.modes." + this.mode_index + ".completion_status",status);
}
LmsComKPath.prototype.utRecordSuccessStatus = function(status) {
    this.doSetValue("upk.modes." + this.mode_index + ".success_status",status);
}
LmsComKPath.prototype.utRecordScoreScaled = function(score) {
    this.doSetValue("upk.modes." + this.mode_index + ".score.scaled",score);
}
LmsComKPath.prototype.utRecordFrameViewed = function(frame) {
    this.doSetValue("upk.modes." + this.mode_index + ".frame_viewed",frame);
    var sesstime = this.computeTime(this.start_date, new Date().getTime());
    this.doSetValue("cmi.session_time", sesstime);
    this.doCommit();
}

///////////////////////////////////////
// AICC LmsCom object defintion
///////////////////////////////////////
function LmsComAICC(aicc_url,aicc_sid) {
    this.allow_launch = false;

    this.aicc_url = aicc_url;
    this.aicc_sid = aicc_sid;
    this.app = document.applets.GetHTTPPostData;
    
    this.object_type_name = "LmsComAICC";
}

LmsComAICC.prototype = new LmsComBase(); 
LmsComAICC.prototype.constructor = LmsComScorm12;
LmsComAICC.prototype.BaseClass = LmsComBase.prototype;

LmsComAICC.prototype.Begin = function() {
    LmsComAICC.prototype.BaseClass.Begin.call(this);

    //Initalizes communication with the LMS.
    var fname = "LmsComAICC.Begin"
    lmslog.addEntry(0, fname, "", "Start");

    this.hacpGetparam();
    
    lmslog.addEntry(0, fname, "", "about to log paramvalues");
}

LmsComAICC.prototype.End = function() {
    LmsComAICC.prototype.BaseClass.End.call(this);

    var fname = "LmsComAICC.End";
    lmslog.addEntry(0, fname, "", "Start");

    if (!this.allow_launch)
        return false;

    this.allow_launch = false;
    
	var NewAiccData = this.hacpGetpostdata();
	var params = "command=putparam&version=" + LmsConfig.AiccVersion + "&session_id=" + this.aicc_sid + "&aicc_data=" + escape(NewAiccData) + "&";
	lmslog.addEntry(0,fname,"params",params);
	var strData = this.app.GetData(unescape(this.aicc_url),params)
	lmslog.addEntry(0,fname,"strData",strData);
	params = "version=" + LmsConfig.AiccVersion + "&command=ExitAU&session_id=" + this.aicc_sid + "&";
	lmslog.addEntry(0,fname,"params",params);
	strData = this.app.GetData(unescape(this.aicc_url),params)
	lmslog.addEntry(0,fname,"strData",strData);
}

// stolen from lmsfunctions.js
var closingAmp = true;  // huh?

LmsComAICC.prototype.hacpGetparam = function() {
	//AICC - Gets startup parameters from the LMS
	var fname="hacpGetparam";
	lmslog.addEntry(0,fname,"","Start");
	var strData="";
	var params;
	params = "version=" + LmsConfig.AiccVersion + "&command=GetParam&session_id=" + this.aicc_sid;
	if (closingAmp)
		params = params + "&";
	lmslog.addEntry(0,fname,"params",params);
	strData = this.app.GetData(unescape(this.aicc_url),params)
	lmslog.addEntry(0,fname,"strData",strData);
	var lessonStatus;
	var lessonFlag;
	var ErrorNum;
	var ErrorText;
	var IsValid = false;
	strData += " ";
	var strArgs = strData.split("\r");
	for (var i=0; i<strArgs.length; i++) {
		var strArg = strArgs[i];
		var tag = trimValue(strArg.substring( 0, strArg.indexOf( "=" ) ));
        var val = trimValue(strArg.substring( strArg.indexOf( "=" ) + 1 ));
		if (tag.toLowerCase() == "error") {
			ErrorNum = val;
			IsValid = true;
		}
		if (tag.toLowerCase() == "error_text") {
			ErrorText = val;
		}
		if (tag.toLowerCase() == "aicc_data") {
			this.aicc_data = strData.substring(strData.indexOf(strArg.substring( 0, strArg.indexOf( "=" ) )) + strArg.substring( 0, strArg.indexOf( "=" ) ).length + 1);
			IsValid = true;
		}
	}
	if (IsValid) {
		if (ErrorNum == 0) {
			// successful
			var CoreData;
			CoreData = get_group_content("core", this.aicc_data);
			var strArgs = CoreData.split("\r");
			for (var i=0; i<strArgs.length; i++) {
				var strArg = strArgs[i];
				var tag = trimValue(strArg.substring( 0, strArg.indexOf( "=" ) ));
	            var val = trimValue(strArg.substring( strArg.indexOf( "=" ) + 1 ));
				if (tag.toLowerCase() == "student_id") {
					this.student_id = val;
				}
				if (tag.toLowerCase() == "student_name") {
					this.student_name = val;
//					this.splitStudentname(val);				
				}
				if (tag.toLowerCase() == "lesson_status") {
					this.lesson_status = val.toLowerCase().charAt(0);
					if (val.indexOf(",")!=-1)
						this.lesson_flag = trimValue(val.substring( val.indexOf( "," ) + 1 )).toLowerCase();
					//map abreviated flags
					if (this.lesson_status == "p")
						this.lesson_status = LMS_PASSED;
					if (this.lesson_status == "c")
						this.lesson_status = LMS_COMPLETED;
					if (this.lesson_status == "f")
						this.lesson_status = LMS_FAILED;
					if (this.lesson_status == "i")
						this.lesson_status = LMS_INCOMPLETE;
					if (this.lesson_status == "n")
						this.lesson_status = LMS_NOT_ATTEMPTED;
					this.original_lesson_status = this.lesson_status;
				}
				if (tag.toLowerCase() == "lesson_location") {
					this.lesson_location = val;
				}
				if (tag.toLowerCase() == "credit") {
					this.credit = val;
				}
				if (tag.toLowerCase() == "score") {
					this.score = val;
				}
				if (tag.toLowerCase() == "time") {
					this.time = val;
				}
			}
			if (this.lesson_status == LMS_INCOMPLETE || 
			    this.lesson_status == LMS_COMPLETED || 
			    this.lesson_status == LMS_PASSED || 
			    this.lesson_status == LMS_FAILED
			    ) {
				this.lesson_data = trimValue(get_group_content("core_lesson", this.aicc_data));
			}
			else {
				this.lesson_data = "";
			}
			this.core_vendor = trimValue(get_group_content("core_vendor", this.aicc_data));
			//startTimer();
			this.allow_launch = true;
		}
		else {
			// unsuccessful, display error and do not launch
			alert(R_error_unexp + ErrorText);
			lmslog.addEntry(0,fname,"","Unable to continue because of the following error: " + ErrorText);
		}
	}
	else {
		alert(R_error_svr + unescape(this.aicc_url) + "\r\r - " + strData);
		lmslog.addEntry(0,fname,"","Unable to post to server " + unescape(this.aicc_url) + " - " + strData);
	}
}

LmsComAICC.prototype.hacpGetpostdata = function() {
	//AICC - Builds the AICC message string for passing to the LMS
	var fname = "hacpGetpostdata";
	lmslog.addEntry(0,fname,"","Start");
	var NewAiccData="";
	NewAiccData = "[CORE]\r\n";
	NewAiccData += "Lesson_Location=" + "\r\n";
	var lesson_status = this.getReportedLessonStatus();
	if (lesson_status === LMS_NOT_ATTEMPTED)
        lesson_status = this.original_lesson_status;
	if (this.lesson_status === LMS_INCOMPLETE) {
		NewAiccData += "Lesson_Status=" + lesson_status + ", suspend\r\n";
	}
	else {
		NewAiccData += "Lesson_Status=" + lesson_status + "\r\n";
	}
	lmslog.addEntry(0,fname,"is_assess",this.is_assess);
	if (this.score !== "") {
		NewAiccData += "Score=" + this.score + "\r\n";
	} else {
		NewAiccData += "Score=\r\n";
	}
	NewAiccData += "Time=" + this.computeTime(this.start_date, this.end_date) + "\r\n";
	NewAiccData += "[CORE_LESSON]\r\n";
	NewAiccData += this.lesson_data + "\r\n";
	lmslog.addEntry(0,fname,"NewAiccData",NewAiccData);
	return NewAiccData;
}

function get_group_content(section, buffer) {
	var contents = "";
	var strArgs = buffer.split("\r");
	var foundSection = false;
	for (var i=0; i<strArgs.length; i++) {
		var line = trimValue(strArgs[i]);
		if (line.substr(0,1) == "[") {
			if (line.toLowerCase().indexOf("[" + section.toLowerCase() + "]") >= 0) {
				foundSection = true;
			}
			else {
				foundSection = false;
			}
		}
		else {
			if (foundSection) {
				contents += line + "\r\n";
			}
		}
	}
	return contents;
}

function trimValue(Val) {
	var strval;
	var startPos = 0;
	var endPos = Val.length;
    for (var i=0; i<Val.length; i++) {
		// space, tab, lf, cr
	   if ((Val.substr(i,1) != " ") && (Val.substr(i,1) != "\u0009") && (Val.substr(i,1) != "\u000A") && (Val.substr(i,1) != "\u000D")) {
	   	startPos = i;
		break;
	   }
	}
	if (i == Val.length)
	   return "";
    for (var i=Val.length-1; i>0; i--) {
		// space, tab, lf, cr
	   if ((Val.substr(i,1) != " ") && (Val.substr(i,1) != "\u0009") && (Val.substr(i,1) != "\u000A") && (Val.substr(i,1) != "\u000D")) {
	   	endPos = i;
		break;
	   }
	}
	if (i == 0)
	   endPos = 0;
	return Val.substring(startPos, endPos + 1);
}

/* Indicate if LMS connection is live */
LmsComAICC.prototype.IsConnected = function() {
    return true;    // what does it mean to be disconnected from an AICC LMS?
}

///////////////////////////////////////
// Cookie based LmsCom object defintion
///////////////////////////////////////
function LmsComCookie() {
    this.allow_launch = false;

    this.object_type_name = "LmsComCookie";
}

LmsComCookie.prototype = new LmsComBase();
LmsComCookie.prototype.constructor = LmsComCookie;
LmsComCookie.prototype.BaseClass = LmsComBase.prototype;

LmsComCookie.prototype.Begin = function() {
    LmsComCookie.prototype.BaseClass.Begin.call(this);
    if (this.toc_hash = window.toc_hash) {  // assignment intended
    	var c = new Cookie(document, "Bookmark_" + this.toc_hash, 30);
    	c.Load();
    	this.lesson_location = c.Location;
	}
}

LmsComCookie.prototype.End = function() {
    LmsComCookie.prototype.BaseClass.End.call(this);
    if (this.toc_hash) {
    	var c = new Cookie(document, "Bookmark_" + this.toc_hash, 30);
    	c.Load();
    	c.Location = this.lesson_location;
    	c.Store();
	}
}

// Get current bookmark. This is only needed for a TOC that is called via lmstart
// but not from an LMS. If you open a Big SCO's concept from kp.html and launch
// it, the Big SCO toc will get an lmscombase from the lmstart, but the lmstart
// page doesn't have the toc_hash, so it can't get the bookmark.
// Note that "view outline" from a normal concept does not need this. It replaces
// the lmstart page with the toc, so the toc will end up with an lmscomcookie of
// its own.
LmsComCookie.prototype.GetBookmark = function(toc_hash) { 
    if (this.toc_hash = toc_hash) { // assignment intended
    	var c = new Cookie(document, "Bookmark_" + this.toc_hash, 30);
    	c.Load();
    	this.lesson_location = c.Location;
	}
    return parseInt(this.lesson_location, 10);
}

///////////////////////////////////////
//
// LmsStatus object defintions
//
///////////////////////////////////////

/* The following are a seriers of objects 
   used to communicate the learning
   asset runtime state with the peristence
   structure used by the LmsCom object */

///////////////////////////////////////
// Basic status
///////////////////////////////////////

/* Really basic status - use by documents
   like concepts in the TOC */ 
function LmsBasicStatus() {
    this.status = LMS_NOT_ATTEMPTED;  
}

LmsBasicStatus.prototype.getStatus = function() {
    return this.status;
}

LmsBasicStatus.prototype.setStatus = function(status) {
    this.status = status;
}

LmsBasicStatus.prototype.Save = function(lmscom) {
    lmscom.lesson_status = this.status;
}

///////////////////////////////////////
// Topic status
///////////////////////////////////////
LmsTopicStatus.prototype = new LmsBasicStatus();
LmsTopicStatus.prototype.constructor = LmsTopicStatus;
LmsTopicStatus.prototype.BaseClass = LmsBasicStatus.prototype;

function LmsTopicStatus() {
    this.score = "";
    this.passed = false;
    this.modes = new Array();
    this.modes["S"] = new Mode("S");
    this.modes["T"] = new Mode("T");
    this.modes["K"] = new Mode("K");
    this.modes["D"] = new Mode("D");
    this.modes["P"] = new Mode("P");
    this.modes["E"] = new Mode("E");
    
    this.anylaunched = false;  // any mode launched this attempt?
}

LmsTopicStatus.prototype.Save = function(lmscom) {
    var fname = "SaveTopicStatus";

    lmscom.lesson_data = lmscom.bigsco ? "" : this.getStatusstring();
    lmscom.lesson_status = this.getLMSStatus();
    lmscom.score = this.getScore();
}

LmsTopicStatus.prototype.setModeavail = function(m, a) {
    this.modes[m].avail = a;
}

LmsTopicStatus.prototype.getModeavail = function(m) {
    return this.modes[m].avail;
}

LmsTopicStatus.prototype.setModestatus = function(m, s) {
    if (this.modes[m].avail)
        this.modes[m].complete = s;
    else
        lmslog.addEntry(0, "setModestatus", "", "Invalid call of setModestatus");
}

LmsTopicStatus.prototype.getModestatus = function(m) {
    return this.modes[m].complete;
}

LmsTopicStatus.prototype.setRequiredMode = function(lmsModes, playerModes) {
    if (GetTopLevelLmsMode() == "LMS")
        this.requiredMode = this._getRequiredMode(lmsModes);
    else
        this.requiredMode = this._getRequiredMode(playerModes);
}

LmsTopicStatus.prototype._getRequiredMode = function(modes) {
    var modeorder = "EKTSPD";
    for (var i=0; i<modeorder.length; i++) {
        if (modes[modeorder.charAt(i)])
            return modeorder.charAt(i);
    }
    return "None"
}

LmsTopicStatus.prototype.GetRequiredMode = function() {
    return this.requiredMode;
}

LmsTopicStatus.prototype.initTopicstat = function(s) {
    var loopVar;
    var fname = "initTopicstat";
    lmslog.addEntry(0, fname, "", "Start");
    lmslog.addEntry(0, fname, "s string", s);

    lmslog.addEntry(0, fname, "s.length", s.length);
    if (s.length != 0) {
        //split the tracking string
        var f = s.split(",");
        for (loopVar = 0; loopVar <= f.length - 1; loopVar++) {
            lmslog.addEntry(0, fname, "f[" + loopVar + "]", f[loopVar]);
            if (f[loopVar].charAt(1) == "=") {
                this.modes[f[loopVar].charAt(0)].complete = this.modeIscomplete(f[loopVar].substr(2, 1));
            }
            else if (f[loopVar].substr(0, 5) == "PASS=") {
                var flag = f[loopVar].substr(5, 1);
                if (flag == "0")
                    this.passed = false;
                else
                    this.passed = true;
            }
            else if (f[loopVar].substr(0, 6) == "SCORE=") {
                this.score = f[loopVar].substr(6);
            }
        }
    }
}

LmsTopicStatus.prototype.clearTopicstat = function() {
    this.score = "";
    this.passed = false;
    for (var m in this.modes)
        this.modes[m].complete = false;
}

LmsTopicStatus.prototype.getStatusstring = function() {
    var fname = "get_statusstring";
    lmslog.addEntry(0, fname, "", "Start");
    var dataString = "";
    for (x in this.modes) {
        if (dataString.length != 0)
            dataString += ",";
        dataString += this.modes[x].id + "=" + (this.modes[x].complete ? "C" : "I");
    }
    /*if (this.modes["E"].complete) {
        dataString += ",PASS=" + (this.passed ? "1" : "0");
    } else*/ if (this.modes["K"].complete && this.isScored) {
        dataString += ",PASS=" + (this.passed ? "1" : "0") + ",SCORE=" + this.score;
    }
    lmslog.addEntry(0, fname, "dataString", dataString);
    return dataString;
}

LmsTopicStatus.prototype.getStatus = function() {
    var itemstatus = "";
    if (this.isComplete()) {
        //topic is complete
        // NB: Test for avail is still correct here. We want to return "C" to 
        // lmsui if knowit unavailable, even if topic was passed when launched in
        // UT mode.
        if (/*this.modes["E"].avail ||*/ (this.modes["K"].avail && this.isScored)) {
            if (this.passed) {
                itemstatus = LMS_PASSED;
            }
            else {
                itemstatus = LMS_FAILED;
            }
        } else {
            itemstatus = LMS_COMPLETED;
            if (this.savedStatus == "P" || this.savedStatus == "F")
                itemstatus = this.savedStatus;
        }
    } else {
        //topic is not complete
        itemstatus = LMS_INCOMPLETE;
        if (this.savedStatus == "P" || this.savedStatus == "F" || this.savedStatus == "C")
            itemstatus = Stat2Lms(this.savedStatus);
    }
    return itemstatus;
}

// Reports Not Attempted for a completed topic where no mode has been launched.
// This keep us from reporting an attempt if the user is just browsing
// the tree and doesn't do anything.
LmsTopicStatus.prototype.getLMSStatus = function() {
    if (this.isComplete() && !this.anylaunched)
        return LMS_NOT_ATTEMPTED;
    return this.getStatus();
}

LmsTopicStatus.prototype.getScore = function() {
    return this.score;
}

// Is considered complete if either the required
// mode is taken or a mode that allows the users
// to demonstrate more knowledge than the required mode
// has been taken.
// From "Play Mode Filtering in LMS"
LmsTopicStatus.prototype.isComplete = function() {
    var fname = "is_complete";
    lmslog.addEntry(0, fname, "", "Start");
    var iscomp = false;
    
    // Topic has no modes hance no required mode,
    // is considered complete just by visiting it.
    if (this.requiredMode === "None") {
        iscomp = true;
    } else {
        var modeorder = ["E", "K", "T", "S", "P", "D"];
        for (i=0; i<modeorder.length; i++) {
            if (this.modes[modeorder[i]].complete) iscomp = true;
            if (modeorder[i] === this.requiredMode)
                break
        }
    }
    lmslog.addEntry(0, fname, "iscomp", iscomp);
    return iscomp;
}

LmsTopicStatus.prototype.modeIscomplete = function(f) {
    var ret = false;
    var fname = "modeIscomplete";
    lmslog.addEntry(0, fname, "", "Start");
    if (f == "C")
        ret = true;
    else if (f == "I")
        ret = false;
    lmslog.addEntry(0, fname, "ret", ret);
    return ret;
}

LmsTopicStatus.prototype.isRequired = function(m) {
    return this.requiredMode === m;
}
                
// holds the status of a single mode launch of a topic
// pretty much duplicates the code in TopicStatus so if topic mode launched
// standalone (UT mode) it can write back to kpath coordinated with a kpath
// launch of the topic
LmsTopicLaunchStatus.prototype = new LmsTopicStatus();
LmsTopicLaunchStatus.prototype.constructor = LmsTopicStatus;
LmsTopicLaunchStatus.prototype.BaseClass = LmsTopicStatus.prototype;

function LmsTopicLaunchStatus(mode) {
    this.mode = this.modes[mode];
    this.score = "";
    this.passed = false;
    
    this.anylaunched = true;
}

LmsTopicLaunchStatus.prototype.Save = function(lmscom) {
    var fname = "SaveTopicLaunchStatus";

    // serialize state to report back to kpath in UT mode; LMS mode will ignore
    // this and use the mode completion flag for roll-up    
    this.BaseClass.Save.call(this,lmscom);
}

LmsTopicLaunchStatus.prototype._getRequiredMode = function(modes) {
    var modeorder = "EKTSPD";
    for (var i=0; i<modeorder.length; i++) {
        if (modes.indexOf(modeorder.charAt(i)) != -1)
            return modeorder.charAt(i);
    }
    return "None"
}

// returns result when topic is used in an assessment
LmsTopicLaunchStatus.prototype.getResult = function() {
    return this.passed ? "correct" : "incorrect";
}
LmsTopicLaunchStatus.prototype.getQuestionType = function() {
    return "other";
}
LmsTopicLaunchStatus.prototype.getLearnerResponse = function() {
    return "";
}

//////////////////////////////////////////
// Mode object definition
function Mode(mid) {
    this.avail = false;
    this.complete = false;
    this.id = mid;
}

///////////////////////////////////////
// Question status
///////////////////////////////////////
LmsQuestionStatus.prototype = new LmsBasicStatus();
LmsQuestionStatus.prototype.constructor = LmsQuestionStatus;
LmsQuestionStatus.prototype.BaseClass = LmsBasicStatus.prototype;

function LmsQuestionStatus() {
    this.question_type = null;
    this.learner_response = null;
    this.result = null;
}

LmsQuestionStatus.prototype.Save = function(lmscom) {
    lmscom.lesson_status = this.status;
    lmscom.lesson_data = Lms2Stat(this.getStatus());
}

LmsQuestionStatus.prototype.getStatus = function() {
    return this.status === LMS_NOT_ATTEMPTED ? this.savedStatus : this.status;
}

/* get/set question type */
LmsQuestionStatus.prototype.getQuestionType = function() {
    return this.question_type;
}

LmsQuestionStatus.prototype.setQuestionType = function(qtype) {
    return this.question_type = qtype;
}

/* get/set Learner Response */
LmsQuestionStatus.prototype.getLearnerResponse = function() {
    return this.learner_response;
}

LmsQuestionStatus.prototype.setLearnerResponse = function(lresp) {
    return this.learner_response = lresp;
}

LmsQuestionStatus.prototype.getResult = function() {
    return this.result;
}

LmsQuestionStatus.prototype.setResult = function(result) {
    return this.result = result;
}

///////////////////////////////////////
// Assessment status
///////////////////////////////////////
LmsAssessmentStatus.prototype = new LmsBasicStatus();
LmsAssessmentStatus.prototype.constructor = LmsAssessmentStatus;
LmsAssessmentStatus.prototype.BaseClass = LmsBasicStatus.prototype;

function LmsAssessmentStatus() {
    this.score = "";
    this.questionstatus = new Array();
    this.stateDiscarded = false;    // saved state was discarded due to change in assessment
}

LmsAssessmentStatus.prototype.Save = function(lmscom) {
    lmscom.lesson_status = this.status;

    if (this.status != LMS_INCOMPLETE &&
        this.status != LMS_NOT_ATTEMPTED)
        lmscom.score = this.score;
    else
        lmscom.score = "";

    var str = "";
    if (!lmscom.bigsco)
        str = this.hash.length + "@" + this.hash;
    // if a new attempt and we didn't do anything, keep old saved status    
    str += this.status == LMS_NOT_ATTEMPTED ? this.savedStatus : Lms2Stat(this.status);
    for (var i=0; i<this.questionstatus.length; i++)
        str += this.questionstatus[i];
    lmscom.lesson_data = str;
}

LmsAssessmentStatus.prototype.getStatus = function() {
    return this.status === LMS_NOT_ATTEMPTED ? Stat2Lms(this.savedStatus) : this.status;
}

LmsAssessmentStatus.prototype.getLMSStatus = function() {
    return this.status;
}
/* get/set Learner Response */
LmsAssessmentStatus.prototype.getScore = function() {
    return this.score;
}

LmsAssessmentStatus.prototype.setScore = function(score) {
    return this.score = score;
}

///////////////////////////////////////
// TOC status
///////////////////////////////////////
LmsTOCStatus.prototype = new LmsBasicStatus();
LmsTOCStatus.prototype.constructor = LmsTOCStatus;
LmsTOCStatus.prototype.BaseClass = LmsBasicStatus.prototype;

function LmsTOCStatus() {
}

LmsTOCStatus.prototype.getStatus = function() {
    return Stat2Lms(this.getTocState().GetStatus(0));
}

LmsTOCStatus.prototype.Save = function(lmscom) {
    lmscom.lesson_status = this.getStatus();

    var tocstat = this.getTocState();
    lmscom.lesson_data = tocstat.SerializeTOC();
}

/* get/set the state structure for the entire
   TOC */
LmsTOCStatus.prototype.getTocState = function() {
    return this.tocstate;
}

LmsTOCStatus.prototype.setTocState = function(tocstate) {
    return this.tocstate = tocstate;
}

function NodeState() {
    this.Status = 'N';
    this.Score = null;
    this.ChildrenStatus = ""; 
}

/* class that holds the state of the tree */
function TOCState(count, tocversion)
{
    this.NodeCounter = count;
    this.TocVersion = tocversion;
    
    this.InitInLookupTable();
}

/* sets the status of the outline element based on its index */
TOCState.prototype.SetStatus = function(index, status) {
    if (!this.LookUpTable[index])
        this.LookUpTable[index] = new NodeState();
    this.LookUpTable[index].Status = status;
}

/* gets the status of the outline element based on its index */ 
TOCState.prototype.GetStatus = function(index) {
    return this.LookUpTable[index].Status;
}

/* sets the score of the outline element based on its index */
TOCState.prototype.SetScore = function(index, score) {
if (!this.LookUpTable[index])
    this.LookUpTable[index] = new NodeState();
    
    this.LookUpTable[index].Score = score;
}

/* gets the score of the outline element based on its index */ 
TOCState.prototype.GetScore = function(index) {
    return this.LookUpTable[index].Score;
}

/* sets the score of the outline element based on its index */
TOCState.prototype.SetChildren = function(index, ChildrenStatus) {
if (!this.LookUpTable[index])
    this.LookUpTable[index] = new NodeState();
    
    this.LookUpTable[index].ChildrenStatus = ChildrenStatus;
}

/* gets the score of the outline element based on its index */ 
TOCState.prototype.GetChildren = function(index) {
    return this.LookUpTable[index].ChildrenStatus;
}

/* Deserializes the persisted state (str) into the TOC XML
   outline structure */
TOCState.prototype.DeserializeTOC = function(str) {
    var count = 0;
    var version;

    var index = str.indexOf("@");
    var count;

    if (index > 0) {
        count = parseInt(str.substring(0, index));
        version = str.substring(index + 1, index + count + 1);
    }
    else
        return;

    /* if the TOC has changed since last 
    time data was persisted, throw away the 
    persisted data */
    if (version != this.TocVersion)
        return;

    var statusstr = str.substring(index + count + 2);

    index = statusstr.indexOf("@");
    if (index > 0) {
        count = parseInt(statusstr.substring(0, index));
        statusstr = statusstr.substring(index + 1, index + count + 1);

        /* if the status string isn't equal to the 
        count we stored for it,then the string got 
        truncated by the LMS because it was too big
        so throw away the data */
        if (statusstr.length != count)
            return;
    }
    else
        return;

    statusstr = this.RLESDecode(statusstr);
    str = this.DeserializeLookUpTable(statusstr);
}

/* Deserializes the persisted state (str) of just the tree portion 
   of the outline into the XML outline structure */
TOCState.prototype.DeserializeLookUpTable = function(str) {
    var count = 0;
    var score = "";

    for (var i = 0; i < str.length; i++) {
        var status = str.charAt(i);
        this.SetStatus(count, status); 
        
        score = "";
        while (i < str.length - 1 && str.charAt(i+1) >= "0" && str.charAt(i+1) <= "9") {
            i++;
            score += str.charAt(i);      
        }

        if (score.length > 0)
           this.SetScore(count, parseInt(score));
        
        if (i < str.length - 1 && str.charAt(i+1) == "{") {
            var j = str.indexOf("}",i+2);
            this.SetChildren(count, str.substring(i+2,j));
            i = j;
        }
        
        count++;
    }
}

//this.TocVersion.length
TOCState.prototype.SerializeTOC = function() {
    var statusstr = this.RLESEncode(this.SerializeLookupTable());
    return this.TocVersion.length + "@" + this.TocVersion + " " + statusstr.length + "@" + statusstr;
}

TOCState.prototype.SerializeLookupTable = function() {
    var str = '';

    for (var i = 0; i < this.NodeCounter; i++) {

        var status = this.LookUpTable[i].Status;
        var score = this.LookUpTable[i].Score;
        var childrenstatus = this.LookUpTable[i].ChildrenStatus;

        if (!status) status = "N";

        str += status;
//        if (score !== null)
//            str += score;
            
        if (childrenstatus)
            str += "{" + childrenstatus + "}";            
    }

    return str;
}

TOCState.prototype.InitInLookupTable = function() {
    this.LookUpTable = new Array();

    for (var i = 0; i < this.NodeCounter; i++) {
        this.LookUpTable[i] = new NodeState();
    }
    this.SetStatus(0, "I");
}

/* Run lenght encode (RLE) the string to compress the storage */
TOCState.prototype.RLESEncode = function(str) {
    var last = '';
    var run = 0;
    var outstr = '';

    last = str.charAt(0);
    run = 1;

    for (var i = 1; i < str.length; i++) {
        if (str.charAt(i) == last) {
            run++;
        }
        else {
            if (run > 2) {
                outstr += "#";
                outstr += run;
                outstr += last;
            }
            else {
                outstr += str.substring(i - run, i)
            }

            last = str.charAt(i);
            run = 1;
        }
    }

    if (run > 2) {
        outstr += "#";
        outstr += run;
        outstr += last;
    }
    else {
        outstr += str.substring(i - run, i)
    }

    return outstr;
}

/* Run lenght decode (RLE) the string */
TOCState.prototype.RLESDecode = function(str) {
    var outstr = '';
    var runcountstr = '';
    var runcount;

    for (var i = 0; i < str.length; i++) {
        if (str.charAt(i) == '#') {
            runcountstr = '';
            i++;
            while (str.charAt(i) >= "0" && str.charAt(i) <= "9") {
                runcountstr += str.charAt(i);
                i++;
            }

            runcount = parseInt(runcountstr);
            for (var j = 0; j < runcount; j++)
                outstr += str.charAt(i);
        }
        else
            outstr += str.charAt(i);
    }

    return outstr;
}

function Lms2Stat(lmsStatus) {
    return lmsStatus.charAt(0).toUpperCase();
}

function Stat2Lms(status) {
    return [LMS_PASSED, LMS_FAILED, LMS_COMPLETED, LMS_INCOMPLETE, LMS_NOT_ATTEMPTED]["PFCIN".indexOf(status)];
}
/////////////////////
// LogEntry object //
/////////////////////

function LogEntry(startdate, ltype, funcname, varname, msgval) {
    this.logType = ltype;
    this.funcName = funcname;
    this.varName = varname;
    this.msgValue = msgval;
    this.dateTime = new Date().getTime() - startdate;   //Store the entry time in millisecs after the log started
    //alert(this.toString());
}

LogEntry.prototype.GetTableRow = function(i) {
    var typeMsg = "Info";
    var color = "#006600";

    if (this.logType === 1) {
        typeMsg = "LMS Comm";
        color = "#000033";
    }

    var varName = this.varName;
    if (varName === "") { varName = "&nbsp;"; }

    var msgValue = this.msgValue;
    if (msgValue === "") { msgValue = "&nbsp;"; }

    var html = "<tr>";
    html += "<td align='right'>" + (this.dateTime / 1000) + "</td>";
    html += "<td style='color:" + color + ";'>" + this.funcName + "</td>";
    html += "<td>" + varName + "</td>";
    html += "<td>" + msgValue + "</td>";
    html += "</tr>";

    return html;
}


////////////////
// Log object //
////////////////
function Log(active) {
    this.traceWindow = null;
    this.logArray = new Array();
    this.enabled = active;
    this.startDateTime = new Date();
    this.changed = true;    // Flag for letting external parties know when the log has changed
    this.windowReady = false;
    this.startLog();
}

Log.prototype.startLog = function() {
    if (this.enabled) {
        //this.log_string += "<table border='1'><tr><td>Type</td><td>Function</td><td>Variable</td><td>Message</td></tr>";
        this.addEntry(0, "initLog", "", "Log Intialized");
        this.openTraceWindow();
    }
}

Log.prototype.addEntry = function(ltype, funcname, varname, msgval) {
    if (this.enabled) {
        this.logArray.push(new LogEntry(this.startDateTime.getTime(), ltype, funcname, varname, msgval));
        this.changed = true;
        if (this.traceWindow && this.windowReady)
            this.traceWindow.UpdateTraceStack();
    }
}

Log.prototype.writeLog = function(sortOrder, traceLength) {
    var t = traceLength;
    if (t > this.logArray.length || t == 0) {
        t = this.logArray.length;
    }

    var html = "<table width='600'>";
    html += "<tr>";
    html += "<th colspan=4>Session start: " + this.startDateTime + "</th>";
    html += "</tr>";

    html += "<tr>";
    html += "<th>time</th>";
    html += "<th>function</th>";
    html += "<th>variable</th>";
    html += "<th>message</th>";
    html += "</tr>";

    var logEntry;
    if (sortOrder == 0) {
        for (var i = this.logArray.length - t; i < this.logArray.length; i++) {
            logEntry = this.logArray[i];
            html += logEntry.GetTableRow(i);
        }
    } else {
        for (var i = this.logArray.length - 1; i >= this.logArray.length - t; i--) {
            logEntry = this.logArray[i];
            html += logEntry.GetTableRow(i);
        }
    }
    html += "</table>";

    this.changed = false;   // Reset the changed flag
    this.windowReady = true;    // window initiates first call to writelog, so we know we're up
    return html;
}

Log.prototype.writeDetails = function(i) {
    return this.logArray[i].GetDetails();
}

Log.prototype.openTraceWindow = function() {
    if (this.traceWindow == null) {
        this.changed = true;
        this.traceWindow = window.open(lms_path + "lmsdebug.html", "_blank");
    }
}
/* lms_init.js */ 
/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

// javascript include area

/*
if (typeof lms_path == 'undefined')
lms_path = "../../../";

document.write('<script type="text/javascript" src="' + lms_path + 'kpsettings.js"></script>');
document.write('<script type="text/javascript" src="' + lms_path + 'js/scormoptions.js"></script>');
document.write('<script type="text/javascript" src="' + lms_path + 'js/lmsoptions.js"></script>');
document.write('<script type="text/javascript" src="' + lms_path + 'js/lmsapplet.js"></script>');
document.write('<script type="text/javascript" src="' + lms_path + 'js/lmsresource.js"></script>');
document.write('<script type="text/javascript" src="' + lms_path + 'js/lmscomfactory.js"></script>');
document.write('<script type="text/javascript" src="' + lms_path + 'js/lmscom.js"></script>');
document.write('<script type="text/javascript" src="' + lms_path + 'js/escape.js"></script>');



<script type="text/javascript" src="kpsettings.js"></script>
<script type="text/javascript" src="js/scormoptions.js"></script>
<script type="text/javascript" src="js/lmsoptions.js"></script>
<script type="text/javascript" src="js/lmsapplet.js"></script>
<script type="text/javascript" src="js/lmsresource.js"></script>
<script type="text/javascript" src="js/lmscomfactory.js"></script>
<script type="text/javascript" src="js/lmscom.js"></script>
<script type="text/javascript" src="js/escape.js"></script>


*/

// launch mode determination

var _lmsMode = null;          // LMS, KPT, Cookie or undefined

var _lmsParser = null;

function InitLmsMode(source) {
    if (_lmsParser == null) {
        _lmsParser = new UrlParser();
        _lmsParser.Parse();

        // direct launch
        if (source == "player") {
            if (_lmsParser.GetParameter("directlaunch") != null) {
                _lmsMode = (Kpath_launch == true ? "KPT" : "Cookie");
            }
        }

        // lmstart
        else if (source == "lmstart") {
            if (_lmsParser.GetParameter("toc") != null) {
                // _lmsMode = null;
            }
            else if (_lmsParser.GetParameter("dhtml") != null) {
                _lmsMode = (Kpath_launch == true ? "KPT" : "Cookie");
            }
            else {
                _lmsMode = "LMS";
            }
        }

        // toc
        else if (source == "toc") {
            if (_lmsParser.GetParameter("sco") == null) {
                _lmsMode = (Kpath_launch == true ? "KPT" : "Cookie");
            }
        }

        else {
            alert(R_undefined_lms_source);
        }
    }
}

function GetTopLevelLmsMode() {
    return _GetTopLevelLmsMode(this);
}

function _GetTopLevelLmsMode(w) {
    var m = w._lmsMode;
    if (m == null) {
        return _GetTopLevelLmsMode(w.lms_store.parentW);
    }
    return m;
}

// common lms callback functionality

var lms_initialized = false;

var lms_store;

var lmslog;

// lms_InitPage()
// called from onLoad event
function lms_InitPage(childIndex, parentW, cguid, callbackfunction) {
    if (lms_initialized == true) {
        setTimeout(callbackfunction, 1);
        return;
    }
    __Ialert("lms_InitPage called with parameters:" + childIndex + "," + parentW + "," + cguid + "," + callbackfunction);

    lms_store = { window: window,
        childIndex: childIndex,
        parentW: parentW,
        cguid: cguid,
        callbackfunction: callbackfunction
    };

    if (!parentW || parentW.closed) {
        lmslog = new Log(LmsConfig.DebugMode);
        InitializeLmsCom();
        InsertRuntimeAPI(lms_LoadRuntimeComplete);
    } else {
        if (!parentW.lms_initialized) return; // handle funky refresh handling of Firefox
        lmslog = parentW.lmslog;
        setTimeout(lms_LoadRuntimeComplete, 1);
    }
}

function lms_LoadRuntimeComplete() {
    __Ialert("lms_LoadRuntimeComplete() called");
    if (lms_store.parentW && !lms_store.parentW.closed) {
        lms_store.parentW.GetChildLmsCom(lms_store);
    } else if (!lms_store.parentW && !lms_store.cguid && !window.bigScoItemCount) { // launching a non-bigsco toc
        // NB: window.bigScoItemCount will only be defined in the lmstart page of a big sco
        document.LmsCom = PlayerConfig.EnableCookies ? new LmsComCookie() : new LmsComBase();
    } else {
        CheckForLMSAPI();
        document.LmsCom = _GlobalLmsComFactory.CreateLmsCom();
    }
    var lmscom = document.LmsCom;

    lmscom.guid = lms_store.cguid;
    lmscom.owner = window;
    lmscom.LoadAPIAdapter(lms_LoadAdapterComplete);
}

// lms_UpdateUI()
// called from first level assets to update the UI status bar
function lms_UpdateUI(status) {
    try {
        if (parent && parent.updateUI)
            parent.updateUI(status);
    } catch (e) { }
}

// lms_ClosePage()
// called from onUnload event
var hasClosed = false;
function lms_ClosePage(callClose) {
    __Ialert("lms_ClosePage() called");
    if (hasClosed == true)
        return;
    hasClosed = true;
    var lmscom = document.LmsCom;
    if (!lmscom || !lmscom.session_active)
        return;
    var childlmscom = lmscom.child;
    if (childlmscom && childlmscom.session_active && childlmscom.owner && !childlmscom.owner.closed)
        childlmscom.owner.lms_ClosePage(true);
    childlmscom = lmscom.ancillaryChild;    // close see also trail, if any
    if (childlmscom && childlmscom.session_active && childlmscom.owner && !childlmscom.owner.closed)
        childlmscom.owner.lms_ClosePage(true);
    if (window._closePage)
        _closePage();   // do any asset specific stuff
    if (lmscom.session_active) {    // test if our twin (lmstart/lmsui) snuck in (FF)
        lmscom.SaveStatus();
        lmscom.End();
        lmscom.NotifyParent();
    }
    if (callClose)
        window.close();
}

// connection drop
function lms_ConnectionLost(errText) {
    if (window.ConnectionLostEvent)
        ConnectionLostEvent(errText);
    if (lms_store.parentW && !lms_store.parentW.closed)
        lms_store.parentW.lms_ConnectionLost(errText);
}

function lms_IsConnected() {
    var lmscom = document.LmsCom;
    if (lmscom)
        return lmscom.IsConnected();
    return false;
}

// KPath logout
function lms_IsKPathLogoutAvailable() {
    return !!window.Kpath_logout_available;
}

function _logout(closeWindow) {
    if (lms_store.parentW && !lms_store.parentW.closed && lms_store.parentW._logout) {
        lms_store.parentW._logout(false);
    } else if (window.Kpath_logout_URL) {
        if (GetTopLevelLmsMode() == "LMS") {
            window.parent.parent.location.replace(Kpath_logout_URL);
        } else if (closeWindow) {   // need to logout through the opener window
            if (window.opener && !window.opener.closed) {
                var thisPage = window.opener.location.href;
                window.opener.location.replace(Kpath_logout_URL + "&RedirectURL=" + escape(thisPage));
                window.close();
            } else if (IsTouchDevice()) {   // this will need to go for HR when we get better with the ipad
                var w = window.location.href.split('/').slice(0,5).join('/') + "/ipad.html";
                window.location.replace(Kpath_logout_URL + "&RedirectURL=" + escape(w));
            } else {    // if no opener available, must logout through full screen topic window
                window.location.replace(Kpath_logout_URL);
            }
        } else {
            var thisPage = window.location.href.replace("?genctx","");  // strip if returning to smartmatch TOC
            window.location.replace(Kpath_logout_URL + "&RedirectURL=" + escape(thisPage));
        }
    }
}

// user profile (so it is accessible from everywhere)
function lms_IsUserProfileAvailable() {
    __alert("lms_IsUserProfileAvailable() called");
    if (GetTopLevelLmsMode() !== "KPT")
        return false;
    return document.LmsCom.doGetUPKValue("upk.anonymous") == "0";
}

function lms_GetUserProfileUrl() {
    __alert("lms_GetUserProfileUrl() called");
    if (Kpath_launch == false)
        return "";
    return Kpath_profile_URL + "?UPKLaunch=true";
}

function GetNoSound() {
    if (lms_store.parentW && !lms_store.parentW.closed)
        return lms_store.parentW.GetNoSound();
    else
        return lms_store.noSound;
}

function SetNoSound(value) {
    lms_store.noSound = value;
}

// lms callback trace functions

var _lms_show_all_alert = false;

function __alert(s) {
    if (_lms_show_alert || _lms_show_all_alert)
        alert(s + "\nfile: " + _lms_module_name);
}

function __Ialert(s) {
    if (_lms_show_alert || _lms_show_Ialert || _lms_show_all_alert)
        alert(s + "\nfile: " + _lms_module_name);
}/* lms_topic.js */ 
/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

// include lms_init.js
/*
document.write('<script> lms_path="../../../"</script>');
document.write('<script type="text/javascript" src="../../../js/lms_init.js"></script>');
*/
var _modeLaunch = "incomplete";	// LMS_INCOMPLETE not ready yet?
var _feedbackUrlArgs = "";

// callback functions from topic

function lms_LoadAdapterComplete() {
    __alert("lms_LoadAdapterComplete() called");
    
    var lmscom = document.LmsCom;
    lmscom.Begin();
    if (lmscom.assessment_guid)
        lmscom.doSetUPKValue("upk.actual_guid",lmscom.assessment_guid);
    lmscom.utPushModeIndex();    // set up for UT tracking if under kpath

    // recall the topic player, do not remove
    lms_initialized = true;
    setTimeout(lms_store.callbackfunction, 1);
}

function GetChildLmsCom(child_store) {
    __Ialert("lms_GetChildLmsCom() called");
    var lmscom = document.LmsCom;
    var childlmscom = child_store.window.document.LmsCom = new LmsComBase(lmscom);
    childlmscom.owner = child_store.window;
    lmscom.child = childlmscom;
}

function ListenChildClose() {
    __alert("lms_ListenChildClose() called");

    var lmscom = document.LmsCom;

    var childlmscom = lmscom.child;
    if (childlmscom) {
        var topicStat = lmscom.status_obj
        var launchStat = childlmscom.status_obj;
        var mode = topicStat.modes[childlmscom.status_obj.mode.id];
        mode.complete = launchStat.mode.complete;
        lmscom.utPopModeIndex();
    }
}

// asset specific processing called from lms_init on ClosePage
// End the UT session. Pulled out of topicFinish so that it can be called from ClosePage in case topic is exited before
// being completed.
function _closePage() {
    var lmscom = document.LmsCom;
    lmscom.utRecordEndTime(new Date());
    lmscom.utRecordCompletionStatus(_modeLaunch);
}

// called when a mode is selected to launch the topic in order to set up the
// child lmscom object
function lms_LaunchTopic(mode) {
    __alert("lms_LaunchTopic(" + mode + ") called");

    var lmscom = document.LmsCom;

    if (mode == "P") {
        lmscom.utPushModeIndex();
        lmscom.utRecordType("print_it");
        lmscom.utRecordStartTime(new Date());
        lmscom.utRecordEndTime(new Date());
        lmscom.utRecordCompletionStatus(LMS_COMPLETED);
        lmscom.utPopModeIndex();
        lmscom.status_obj.setModestatus("P", true);
        lmscom.SaveStatus();
        return;
    }
}

// lms_topicStart(guid,mode)
// called when a topic starts
function lms_topicStart(guid, mode) {
    __alert("lms_topicStart() called with parameters: " + guid + "," + mode);

    var lmscom = document.LmsCom;
    if (lmscom.assessment_guid) // if in an assessment, make sure knowit is in modes so it will be reported scored
        lmscom.OpenTopicLaunchStatus(mode, lmsModes + 'K', playerModes + 'K');
    else
        lmscom.OpenTopicLaunchStatus(mode, lmsModes, playerModes);
    if (lmscom.lesson_status === LMS_NOT_ATTEMPTED && lmscom.status_obj.isComplete()) {    // new attempt with kpath-persisted data
        lmscom.status_obj.clearTopicstat();    // clear out old state
    }

    var modeType = ["see_it", "try_it", "know_it", "do_it", "print_it", "test_it"]["STKDPE".indexOf(mode)];
    lmscom.utRecordType(modeType);
    lmscom.utRecordStartTime(new Date());
}

// lms_topicFinish(guid)
// called when a topic finishes
function lms_topicFinish(guid) {
    __alert("lms_topicFinish() called with parameter: " + guid);
    var lmscom = document.LmsCom;
    lmscom.status_obj.mode.complete = true;
    _modeLaunch = LMS_COMPLETED;
}

// lms_frameView(guid, mode, frameid)
// called when a frame appears
function lms_frameView(guid, mode, frameid) {
    __alert("lms_frameView() called with parameter: " + guid + "," + mode + "," + frameid);
    var lmscom = document.LmsCom;
    lmscom.utRecordFrameViewed(frameid);
    _feedbackUrlArgs = "&FrameID=" + frameid + "&UPKMode=" + mode; 
}

// lms_knowitScore(guid, score, passed)
// called when a topic finished in knowit mode
function lms_knowitScore(guid, score, passed) {
    __alert("lms_knowitScore called with parameter: " + guid + "," + score + "," + passed);
    var lmscom = document.LmsCom;
    lmscom.status_obj.mode.complete = true;
    lmscom.status_obj.score = score;
    lmscom.status_obj.passed = passed;
    lmscom.utRecordSuccessStatus(passed ? "passed" : "failed");
    lmscom.utRecordScoreScaled(score / 100);
}

function lms_getUserName() {
    var lmscom = document.LmsCom;
    var username = lmscom.student_name;
    return username;
}

function lms_KPathLogout() {
    _logout(true);
}
    
//----------------------------------------------------------------------------------------------/

var _lms_module_name = "lms_topic.js";
var _lms_show_alert = false;
var _lms_show_Ialert = false;
/* relativelink.js */ 
﻿// Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.

// Split an URI into three main parts
function splitUri(uri) {
    // Split the URI into parts
    var parts = uri.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/);
    parts.shift();

    // Identidy tge different parts
    var scheme = parts[1], authority = parts[3], path = parts[4], querystring = parts[6], frag = parts[8];

    // Build the three main part of the URI: prefix, path, postfix
    parts = [scheme + "://" + authority, path, querystring + frag];

    // Return the three main parts as an array
    return parts;
}

// Combine base and relative URL into a resolved URL
function combine(baseUrl, relativeUrl) {

    // Remove the "odrel://" prefix if exists
    var relativePath = relativeUrl;
    if (relativePath.indexOf('odrel://') == 0)
        relativePath = relativePath.substr('odrel://'.length);

    // Empty relative path points to base path
    if (relativePath == "") relativePath = ".";

    // Split the base url into the main three parts
    var baseUrlparts = splitUri(baseUrl);
    var baseUrlPrefix = baseUrlparts[0]; var baseUrlPath = baseUrlparts[1];

    // Trim slashes
    if (baseUrlPath.charAt(0) == '/') baseUrlPath = baseUrlPath.substr(1);
    if (baseUrlPath.charAt(baseUrlPath.length - 1) == '/') baseUrlPath = baseUrlPath.substr(0, baseUrlPath.length - 1);
    if (relativePath.charAt(relativePath.length - 1) == '/') relativePath = relativePath.substr(0, relativePath.length - 1);

    // Split the paths into segments
    var baseUrlPathSegments = baseUrlPath.split('/');
    var relativePathSegments = relativePath.split('/');

    if ((relativePathSegments.length > 2) && (relativePathSegments[0] == '') && (relativePathSegments[1] == '')) {
        var path = baseUrlPrefix.split(':')[0] + ":/";
        for (var i = 2; i < relativePathSegments.length; i++)
            path += "/" + relativePathSegments[i];

        return path;
    }

    // Initialize the segments of the resolved path
    var resolvedPathSegments = new Array();
    for (var i = 0; i < baseUrlPathSegments.length; i++)
        resolvedPathSegments[i] = baseUrlPathSegments[i];

    // Resolve the relative address
    for (var i = 0; i < relativePathSegments.length; i++) {
        if (relativePathSegments[i] == "..") {
            if (resolvedPathSegments.length > 0) {
                // Remove the last folder in the URI
                resolvedPathSegments = resolvedPathSegments.slice(0, resolvedPathSegments.length - 1);
            }
        }
        else if (relativePathSegments[i] == ".") {
            // Do nothing
        }
        else if (relativePathSegments[i] == "") {
            // Remove all segments from the base URL
            resolvedPathSegments = new Array();
        }
        else {
            // Add the segment to the end of the resolved address
            resolvedPathSegments[resolvedPathSegments.length] = relativePathSegments[i];
        }
    }

    // Build the resolved path
    var resolvedPath = '';
    for (var i = 0; i < resolvedPathSegments.length; i++)
        resolvedPath += '/' + resolvedPathSegments[i];
    var resolvedUrl = baseUrlPrefix + resolvedPath;

    // Return the resolved URI
    return resolvedUrl;
}

// Get the root URL of the player (folder of the index.html)
function getRootUrl() {

    // If the function is running in toc.html
    if (typeof (isTocHtml) != "undefined") {
        var url = document.location.href;
        return url.substr(0, url.lastIndexOf("/"));
    }

    // Split the URL of current document into parts
    var documentUrlParts = splitUri(document.location.href);
    var documentUrlPrefix = documentUrlParts[0];
    var documentUrlPath = documentUrlParts[1];

    // Trim the document path
    if (documentUrlPath.charAt(0) == '/') documentUrlPath = documentUrlPath.substr(1);

    // Split the document URL path into segments
    var documentPathSegments = documentUrlPath.split('/');

    // Find the tpc folder in the document path
    var i;
    for (i = documentPathSegments.length - 1; documentPathSegments[i] != 'tpc' && i >= 0; i--) { };

    if (i > 0) i = i - 1;

    // Build the path of the root URL
    var rootPath = "";
    for (var j = 0; j < i; j++)
        rootPath += "/" + documentPathSegments[j];

    // Build the root URL
    var rootUrl = documentUrlPrefix + rootPath;

    // Return the root URL
    return rootUrl;
}

function isRelative(uri) {
    // Split the URI into parts
    var parts = uri.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/);

    // If there is no scheme in the uri, then it's relative
    return (parts[1] == '') || (parts[1] == undefined);
}

// Checks the url and resolves if it is relative
function resolveIfRelative(Url) {
    if (Url.indexOf("odrel://") == 0)
        return resolve(Url);
    else
        return Url;
}

// Resolve a relative URL based on the configured base address
function resolve(relativeUrl) {

    // If the base URL is relative
    if (isRelative(PlayerConfig.BaseUrl)) {
        // Get the URL of the player root
        var rootUrl = getRootUrl();
        // Get hte basolute base URL
        var absoluteBaseUrl = combine(rootUrl, PlayerConfig.BaseUrl);
        // Resolve the relative URL
        return combine(absoluteBaseUrl, relativeUrl);
    }
    // If the base URL is absolute
    else {
        // Resolve the relative URL
        return combine(PlayerConfig.BaseUrl, relativeUrl);
    }
}

// Resolve all link in a web page
function resolveLinksInWebPage() {
    // Get the links from the document
    var links = document.getElementsByTagName("a");

    // For each link
    for (var i = 0; i < links.length; i++)
    // If the link is relative        
        if (links[i].getAttribute("href").indexOf('odrel://') == 0) {
        // Resolve the URL
        links[i].href = resolve(links[i].getAttribute("href"));
    }
}/* timeline.js */ 
/*--
Copyright � 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

// adding a last operator to the JavaScript
// array class  
if (!Array.prototype.last) {
    Array.prototype.last = function () {

        if (this.length > 0)
            return this[this.length - 1];
        else
            return null;
    }
}

// adding a first operator to the JavaScript 
// array class.  Isn't used anywhere, I just
// like symmetry. 
if (!Array.prototype.first) {
    Array.prototype.first = function () {
        if (this.length > 0)
            return this[0];
        else
            return null;
    }
}


// UPKDelegate class

function UPKDelegate() {
    this.fn = new Array();
}

UPKDelegate.prototype.Raise = function (sender, args) {
    for (var i = 0; i < this.fn.length; i++) {
        this.fn[i](sender, args);
    }
}

UPKDelegate.prototype.Register = function (fn) {
    this.fn.push(fn);
}

UPKDelegate.prototype.Unregister = function (fn) {
    for (var i = 0; i < this.fn.length; i++) {
        if (this.fn[i] == fn) {
            this.fn.splice(i, 1);
            return;
        }
    }
    alert("UPKDelegate.Unregister failed to find function");
}

UPKDelegate.prototype.Count = function () {
    return this.fn.length;
}


var upk = upk || {};


upk.Timeline = (function () {
    var _this = {};

    var _timeline = new Array();
    var _lockTimeline = false;

    var _currentFrameIndex = -1;
    _timeline.push("start");

    var _TotalTime = 0;
    var _AccumalitiveCurrentFrameTime = 0;
    var _lastFrameTime = 0;
    var _lastFrame = 0;
    var _initialized = false;

    var _ProgressDelegate = new UPKDelegate();

    // Used by the frame walking algorithm to 
    // make sure we cycles in the graphi are 
    // only traversed once.  
    // Note we only need to put branch points
    // onto the list. 
    var _marklist;


    /*  What state is the frame playing it.  
    
    can be one of:
    B - beginning
    D - waiting out frame delay
    S - Play sound
    A - Playing out animation 
    */
    var _FrameState = "B";

    /* time counter used by the delay and 
    animation parts of the frame playback
    to update time progress. */
    var _FrameTimeCounter;

    /******************* private method section ******************************/

    /* This function  looks for the frame.  This search
    is sensitive which direction the timeline is 
    being played in.  Hence why direction is passed 
    in. */
    function FindTimelineIndex(frame, dir) {
        /* see if the requested frame is somewhere after current */

        if (dir == "back") {
            /* check back in the timeline first */
            for (var i = (_currentFrameIndex - 1); i >= 0; i--) {
                if (_timeline[i] == frame) {
                    return i;
                }
            }

            /* Check forward on the timline second*/
            for (var i = _currentFrameIndex; i < _timeline.length; i++) {
                if (_timeline[i] == frame) {
                    return i;
                }
            }
        }
        else {
            /* Check forward on the timline first */
            for (var i = _currentFrameIndex; i < _timeline.length; i++) {
                if (_timeline[i] == frame) {
                    return i;
                }
            }

            /* check back in the timeline second */
            for (var i = (_currentFrameIndex - 1); i >= 0; i--) {
                if (_timeline[i] == frame) {
                    return i;
                }
            }
        }

        return -1;
    }


    /* function to check is the frame is
    in the already visited marked list */
    function InMarkList(frame) {
        for (var i = 0; i < _timeline.length; i++) {
            if (_marklist[i] == frame) {
                return true;
            }
        }

        return false;
    }

    function GetFrameSoundDuration(frame) {
        var action = screens[frame].actions[0];

        if (_HasSound(action)) {
            var asx = (action.id).substr(1) + ".ASX";
            var ret = StandardTimeToMillisecs(sounds[asx].duration);
            return (isNaN(ret) ? 0 : (ret + 300));
        }

        return 0;
    }

    function GetFrameDelayTime(frame) {
        var delay = screens[frame].actions[0].delay;

        if (delay != DELAY_INFINITE)
            return delay * 100;

        return 0;
    }

    // Computes the time it takes to play a specic frame
    // in 1/1000 of a second. 

    function GetFrameDurationNarration(frame) {
        if (frame == "end")
            return 0;
        var action = screens[frame].actions[0];
        if (_HasSound(action))
            return GetFrameSoundDuration(frame);

        else
            return GetFrameDelayTime(frame);
    }

    function GetFrameDurationAnimation(frame) {
        if (frame == "end")
            return 0;
        var action = screens[frame].actions[0];
        return action.animTime;
    }

    function GetFrameDuration(frame) {
        return GetFrameDurationNarration(frame) + GetFrameDurationAnimation(frame);
    }

    function GetFrameCurrentTime() {
        var time = 0;
        var frame = _this.GetCurrentFrame();
        if (!frame)
            return 0;
        if (frame == "end")
            return 0;
        var action = screens[frame].actions[0];

        switch (_FrameState) {
            case "A": /* in animatio section */
                if (_HasSound(action))
                    time += GetFrameSoundDuration(frame);
                else
                    time += GetFrameDelayTime(frame);

                time += _FrameTimeCounter;
                break;

            case "D": /* in time delay */
                time = _FrameTimeCounter;
                break;

            case "S":  /* in sound play back */
                time = SoundPlayer_GetTime();
                break;

            case "B": /* just started */
                time = 0;
                break;
        }
        var frameduration = GetFrameDuration(frame);
        if (time > frameduration)
            time = frameduration;

        if (_lastFrame == frame) {
            if (time < _lastFrameTime)
                time = _lastFrameTime;
            else
                _lastFrameTime = time;
        }
        else
            time = 0;

        _lastFrame = frame;
        return time;
    }


    /* Reset some frame state stuff and update 
    the accumaltive timeline */
    function SetCurrentFrameIndex(index) {
        _lastFrameTime = 0;
        _FrameState = "B";
        _FrameTimeCounter = 0;
        _currentFrameIndex = index;
    }

    function RecalculateAccumalitiveTime() {
        var temp = 0;
        for (var i = 0; i < _currentFrameIndex; i++)
            temp += GetFrameDuration(_timeline[i]);

        _AccumalitiveCurrentFrameTime = temp;
    }

    /* Simple wrapper around the real append path,
    Just makes sure the marklist get reset before
    starting the search */
    function AppendPathToTimeLine(toframe) {
        _marklist = new Array();
        if (AppendPathToTimeLine2(toframe, false))
            return true;

        _marklist = new Array();
        return (AppendPathToTimeLine2(toframe, true))
    }


    /* Find a way to get to the "toframe" from the 
    last node currently on the timeline.  Append that
    path to the timeline.  */
    function AppendPathToTimeLine2(toframe, allowloops) {
        var branches = screens[_timeline.last()].actions.length;

        for (var i = 0; i < branches; i++) {
            var next = screens[_timeline.last()].actions[i].nextFrame;

            if (next == toframe) {
                _timeline.push(next);
                return true;
            }
            else if (next == "end") {
                continue;
            }

            /* frame is marked as skip move
            to next frame */
            else if (_SkipFrame(screens[next])) {
                var next2 = screens[next].actions[i].nextFrame;
                next = next2;
            }

            if (allowloops) {
                /* this code below is here to avoid getting stuck
                in loops.  It is coded based on knowing we
                have to support looping back into the primary 
                path.

                Hence why it doesn't 'mark' branch 0 */
                if (i > 0) {
                    if (InMarkList(next))
                        continue;
                    else
                        _marklist.push(next);
                }
            }
            else {
                if (FindTimelineIndex(next) >= 0) {
                    continue;
                }
            }
            _timeline.push(next);
            if (AppendPathToTimeLine2(toframe, allowloops)) {
                return true;
            }
            else {
                _timeline.pop();
                continue;
            }

        }

        return false;
    }


    function FireProgressEvent() {
        _ProgressDelegate.Raise(_this,
            { 'CurrentTime': _this.GetCurrentTime(),
                'TimelineDuration': _TotalTime,
                'FrameState': _this.GetFrameState(),
                'Locked': _lockTimeline
            });
    }

    /******************* public method section ******************************/

    _this.Init = function (startscreen) {
        if (_initialized)
            return false;
        _initialized = true;
        _timeline.push(startscreen);
        _lastFrame = 0;
        _lastFrameTime = 0;
        return true;
    }

    _this.Lock = function (lock) {
        _lockTimeline = lock;
    }

    _this.OnProgressUpdate = function (handler) {
        _ProgressDelegate.Register(handler);

        /* Set up timer if this is the first event
        being registered */
        if (_ProgressDelegate.Count() == 1) {
            setInterval(FireProgressEvent, 300);
        }
    }


    /* player needs to notify this class where
    in the frames timeline the play head is 

    What state is the frame playing it.  
    
    can be one of:
    B - beginning
    D - waiting out frame delay
    S - Play sound
    A - Playing out animation */
    _this.SetFrameState = function (state) {
        _FrameState = state;
        _FrameTimeCounter = 0;
    }

    _this.GetFrameState = function () {
        return _FrameState;
    }

    /* Set the time counter used by the delay and 
    animation parts of the frame playback
    to manually update time progress */
    _this.IncFrameTimeCounter = function (val) {
        _FrameTimeCounter += val;
    }




    _this.CalculateTimeline = function (toframe) {
        _this.CalculateTimelineThrough(toframe);
        return;
        /* truncate back to start */
        _timeline = new Array();
        _timeline.push(StartScreen);

        SetCurrentFrameIndex(0);

        AppendPathToTimeLine(toframe);
        _this.UpdateTimelineDuration();
    };


    /* use this function primarily for jump in points and hemi where
    we want to create a new path from start to end going through
    a specific node. */
    _this.CalculateTimelineThrough = function (throughframe) {
        /* truncate back to start */
        _timeline = new Array();
        _timeline.push(StartScreen);

        if (throughframe != "end")
            AppendPathToTimeLine(throughframe);
        AppendPathToTimeLine("end");

        SetCurrentFrameIndex(throughframe == "end" ? 0 : FindTimelineIndex(throughframe));
        _this.UpdateTimelineDuration();

    }


    /* this function should be called whenever the current 
    display frame changes. */
    _this.UpTimelineAt = function (selectedframe, dir, tdesc) {
        var findex = FindTimelineIndex(selectedframe, dir);

        if (tdesc && tdesc.valid) {
            findex = tdesc.timelineindex;
        }

        /* Desired frame is already on the timeline and
        we didn't go backwards, set current location there
        and  just return. */
        if ((findex >= 0) && (dir != "back")) {
            SetCurrentFrameIndex(findex);
            RecalculateAccumalitiveTime();
            if (tdesc && tdesc.valid) {
                _lastFrameTime = tdesc.resttime;
                _lastFrame = this.GetCurrentFrame();
            }
            return;
        }
        else if (findex >= 0) {
            /* Truncate the timeline back to the current 
            found frame and then recompute path from 
            current  frame to end frame */
            _timeline = _timeline.slice(0, findex + 1);

            AppendPathToTimeLine("end");
        }
        else {
            /* Truncate the timeline back to the current 
            display frame and then recompute path from 
            current  frame to selected frame and then to end frame 
               
            *There is an assumption here that selected frame can be 
            reached from the current frame.   Probably safe, however 
            if you wanted to be extra safe, check the return from
            AppendPathToTimeline, if it returns false, call 
            CalculateTimelineThrough to compute a path through
            selected. 
            */
            _timeline = _timeline.slice(0, _currentFrameIndex + 1);

            AppendPathToTimeLine(selectedframe);

            if (selectedframe != "end")
                AppendPathToTimeLine("end");

            findex = FindTimelineIndex(selectedframe, dir);
        }

        SetCurrentFrameIndex(findex);
        _this.UpdateTimelineDuration();
        if (tdesc && tdesc.valid) {
            _lastFrameTime = tdesc.resttime;
            _lastFrame = this.GetCurrentFrame();
        }
    }


    _this.GetCurrentFrame = function () {
        return _timeline[_currentFrameIndex];
    }


    _this.GetTimeline = function () {
        return _timeline;
    }


    _this.GetCurrentFrameIndex = function () {
        return _currentFrameIndex;
    }


    /* returns the current timeline duration
    in 1000ths of seconds */
    _this.GetTimelineDuration = function () {
        return _TotalTime;
    }

    /* returns the play head location 
    in 1000ths of seconds */
    _this.GetCurrentTime = function () {
        return _AccumalitiveCurrentFrameTime + GetFrameCurrentTime();
    }



    // Used to update showHistory when the slider
    // is used to change the postion of the timeline. 
    _this.GetHistory = function () {
        var history = new Array();

        for (var i = 0; i < _currentFrameIndex; i++) {
            history.push(_timeline[i]);
        }

        return history;
    }


    /* Recomputes the duration of the current timeline. 
    this sometimes needs to be triggered from outside
    code line when preferences change */
    _this.UpdateTimelineDuration = function () {
        var temp = 0;

        for (var i = 0; i < _timeline.length; i++) {
            temp += GetFrameDuration(_timeline[i]);
        }

        RecalculateAccumalitiveTime();
        _TotalTime = temp;
    }

    _this.FrameTimeStructure = function (frameid, timelineindex, narration, animation, resttime) {
        this.frameid = frameid;
        this.timelineindex = timelineindex;
        this.narration = narration;
        this.animation = animation;
        this.resttime = resttime;
    }

    _this.DeterminateCurrentFrameFromTime = function (time) {
        var temp = 0;
        var summarytime = 0;
        var i = 0;
        for (i = 0; i < _timeline.length; i++) {
            var n = GetFrameDurationNarration(_timeline[i]);
            var a = GetFrameDurationAnimation(_timeline[i]);
            temp += n + a;
            if (temp >= time) {
                break;
            }
            summarytime = temp;
        }
        return new _this.FrameTimeStructure(_timeline[i], i, n, a, time - summarytime);
    }

    return _this;
})();

function StandardTimeToMillisecs(time) {
    var a = time.split(":");
    var t = DELAY_INFINITE;
    try {
        t = parseFloat(a[0] * 3600) + parseFloat(a[1] * 60) + parseFloat(a[2]); // hours, minutes, seconds
        t *= 1000;                          // convert to milliseconds
    }
    catch (e) { };
    return t;
}

function MillisecsToFormattedTime(time) {
    var t = time / 1000;
    var ss = "" + t;
    var sss = ss.split(".");
    if (sss.length == 1) {
        if (sss[0].length < 2)
            sss[0] = "0" + sss[0];
        sss[1] = "00";
    }
    else {
        if (sss[0].length < 2)
            sss[0] = "0" + sss[0];

        if (sss[1].length < 2)
            sss[1] = sss[1] + "0";
    }

    sss[0] = sss[0].substr(0, 2);
    sss[1] = sss[1].substr(0, 2);

    return "" + sss[0] + "." + sss[1];
}


/* test code */

var fidiv = document.getElementById("frameiddiv");
var showtest = false;

function SetUpProgressReporting() {
    if (showtest) {
        $("#frameiddiv").append("<div id='testtiming'>timing</div>");
        $("#frameiddiv").append("<div id='testtimeline'>timeline</div>");
        $("#frameiddiv").append("<input id='testback' type='button' value='Back' onclick='return testback_onclick()' />");
    }
    upk.Timeline.OnProgressUpdate(TestTimelineProgress);
}

function testback_onclick() {
    DemoPrev();
}

function TestTimelineProgress(sender, event) {
    if (event.Locked)
        return;
    if (showtest) {
        var str = MillisecsToFormattedTime(event.CurrentTime) + " : " + MillisecsToFormattedTime(event.TimelineDuration);
        str += " - " + event.FrameState;
        $("#testtiming").html(str);

        var timeline = upk.Timeline.GetTimeline();
        var currentFrameIndex = upk.Timeline.GetCurrentFrameIndex();

        str = "Cindex: " + currentFrameIndex + " | ";
        for (var i = 0; i < timeline.length; i++) {
            if (i == currentFrameIndex) str += "->";
            str += timeline[i];
            if (i == currentFrameIndex) str += "<-";

            str += " ";
        }

        $("#testtimeline").html(str);
    }
    if (navBar) {
        navBar.setEndTime(event.TimelineDuration);
        navBar.setCurrentTime(event.CurrentTime);
    }

}
/* topic.js */ 
﻿/*--
Copyright © 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/
//	V: 47 LM: 10/23/2002 by lw
//	V: 52 LM: 10/28/2002 by gh
//	Aladdin closed...
//	V: 123 LM: 11/04/2003 by gh
//	Barbary Coast closed...
//	V: 173 LM: 01/10/2005 by gh 

///////// User defined area for knowit mode ///////////

// variables


//variables for tracking
var trackArgList;        // An array of strings contains the parameter list of the url
var trackScoreCompleted; // A number contains the result in percent
var trackScoreRequired;  // A number contains the required result defined by database in percent
// user can define additional variables (called track...) used by following functions e.q. trackTime

function trackOnBegin()
// called by the begin of the track in Knowit mode
// trackArgList is reachable -> user can parse and interpret his own parameters, init variables etc.
{
    // KP related code ///////////////////
    for (var i = 0; i < trackArgList.length; i++) {
        strArg = trackArgList[i];
        if (strArg.substr(0, 9) == "kpfeedbk=") {
            PlayerConfig.TrackFeedBack = (strArg.substr(9) == "0" ? false : true);
            PlayerConfig.ShowScoreNeeded = PlayerConfig.TrackFeedBack;
            // PlayerConfig.TrackFeedBack is able to suppress the PlayerConfig.ShowScoreNeeded setting!!!
        }
    };
    // End of KP related code ////////////	
};

function trackComplete()
// called by the end of the track in Knowit mode after the topic is complete
// trackArgList, trackScoreCompleted, trackScoreRequired are reachable
{
    // KP related code ///////////////////
    var kpnextpage = "";
    for (var i = 0; i < trackArgList.length; i++) {
        strArg = trackArgList[i];
        if (strArg.substr(0, 11) == "kpnextpage=") {
            kpnextpage = strArg.substr(11);
        }
    };
    if (kpnextpage.length > 0) {
        var answer = "" + trackScoreCompleted + "%";
        var score = 0;
        if (trackScoreCompleted >= trackScoreRequired)
            score = 1;
        var newloc = "";
        if ((kpnextpage.indexOf("?") >= 0) || (kpnextpage.indexOf("#") >= 0)) {
            newloc = kpnextpage + "&score=" + score + "&answer=" + answer;
        }
        else {
            newloc = kpnextpage + "?score=" + score + "&answer=" + answer;
        }
        if (window.parent.opener)
            window.parent.opener.location.href = newloc;
    };
    // End of KP related code ////////////	
};

function trackIncomplete()
// called by the end of the track in Knowit mode by mid topic exit
// trackArgList, trackScoreCompleted, trackScoreRequired are reachable
{
    // KP related code ///////////////////
    // End of KP related code ////////////	
};

///////// End of the User defined area ////////////////

var guidedParent = null;
var gopener = null;

function GetOpener() {
    if (top.window.opener) {
        try {
            if (!top.window.opener.closed) {
                if (top.window.opener.GIPlayer) {
                    guidedParent = top.window.opener.GIPlayer;
                    gopener = guidedParent;
                }
            }
        }
        catch (e) { };
    }
}

var playMode = "S"
var param_frame = ""
var param_ctx = ""
var param_ecid = ""
var param_printitname = "";
var lms_childIndex = 0;
var lms_inAssessment = false;

var screenshotPath = "";

var DEF_KWARNINGSCORELEVEL = 1; // defines the level where the step not accepted
var KWarningLevel = 0;
var KScoreNeeded = 80;
var KTopicFinished = false;
var soundIsExported = false;
var KWrongScreens = new Array();
var KScoringScreen = false;
var KConfirmDemo = false;
var KConfirmCheckBox = true;
var KFinishClose = false;
var KContinueFlag = 0; // 1, after guest demo playing
var KGuestDemoMode = 0;
var KRemediation1 = true;
var KRemediation2 = true;
var KRemediation3 = true;

var binterf = 0;
var def_PLAYER_CLOSE = "PLAYER_CLOSE"

var NS4 = (navigator.appName == "Netscape" && parseInt(navigator.appVersion) == 4)

var screens = new Array()
var screenNames = new Array()
var currentScreenObj
var currentscreenName
var FirstScreenName = ""
var showLeadIn = 2; // 0 -> hide, 1 -> show, other -> defined by cookies
var firsthemialternativeindex = 0;
var nosound = false;

var concepts = new Array()
var preloadImages = new Array();

var showScreen = ""
var showAct = 0

var moduleName = "";
var topicName = unescape(document.title);
var topicShowBubbles = "";

var StartAction = 0;

var Knowit_minimum = 167;
var Rem1_minimum = 200;
var Rem2_minimum = 250;
var Rem4_width = 300;

function DummyObj() {
    this.type = "";
};
var showActObj = new DummyObj();

var showActInpObj
var showHistory = new Array()
var historyActionMap = new Array()
//var isTabbed = false
var isPaused = false

var DELAY_INFINITE = 999
var MOUSE_STEP = 25

var scrH = 0;
var scrW = 0;

var animTimeout;
var bullsTimeout;
var animPhase = ""
var animCmd = ""
var animSteps = 0
var animStepOriginal = 0
var anim_x, anim_y
var anim_to_x, anim_to_y

var screenshot = new Image();
var event_blocked;

var animObject;

var showFrameIDToggle = 0;

function InputOnFocus() {
    if (showActInpObj)
        showActInpObj.hasfocus = true;
}

function InputOnBlur() {
    if (showActInpObj)
        showActInpObj.hasfocus = false;
}

function FocusMe() {
    try {
        window.focus();
    }
    catch (e) { };
};

function FocusInpObj() {
    if (showActInpObj) {
        try {
            showActInpObj.focus();
        }
        catch (e) { };
        var cObjID = showActInpObj.id;
        var cObj = document.getElementById(cObjID);
        var txt = cObj.text;
        cObj.text = txt;
        /*
        var txtRange=showActInpObj.createTextRange()
        var txt=txtRange.text;
        txtRange.text=txt;
        */
        SelectText(showActInpObj);
    };
}

function SelectText(obj) {
    if (IsTouchDevice() == null) {
        obj.select();
    }
    else {
        obj.setSelectionRange(0, 9999);
    }
}

function OnFocus() {
    if (!showActObj)
        return;
    if (showActObj.type) {
        if (showActObj.type == 'Input') {
            if (showActInpObj)
                setTimeout("FocusInpObj()", 10);
        };
    };
};

function OnBubbleMoved() {
    OnFocus();
};

function OnBubbleClicked() {
    if (actionMenu) {
        if (actionMenu.IsOnScreen()) {
            actionMenu.Close();
        };
    }
};

function AnimObject(cmd, timeout, phase) {
    this.cmd = cmd;
    this.timeout = timeout;
    this.phase = phase;
};

function IsLeadIn(o) {
    if (o == null)
        o = showActObj;
    return (screens["start"].actions[0].id == o.id);
};

function IsLeadOut(o) {
    if (o == null)
        o = showActObj;
    return (o.nextFrame == "end");
};

function IsDecision(o) {
    if (o == null)
        o = showActObj;
    return (o.type == "Decision");
};

function IsExplanation(o) {
    if (o == null)
        o = showActObj;
    if (IsLeadIn(o) || IsLeadOut(o))
        return false;
    return (o.type == "None");
};

function IsActionFrame(o) {
    if (o == null)
        o = showActObj;
    return (o.type == "Normal");
}

function StoredEvent(x, y, shiftState, buttonID) {
    this.storedEvent = true;
    this.pX = x;
    this.pY = y;
    this.pShState = shiftState;
    this.pButton = buttonID;
};

function AddToWrongScreens(id) {
    for (var i = 0; i < KWrongScreens.length; i++) {
        if (KWrongScreens[i] == id)
            return;
    };
    KWrongScreens[KWrongScreens.length] = id;
};

function GetResultInPercent(unfinished) {
    //    var allsteps = showHistory.length - 2;

    var allsteps = 0;
    for (var i = 0; i < showHistory.length; i++) {
        if (screens[showHistory[i]].actions[0].type != "None")
            allsteps++;
    }
    var wrongsteps = KWrongScreens.length;
    if (!unfinished) {
    }
    else {
        if (!IsLeadOut()) {
            var myscr = screens[showScreen];
            var id = myscr.actions[0].nextFrame;
            while (id != "end") {
                if (myscr.type != "decision" && myscr.type != "none") {
                    allsteps++;
                    wrongsteps++;
                };
                myscr = screens[id];
                id = myscr.actions[0].nextFrame;
            };
        };
    };
    if (allsteps == 0)
        return 100;
    return Math.round(100 - ((wrongsteps / allsteps) * 100));
};

function StartDemoInKnowIt() {
    if (!IsDragBegin)
        AddToWrongScreens(showScreen);
    KGuestDemoMode = 1;
    binterf.SetMoveable(false);
    setTimeout("ShowScreen(showScreen)", 200);
};

function StartDemoInTryIt() {
    KGuestDemoMode = 1;
    setTimeout("ShowScreen(showScreen)", 200);
}

function HLink(s) {
    if (playMode == "T")	// 0 -> leadin, 1 -> leadout, 2 -> explanation
    {
        if (s == 0 || s == 1 || s == 2) {
            HLinkStart = true;
            TeacherForward(true);
        }
        else if (s == 13)		// typingcomplete
        {
            if (AssessStringInput(true, true)) {
                TeacherForward(true);
            }
            else {
                TeacherWrong();
            };
        }
        else if (s == 130) {
            UpdateDoneTyping(false);
        }
        else if (s == 131) {
            UpdateDoneTyping(true);
        };
    }
    else if (playMode == "S") // 0 -> leadin, 1 -> leadout
    {
        if (s == 0 || s == 1 || s == 2) {
            DemoForward();
        }
        else if (s == 600)	// pause/resume link pressed in seeit
        {
            PauseToggle();
        }
    }
    else	// playMode=="K"	
    {
        if (s == 0 || s == 1)	// leadin, leadout
        {
            HLinkStart = true;
            TeacherForward(true);
        }
        else if (s == 2)	// nextstep
        {
            if (KWarningLevel < DEF_KWARNINGSCORELEVEL && KConfirmCheckBox) {
                HideAction();
                KConfirmDemo = true;
                ShowAction();
                return;
            }
            else if (KWarningLevel < DEF_KWARNINGSCORELEVEL && !KConfirmCheckBox) {
                AddToWrongScreens(showScreen);
            };
            StartDemoInKnowIt();
        }
        else if (s == 10)		// ok button on level 4 panel
        {
            StartDemoInKnowIt(); ;
        }
        else if (s == 11)		// yes on confirm panel
        {
            KConfirmDemo = false;
            AddToWrongScreens(showScreen);
            StartDemoInKnowIt();
        }
        else if (s == 110) {
            UpdateYesNo(false, false);
        }
        else if (s == 111) {
            UpdateYesNo(true, false);
        }
        else if (s == 12)		// no on confirm panel
        {
            HideAction();
            KConfirmDemo = false;
            ShowAction();
        }
        else if (s == 120) {
            UpdateYesNo(false, false);
        }
        else if (s == 121) {
            UpdateYesNo(false, true);
        }
        else if (s == 13)		// typingcomplete
        {
            if (AssessStringInput(true, true)) {
                TeacherForward(true);
            }
            else {
                TeacherWrong();
            };
        }
        else if (s == 130) {
            UpdateDoneTyping(false);
        }
        else if (s == 131) {
            UpdateDoneTyping(true);
        }
        else if (s == 125) {
            KConfirmCheckBox = !KConfirmCheckBox;
        }
        else if (s == 126) {
            KConfirmCheckBox = !KConfirmCheckBox;
            document.getElementsByName("KConfCB")[0].checked = !document.getElementsByName("KConfCB")[0].checked;
        }
        else if (s == 20)		// finish
        {
            ClosePlayer(1);
        }
        else if (s == 30)		// drag&drop start
        {
            StartDemoInKnowIt(); ;
        }
        else if (s == 400)	// print site
        {
            if (trackSent)
                return;
            var passed = GetResultInPercent();

            var moduledesc = R_module + moduleName;
            //			var topicdesc= R_topic + escape(document.title);
            //			var topicdesc= R_topic + encodeURIComponent(document.title);
            //			var topicdesc= R_topic + document.title;

            page = window.open("../../../certificate/certificate.html" +
							"#ModuleDesc=1" +
							"&TopicDesc=1" +
							"&PctComplete=" + passed +
							"&PctNeeded=" + KScoreNeeded,
							'print',
							'toolbar=1,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=800,height=600,left=147,top=131');
        }
        else if (s == 500)	// exit on finish/close panel
        {
            ClosePlayer();
        }
        else if (s == 501)	// remain on finish/close panel
        {
            HideAction();
            KFinishClose = false;
            ShowAction();
        }
        else if (s == 502)    // exit assessment
        {
            ClosePlayer(0, 1);
        }
        else if (s == 503)    // exit
        {
            lms_knowitScore(getMyGuid(), 0, 0);
            lms_topicFinish(getMyGuid());
            ClosePlayer();
        }
        else if (s == 504)    //return to know it
        {
            HideAction();
            KFinishClose = false;
            ShowAction();
        }
        else if (s == 600)	// pause/resume link pressed in seeit
        {
            PauseToggle();
        }
    };
};

function Certification_GetModuleName() {
    if (moduleName.length == 0)
        return "";
    return (R_outline + moduleName);
}

function Certification_GetTopicName() {
    if (topicName.length == 0)
        return "";
    return (R_topic + topicName);
}

function OnClose() {
    if (playMode == "K") {
        if (IsLeadOut()) {
            if (KScoringScreen) {
                ClosePlayer(1);
            }
            else {
                HLink(1);
            };
            return;
        };
        HideAction();
        KFinishClose = true;
        ShowAction();
    }
    else {
        ClosePlayer();
    };
};

var actionMenu = 0;
var closedbyEnter = false;

function OnAction() {
    if (closedbyEnter) {
        closedbyEnter = false;
        return;
    };
    if (actionMenu) {
        if (actionMenu.IsOnScreen()) {
            actionMenu.Close();
            return true;
        };
    }
    if (playMode == "T" || (playMode == "K" && KGuestDemoMode == 0)) {
        if (actionMenu == 0)
            actionMenu = new ActionMenu();
        actionMenu.Open();
        RefreshActionMenu();
    };
    if (playMode == "S" || (playMode == "K" && KGuestDemoMode > 0)) {
        if (!isPaused)
            PauseToggle();
        if (actionMenu == 0)
            actionMenu = new ActionMenu();
        actionMenu.Open();
        RefreshActionMenu();
    };
};

function OnAlternative() {
    TeacherAlter();
};

function RefreshActionMenu(changeconcept, changeinfo, frompref) {
    if (actionMenu) {
        var next = (showActObj.nextFrame != "end" && showActObj.type != "Decision");
        if (!UserPrefs.TryIt.EnableSkipping)
            next = false;
        var prev = (showHistory.length > 1);
        var alt = (screens[showScreen].actions.length > 1 && showActObj.type != "Decision");
        var printit = param_printitname.length > 0;
        actionMenu.Refresh(next, prev, prev, alt, changeconcept, changeinfo, frompref, printit);
    };
};

function OnMenuAlternative(s, p1, p2, p3, p4) {
    CloseAction();
    if (p1 != null && p2 == null) {
        LaunchHelp(p1);
    }
    else {
        eval(s);
    }
};

function LaunchHelp(s) {
    if (!isPaused)
        PauseToggle();
    onHelp(s);
};

function CloseAction(notfocus) {
    if (actionMenu)
        actionMenu.Close();
    if (!notfocus)
        FocusMe();
};

function ShowPrintit() {
    if (param_printitname.length > 0)
        window.open("../../printit/" + param_printitname);
}

function LogOut() {
    lms_KPathLogout();
}

////////////////////////////////////////////////////////////////////////

function OpenPreferences() {
    var s = window.location;
    var nosound = !SoundPlayerObj.IsAvailable();
    var p = MakeAbsolute("../../../preferences/preferences.html");
    var params = new Array();
    if (lms_IsUserProfileAvailable()) {
        var url = lms_GetUserProfileUrl();
        if (url != "")
            params[params.length] = "UserProfileUrl=" + Escape.MyEscape(url);
    }
    if (nosound) {
        params[params.length] = "nosound";
    }
    for (var i = 0; i < params.length; i++) {
        p += (i == 0) ? "?" : "&";
        p += params[i];
    }
    saved_preferences_event = getOnCloseEvent();
    setOnCloseEvent("preferences_return()");
    parent.showDialog(p, -1, -1, 470, 380, true, 96, "../../../");
};

var saved_preferences_event = "";

function preferences_return() {
    setOnCloseEvent(saved_preferences_event);
}

function Menu_Resume() {
    if (isPaused)
        PauseToggle();
}

function InsertStart() {
    var c = new Array();
    for (var i = 0; i < showHistory.length; i++)
        c[c.length] = showHistory[i];
    showHistory = new Array();
    showHistory[0] = "start";
    for (var i = 0; i < c.length; i++)
        showHistory[showHistory.length] = c[i];
};

function DeleteStart() {
    var c = new Array();
    for (var i = 0; i < showHistory.length; i++)
        c[c.length] = showHistory[i];
    showHistory = new Array();
    for (var i = 1; i < c.length; i++)
        showHistory[showHistory.length] = c[i];
};

function OnUpdatePreferences(userpref) {
    UserPrefs.Copy(userpref);
    if ((showLeadIn == 1) || (userpref.ShowLeadIn == "all" && showLeadIn != 0)) {
        if (showHistory.length > 0) {
            if (showHistory[0] != "start") {
                // insert
                InsertStart();
            };
        };
    }
    else {
        if (showHistory.length > 0) {
            if (showHistory[0] == "start") {
                // delete
                DeleteStart();
            };
        };
    };
    try {
        if (opener.OnUpdatePreferences)
            opener.OnUpdatePreferences(userpref);
    }
    catch (e) { };
    //	RefreshActionMenu(false,false,true);
    //	SetActionColor();
};

//////////////////////////////////////////////////////
// DownloadImage function

function DownloadImage_(image, url, vfnRet) {
    image.user_url = Format(url);
    image.user_retFn = vfnRet;
    image.onload = Loaded_;
    image.onerror = LoadError_;
    image.src = url;
};

function Loaded_() {
    var s;
    s = this.user_retFn + '("' + this.user_url + '",true)';
    eval(s);
};

function LoadError_() {
    var s;
    s = this.user_retFn + '("' + this.user_url + '",false)';
    eval(s);
};

function Format(s) {
    var ss = "";
    for (i = 0; i < s.length; i++) {
        var c = s.charAt(i);
        if (c == "\\") {
            ss += "\\\\";
        }
        else {
            ss += c;
        };
    };
    return ss;
};

function GetImage(image, url) {
    if (preloadImages[url])
        image.src = preloadImages[url].src;
};

function DownloadImage(url, vfnret) {
    if (!preloadImages[url]) {
        PreloadImage(url);
    };
    WaitForImage(url, vfnret);
};

function WaitForImage(url, vfnret) {
    var s;
    if (preloadImages[url].loaded) {
        s = vfnret + '("' + preloadImages[url].user_url + '",true)';
        eval(s);
        return;
    };
    if (preloadImages[url].error) {
        s = vfnret + '("' + preloadImages[url].user_url + '",false)';
        eval(s);
        return;
    };
    s = "WaitForImage('" + url + "','" + vfnret + "');";
    setTimeout(s, 300);
};

function PreloadImage(url) {
    if (preloadImages[url])
        return;
    preloadImages[url] = new Image();
    preloadImages[url].loaded = false;
    preloadImages[url].error = false;
    DownloadImage_(preloadImages[url], url, "Preload_Return");
};

function Preload_Return(url, success) {
    if (success)
        preloadImages[url].loaded = true
    else
        preloadImages[url].error = true;
};

// DownloadImage end //////////////////////////////////////

//
// Topic object model
//

function ScreenObj(image, showBubble) {
    this.image = image;
    this.showBubble = showBubble;
    this.actions = new Array();
    this.infoblocks = new Array();
    this.emptyinfo = true;
}

function Screen(id, image, showBubble) {
    var scr = new ScreenObj(image, showBubble)
    screens[id] = scr
    currentScreenObj = scr
    screenNames[screenNames.length] = id;
    currentScreenName = id;
}

function FilterTryItText(text) {
    var ss = text;
    var s = ss.toLowerCase();

    var l = true;
    while (l) {
        l = false;
        var k1, k2;
        for (var i = 0; i < s.length; i++) {
            if (s.substr(i, 5) == "href=") {
                l = true;
                k1 = i;
                break;
            };
        };
        if (l) {
            k2 = 0
            for (var j = i; j < s.length; j++) {
                if (s.substr(j, 7) == "hrefend") {
                    k2 = j + 10;
                    break;
                };
            };
            if (k2 > 0) {
                var sss = ss;
                ss = sss.substr(0, k1) + sss.substr(k2);
                s = ss.toLowerCase();
            }
            else {
                l = false;
            }
        };
    };

    s = ss;

    l = true;
    while (l) {
        l = false;
        var k1, k2;
        for (var i = 0; i < s.length; i++) {
            if (s.substr(i, 6) == "title=") {
                l = true;
                k1 = i;
                break;
            };
        };
        if (l) {
            k2 = 0
            for (var j = i; j < s.length; j++) {
                if (s.substr(j, 8) == "titleend") {
                    k2 = j + 11;
                    break;
                };
            };
            if (k2 > 0) {
                var sss = ss;
                ss = sss.substr(0, k1) + sss.substr(k2);
                s = ss.toLowerCase();
            }
            else {
                l = false;
            }
        };
    };

    return ss;
};

function IsTextEmpty(s) {
    var status = true;
    for (var i = 0; i < s.length; i++) {
        var c = s.substr(i, 1);
        if (status == true) {
            if (c == "<")
                status = false
            else if (s.charCodeAt(i) != 13 && s.charCodeAt(i) != 10)
                return false;
        }
        else {
            if (c == ">")
                status = true;
        };
    };
    return true;
}

function Replace(str, s, r) {
    var l = s.length;
    var k = str.indexOf(s);
    if (k < 0)
        return str;
    var s1 = str.substr(0, k);
    var s2 = str.substr(k + l);
    return (s1 + r + s2);
};

function DisplayInputTextPart(templatetext, part, disp) {
    var p1 = '<DIV id=' + part + ' style="DISPLAY: inline">';
    var k1 = templatetext.indexOf(p1);
    if (k1 < 0) {
        p1 = '<div id="' + part + '" style="display: inline;">';
        k1 = templatetext.indexOf(p1);
        if (k1 < 0) {
            p1 = '<div id="' + part + '" style="display:inline">';
            k1 = templatetext.indexOf(p1);
            if (k1 < 0) {
                p1 = '<DIV style="DISPLAY: inline" id=' + part + '>';
                k1 = templatetext.indexOf(p1);
                if (k1 < 0)
                    return templatetext;
            }
        }
    }
    var t1 = templatetext.substr(k1 + p1.length);
    var k2 = t1.indexOf('</DIV>');
    if (k2 < 0)
        k2 = t1.indexOf('</div>');
    if (disp == true)
        return templatetext.substr(0, k1) + t1.substr(0, k2) + t1.substr(k2 + 6);
    return templatetext.substr(0, k1) + t1.substr(k2 + 6);
}

function BuildInputText(aobj, templatetext) {
    var display_anything = false;
    var display_example = false;
    var display_inputtext = false;
    var display_inputalt = false;
    var display_blank = false;

    if ((playMode == "S") || (playMode == "T"))
        display_inputtext = true
    else if (aobj.par1[0] == "S") {
        display_anything = true;
        if (template_strinp_suppress_example == "<span>0</span>") {
            display_example = true;
            display_inputtext = true;
        }
    }
    else if (aobj.par1[0] == "A") {
        display_anything = true;
        display_blank = true;
        if (template_strinp_suppress_example == "<span>0</span>") {
            display_example = true;
            display_inputtext = true;
        }
    }
    else if (aobj.par1[0] == "N") {
        display_inputtext = true;
        display_inputalt = true;
        display_blank = true;
    }
    else {
        display_inputtext = true;
        display_inputalt = true;
    }

    var s = templatetext;
    s = DisplayInputTextPart(s, "anything", display_anything);
    s = DisplayInputTextPart(s, "example", display_example);
    s = DisplayInputTextPart(s, "inputtext", display_inputtext);
    s = DisplayInputTextPart(s, "inputalt", display_inputalt);
    s = DisplayInputTextPart(s, "blank", display_blank);

    // begin 22282 hack
    s = s.replace(new RegExp("<SPAN></SPAN>", "g"), "<SPAN> </SPAN>");
    s = s.replace(new RegExp("\r", "g"), "");
    s = s.replace(new RegExp("\n", "g"), "");
    // end 22282 hack

    return s;
};

function StartsWith(s, prefix) {
    if (s.length < prefix.length)
        return false;
    var prlow = prefix.toLowerCase();
    var sp = s.substr(0, prefix.length);
    var slow = sp.toLowerCase();
    if (slow == prlow)
        return true;
    return false;
}

function RemoveNbsp(s)
// Remove &nbsp; characters from bubbletext, except the leadin characters in every paragraphs
{
    return s;
}

function DummyActionObj(id, nextFrame, hotspots, type, par1) {
    this.realAction = false;
    this.id = id;
    this.nextFrame = nextFrame;
    this.hotspots = hotspots;
    this.type = type;
    this.par1 = par1;
}

function AddDummyActions(actArray, a) {
    if (IsMacOs()) {
        if (IsFF()) {
            if (a.type == "RClick1" && a.par1 == "") { // mac ff
                actArray[actArray.length] = new DummyActionObj(a.id, a.nextFrame, a.hotspots, "RClick1", "c");
            }
            if (a.type == "LClick1" && a.par1 == "c") { // mac ff
                actArray[actArray.length] = new DummyActionObj(a.id, a.nextFrame, a.hotspots, "RClick1", "c");
            }
        }
        if (IsSafari()) {
            if (a.type == "RClick1" && a.par1 == "") { // mac safari
                actArray[actArray.length] = new DummyActionObj(a.id, a.nextFrame, a.hotspots, "LClick1", "c");
            }
            if (a.type == "RClick1" && a.par1 == "c") { // mac safari
                actArray[actArray.length] = new DummyActionObj(a.id, a.nextFrame, a.hotspots, "LClick1", "c");
            }
        }
    }
}

function ActionObj(id, nextFrame, hotspots, bubpos, xpos, ypos, width, height, kwidth, kheight, ctx, ecidarray, type, delay, par1, par2, par3, iconname,
					bubcolor, tryittext, knowittext, templatetext, fonttext,
					bubtextfirst, knowitflag, disabledmodes)
// tryittext -> text for simulated modes
// knowittext -> text for knowit mode
// templatetext -> templatetext
// fonttext -> font information for every texts
// bubtextfirst -> use tryittext/knowittext before templatetext
// knowitflag -> show also templatetext on level 0, 1
{
    this.realAction = true;
    this.disabledmodes = (disabledmodes == null ? "" : disabledmodes);
    tryittext = RemoveNbsp(tryittext);
    knowittext = RemoveNbsp(knowittext);
    //	tryittext=replaceString("&nbsp;"," ",tryittext)
    //	knowittext=replaceString("&nbsp;"," ",knowittext)
    if (!knowittext)
        knowittext = "";
    if (IsTextEmpty(knowittext))
        knowittext = "";
    if (!templatetext)
        templatetext = "";
    this.id = id
    this.nextFrame = nextFrame
    this.hotspots = hotspots;
    this.bubpos = bubpos;
    this.xpos = xpos;
    this.ypos = ypos;
    this.width = width;
    this.height = height;
    this.kwidth = kwidth;
    this.kheight = kheight;
    this.ctx = ctx;
    this.ecidarray = ecidarray;

    if (this.ecidarray) {
        for (var i = 0; i < this.ecidarray.length; i++) {
            s = this.ecidarray[i];
            var k = s.indexOf('$');
            sapp = s.substr(0, k + 1);
            sctx = Escape.MyEscape(s.substr(k + 1));
            s = sapp + sctx;
            var k = s.indexOf("$0026amp$003B");
            while (k > 0) {
                s = s.substr(0, k + 5) + s.substr(k + 13);
                k = s.indexOf("$0026amp$003B");
            }
            this.ecidarray[i] = s;
        }
    }

    this.type = type
    this.delay = delay
    this.par1 = par1;
    try {
        this.par1[1] = DecodeTagElements(par1[1]);
    }
    catch (e) { }
    this.par2 = DecodeInputString(par2);
    this.par3 = par3
    this.par4 = false	// input edit has been started
    this.lastIMEtext = "";
    this.par5 = ""	// input edit text
    this.iconname = iconname;
    this.bubcolor = bubcolor;

    var fontbegin = "<font " + fonttext + ">";
    var fontend = "</font>";

    var animationsoundtime = 0;
    if (UserPrefs.PlayAudio != 'none') {
        /* adding 600 millisecs to compensate playing clicks (~300) 
        + load overhead (~300) */
        animationsoundtime = 600;
    }

    /* edw */
    if (this.type == "Input") {
        var numofkeys = 10;
        try {
            numofkeys = DecodeInputString(this.par1[1]).length;
        }
        catch (e) { };
        this.animTime = PlayerConfig.InputDelay * numofkeys;
        this.animTime += animationsoundtime;
    }
    else if (this.type == "Key") {
        this.animTime = PlayerConfig.InputDelay;
        this.animTime += animationsoundtime;
    }
    else if (this.type.indexOf("Wheel") != -1) {
        this.animTime = PlayerConfig.WheelDelay;
        this.animTime += animationsoundtime;
    }
    else if (this.type == "None")
        this.animTime = 0;
    else if (this.type == "Decision")
        this.animTime = 0;
    else { /* we assume mouse event? */
        this.animTime = PlayerConfig.MouseDelay * PlayerConfig.MouseSteps;
        this.animTime += 2 * PlayerConfig.BullseyeDelay;
        this.animTime += animationsoundtime;
    }

    this.fontbegin = fontbegin;
    this.fontend = fontend;

    var s;
    var ss;
    //////////////////////////	 text -> for simulated modes & K mode Level 2,3

    if (playMode == "S" && type != "Decision") {
        s = FilterTryItText(tryittext);
        tryittext = s;
    };

    if (this.type == "Input" && templatetext.length > 0) {
        templatetext = BuildInputText(this, templatetext);
    };

    if (tryittext.length == 0 && templatetext.length == 0) {
        s = "";
    }
    else if (tryittext.length == 0) {
        s = templatetext;
    }
    else if (templatetext == 0) {
        s = tryittext;
    }
    else {
        if (bubtextfirst)
        //			s=tryittext+"<br>"+templatetext
            s = tryittext + "<p>" + templatetext + "</p>";
        else
        //			s=templatetext+"<br>"+tryittext;
            s = templatetext + tryittext;
    };

    if (knowittext.length == 0 && templatetext.length == 0) {
        ss = "";
    }
    else if (knowittext.length == 0) {
        ss = templatetext;
    }
    else if (templatetext == 0) {
        ss = knowittext;
    }
    else {
        if (bubtextfirst)
        //			s=tryittext+"<br>"+templatetext
            ss = knowittext + templatetext
        else
        //			s=templatetext+"<br>"+tryittext;
            ss = templatetext + knowittext;
    };

    if (type == "None") {
        if (currentScreenName == "start" && playMode != "S") {
            s += "<br><p class='MsoNormal'>" + fontbegin + template_leadin + fontend + "</p>";
            if (PlayerConfig.ShowScoreNeeded)
                ss += "###KSCORE###";
            ss += "<br><p class='MsoNormal'>" + fontbegin + template_knowit_leadin + fontend + "</p>";
            this.delay = 999;
        }
        else if (nextFrame == "end" && playMode != "S") {
            s += "<br><p class='MsoNormal'>" + fontbegin + template_leadout + fontend + "</p>";
            ss += "<br><p class='MsoNormal'>" + fontbegin + template_knowit_leadout + fontend + "</p>";
            this.delay = 999;
        }
        else if (delay == 999) {
            s += "<br><p class='MsoNormal'>" + fontbegin + template_explanation + fontend + "</p>";
            ss += "<br><p class='MsoNormal'>" + fontbegin + template_knowit_explanation + fontend + "</p>";
        }
        else if (!IsTextEmpty(s) && this.delay != 999 && playMode == "T") {
            s += "<br><p class='MsoNormal'>" + fontbegin + template_explanation + fontend + "</p>";
            this.delay = 999;
        };
    }
    else if (playMode == "S") {
        if (delay == 999) {
            if (type != "Decision") {
                s += "<br><p class='MsoNormal'>" + fontbegin + template_explanation + fontend + "</p>";
            };
        };
    };
    //	this.text=fontbegin+s+fontend;
    if (IsTextEmpty(s))
        this.text = ""
    else
        this.text = s;
    this.emptytext = (this.text.length == 0);
    if (IsTextEmpty(ss))
        this.ktext = ""
    else
        this.ktext = ss;
    this.kemptytext = (this.ktext.length == 0);
    //////////////////////////	 knowittext -> for K mode Level 0,1
    s = "";
    if (!knowitflag)
        templatetext = "";
    if (knowittext.length == 0 && templatetext == 0) {
        s = "";
    }
    else if (knowittext.length == 0) {
        s = templatetext;
    }
    else if (templatetext == 0) {
        s = knowittext;
    }
    else {
        if (bubtextfirst)
        //			s=knowittext+"<br>"+templatetext
            s = knowittext + templatetext
        else
        //			s=templatetext+"<br>"+knowittext;
            s = templatetext + knowittext;
    };
    //	this.knowittext=fontbegin+s+fontend;
    this.knowittext = s;
}

function Action(id, nextFrame, hotspots, bubpos, xpos, ypos, width, height, kwidth, kheight, ctx, ecidarray, type, delay, par1, par2, par3, iconname, bubcolor,
					tryittext, knowittext, templatetext, fonttext, bubtextfirst, knowitflag, disabledmodes) {
    // +++ add new params xpos,ypos
    if (currentScreenObj) {
        var actArray = currentScreenObj.actions;
        var a = new ActionObj(id, nextFrame, hotspots, bubpos, xpos, ypos, width, height, kwidth, kheight, ctx, ecidarray,
									type, delay,
									par1, par2, par3, iconname, bubcolor, tryittext, knowittext,
									templatetext, fonttext, bubtextfirst, knowitflag, disabledmodes);
        actArray[actArray.length] = a;
        AddDummyActions(actArray, a);
    }
}

function InfoObj(buttonfile, url, tooltip, infotype, infokey) {
    this.buttonfile = buttonfile;
    this.url = url;
    this.tooltip = DecodeInputString(tooltip);
    if (isNaN(infotype))
        infotype = 999;
    this.infotype = infotype;
    this.infokey = infokey;
    this.simpleurl = url;
    this.width = 0;
    this.height = 0;
};

function InfoBlock(buttonfile, url, tooltip, infotype, infokey) {
    if (!tooltip)
        tooltip = "";
    if (currentScreenObj) {
        _buttonfile = buttonfile;
        _img = "infobitmapimage.gif";
        _sb = buttonfile.toLowerCase();
        if (_sb.substr(_sb.length - _img.length) == _img) {
            _buttonfile = buttonfile.substr(0, _sb.length - _img.length) + _img;
        }
        var infoArray = currentScreenObj.infoblocks;
        infoArray[infoArray.length] = new InfoObj(_buttonfile, url, tooltip, infotype, infokey);
        currentScreenObj.emptyinfo = false;
    };
};

function ConceptObj(url, width, height, text, infotype, infokey) {
    this.url = url;
    this.width = width;
    this.height = height;
    this.text = text;
    if (isNaN(infotype))
        infotype = 999;
    this.infotype = infotype;
    this.infokey = infokey;
};

function ConceptInfo(url, width, height, text, infotype, infokey) {
    concepts[concepts.length] = new ConceptObj(url, width, height, text, infotype, infokey);
};

//
// Demo mode animations
//

function Animate2(fname, demosound, cmd, timeout, phase) {
    if (isPaused) {
        var cmd3 = 'Animate2("' + fname + '",' + demosound + ',"' + cmd + '",' + timeout + ',"' + phase + '")';
        setTimeout(cmd3, PlayerConfig.PausedDelay);
        return;
    }
    if (!demosound)
        upk.Timeline.SetFrameState("D");
    animObject = new AnimObject(cmd, timeout, phase);
    if (KGuestDemoMode)
        Animate(cmd, timeout, phase)
    else {
        PlaySound(fname, demosound);
    };
};

var DELAY_STEP = 20;

function Animate(cmd, timeout, phase) {
    animCmd = cmd
    animPhase = phase
    if (timeout == DELAY_INFINITE * 100) {
        animPhase = "";
        return;
    };
    clearTimeout(animTimeout);
    if (animObject)
        animObject.delaystep = 0;
    animObject.timeout = timeout;
    animTimeout = setTimeout("AnimateTimer()", DELAY_STEP)
    upk.Timeline.IncFrameTimeCounter(DELAY_STEP);
}

function AnimateTimer() {
    if (animObject) {
        if (animObject.timeout == DELAY_INFINITE * 100) {
            if (_ShowBubble(showActObj) == true) {
                animPhase = "";
                return;
            }
        }
    }
    if (isPaused) {
        clearTimeout(animTimeout);
        animTimeout = setTimeout("AnimateTimer()", PlayerConfig.PausedDelay)
        return;
    }
    if (animObject) {
        animObject.delaystep += DELAY_STEP;
        if (animObject.delaystep < animObject.timeout) {
            if (animObject.phase != "input")
                upk.Timeline.IncFrameTimeCounter(DELAY_STEP);
            clearTimeout(animTimeout);
            animTimeout = setTimeout("AnimateTimer()", DELAY_STEP)
            return;
        }
    }
    eval(animCmd)
}

function AnimateKeyboard() {
    Animate2("stype.flv", true, "ShowScreen('" + showActObj.nextFrame + "')", PlayerConfig.InputDelay, "nostop")
};

function AnimateInput(internal) {
    if (!internal)
        upk.Timeline.SetFrameState("A");
    hide("cursor");
    upk.Timeline.IncFrameTimeCounter(PlayerConfig.InputDelay);

    --animSteps

    Ds = DecodeInputString(showActObj.par1[1]);
    try {
        var a = Ds.length;
    }
    catch (e) {
        return;
    }
    //    if (IsSafari()) {
    //        showActInpObj.value = Ds.substr(0, Ds.length - animSteps);
    //        showActInpObj.original = showActInpObj.value;
    //        try {
    //            var txtRange = showActInpObj.createTextRange();
    //            txtRange.scrollIntoView(false);
    //        }
    //        catch (e) {
    //        }
    //    }
    //    else 
    {
        //LÉTREHOZOK EGY SZÁMLÁLÓT AZ ANIMÁLT SZTRING ELEJÉNEK VÁGÁSÁHOZ	
        if (typeof (trimAnimTxt) == 'undefined') {
            trimAnimTxt = 0;
        }

        if ((Ds.length - animSteps) == 1) {
            //AZ INPUT MEZŐRE ÁLLÁSKOR KINULLÁZOM A KEZDŐ STRINGET HELYÉT
            trimAnimTxt = 0;
            //KIOLVASOM A CSS FÁJLBÓL AZ INPUT MEZŐ FONT MÉRETÉT
            var dCss = document.styleSheets;
            for (var i in dCss) {
                if (dCss[i].cssRules) {
                    for (var j in dCss[i].cssRules) {
                        var selText1 = '.' + showActInpObj.className;
                        var selText2 = selText1.toLowerCase();
                        if (dCss[i].cssRules[j].selectorText == selText1 ||
							dCss[i].cssRules[j].selectorText == selText2) {
                            iSDFontSize = dCss[i].cssRules[j].style.fontSize;
                            break;
                        }
                    }
                }
                else {
                    for (var j in dCss[i].rules) {
                        if (dCss[i].rules[j].selectorText == '.' + showActInpObj.className) {
                            iSDFontSize = dCss[i].rules[j].style.fontSize;
                            break;
                        }
                    }
                }
            }
        }

        showActInpObj.value = Ds.substr(trimAnimTxt, Ds.length - animSteps);
        showActInpObj.original = showActInpObj.value;

        //LÉTREHOZOK EGY OBJEKTUMOT A BEÍRT SZÖVEG VALÓDI HOSSZÁNAK ELLENŐRZÉSÉHEZ ÉS ÁTADOM NEKI AZ INPUT ÉRTÉKÉT
        try {
            iSD = document.getElementById('InpSizeDetect');
            iSD.innerHTML = showActInpObj.value
            iSD.style.fontSize = iSDFontSize;
        }
        catch (e) {
            var InpSizeDetect_ = document.createElement('SPAN');
            InpSizeDetect_.id = 'InpSizeDetect';
            InpSizeDetect_.style.fontFamily = 'arial';
            InpSizeDetect_.style.fontSize = iSDFontSize;
            InpSizeDetect_.style.paddingRight = '12px';
            InpSizeDetect_.style.visibility = 'hidden';
            document.body.appendChild(InpSizeDetect_);
            iSD = document.getElementById('InpSizeDetect');
        }

        //ELLENÖRZÖM , HOGY AZ ÚJ NODE - TARTALOMMAL NYÚLIK - SZÉLESSÉGE MEGHALADJA-E AZ INPUT MEZŐÉT
        //HA MEGHALADJA, AKKOR ELKEZDEM LEVÁGNI AZ STRING OBJEKTUM ELEJÉRŐL A KARAKTEREKET	
        if (iSD.offsetWidth >= showActInpObj.offsetWidth) {
            trimAnimTxt++;
        }
    }

    if ((DecodeInputString(showActObj.par1[1]).length - 1) == animSteps) {
        PlaySound_asyncron("strinput.flv");
    }

    if (animSteps > 0)
        Animate2("", true, "AnimateInput(true)", PlayerConfig.InputDelay, animPhase)
    else {
        show("cursor");
        Animate2("", true, "ShowScreen('" + showActObj.nextFrame + "')", PlayerConfig.InputDelay, "nostop")
    }
}

function ShowBullsEye() {
    if (PlayerConfig.HideClickMark != true)
        show("bullseye");
}

function HideBullsEye() {
    hide("bullseye");
}

var cursor_alignment_x = 25;
var cursor_alignment_y = 25;

function AnimateMouse(internal) {
    if (!internal)
        upk.Timeline.SetFrameState("A");
    var cx, cy
    show("cursor");
    animSteps--;
    if (animSteps >= 0) {
        var hot = "hot" + showActObj.id + "_0";
        anim_to_x = getObjLeft(hot) + getObjWidth(hot) / 2
        anim_to_y = getObjTop(hot) + getObjHeight(hot) / 2
        cx = anim_to_x - animSteps * anim_x
        cy = anim_to_y - animSteps * anim_y
        if (!isNaN(cx) && !isNaN(cy)) {
            shiftTo("cursor", cx - cursor_alignment_x, cy - cursor_alignment_y);
            shiftTo("bullseye", cx - getObjWidth("bullseye") / 2, cy - getObjHeight("bullseye") / 2)
        };
    };
    if (animSteps >= 0) {
        var delay = PlayerConfig.MouseDelay;
        if (animStepOriginal > 15) {
            if ((animSteps > 5) && (animSteps < (animStepOriginal - 5))) {
                delay = PlayerConfig.MinMouseDelay;
            }
        }
        upk.Timeline.IncFrameTimeCounter(delay);
        Animate("AnimateMouse(true)", delay, animPhase)
    }
    else {
        animSteps = parseInt(showActObj.type.substr(showActObj.type.length - 1, 1)) * 2
        if (animSteps > 0) {
            ShowBullsEye();
            if (animPhase != "")
                clearTimeout(animTimeout)
            Animate2("sclick.flv", true, "AnimateBullseye()", PlayerConfig.BullseyeDelay, "nostop")
        }
        else if (showActObj.type.indexOf("Down") != -1) {
            ShowBullsEye();
            Animate2("sclick.flv", true, "ShowScreen(\'" + showActObj.nextFrame + "\')", PlayerConfig.MouseDelay, "nostop")
            //			ShowScreen(showActObj.nextFrame)
        }
        else if (showActObj.type.indexOf("BeginDrag") != -1) {
            ShowBullsEye();
            clearTimeout(bullsTimeout);
            bullsTimeout = setTimeout("DragStart()", PlayerConfig.BullseyeDelay);
            //			Animate2("sclick.wav",true,"ShowScreen(\'"+showActObj.nextFrame+"\')",PlayerConfig.MouseDelay,"nostop")
            //			ShowScreen(showActObj.nextFrame)
        }
        else if (showActObj.type.indexOf("Up") != -1) {
            ShowBullsEye();
            clearTimeout(bullsTimeout);
            bullsTimeout = setTimeout("DragEnd()", PlayerConfig.BullseyeDelay);
            //			hide("bullseye")
            //			Animate2("sclick.wav",true,"ShowScreen(\'"+showActObj.nextFrame+"\')",PlayerConfig.MouseDelay,"nostop")
            //			ShowScreen(showActObj.nextFrame)
        }
        else if (showActObj.type.indexOf("Wheel") != -1) {
            ShowBullsEye();
            Animate2("swheel.flv", true, "ShowScreen(\'" + showActObj.nextFrame + "\')", PlayerConfig.WheelDelay, "nostop")
            //			ShowScreen(showActObj.nextFrame)
        }
        else
            ShowScreen(showActObj.nextFrame)
    }
}

function DragStart() {
    Animate2("sclick.flv", true, "ShowScreen(\'" + showActObj.nextFrame + "\')", PlayerConfig.MouseDelay, "nostop")
};

function DragEnd() {
    HideBullsEye();
    Animate2("sclick.flv", true, "ShowScreen(\'" + showActObj.nextFrame + "\')", PlayerConfig.MouseDelay, "nostop")
};

function AnimateBullseye() {
    --animSteps;

    upk.Timeline.IncFrameTimeCounter(PlayerConfig.BullseyeDelay);

    if (Math.floor(animSteps / 2) == animSteps / 2) {
        HideBullsEye();
        if (animSteps > 0)
            Animate2("sclick.flv", true, "AnimateBullseye()", PlayerConfig.BullseyeDelay, animPhase)
        else
            ShowScreen(showActObj.nextFrame)
    }
    else {
        ShowBullsEye();
        if (animSteps > 0)
            Animate("AnimateBullseye()", PlayerConfig.BullseyeDelay, animPhase)
        else
            ShowScreen(showActObj.nextFrame)
    }
}

function DemoNext() {
    upk.Timeline.Lock(true);
    clearTimeout(animTimeout);
    clearTimeout(bullsTimeout);
    PlayStop();
    HideBullsEye();
    ShowScreen(showActObj.nextFrame)
}

function DemoPrev() {
    upk.Timeline.Lock(true);
    clearTimeout(animTimeout);
    clearTimeout(bullsTimeout);
    PlayStop();
    HideBullsEye();

    l = showHistory.length;
    if (l == 0)
        return;
    if (l == 1) {
        s = showHistory[0];
        showHistory.length--;
    }
    else {
        s = showHistory[l - 2];
        while (screens[s].actions[0].type == "Drag") {
            showHistory.length--;
            s = showHistory[showHistory.length - 2];
        }
        showHistory.length -= 2;

    }
    ShowScreen(s, null, "back");
}

function DemoForward(gonext) {
    if (!gonext)
        gonext = false;
    if (gonext || (!gonext && isPaused)) {
        clearTimeout(animTimeout);
        clearTimeout(bullsTimeout);
        PlayStop();
        HideBullsEye();
        setTimeout("ShowScreen(\"" + showActObj.nextFrame + "\")", 10);
        return;
    };
    if (showActObj && animPhase == "mouse" && animSteps != animStepOriginal) {
        HideBullsEye();
        ShowScreen(showActObj.nextFrame)
    }
    else if (showActObj && animPhase != "nostop") {
        if (showActObj.type != "Input" && showActObj.type != "Key" && showActObj.type != "None" && showActObj.type != "Decision") {
            animObject.timeout = 50;
            PlaySound("dummy.flv");
        }
        else {
            ShowScreen(showActObj.nextFrame)
        }
    }
}

//
// Teacher mode
//

function TeacherFastBack() {
    if (showHistory.length > 1) {
        //    var firstID = showHistory[0]
        showHistory.length = 0
        //    ShowScreen(firstID)
    }
    FirstScreen(true);
}

function TeacherTestSkip(type) {
    return (type == "Drag" || type.indexOf("Up") != -1)
}

var _backStep = false;

function TeacherBack() {
    _backStep = true;
    if (showHistory.length > 1) {
        showHistory.length--;
        var prevID = showHistory[showHistory.length - 1];
        while (showHistory.length > 1 && TeacherTestSkip(screens[prevID].actions[0].type)) {
            showHistory.length--;
            prevID = showHistory[showHistory.length - 1];
        }
        showHistory.length--;
        HideAction();
        if (historyActionMap[prevID])
            ShowScreen(prevID, historyActionMap[prevID])
        else
            ShowScreen(prevID);
        //	binterf.SetErrorMessage("");
    }
}

function TeacherForward(noskip, id, actid) {
    _backStep = false;
    if (event_blocked)
        return;

    if (KFinishClose)
        return

    KnowItForward();
    if (id == null)
        id = showActObj.nextFrame

    if (actid) {
        for (var i = 0; i < screens[showScreen].actions.length; i++) {
            if (actid == screens[showScreen].actions[i].id) {
                historyActionMap[showScreen] = i;
                break;
            };
        };
    };

    var count = 999

    if (id != "end") {
        while (!noskip && id != "end" && TeacherTestSkip(screens[id].actions[0].type) && count--) {
            showHistory[showHistory.length] = id
            id = screens[id].actions[0].nextFrame
        }
    }
    ///	binterf.SetErrorMessage("");
    ShowScreen(id)
}

function TeacherAlter() {
    var k = true;
    while (k) {
        showAct++;
        if (showAct == screens[showScreen].actions.length)
            showAct = 0;
        k = screens[showScreen].actions[showAct].realAction == false;
        if (k == true)
            k = screens[showScreen].actions[showAct].emptybubble;
    };
    showHistory.length--
    ShowScreen(showScreen, showAct)
}

function FrameIDUpdated(id) {
    document.getElementById("frameidvalue").innerHTML = id == "start" ? "Start" : id.substr(1);
    //    alert(id);
}

function ToggleShowFrameID() {
    if (document.getElementById("frameiddiv").style.display == "none") { document.getElementById("frameiddiv").style.display = "block"; }
    else document.getElementById("frameiddiv").style.display = "none";
}

function CheckFrameIDKeys(e) {
    if (e != undefined) {
        if (e.type == "keydown") {
            if (e.keyCode == showFrameIDToggle) {
                if (e.shiftKey == true) {
                    return true;
                }
            }
            try {
                if (e.originalCode == showFrameIDToggle) {
                    if (e.shiftKey == true) {
                        return true;
                    }
                }
            }
            catch (ee) { }
        }
    }
    return false;
}

function TeacherWrong(e) {
    if (showFrameIDToggle && CheckFrameIDKeys(e) == true) {
        ToggleShowFrameID();
        return;
    }

    if (showActObj.type == "None")
        return;

    if (KFinishClose)
        return

    if (event_blocked)
        return;
    if (playMode == "K") {
        if (showActObj.type == "Input")
            showActObj.par2 = showActInpObj.value;
        if (!IsLeadIn() && !IsLeadOut())
            KnowItWrong();
        return;
    };
    var text

    if (showActObj.type == "Input")
        text = R_wrong_input
    else if (showActObj.type == "Key")
        text = R_wrong_key
    else if (showActObj.type == "Decision")
        text = R_wrong_decision
    else
        text = R_wrong_mouse

    if (showActObj.type == 'Input') {
        line = "FocusInpObj()";
    }
    else
        line = "";

    if (showHistory.length > 1 && TeacherTestSkip(showActObj.type)) {
        var prevID = showHistory[showHistory.length - 1]
        while (showHistory.length > 1 && TeacherTestSkip(screens[prevID].actions[0].type)) {
            showHistory.length--
            prevID = showHistory[showHistory.length - 1]
        }
        showHistory.length--
        line = "ShowScreen('" + prevID + "')"
    }

    if (_ShowBubble(showActObj)) {
        binterf.SetErrorMessage(text);
    }

    Animate2("ding.flv", true, "", "", "");
    if (line.length > 0) {
        if (IsTouchDevice()) {
            if (line == "FocusInpObj()") {
                FocusInpObj();
            }
            else {
                setTimeout(line, 0);
            }
        }
        else
            setTimeout(line, 0);
    }
}

//
// Generic player functions
//

function Decision(num) {
    // Go down decision path #num (num is 1-based)
    OffLink();
    Menu_Resume();
    ShowScreen(screens[showScreen].actions[num - 1].nextFrame)
}

var trackSent = false;

function ClosePlayer(topicfinished, closeassessment) {
    lms_ClosePage();
    //close dialog if possibe
    if (parent.isOpenDialog) {
        if (parent.isOpenDialog()) {
            parent.closeDialog();
            return;
        }
    }
    if (!trackSent) {
        trackSent = true;
        try {
            if (opener.OnQuestionContinue_fromTopic) {
                var success = topicfinished;
                if (!success)
                    success = 0;
                if (!closeassessment)
                    closeassessment = 0;
                if (success == 1)
                    success = (GetResultInPercent() >= KScoreNeeded);
                opener.OnQuestionContinue_fromTopic(success, closeassessment);
            }
        }
        catch (e) { };
    }
    setTimeout("TimedClosePlayer(" + topicfinished + ")", 500);
};

function TimedClosePlayer(topicfinished) {
    PlayStop();
    CloseAction();

    KTopicFinished = topicfinished;
    /*	
    if (playMode=="K")
    {
    trackScoreCompleted=GetResultInPercent(true);
    trackScoreRequired=KScoreNeeded;
    if (topicfinished)
    trackComplete()
    else
    trackIncomplete();
    };
    */
    this.blur();

    //	moved to onUnload
    //	if (guidedParent)
    //	{
    //		guidedParent.GITMClosed();
    //	}
    if (IsTouchDevice()) {
        history.back();
    }
    else {
        try {
            if (window.opener != null)
                window.opener.focus();
        }
        catch (e) { };
        top.close();
    }
    /*	
    if (top.window.opener)
    {
    if (!top.window.opener.closed)
    {
    if (top.window.opener.GITMClosed)
    top.window.opener.GITMClosed();
    }
    };
    top.close()
    */
}

function HandleResize0() {
    // 10009037  PLAYER - PREFERENCES DIALOG MESSED UP ON BROWSER RESIZE
    // Zsolt, 10/08/2010
    // if the window size is changed, i will refresh the gray area
    if (isOpenDialog)
        if (isOpenDialog() == true)
            resizeDialog();
    if (IsTouchDevice()) { return; }
    Scroll2Action(true);
    HandleResize();
}

function HandleResize() {
    if (IsTouchDevice()) { return; }
    if (scrW == 0)
        return;
    if (binterf) binterf.HandleRepos()
    if (NS4) {
        if (loadWidth != window.innerWidth || loadHeight != window.innerHeight) {
            history.go(0)
            return
        }
    }

    var x, y, py
    var wh, ww
    var sx, sy

    wh = getInsideWindowHeight()
    ww = getInsideWindowWidth()

    sx = getScrollLeft()
    sy = getScrollTop()

    x = Math.round((ww - scrW) / 2)
    if (x < 0) x = 0;

    y = Math.round((wh - scrH) / 2)
    if (y < 0) {
        y = Math.round((wh - scrH) / 2)
        if (y < 0)
            y = 0
    }
    if (IsiOS()) { y = 0; }
    ClearScrBorder();
    shiftTo("screen", x, y)
    if (IsTouchDevice()) {
        try {
            binterf.RefreshPosition();
        }
        catch (e) { }
    }
    if (StartScreen.length > 0)
        SetScrBorder(x, y, scrW, scrH, 1);

}

function ClearScrBorder() {
    var borderobj = document.getElementById("scrborder");
    if (!borderobj)
        return;
    hide("scrborder");
};

function SetScrBorder(x, y, w, h, b) {
    var borderobj = document.getElementById("scrborder");
    if (!borderobj)
        return;
    if (IsFF() || IsSafari()) {
        w -= 2;
        h -= 2;
    }
    borderobj.style.left = x - b;
    borderobj.style.top = y - b;
    borderobj.style.width = w + 2 * b;
    borderobj.style.height = h + 2 * b;
    borderobj.style.borderWidth = String(b) + "px";
    show("scrborder");
};

function max(a, b) {
    return (a > b) ? a : b
}

function min(a, b) {
    return (a < b) ? a : b
}

function SetActionColor() {
    var bub = showActObj.id
    var color = UserPrefs.MarqueeColor;
    for (var i = 0; i < showActObj.hotspots; i++) {
        var hotp = "hot" + bub + "_" + i + "p";
        document.getElementById(hotp).style.borderColor = color;
    }
};

function KnowItWrong() {
    if (KWarningLevel == 4) {
        Animate2("ding.flv", true, "", "", "");
        return;
    };
    HideKnowItBubble()
    KWarningLevel++;
    if (KWarningLevel == 1 && KRemediation1 == false)
        KWarningLevel++;
    if (KWarningLevel == 2 && KRemediation2 == false)
        KWarningLevel++;
    if (KWarningLevel == 3 && KRemediation3 == false)
        KWarningLevel++;
    if (KWarningLevel >= DEF_KWARNINGSCORELEVEL)
        AddToWrongScreens(showScreen);
    Animate2("ding.flv", true, "", "", "");
    ShowKnowItBubble();
};

function KnowItForward() {
    KWarningLevel = 0;
};

function IsDragBegin(ss) {
    var s = showActObj.type;
    if (ss)
        s = ss;
    return (s == "LBeginDrag" || s == "RBBeginDrag" || s == "MBBeginDrag")
};

function IsDragSequence2(ss) {
    var s = showActObj.type;
    if (ss)
        s = ss;
    return (s == "Drag");
};

var nib_Positioned = false;
var nib_l, nib_t, nib_r, nib_b;
var nib_bCloseEnabled = true;

function DecodeTagElements(s) {
    s = replaceString("&lt;", "<", s);
    s = replaceString("&gt;", ">", s);
    return s;
}

function AddTopMargin(s) {
    if (s.substr(0, 17) == '<p align="right">') {
        ss = s.substr(0, 16) + ' style="margin-top: 10px;" ' + s.substr(16);
        return ss;
    }
    return s;
}

function ShowKnowItBubble() {
    binterf.m_bFFClearHeight = false;
    var s = "";
    nib_Positioned = false;
    nib_bCloseEnabled = true;
    if (KFinishClose) {
        binterf.m_bFFClearHeight = true;
        s = (lms_inAssessment == true ? template_knowit_finish_close_inassessment : template_knowit_finish_close);
        nib_Positioned = true;
        nib_bCloseEnabled = false;
    }
    else if (KConfirmDemo) {
        binterf.m_bFFClearHeight = true;
        s = template_knowit_confirmdemo;
        nib_Positioned = true;
    }
    else if (IsLeadIn()) {
        s = DecodeTagElements(R_titleformat_begin) + topicName + DecodeTagElements(R_titleformat_end);
        s += showActObj.ktext;
        sscore = GetTemplate_knowit_leadin_score("" + KScoreNeeded);
        sscore = '<p id="scoretext" class="InstructText">' + sscore + '</p>';
        s = replaceString("###KSCORE###", sscore, s);
        if (PlayerConfig.ShowScoreNeeded)
            binterf.m_bFFClearHeight = true;
        nib_Positioned = false;
    }
    else if (IsLeadOut()) {
        if (KScoringScreen) {
            binterf.m_bFFClearHeight = true;
            var passed = GetResultInPercent();
            var result = "";
            s = DecodeTagElements(R_titleformat_begin) + topicName + DecodeTagElements(R_titleformat_end);

            if (passed >= KScoreNeeded) {
                lms_knowitScore(getMyGuid(), passed, 1);
                result = template_scoring_YES;
            }
            else {
                lms_knowitScore(getMyGuid(), passed, 0);
                result = template_scoring_NO;
            };
            s += GetTemplate_scoring("" + passed, "" + KScoreNeeded, result);
        }
        else {
            s = DecodeTagElements(R_titleformat_begin) + topicName + DecodeTagElements(R_titleformat_end);
            s += showActObj.ktext;
        };
        nib_Positioned = false;
    }
    else if (IsExplanation()) {
        s = showActObj.knowittext + "<br><p class='MsoNormal'>" + showActObj.fontbegin + template_knowit_explanation + showActObj.fontend + "</p>";
        nib_Positioned = false;
        binterf.m_bFFClearHeight = true;
    }
    else {
        switch (KWarningLevel) {
            case 0:
                binterf.m_bFFClearHeight = true;
                if (IsDragBegin()) {
                    s = template_knowit_dragwarning;
                }
                else {
                    s = "";
                    if (KContinueFlag == 1) {
                        s = template_knowit_continue;
                        if (showActObj.knowittext.length > 0)
                            s += "<br><br>";
                    };
                    s += showActObj.knowittext;
                    if (showActObj.type == "Input")
                        s += template_typingcomplete;
                    s += AddTopMargin(template_knowit_nextstep);
                };
                break;
            case 1:
                binterf.m_bFFClearHeight = true;
                if (showActObj.knowittext.length > 0) {
                    s = template_knowit_warningL1 + "<hr>" + showActObj.knowittext;
                    if (showActObj.type == "Input")
                        s += template_typingcomplete;
                    s += AddTopMargin(template_knowit_nextstep);
                }
                else {
                    s = template_knowit_warningL1;
                    if (showActObj.type == "Input")
                        s += template_typingcomplete;
                    s += AddTopMargin(template_knowit_nextstep);
                };
                break;
            case 2:
                binterf.m_bFFClearHeight = true;
                s = template_knowit_warningL2 + showActObj.text;
                if (showActObj.type == "Input")
                    s += template_typingcomplete;
                s += AddTopMargin(template_knowit_nextstep);
                break;
            case 3:
                binterf.m_bFFClearHeight = true;
                if (showActObj.hotspots == 0) {
                    s = template_knowit_warningL3_0 + showActObj.text;
                    if (showActObj.type == "Input")
                        s += template_typingcomplete;
                    s += AddTopMargin(template_knowit_nextstep);
                }
                else {
                    s = template_knowit_warningL3_H + showActObj.text;
                    if (showActObj.type == "Input")
                        s += template_typingcomplete;
                    s += AddTopMargin(template_knowit_nextstep);
                    var bub = showActObj.id
                    SetActionColor();
                    for (var i = 0; i < showActObj.hotspots; i++) {
                        var hot = "hot" + bub + "_" + i;
                        if (getDIV(hot)) show(hot, playMode == "S")
                    }
                };
                break;
            default: // level 4
                binterf.m_bFFClearHeight = true;
                s = template_knowit_warningL4;
        };
        nib_Positioned = true;
    };

    nib_l = nib_t = nib_r = nib_b = (-1);
    if (nib_Positioned) {
        if (showActObj.hotspots) {
            var d = "hot" + showActObj.id + "_0";
            nib_l = getObjLeft(d) + getObjLeft("screen");
            nib_t = getObjTop(d) + getObjTop("screen");
            nib_r = nib_l + getObjWidth(d);
            nib_b = nib_t + getObjHeight(d);
            if (showActObj.type == "Input") {
                //				nib_t+=16;
                nib_b -= 16;
            };
        }
    };
    nib_Positioned = !nib_Positioned;

    binterf.ResetContent();
    binterf.SetText(s);
    binterf.SetColor(showActObj.bubcolor);
    //binterf.Download("ShowKnowItBubble2");
    ShowKnowItBubble2();
};

function ShowKnowItBubble2(retOK, retError) {
    if (IsExplanation()) {
        binterf.SetPosition(-1, -1, -1, -1, true, false, showActObj.xpos, showActObj.ypos, showActObj.kwidth, showActObj.kheight);
    }
    else {
        w = (KWarningLevel < 2 ? showActObj.kwidth : showActObj.width);
        h = (KWarningLevel < 2 ? showActObj.kheight : showActObj.height);
        w = (w < Knowit_minimum ? Knowit_minimum : w);
        if (KWarningLevel == 1 || KConfirmDemo == true) {
            w = (w < Rem1_minimum ? Rem1_minimum : w);
        }
        if (KWarningLevel == 2 || KWarningLevel == 3) {
            w = (w < Rem2_minimum ? Rem2_minimum : w);
        }
        if (KWarningLevel == 4) {
            w = Rem4_width;
        }
        if (KFinishClose) {
            w = 58;
        }
        binterf.SetPosition(nib_l, nib_t, nib_r, nib_b, nib_Positioned, 0, 0, 0, w, h);
    }
    binterf.SetEnableCloseButton(nib_bCloseEnabled ? 1 : 0);
    binterf.Show();
    if (showActObj.type == "Input") {
        var bub = showActObj.id;
        SetActionColor();
        for (var i = 0; i < showActObj.hotspots; i++) {
            var hot = "hot" + bub + "_" + i;
            var hotdiv = getDIV(hot);
            if (hotdiv) {
                var inp = getDIV(hot + "p");
                if (KWarningLevel < 3 || KWarningLevel == 4 || KFinishClose) {
                    if (!hotdiv.LeftOriginal)
                        hotdiv.LeftOriginal = hotdiv.offsetLeft;
                    if (!hotdiv.TopOriginal)
                        hotdiv.TopOriginal = hotdiv.offsetTop;
                    hotdiv.style.left = "" + (hotdiv.LeftOriginal + 2) + "px";
                    hotdiv.style.top = "" + (hotdiv.TopOriginal + 2) + "px";

                    if (!inp.WidthOriginal)
                        inp.WidthOriginal = inp.offsetWidth;
                    if (!inp.HeightOriginal)
                        inp.HeightOriginal = inp.offsetHeight;
                    if (!inp.borderColorOriginal)
                        inp.borderColorOriginal = inp.style.borderColor;

                    inp.style.border = "0px";
                    inp.style.width = "" + (inp.WidthOriginal - 4) + "px";
                    inp.style.height = "" + (inp.HeightOriginal - 4) + "px";
                }
                else {
                    if (inp.borderColorOriginal) {
                        inp.style.border = "3px";
                        inp.style.borderColor = inp.borderColorOriginal;
                        inp.style.borderStyle = "solid";
                    };
                    if (inp.WidthOriginal)
                        inp.style.width = "" + inp.WidthOriginal + "px";
                    if (inp.HeightOriginal)
                        inp.style.height = "" + inp.HeightOriginal + "px";
                    if (hotdiv.LeftOriginal)
                        hotdiv.style.left = "" + hotdiv.LeftOriginal + "px";
                    if (hotdiv.TopOriginal)
                        hotdiv.style.top = "" + hotdiv.TopOriginal + "px";
                };
                show(hot, playMode == "S")
            };
        }
        if (showActObj.par4) {
            // Preset input field
            showActObj.par4 = false;
            if (KWarningLevel == 0) {
                showActInpObj = document.layers ? document.layers.screen.document.layers["hot" + showActObj.id + "_0"].document["f" + showActObj.id]["inp" + showActObj.id] : document["f" + showActObj.id + "_0"]["inp" + showActObj.id + "_0"]
                showActInpObj.value = showActObj.par5
                showActInpObj.original = showActInpObj.value;
                showActInpObj.onkeyup = EventKeyUp
                showActInpObj.onkeypress = EventInputKey
                showActInpObj.onpropertychange = EventPropertyChange
                showActInpObj.onfocus = InputOnFocus;
                showActInpObj.onblur = InputOnBlur;
            }
            try {
                showActInpObj.focus()
            }
            catch (e) { };
        };
    };
    ShowScreen3();
};

function HideKnowItBubble() {
    var bub = showActObj.id
    for (var i = 0; i < showActObj.hotspots; i++) {
        var hot = "hot" + bub + "_" + i;
        if (getDIV(hot)) hide(hot, playMode == "S")
    }
    binterf.ResetContent();
    binterf.Hide();
};

////////////////////////////////////////////////////////////////////////////////
// sound support

var soundplayed = false;

function PlayStop() {
    SoundPlayerObj.Stop();
};

function PlayPause() {
    SoundPlayerObj.Pause();
}

function PlayResume() {
    if (soundplayed) {
        SoundPlayerObj.Resume();
        return true;
    }
    else if (!bPlayerIsAvailable) {
        return true;
    }
    else if (showScreen == StartScreen) {
        return false;
    }
    return true;
};

function GetDecisionSound(actionfname) {
    return actionfname;
};

function PlaySound_asyncron(fname) {
    var pa = UserPrefs.PlayAudio;
    if (pa != "none")
        SoundPlayerObj.Play(fname, true, false, true);
}

function PlaySound(fname, demosound, temp) {
    if (fname == "dummy.flv") {
        PlayStop();
        soundplayed = false;
        if (animObject) {
            if (animObject.cmd.length > 0) {
                Animate(animObject.cmd, animObject.timeout, animObject.phase);
            };
        };
        return;
    };
    var dname = GetDecisionSound(fname);
    fname = dname;
    if (!temp) {
        animObject.fname = fname;
        animObject.demosound = demosound;
    };
    var dmsound = true;
    if (!demosound)
        dmsound = false;

    var pa = UserPrefs.PlayAudio;
    if (playMode == "T" || playMode == "K") {
        if ((pa == "all" && soundIsExported) || (dmsound && (pa == "demo" || pa == "all"))) {
            if (KScoringScreen == false && KFinishClose == false && (KWarningLevel == 0 || dmsound)) {
                soundplayed = true;
                SoundPlayerObj.Play(fname, dmsound, temp);
                upk.Timeline.IncFrameTimeCounter(1000);
            }
        }
        else if (animObject.cmd.length > 0)
            Animate(animObject.cmd, animObject.timeout, animObject.phase);
    };
    if (playMode == "S" || KGuestDemoMode) {
        if ((pa == "all" && soundIsExported) || (dmsound && (pa == "demo" || pa == "all"))) {
            soundplayed = true;
            SoundPlayerObj.Play(fname, dmsound, temp);
            upk.Timeline.IncFrameTimeCounter(1000);
        }
        else if (animObject.cmd.length > 0)
            Animate(animObject.cmd, animObject.timeout, animObject.phase);
    };
    //    if (playMode == "K") {
    //        if (dmsound && (pa == "demo" || pa == "all")) {
    //            soundplayed = true;
    //            SoundPlayerObj.Play(fname, dmsound, temp);
    //        }
    //    };
};

function OnErrorPlaySound(v1, v2) {
    soundplayed = false;
    if (animObject) {
        if (animObject.cmd.length > 0 && playMode != "K") {
            if (timelineDescriptor.valid == true) {
                if (timelineDescriptor.type == "narration") { // sound playing failed
                    if (animObject.timeout != DELAY_INFINITE * 100)
                        animObject.timeout = timelineDescriptor.resttime;
                }
                if (timelineDescriptor.type == "animationstart") {
                    if (animObject.timeout != DELAY_INFINITE * 100)
                        animObject.timeout = 1;
                }
                if (timelineDescriptor.type == "nextframe") {
                    DemoNext();
                    timelineDescriptor.valid = false;
                    return;
                }
                timelineDescriptor.valid = false;
            }
            Animate(animObject.cmd, animObject.timeout, animObject.phase);
        };
    };
};

function OnEndPlaySound(v1) {
    soundplayed = false;
    timelineDescriptor.valid = false;
    if (animObject) {
        if (animObject.cmd.length > 0 && playMode != "K") {
            animCmd = animObject.cmd;
            animPhase = animObject.phase;
            clearTimeout(animTimeout);
            animTimeout = setTimeout("AnimateTimer();", 100);
            upk.Timeline.IncFrameTimeCounter(100);
        };
    };
};

////////////////////////////////////////////////////////////////////////////////

function _HasSound(a) {
    if (UserPrefs.PlayAudio != "all")
        return false;
    ix = (a.id).substr(1) + ".ASX";
    if (sounds[ix]) {
        if (sounds[ix].fct == 0)
            return false;
        return (sounds[ix].flist[0].length > 0);
    }
    return false;
}

function _HasActionArea(a) {
    if (IsExplanation(a))
        return false;
    if (IsLeadIn(a))
        return false;
    if (IsLeadOut(a))
        return false;
    if (IsDecision(a))
        return false;
    return (a.hotspots > 0);
}

function _ShowBubble(a) {
    f = screens[a.prevFrame];
    if (playMode == "S" || playMode == "T") {
        if (a.type == "Decision")
            return true;
        if (topicShowBubbles == "Always")
            return true;
        if (topicShowBubbles == "Never")
            return false;
        return (f.showBubble == "true" ? true : false);
    }
    return true;
}

function _ShowActionArea() {
    if (playMode == "S" && PlayerConfig.HideActionBordersInSeeIt == true) {
        return false;
    }
    return (topicShowBubbles != "Never");
}

function _SkipFrame(f) {
    a = f.actions[0];
    // only one decision branch
    if (f.actions.length == 1 && a.type == "Decision")
        return true;
    // explanation, start and end frame, null delay in S and T modes
    if (playMode == "S" && a.type == "None" && a.delay == 0)
        return true;
    if (playMode == "T" && a.type == "None" && a.delay == 0)
        return true;
    // decision frame and null delay in S mode
    if (playMode == "S" && a.type == "Decision" && a.delay == 0)
        return true;
    // all decision in K mode
    if (playMode == "K" && a.type == "Decision")
        return true;
    // explanation frame with empty text in K mode
    if (playMode == "K" && a.type == "None" && a.prevFrame != "start" && a.nextFrame != "end" && a.knowittext.length == 0)
        return true;

    if (playMode == "K")
        return false;

    _HasActionArea(a);

    if (!_ShowBubble(a)) {
        if (_HasSound(a)) {
            return false;
        }
        else {
            if (IsLeadIn(a))
                return true;
            if (IsLeadOut(a))
                return true;
            if (IsExplanation(a))
                return true;
            if (IsDecision(a))
                return false;
            if (a.delay == DELAY_INFINITE) {
                if (playMode == "S") {
                    return true;
                }
                else {
                    return false;
                }
            }
        }
    }
    return false;
}

function FilterDecisionText() {
    if (IsDecision()) {
        var frameid = showActObj.prevFrame;
        var eobj = ecidStartDecisions[frameid];
        if (eobj == null) {
            var newstr = showActObj.text;
            if (IsIE10())
                newstr = replaceString("DecisionList", "DecisionListIE10", showActObj.text);
            return newstr;
        }
        var dpathlist = new Array();
        var prefix = "";
        var postfix = "";
        var s = showActObj.text.toLowerCase();

        var liclass1 = '<li class=decisionlist>';
        var liclass2 = '<li class="decisionlist">';
        if (IsIE10()) {
            liclass1 = '<li class=decisionlistie10>';
            liclass2 = '<li class="decisionlistie10">';
        }

        var k1 = s.indexOf(liclass1);
        if (k1 < 0)
            k1 = s.indexOf(liclass2);
        prefix = showActObj.text.substr(0, k1);
        var k2 = s.lastIndexOf('</li>') + 5;
        postfix = showActObj.text.substr(k2);
        while (true) {
            if (k1 < 0)
                break;
            var k21 = s.indexOf(liclass1, k1 + 1);
            if (k21 < 0)
                k21 = s.indexOf(liclass2, k1 + 1);
            if (k21 > 0) {
                dpathlist[dpathlist.length] = showActObj.text.substr(k1, k21 - k1 - 1);
                k1 = k21;
            }
            else {
                dpathlist[dpathlist.length] = showActObj.text.substr(k1, k2 - k1);
                break;
            }
        }

        for (var i = 0; i < dpathlist.length; i++) {
            var s = dpathlist[i].toLowerCase();
            var l = s.length;
            if (s.substr(l - 5) != '</li>') {
                dpathlist[i] = dpathlist[i] + "</li>";
            }
        }

        var stext = prefix;
        var actions = screens[frameid].actions;
        for (var i = 0; i < actions.length; i++) {
            var l = true;
            for (ii = 0; ii < eobj.pathstoignore.length; ii++) {
                if (eobj.pathstoignore[ii] == actions[i].id) {
                    l = false;
                }
            }
            if (l)
                stext += dpathlist[i];
        }
        stext += postfix;
        return stext;
    }
    return showActObj.text;
}

function ShowAction() {
    binterf.m_bFFClearHeight = false;
    var pointerDirection = showActObj.bubpos;
    var pointerXpos = showActObj.xpos;
    var pointerYpos = showActObj.ypos;

    if (playMode == "K" && !KGuestDemoMode) {
        ShowKnowItBubble();
        if (IsDragBegin() && !KFinishClose)
            Animate2("ding.flv", true, "", "", "");
        return;
    };
    if (showActObj.type == "None" && showActObj.emptytext) {
        if (!IsLeadIn() && !IsLeadOut()) {
            ShowScreen3();
            return;
        };
    };
    var bub = showActObj.id
    binterf.ResetContent();
    var bubtext = FilterDecisionText();
    if (playMode == "T" && showActObj.type == "Input") {
        bubtext = showActObj.text + template_typingcomplete;
    }
    if (playMode == "S" || (playMode == "K" && KGuestDemoMode)) {
        var k1 = template_pauselink.indexOf("HLink(600)");
        var k2 = template_pauselink.indexOf("</a>");
        var tpl1 = template_pauselink.substr(0, k1 + 12);
        var tpl2 = template_pauselink.substr(k2);
        var tpl = tpl1 + (isPaused ? R_interface_resume : R_interface_pause) + tpl2;
        bubtext += tpl;
        binterf.m_bFFClearHeight = true;
    }

    if (playMode == "T" && IsDragBegin() && IsTouchDevice() && KGuestDemoMode == 0) {
        binterf.ResetContent();
        bubtext = '<p class="InstructText" style="margin-top: 0px; color: #000080; font-weight:bold;">' + R_swipe_drag + '</p>';
        binterf.SetText(bubtext);
        binterf.SetIcon(showActObj.iconname);
        binterf.SetColor(showActObj.bubcolor);
        binterf.SetPosition(-1, -1, -1, -1, true, 0, 0, 0);
        //     binterf.SetPosition(-1, -1, -1, -1, true, pointerDirection, pointerXpos, pointerYpos, showActObj.width, showActObj.height);
        ShowAction2();
        return;
    }

    binterf.SetText(bubtext);
    binterf.SetIcon(showActObj.iconname);
    binterf.SetColor(showActObj.bubcolor);
    if (playMode == "T") {
        binterf.SetAlternative(showActObj.showalternatives);
        for (var i = 0; i < screens[showScreen].infoblocks.length; i++) {
            var ib = screens[showScreen].infoblocks[i];
            binterf.AddInfoBlock(ib.buttonfile, ib.url, ib.tooltip);
        };
    };
    if (showActObj.type == "Decision" || showActObj.type == "Input")
        binterf.m_bFFClearHeight = true;
    if (showActObj.hotspots) {
        var d = "hot" + bub + "_0";

        l = getObjLeft(d) + getObjLeft("screen");
        if (l < 0) l = 0;
        t = getObjTop(d) + getObjTop("screen");
        if (t < 0) t = 0;
        r = l + getObjWidth(d);
        b = t + getObjHeight(d);
        if (showActObj.type == "Input") {
            //			t+=16;
            b -= 16;
        };
        if (showActObj.bubpos > 0) {
            binterf.SetPosition(l, t, r, b, true, pointerDirection, pointerXpos, pointerYpos, showActObj.width, showActObj.height);
        }
        else {
            if (showActObj.type == "None")
                binterf.SetPosition(-1, -1, -1, -1, true, pointerDirection, pointerXpos, pointerYpos, showActObj.width, showActObj.height)
            else
                binterf.SetPosition(l, t, r, b, false, pointerDirection, pointerXpos, pointerYpos, showActObj.width, showActObj.height);
        };
    }
    else {
        binterf.SetPosition(-1, -1, -1, -1, true, pointerDirection, pointerXpos, pointerYpos, showActObj.width, showActObj.height);
    };

    if (KGuestDemoMode == 0 && !showActObj.emptybubble)
    //binterf.Download("ShowAction2")
        ShowAction2()
    else
        ShowAction2();
}

function ShowAction2(retOK, retError) {
    if (KGuestDemoMode == 0 && !showActObj.emptybubble && _ShowBubble(showActObj))
        binterf.Show();

    if (showActObj.type != "None") {
        SetActionColor();
        var bub = showActObj.id
        for (var i = 0; i < showActObj.hotspots; i++) {
            if (i == 0 || showActObj.type != "Input") {
                var hot = "hot" + bub + "_" + i;
                var hotdiv = getDIV(hot);
                var hotp = hot + "p";

                w = getObjWidth("screen");
                h = getObjHeight("screen");

                if (!showActObj.areacorrected) {
                    bord1 = document.getElementById(hotp).border;

                    if (document.getElementById(hotp).type == "password") {
                        document.getElementById(hotp).style.fontFamily = "Arial";
                        document.getElementById(hotp).style.fontSize = "12px";
                    }

                    hl = hotdiv.offsetLeft;
                    if (hl < 0) {
                        hw = document.getElementById(hotp).clientWidth;
                        document.getElementById(hotp).style.width = "" + (hw + hl) + "px";
                        hotdiv.style.left = 0;
                    }
                    ht = hotdiv.offsetTop;
                    if (ht < 0) {
                        hh = document.getElementById(hotp).clientHeight;
                        document.getElementById(hotp).style.height = hh + ht;
                        hotdiv.style.top = 0;
                    }

                    bord = bord1 * 2;
                    hl = hotdiv.offsetLeft;
                    hw = document.getElementById(hotp).clientWidth + bord;
                    ht = hotdiv.offsetTop;
                    hh = document.getElementById(hotp).clientHeight + bord;

                    var c = bord1;

                    if (hl + hw > w - c)
                        document.getElementById(hotp).style.width = "" + (hw - bord - 3 - c) + "px";
                    if (ht + hh > h)
                        document.getElementById(hotp).style.height = "" + (hh - bord - 3) + "px";
                    showActObj.areacorrected = true;
                }

                if (hotdiv) {
                    if (showActObj.type == "Input") {
                        var inp = getDIV(hot + "p");
                        if (inp.borderColorOriginal) {
                            inp.style.border = "3px";
                            inp.style.borderColor = inp.borderColorOriginal;
                            inp.style.borderStyle = "solid";
                        };
                        if (inp.WidthOriginal)
                            inp.style.width = "" + inp.WidthOriginal + "px";
                        if (inp.HeightOriginal)
                            inp.style.height = "" + inp.HeightOriginal + "px";
                        if (hotdiv.LeftOriginal)
                            hotdiv.style.left = "" + hotdiv.LeftOriginal + "px";
                        if (hotdiv.TopOriginal)
                            hotdiv.style.top = "" + hotdiv.TopOriginal + "px";

                        var noborder = (_ShowActionArea() == false);
                        var cstr = hotdiv.style.cssText.toLowerCase();
                        if (cstr.indexOf("marquee: false") >= 0)	// no border
                            noborder = true;
                        if (noborder == true) {
                            if (!showActObj.marqueecorrected) {
                                showActObj.marqueecorrected = true;
                                //hotdiv.style.left=""+(hotdiv.style.pixelLeft+3)+"px";
                                hotdiv.style.left = "" + Number(getObjLeft(hotdiv) + 3) + "px";
                                //hotdiv.style.top=""+(hotdiv.style.pixelTop+3)+"px";
                                hotdiv.style.top = "" + Number(getObjTop(hotdiv) + 3) + "px";
                                inp.style.border = "0px";
                                inp.style.width = "" + (inp.offsetWidth - 6) + "px";
                                inp.style.height = "" + (inp.offsetHeight - 6) + "px";
                            }
                        }
                        show(hot, playMode == "S");
                    }
                    else {
                        if (_ShowActionArea())
                            show(hot, playMode == "S");
                    }
                };
            };
        }
    };
    if (playMode == "S") {
        if (isPaused) {
            binterf.SetPRText(R_interface_resume);
        }
        else {
            binterf.SetPRText(R_interface_pause);
        }
    }
    ShowScreen3();
};

function _getObjTop(o) {
    k = getObjTop(o) - 10;
    if (k < 0)
        k = 0;
    return k;
}

function _getObjLeft(o) {
    k = getObjLeft(o) - 10;
    if (k < 0)
        k = 0;
    return k;
}

function ScrollToAction() {
    if (playMode == "K") {
        if (showScreen == "start")
            window.scrollTo(0, 0);
        if (showActObj.nextFrame == "end")
            window.scrollTo(0, 0);
        setTimeout("ShowScreen4()", 5);
        return;
    }
    Scroll2Action();
}

var Actionarea_left = 150;
var Actionarea_top = 32;
var Actionarea_right = 0;
var Actionarea_bottom = 0;

var Bubble_horizontal = 150
var Bubble_vertical = 32

function RectArea(x, y, dx, dy, bubpt) {
    this.x = x;
    this.y = y;
    this.dx = dx;
    this.dy = dy;
    this.bubpt = bubpt;
}

function combineRect(r1, r2) {
    if (r1.dx == 0 && r1.dy == 0) {
        return r2;
    }
    if (r2.dx == 0 && r2.dy == 0) {
        return r1;
    }
    var x = min(r1.x, r2.x);
    var y = min(r1.y, r2.y);
    var dx = max(r1.x + r1.dx, r2.x + r2.dx) - x;
    var dy = max(r1.y + r1.dy, r2.y + r2.dy) - y;
    var r = new RectArea(x, y, dx, dy, 0);
    return r;
}

function fitRectinRect(r1, r2) { // fits r1 IN r2
    if (r1.dx == 0 && r1.dy == 0)
        return true;
    if (r1.dx > r2.dx)
        return false;
    if (r1.dy > r2.dy)
        return false;
    return true;
}

function containRect(r1, r2) {  // is r1 IN r2
    if (r1.dx == 0 && r1.dy == 0)
        return true;
    if (r1.x < r2.x)
        return false;
    if (r1.y < r2.y)
        return false;
    if (r1.x + r1.dx > r2.x + r2.dx)
        return false;
    if (r1.y + r1.dy > r2.y + r2.dy)
        return false;
    return true;
}

function getArea(bubrect, hotspotrect, screenarea) {
    sdx = document.getElementById("screen").clientWidth;
    sdy = document.getElementById("screen").clientHeight;
    brect = new RectArea(0, 0, 0, 0, 0);
    brectnopadding = new RectArea(0, 0, 0, 0, 0);
    if (bubrect.dx > 0 && bubrect.dy > 0) {
        brect = new RectArea(bubrect.x, bubrect.y, bubrect.dx, bubrect.dy, bubrect.bubpt);
        brectnopadding = new RectArea(bubrect.x, bubrect.y, bubrect.dx, bubrect.dy, bubrect.bubpt);
        switch (brect.bubpt) {
            case BUBB07_NOPOINTER:
                break;
            case BUBB07_TOPLEFT:
            case BUBB07_TOPRIGHT:
                if (brect.y > Bubble_vertical) {
                    brect.y -= Bubble_vertical;
                    brect.dy += Bubble_vertical;
                }
                else {
                    brect.dy += brect.y;
                    brect.y = 0;
                }
                break;
            case BUBB07_BOTTOMLEFT:
            case BUBB07_BOTTOMRIGHT:
                if (brect.y + brect.dy < sdy) {
                    brect.dy += Bubble_vertical;
                }
                else {
                    brect.dy = sdy - brect.dy;
                }
                break;
            case BUBB07_LEFTTOP:
            case BUBB07_LEFTBOTTOM:
                if (brect.x > Bubble_horizontal) {
                    brect.x -= Bubble_vertical;
                    brect.dx += Bubble_vertical;
                }
                else {
                    brect.dx += brect.x;
                    brect.x = 0;
                }
                break;
            case BUBB07_RIGHTTOP:
            case BUBB07_RIGHTBOTTOM:
                if (brect.x + brect.dx < sdx) {
                    brect.dx += Bubble_horizontal;
                }
                else {
                    brect.dx = sdx - brect.dx;
                }
                break;
        }
    }
    hrect = new RectArea(0, 0, 0, 0, 0);
    hrectnopadding = new RectArea(0, 0, 0, 0, 0);
    if (hotspotrect.dx > 0 && hotspotrect.dy > 0) {
        hrect = new RectArea(hotspotrect.x, hotspotrect.y, hotspotrect.dx, hotspotrect.dy, hotspotrect.bubpt);
        hrectnopadding = new RectArea(hotspotrect.x, hotspotrect.y, hotspotrect.dx, hotspotrect.dy, hotspotrect.bubpt);
        if (hrect.x > Actionarea_left) {
            hrect.x -= Actionarea_left;
            hrect.dx += Actionarea_left;
        }
        else {
            hrect.dx += hrect.x;
            hrectx = 0;
        }
        if (hrect.y > Actionarea_top) {
            hrect.y -= Actionarea_top;
            hrect.dy += Actionarea_top;
        }
        else {
            hrect.dy -= hrect.y;
            hrect.y = 0;
        }
        if (hrect.x + hrect.dx < sdx) {
            hrect.dx += Actionarea_right;
        }
        else {
            hrect.dx = sdx - hrect.x;
        }
        if (hrect.y + hrect.dy < sdy) {
            hrect.dy += Actionarea_bottom;
        }
        else {
            hrect.dy = sdy - hrect.y;
        }
    }
    var r0 = combineRect(brect, hrect);
    if (fitRectinRect(r0, screenarea))       // bubble + hotspot with padding
        return r0;
    r1 = combineRect(brectnopadding, hrectnopadding);
    if (fitRectinRect(r1, screenarea))       // bubble + hotspot no padding
        return r1;
    if (fitRectinRect(brect, screenarea))   // bubble with padding (full)
        return brect;
    if (fitRectinRect(brectnopadding, screenarea))
        return brectnopadding;
    brectnopadding.dx = screenarea.dx;
    if (brectnopadding.x + brectnopadding.dx > sdx)
        brectnopadding.dx = sdx - brectnopadding.x;
    brectnopadding.dy = screenarea.dy;
    if (brectnopadding.y + brectnopadding.dy > sdy)
        brectnopadding.dy = sdy - brectnopadding.y;
    return brectnopadding;
}

function getHorizontalScrollPosition(r1, r2) {  // r1 is IN r2
    if (r1.x < r2.x) {
        return r1.x;
    }
    if (r1.x + r1.dx > r2.x + r2.dx) {
        return r1.x - (r2.dx - r1.dx);
    }
    return r2.x;
}

function getVerticalScrollPosition(r1, r2) {    // r1 is IN r2
    if (r1.y < r2.y) {
        return r1.y;
    }
    if (r1.y + r1.dy > r2.y + r2.dy) {
        return r1.y - (r2.dy - r1.dy);
    }
    return r2.y;
}

function getDefinedBubbleRect(r0) {
    switch (r0.bubpt) {
        case BUBB07_NOPOINTER:
            break;
        case BUBB07_TOPLEFT:
        case BUBB07_TOPRIGHT:
        case BUBB07_BOTTOMLEFT:
        case BUBB07_BOTTOMRIGHT:
            r0.dy += 40 + Bubble_vertical;
            break;
        case BUBB07_LEFTTOP:
        case BUBB07_LEFTBOTTOM:
        case BUBB07_RIGHTTOP:
        case BUBB07_RIGHTBOTTOM:
            r0.dx += 40 + Bubble_horizontal;
            break;
    }
    return r0;
}

function Scroll2Action(simplereturn) {
    //    if (showScreen == "start") {
    //        window.scrollTo(0, 0);
    //        if (!simplereturn)
    //            setTimeout("ShowScreen4()", 5);
    //        return;
    //    }
    //    if (showActObj.nextFrame == "end") {
    //        ScrollTo(0, 0);
    //        if (!simplereturn)
    //            setTimeout("ShowScreen4()", 5);
    //        return;
    //    }
    var wh = getInsideWindowHeight();
    var ww = getInsideWindowWidth();
    var scrX = getObjLeft("screen");
    var sx = getScrollLeft() - scrX;
    var scrY = getObjTop("screen");
    var sy = getScrollTop() - scrY;
    var srect = new RectArea(sx, sy, ww, wh, 0);

    var bub = showActObj.id;
    if (showScreen == "start")
        bub += "S";
    var brect = new RectArea(0, 0, 0, 0, 0);
    if (getDIV(bub)) {
        brect = new RectArea(binterf.GetBubbleLeft(true), binterf.GetBubbleTop(true),
								binterf.GetBubbleWidth(true), binterf.GetBubbleHeight(true), binterf.GetBubblePointer());
        //        brect = new RectArea(_getObjLeft(bub), _getObjTop(bub), getObjWidth(bub), getObjHeight(bub), showActObj.bubpos);
        //        brect = new RectArea(showActObj.xpos, showActObj.ypos,showActObj.width,showActObj.height, showActObj.bubpos);
    }
    var hot = "hot" + bub + "_0";
    var hrect = new RectArea(0, 0, 0, 0, 0);
    if (getDIV(hot)) {
        hrect = new RectArea(_getObjLeft(hot), _getObjTop(hot), getObjWidth(hot), getObjHeight(hot), 0);
    }
    var r = getArea(brect, hrect, srect);
    if (containRect(r, srect)) {
        if (!simplereturn)
            setTimeout("ShowScreen4()", 5);
    }
    else {
        if (showActObj.nextFrame != "end") {
            var nextObj = screens[showActObj.nextFrame].actions[0];
            var l = true;
            while (l) {
                var nbub = nextObj.id;
                var nbrect = new RectArea(0, 0, 0, 0, 0);
                if (getDIV(nbub)) {
                    nbrect = getDefinedBubbleRect(new RectArea(nextObj.xpos, nextObj.ypos, nextObj.width, nextObj.height, nextObj.bubpos));
                }
                var nhot = "hot" + nbub + "_0";
                var nhrect = new RectArea(0, 0, 0, 0, 0);
                if (getDIV(nhot)) {
                    nhrect = new RectArea(_getObjLeft(nhot), _getObjTop(nhot), getObjWidth(nhot), getObjHeight(nhot), 0);
                }
                var nextRect = getArea(nbrect, nhrect, srect);
                var cRect = combineRect(r, nextRect);
                if (fitRectinRect(cRect, srect)) {
                    r = cRect;
                }
                else {
                    l = false;
                }
                if (nextObj.nextFrame == "end")
                    l = false;
                if (l)
                    nextObj = screens[nextObj.nextFrame].actions[0];
            }
        }
        ssx = getHorizontalScrollPosition(r, srect);
        ssy = getVerticalScrollPosition(r, srect);
        ScrollTo(ssx, ssy, simplereturn);
    }
}

function ScrollTo(x, y, nosmooth) {
    if (fusionmode) {
        if (nosmooth)
            window.scrollTo(x, y);
        else
            SmoothScroll(x, y);
    }
    else {
        //        y += 18;
        window.scrollTo(x, y);
        setTimeout("ShowScreen4()", 5);
    }
}

function TimerObj(x, y, currentx, currenty, targetx, targety, dx, dy) {
    this.x = x;
    this.y = y;
    this.currentx = currentx;
    this.currenty = currenty;
    this.targetx = targetx;
    this.targety = targety;
    this.dx = dx;
    this.dy = dy;
}
var timerObj = new TimerObj(0, 0, 0, 0, 0, 0, 0, 0, 0);

function SmoothScroll(targetx, targety) {
    currentx = getScrollLeft();
    currenty = getScrollTop();

    l = PlayerConfig.PanSpeed;
    dx = targetx - currentx;
    dy = targety - currenty;
    x = (dx > 0 ? l : 0 - l);
    y = (dy > 0 ? l : 0 - l);
    step = 0;
    if (Math.abs(dx) > Math.abs(dy)) {
        step = Math.abs(Math.round(dx / l)) + 1;
        y = Math.round(dy / step);
        if (y == 0) {
            y = (dy > 0 ? 1 : -1);
        }
    }
    else {
        step = Math.abs(Math.round(dy / l)) + 1;
        x = Math.round(dx / step);
        if (x == 0) {
            x = (dx > 0 ? 1 : -1);
        }
    }

    //    x *= 2;
    //    y *= 2;

    timerObj = new TimerObj(x, y, currentx, currenty, targetx, targety, dx, dy);
    setTimeout("SmoothScollTimed()", 5);
}

function SmoothScollTimed() {
    if (isPaused) {
        if (navBar)
            navBar.setKeepHidden(false);
        setTimeout("SmoothScollTimed()", 5);
        return;
    }
    if (navBar)
        navBar.setKeepHidden(true);
    if (timerObj.currentx == timerObj.targetx && timerObj.currenty == timerObj.targety) {
        if (navBar)
            navBar.setKeepHidden(false);
        setTimeout("ShowScreen4()", 5);
        return;
    }
    timerObj.currentx += timerObj.x;
    if (timerObj.dx > 0) {
        if (timerObj.targetx - timerObj.currentx < 0)
            timerObj.currentx = timerObj.targetx;
    }
    else {
        if (timerObj.targetx - timerObj.currentx > 0)
            timerObj.currentx = timerObj.targetx;
    }
    timerObj.currenty += timerObj.y;
    if (timerObj.dy > 0) {
        if (timerObj.targety - timerObj.currenty < 0)
            timerObj.currenty = timerObj.targety;
    }
    else {
        if (timerObj.targety - timerObj.currenty > 0)
            timerObj.currenty = timerObj.targety;
    }
    window.scrollTo(timerObj.currentx, timerObj.currenty);
    setTimeout("SmoothScollTimed()", 5);
}

function HideAction() {
    if (playMode == "K" && !KGuestDemoMode) {
        HideKnowItBubble();
        return;
    };
    var bub = showActObj.id

    binterf.ResetContent();
    binterf.Hide();

    for (var i = 0; i < showActObj.hotspots; i++) {
        var hot = "hot" + bub + "_" + i;
        if (getDIV(hot)) hide(hot, playMode == "S")
    }
}

var myscr = "";

function ShowScreen(scr, act, dir, fromslider) {
    if (!fromslider)
        timelineDescriptor.valid = false;
    if (scr != "end") {
        if (screens[scr].actions[0].nextFrame == "end") {
            lms_frameView(getMyGuid(), playMode, "end");
        }
        else {
            lms_frameView(getMyGuid(), playMode, scr);
        }
    }

    //AICC_STORM mode completing verification
    if (scr != "end") {
        var ASmyscr = screens[scr];
        var l = 0;
        while (l == 0) {
            var ASid = ASmyscr.actions[0];
            var ASNext = ASid.nextFrame;
            if (ASNext == "end") {
                l = 1;
            }
            else if (ASid.delay == 0 || ASid.type == "None") {
                ASmyscr = screens[ASNext];
            }
            else {
                l = 2;
            };
        };
    };

    if (act == null) {
        act = firsthemialternativeindex;
        firsthemialternativeindex = 0;
    }

    if (KGuestDemoMode == 2) {
        KGuestDemoMode = 0;
        KWarningLevel = 0;
        binterf.SetPosition(-1, -1, -1, -1, true, 0, 0, 0);
        binterf.SetMoveable(true);
        KContinueFlag = 1;
        //		if (showActObj.type!="Input")
        ShowScreen(scr, act);
        KContinueFlag = 2;
        return;
    };
    if (KGuestDemoMode == 1) {

        var myact = screens[scr].actions[0];
        if (IsDragBegin(myact.type) && showActObj.id == myact.id) {
        }
        else {
            if (!IsDragSequence2(myact.type))
                KGuestDemoMode = 2;
        };
    };
    if (KContinueFlag == 2)
        KContinueFlag = 0;


    try {
        var myframe = scr;
        while (_SkipFrame(screens[myframe])) {
            myframe = screens[myframe].actions[0].nextFrame;
        }
        if (screens[myframe].actions[0].nextFrame == "end") {
            lms_topicFinish(getMyGuid());
        }
    }
    catch (e) { };

    /* edw */
    if (playMode == "S") {
        if (upk.Timeline.Init(myframe))
            StartScreen = myframe;
        upk.Timeline.UpTimelineAt(myframe, dir, timelineDescriptor);
        upk.Timeline.Lock(false);
    }

    if (scr == "end") {
        if (playMode == "K" && PlayerConfig.TrackFeedBack) {
            HideAction();
            KScoringScreen = true;
            ShowAction();
            return;
        };
        ClosePlayer(1);
        return;
    }

    //  isTabbed = false

    // Bubble and Action Area
    if (showScreen != "") {
        if (showActObj.type == 'Input') {
            if (showActInpObj)
                showActInpObj.blur()
        }
        HideAction()
    }

    oldscr = scr;
    while (_SkipFrame(screens[scr]))
    //    ((screens[scr].actions.length == 1 && screens[scr].actions[0].type == "Decision") ||
    //	(playMode == "S" && screens[scr].actions[0].type == "None" && screens[scr].actions[0].delay == 0) ||
    //	(playMode == "T" && screens[scr].actions[0].type == "None" && screens[scr].actions[0].delay == 0) ||
    //	(playMode == "S" && screens[scr].actions[0].type == "Decision" && screens[scr].actions[0].delay == 0) ||
    //	(playMode == "K" && screens[scr].actions[0].type == "Decision") ||
    //	(playMode == "K" && screens[scr].actions[0].type == "None" && scr != "start" &&
    //				screens[scr].actions[0].nextFrame != "end" && screens[scr].actions[0].knowittext.length == 0) ||
    {
        scr = screens[scr].actions[0].nextFrame
        if (scr == "end") {
            setTimeout("ShowScreen(\"end\")", 10)
            return;
        };
        act = 0
    }

    if (ecidStartDecisions[scr]) {
        if (ecidStartDecisions[scr].display) {
            ecidDecisionStart = true;
        }
    }
    if (ecidDecisionStart) {
        scr = FindEcidStartNextFrame(scr);
        act = 0;
    }

    if (scr != oldscr) {
        if (scr != "end") {
            if (screens[scr].actions[0].nextFrame == "end") {
                lms_frameView(getMyGuid(), playMode, "end");
            }
            else {
                lms_frameView(getMyGuid(), playMode, scr);
            }
        }
    }

    showScreen = scr;
    if (!KGuestDemoMode) {
        showHistory[showHistory.length] = scr;
    };

    if (act)
        showAct = act
    else
        showAct = 0

    if (animPhase != "") {
        clearTimeout(animTimeout)
        animPhase = ""
    }

    showActObj = screens[showScreen].actions[showAct]

    if (showActObj == null) {
        showActObj = screens[showScreen].actions[0];
    }

    myscr = scr;
    url = screenshotPath + screens[showScreen].image;
    screenshot = new Image();
    event_blocked = true;
    DownloadImage(url, "Returned");
}

function Returned(url, success) {
    GetImage(screenshot, url);
    event_blocked = false;
    // Screenshot
    FrameIDUpdated(myscr);
    if (document.layers) {
        document.layers.screen.document.screenshot.src = screenshot.src;
    }
    else {
        document["screenshot"].src = screenshot.src;
        //    document.all["scrbg"].style.backgroundColor="black";
        //	if (IsLeadIn() || IsLeadOut() || IsDecision())
        //	{
        //	    document["screenshot"].style.filter='Alpha(opacity=80) gray()';
        //	}
        //	else
        //	{
        //	    document["screenshot"].style.filter='';
        //	}
    }
    ShowScreen2();
};

function GetDelay() {
    if (KGuestDemoMode)
        return 200;
    return showActObj.delay * 100;
};

function ShowScreen2() {
    scr = myscr;
    if (showActObj.type == "Input") {
        showActObj.par4 = false;
        showActObj.lastIMEtext = "";
    };
    ShowAction()
};

function ShowScreen3() {
    // Cursor
    if (playMode == "S" || KGuestDemoMode) {
        if (!showCursor)
            hide("cursor");
        showCursor = true;
    }
    if (playMode == "K" && !KGuestDemoMode)
        hide("cursor");
    if (playMode == "T" && !KGuestDemoMode)
        hide("cursor");

    // Preset input field
    if ((showActObj.type == 'Input' && playMode != "K") ||
	 (showActObj.type == 'Input' && playMode == "K" && !showActObj.par4)) {
        showActInpObj = document.layers ? document.layers.screen.document.layers["hot" + showActObj.id + "_0"].document["f" + showActObj.id]["inp" + showActObj.id] : document["f" + showActObj.id + "_0"]["inp" + showActObj.id + "_0"]
        //    showActInpObj.value = showActObj.par2
        showActInpObj.original = "";
        showActInpObj.onkeyup = EventKeyUp;
        // The onKeyPress handler is also assigned statically to the input element
        // to work around a Mozilla bug.
        showActInpObj.onkeypress = EventInputKey;
        //showActInpObj.onpropertychange = EventPropertyChange;
        EventPropertyChange();
        showActInpObj.onfocus = InputOnFocus;
        showActInpObj.onblur = InputOnBlur;
        try {
            showActInpObj.focus();
        }
        catch (e) { };
        //	var txtRange=showActInpObj.createTextRange()
        //	var txt=txtRange.text;
        //	txtRange.text=txt;
        setTimeout("SelectText0()", 50)
    }

    // Scroll to make action visible
    ScrollToAction()
}

function SelectText0() {
    showActInpObj.value = showActObj.par2;
    showActInpObj.original = showActInpObj.value;
    SelectText(showActInpObj);
    _backStep = false;
}

function ShowPlayButtons() {
    var w = ($(document.body).width() - 192) / 2;
    var h = $(document.body).height();
    var h2 = (h - 195) / 2;
    var s = '<div id="graydiv" scrolling="yes" class="pointerdiv" onclick="onStartClick()">';
    s += '<img src="../../../img/ipad_playbutton.png" style="position:absolute; top: ' + h2 + 'px; left: ' + w + 'px;"/>';
    s += '<div id="startplayfont" ';
    s += 'style="position:absolute; width: 100%; height: 50px; left: 0px; top: ' + (h - 50) + 'px; text-align: center; padding-top: 10px; ';
    s += 'background-image: url(../../../img/ipad_messagebar.png); background-repeat: repeat;">' + R_swipe_instruction + '</div>';
    s += '</div>';
    $(document.body).append(s);
    $("#graydiv").bind('touchstart', function (e) {
        swipe.Init(screenwidth);
    });
    $("#graydiv").bind('touchmove', function (e) {
        try {
            if (e.originalEvent.touches[1] || e.originalEvent.changedTouches[1]) {
                swipe.DetectedMulti();
            }
            else if (swipe.IsNotZoomed()) {
                e.preventDefault();
            }
        }
        catch (e) { };
        var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
        swipe.Add(touch.pageY, touch.pageX);

    });
    $("#graydiv").bind('touchend', function (e) {
        var sensitivity = 30;
        if (swipe.IsMulti()) {
            return;
        }
        if (swipe.IsNotZoomed() == false) {
            return;
        }
        var x = swipe.GetX();
        var y = swipe.GetY();
        if (Math.abs(x) > Math.abs(y)) {
            return;
        }
        if (y < (0 - sensitivity)) {
            onStartClick();
        }
    });
    var bH = getFullHeight();
    $("#graydiv").css("height", bH + "px");
    $("#startplayfont").css("top", bH - 50 + "px");
}

function onStartClick() {
    $("#graydiv").remove();
    SoundPlayerObj.InitAudioPlayer();
    setTimeout("iPadStartingProcess(1)", 200);
}

function iPadStartingProcess(mode) {
    switch (mode) {
        case 0:
            touchIntroChecked = true;
            binterf.Hide();
            ShowPlayButtons();
            break;
        case 1:
            binterf.Show();
            if (navBar) {
                navBar.setKeepHidden(false);
                navBar.show();
            }
            ShowScreen4();
            break;
        default:
            break;
    }
}

var touchIntroChecked = false;

function ShowScreen4() {
    // Panel up/down
    HandleResize()

    if (IsTouchDevice() && !touchIntroChecked) {
        iPadStartingProcess(0);
        return;
    }


    /*
    // Preload next screenshot(s)
    var preloadID = showActObj.nextFrame
    var preloadNext = true
    var count = 5
    preloadScreen = new Array()
    while(preloadID!="end" && preloadNext && count--)
    {
    preloadScreen[preloadScreen.length] = new Image()
    preloadScreen[preloadScreen.length-1].src = screenshotPath+screens[preloadID].image;
    preloadNext = TeacherTestSkip(screens[preloadID].actions[0].type)
    preloadID = screens[preloadID].actions[0].nextFrame
    }
    */
    PreloadImages();
    // Set buttons
    //	RefreshActionMenu()

    var hot = "hot" + showActObj.id + "_0"
    var asx = (showActObj.id).substr(1) + ".ASX";

    // Kick off timers and animations in Demo mode
    if (playMode == "S" || KGuestDemoMode) {
        if (showActObj.nextFrame == "end") {
            Animate2(asx, false, "ClosePlayer(1)", GetDelay(), "other");
        };

        if (showActObj.type == "Input") {
            animSteps = DecodeInputString(showActObj.par1[1]).length
            Animate2(asx, false, "AnimateInput()", GetDelay(), "input")
        }
        else if (showActObj.type == "Key") {
            Animate2(asx, false, "AnimateKeyboard()", GetDelay(), "keyboard")
        }
        else if (showActObj.type == "None" || showActObj.type == "Decision" || !getDIV(hot)) {
            Animate2(asx, false, "ShowScreen('" + showActObj.nextFrame + "')", GetDelay(), "other")
        }
        else {
            var cx, cy
            var dx, dy
            anim_to_x = sx + getObjLeft(hot) + getObjWidth(hot) / 2
            anim_to_y = sy + getObjTop(hot) + getObjHeight(hot) / 2
            cx = getObjLeft("cursor") + cursor_alignment_x;
            cy = getObjTop("cursor") + cursor_alignment_y;
            dx = anim_to_x - cx - (IsiOS() ? sx : 0);
            dy = anim_to_y - cy - (IsiOS() ? sy : 0);

            animSteps = Math.round(Math.sqrt(dx * dx + dy * dy) / MOUSE_STEP);
            if (animSteps == 0) animSteps++;
            animStepOriginal = animSteps;

            anim_x = dx / animSteps
            anim_y = dy / animSteps

            if ((showActObj.type == "Drag" || showActObj.type.indexOf("Up") != -1)) {
                shiftTo("bullseye", cx - sx - getObjWidth("bullseye") / 2, cy - sy - getObjHeight("bullseye") / 2)
                HideBullsEye();
                //        show("bullseye")
            }
            else {
                HideBullsEye();
            }

            Animate2(asx, false, "AnimateMouse()", GetDelay(), "mouse")
        }
    }
    else {
        if ((showActObj.emptybubble && _ShowBubble(showActObj)) && showActObj.type == "None" && scr != "start") {
            Animate2(asx, false, "ShowScreen('" + showActObj.nextFrame + "')", GetDelay(), "other")
        }
        else {
            animObject = new AnimObject("", "", "");
            PlaySound(asx, false);
        };
    }
};

function PreloadImages() {
    if (!PlayerConfig.PreloadScreenEnabled)
        return;
    // Preload next screenshot(s)
    var preloadID = showActObj.nextFrame
    var preloadNext = true
    var count = 3;
    while (preloadID != "end" && preloadNext && count--) {
        url = screenshotPath + screens[preloadID].image;
        PreloadImage(url);
        //		preloadNext = TeacherTestSkip(screens[preloadID].actions[0].type);
        preloadID = screens[preloadID].actions[0].nextFrame;
    }
    for (var i = 0; i < screens[showScreen].actions.length; i++) {
        preloadID = screens[showScreen].actions[i].nextFrame;
        if (preloadID != "end") {
            url = screenshotPath + screens[preloadID].image;
            PreloadImage(url);
        };
    };
}

function GetShiftState(event) {
    if (event == 0)
        event = window.event;
    if (event.storedEvent)
        return event.pShState;
    var alt = event.modifiers ? (event.modifiers & Event.ALT_MASK) : event.altKey;
    var ctrl = event.modifiers ? (event.modifiers & Event.CONTROL_MASK) : event.ctrlKey;
    var shift = event.modifiers ? (event.modifiers & Event.SHIFT_MASK) : event.shiftKey
    var ret = (shift ? "s" : "") + (ctrl ? "c" : "") + (alt ? "a" : "");
    return ret;
}

function GetButton(event) {
    if (event == 0)
        event = window.event;
    if (event.storedEvent)
        return event.pButton;
    if (event.button)
        return (event.button & 1) ? "L" : (event.button & 2) ? "R" : (event.button & 4) ? "M" : ""
    else
        return (event.which == 1) ? "L" : (event.which == 3) ? "R" : ""
}

function GetMouseX(event) {
    if (event == 0)
        event = window.event;
    if (event.storedEvent)
        return event.pX;
    if (event.pageX)
        if (event.type == "DOMMouseScroll")
            return event.screenX - getObjLeft("screen") + document.body.scrollLeft
        else
            return event.pageX - getObjLeft("screen")
    else if (event.x)
        return event.x - getObjLeft("screen") + getScrollLeft()
    else
        return event.layerX;
}

function GetMouseY(event) {
    if (event == 0)
        event = window.event;
    if (event.storedEvent)
        return event.pY;
    if (event.pageY)
        if (event.type == "DOMMouseScroll")
            return event.screenY - getObjTop("screen") + document.body.scrollTop
        else
            return event.pageY - getObjTop("screen")
    else if (event.y)
        return event.y - getObjTop("screen") + getScrollTop()
    else
        return event.layerY;
}

function MouseInObject(event, objID) {
    var hot = getDIV(objID)
    if (hot) {
        var mx = GetMouseX(event);
        var my = GetMouseY(event);
        var hx = getObjLeft(objID);
        var hy = getObjTop(objID);
        var hw = getObjWidth(objID);
        var hh = getObjHeight(objID);

        /*
        var sL = document.body.scrollLeft;
        var sT = document.body.scrollTop;

        if (IsIE10()) {
        }
        */

        if (showActObj.type == "Input") {
            var s = showActInpObj.id.substr(0, 14);
            while (s.substr(s.length - 1, 1) == 'p' || s.substr(s.length - 1, 1) == 'x') {
                s = s.substr(0, s.length - 1);
            }
            if (s == objID) {
                hw = showActInpObj.offsetWidth;
                hh = showActInpObj.offsetHeight;
            }
        }
        if (mx >= hx && my >= hy && mx < hx + hw && my < hy + hh)
            return true
        if (IsTouchDevice()) {
            var dd = 30;
            if (hx > dd) {
                hx -= dd;
            }
            else {
                hx = 0;
            }
            if (hy > dd) {
                hy -= dd;
            }
            else {
                hy = 0;
            }
            hw += 2 * dd;
            hh += 2 * dd;
            if (mx >= hx && my >= hy && mx < hx + hw && my < hy + hh)
                return true
        }
    }
    return false
}

function MouseInHotspot(event, action) {
    if (action == null)
        action = showActObj;
    for (var i = 0; i < action.hotspots; i++) {
        if (MouseInObject(event, "hot" + action.id + "_" + i) &&
									GetShiftState(event) == action.par1)
            return true;
    };
    return false;
}

var touchEvents = ["LClick1", "LClick2", "LClick3", "LBeginDrag", "LDown", "LUp", "RClick1", "RClick2", "RClick3", "RBeginDrag", "RDown", "RUp", "Drag"]

function InArray(k, a) {
    for (var i = 0; i < a.length; i++) {
        if (k == a[i])
            return true;
    }
    return false;
}

function MouseEventControl(type1, type2) {
    if (type1 == type2) {
        return true;
    }
    if (IsTouchDevice()) {
        if (InArray(type1, touchEvents) && InArray(type2, touchEvents))
            return true;
    }
    return false;
}

function ActionControl(type, event, avoidinput) {
    if (playMode == "K" && KGuestDemoMode > 0)
        return null;
    if (avoidinput == null)
        avoidinput = false;
    if (event == null) {
        for (var i = 0; i < screens[showScreen].actions.length; i++) {
            var myAct = screens[showScreen].actions[i];
            if (MouseEventControl(myAct.type, type)) {
                return myAct;
            };
        };
        return 0;
    };

    for (var i = 0; i < screens[showScreen].actions.length; i++) {
        var myAct = screens[showScreen].actions[i];
        if (MouseEventControl(myAct.type, type) && MouseInHotspot(event, myAct)) {
            return myAct;
        };
    };

    if (avoidinput == true)
        return null;

    if (showActObj.type == "Input") {
        var nf = showActObj.nextFrame;
        for (var i = 0; i < screens[nf].actions.length; i++) {
            var myAct = screens[nf].actions[i];
            if (MouseEventControl(myAct.type, type) && MouseInHotspot(event, myAct)) {
                return myAct;
            };
        };
    };

    return 0;
};

function ToStandard(k) {
    var c = String.fromCharCode(k);
    var cc = c.toUpperCase(c);
    return cc.charCodeAt(0);
}

function ToStandard2(k) {
    if (k >= 112 && k <= 123)
        return k;
    return ToStandard(k);
}

function ActionKeyControl(code, event, noShift) {
    if (!noShift)
        noShift = false;
    var code1 = code;
    if (code == 107 || code == 187)		// + key
        code1 = 43;
    var shState = GetShiftState(event);
    if (shState.length > 0) {
        if (noShift) {
            if (shState.substr(0, 1) == "s")
                shState = shState.substr(1);
        };
    };
    for (var i = 0; i < screens[showScreen].actions.length; i++) {
        var myAct = screens[showScreen].actions[i];
        if (myAct.type == "Key" &&
			(code1 == ToStandard(myAct.par1) || code1 == ToStandard2(myAct.par1)) &&
			 shState == myAct.par2) {
            return myAct;
        };
    };
    return 0;
};

function IsDragSequence() {
    var k = screens[showScreen].actions.length;
    return (k == 1 && screens[showScreen].actions[0].type == "Drag");
};

///////////////////////////////////////////
// mouse global variables
var m_mouseStatus = 0;
var m_p1 = new StoredEvent(0, 0, "", "");
var m_p2 = new StoredEvent(0, 0, "", "");
var m_p3 = new StoredEvent(0, 0, "", "");
var m_buttonID;
var DOUBLECLICKTIME = 500;
var m_timer1 = 0;
var m_timer2 = 0;
var m_bClkEvent = false;
var m_begindragEvent = 0;
///////////////////////////////////////////

function BDown(point) {
    m_begindragEvent = 0;
    var act = ActionControl(m_buttonID + "BDown", point);
    if (showActObj.type == "Input") {
        if (AssessStringInput(true, true)) //complete
        {
            showHistory[showHistory.length] = showActObj.nextFrame;
            historyActionMap[showActObj.nextFrame] = 0;
            TeacherForward(true, act.nextFrame, act.id);
            return;
        }
    }
    if (act) {
        TeacherForward(true, act.nextFrame, act.id);
    }
    else {
        m_mouseStatus = 0;
        FalseEvent();
    };
};

function BBeginDrag(point) {
    var act = ActionControl(m_buttonID + "BeginDrag", point);
    if (showActObj.type == "Input") {
        if (AssessStringInput(true, true)) //complete
        {
            showHistory[showHistory.length] = showActObj.nextFrame;
            historyActionMap[showActObj.nextFrame] = 0;
            TeacherForward(true, act.nextFrame, act.id);
            return;
        }
    }
    if (act) {
        TeacherForward(true, act.nextFrame, act.id);
    }
    else {
        m_mouseStatus = 0;
        FalseEvent();
    };
};

function BUp(point) {
    if (isOnLink)
        return;
    m_begindragEvent = 0;
    var act = ActionControl(m_buttonID + "Up", point);
    if (act) {
        TeacherForward(true, act.nextFrame, act.id);
    }
    else {
        m_mouseStatus = 0;
        if (playMode == "K" && KScoringScreen)
            return
        else if (IsLeadIn() || IsLeadOut() || showActObj.type == "None")
            return
        else
            FalseMouseEvent();
    };
};

function BClk(point) {
    m_begindragEvent = 0;
    var act = ActionControl(m_buttonID + "Click1", point, false);
    if (showActObj.type == "Input") {
        if (AssessStringInput(true, true)) //complete
        {
            showHistory[showHistory.length] = showActObj.nextFrame;
            historyActionMap[showActObj.nextFrame] = 0;
            TeacherForward(true, act.nextFrame, act.id);
            return;
        }
    }
    if (act) {
        TeacherForward(true, act.nextFrame, act.id);
    }
    else {
        FalseEvent();
    };
};

function BDblClk(point) {
    m_begindragEvent = 0;
    var act = ActionControl(m_buttonID + "Click2", point, false);
    if (showActObj.type == "Input") {
        if (AssessStringInput(true, true)) //complete
        {
            showHistory[showHistory.length] = showActObj.nextFrame;
            historyActionMap[showActObj.nextFrame] = 0;
            TeacherForward(true, act.nextFrame, act.id);
            return;
        }
    }
    if (act) {
        TeacherForward(true, act.nextFrame, act.id);
    }
    else {
        FalseEvent();
    };
};

function BTrplClk(point) {
    m_begindragEvent = 0;
    var act = ActionControl(m_buttonID + "Click3", point, false);
    if (showActObj.type == "Input") {
        if (AssessStringInput(true, true)) //complete
        {
            showHistory[showHistory.length] = showActObj.nextFrame;
            historyActionMap[showActObj.nextFrame] = 0;
            TeacherForward(true, act.nextFrame, act.id);
            return;
        }
    }
    if (act) {
        TeacherForward(true, act.nextFrame, act.id);
    }
    else {
        FalseEvent();
    };
};

function BWheel(point) {
    var act = ActionControl("Wheel", point);
    if (showActObj.type == "Input") {
        if (AssessStringInput(true, true)) //complete
        {
            showHistory[showHistory.length] = showActObj.nextFrame;
            historyActionMap[showActObj.nextFrame] = 0;
            TeacherForward(true, act.nextFrame, act.id);
            return;
        }
    }
    if (act) {
        TeacherForward(true, act.nextFrame, act.id);
    }
    else {
        FalseEvent();
    };
};

function FalseMouseEvent() {
    if (showActObj.type == "Input") {
        if (AssessStringInput(true, true)) //complete
        {
            TeacherForward(true, showActObj.nextFrame, showActObj.id);
            setTimeout("FalseEvent();", 300);
            return;
        }
    }
    FalseEvent();
}

function FalseEvent() {
    TeacherWrong();
};

var g_x, g_y, g_shst;
var g_timer = 0;

function EventMouseMove(event) {
    if (event == null)
        event = window.event;
    if (playMode == "K") {
        g_x = GetMouseX(event);
        g_y = GetMouseY(event);
        g_shst = GetShiftState(event)
    };
    if (playMode == "K" && KGuestDemoMode)
        return false;
    if (playMode == "K" && IsDragBegin())
        return false;
    //	defaultStatus=GetMouseX(event)+","+GetMouseY(event);
    // begindrag
    if (m_begindragEvent) {
        if (!MouseInHotspot(event, m_begindragEvent)) {
            TeacherForward(true, m_begindragEvent.nextFrame, m_begindragEvent.id);
            m_begindragEvent = 0;
        };
    };
    // drag
    var act = ActionControl("Drag", event);
    if (act) {
        TeacherForward(true, act.nextFrame, act.id);
    };
    // point
    act = ActionControl("Move", event)
    if (act) {
        if (playMode == "K") {
            if (g_timer == 0) {
                g_timer = setTimeout("PointDelay();", 300);
            };
        }
        else
            TeacherForward(true, act.nextFrame, act.id);
    };
};

function PointDelay() {
    var myevent = new StoredEvent(g_x, g_y, g_shst);
    g_timer = 0;
    act = ActionControl("Move", myevent)
    if (act) {
        TeacherForward(true, act.nextFrame, act.id);
    };
};

function EventDblClk(event) {
    return false;
    /*
    if (playMode == "S")
    return false;
    if (playMode == "K" && KGuestDemoMode)
    return false;
    if (playMode == "K" && IsDragBegin())
    return false;
    if (document.layers)
    return false;
    if (m_mouseStatus == 0)
    return false;
    EventMouseDown(event);
    return false;
    */
};

function EventWheel(event) {
    if (playMode == "K" && KGuestDemoMode)
        return false;
    if (playMode == "K" && IsDragBegin())
        return false;
    if (playMode == "K" && (KConfirmDemo > 0))
        return false;
    if (playMode == "S")
        return false;
    if (m_mouseStatus != 0)
        return false;
    if (event == null)
        event = window.event;
    BWheel(event);
    return false;
};

function DocEventMouseDown(event) {
    if (!event)
        event = window.event;
    if (event.srcElement) {
        if (event.srcElement.id == "m_ActionText")
            return;
    }
    if (event.target) {
        if (event.target.id == "m_ActionText")
            return;
    }
    if (actionMenu) {
        if (actionMenu.IsOnScreen()) {
            actionMenu.Close();
            return true;
        };
    }
};

function EventMouseDown(event) {
    if (actionMenu) {
        if (actionMenu.IsOnScreen()) {
            actionMenu.Close();
            return true;
        };
    }
    if (playMode == "K" && KGuestDemoMode)
        return false;
    if (playMode == "K" && IsDragBegin())
        return false;
    if (playMode == "K" && (KConfirmDemo > 0))
        return false;
    if (playMode == "S") {
        if (isOnLink)
            return true;
        //		else if(showActObj.type!="Decision")
        //			DemoForward()
        //		else
        //			TeacherWrong()
        //		else if (IsLeadIn() || IsLeadOut())
        //			DemoForward();
        return false
    }

    if (event == null)
        event = window.event;
    var but = GetButton(event);
    if (!m_buttonID)
        m_buttonID = but;
    if (but == "")
        but = m_buttonID;
    if (playMode == "K" || playMode == "T") {
        if (showActObj.type == "Input") {
            for (var i = 0; i < showActObj.hotspots; i++) {
                if (MouseInObject(event, "hot" + showActObj.id + "_" + i)) {
                    return true;
                };
            };
        };
    };
    if (screens[showScreen].actions.length > 0) {
        if (screens[showScreen].actions[0].type == "Decision")
            return true;
    };
    var downEvent = ActionControl(but + "BDown", event);
    var begindragEvent = ActionControl(but + "BeginDrag", event);
    var clkEvent = ActionControl(but + "Click1", event);
    var dblclkEvent = ActionControl(but + "Click2", event);
    var trplclkEvent = ActionControl(but + "Click3", event);
    switch (m_mouseStatus) {
        case 0:
            // first down event arrived
            m_bClkEvent = false;
            m_mouseStatus = 1;
            m_p1 = new StoredEvent(GetMouseX(event), GetMouseY(event), GetShiftState(event), but);
            m_buttonID = but;
            m_begindragEvent = 0;
            if (clkEvent == 0 && dblclkEvent == 0 && trplclkEvent == 0) {
                if (downEvent)
                    BDown(m_p1);
                if (begindragEvent)
                    BBeginDrag(m_p1);
                break;
            };
            if (begindragEvent) {
                m_begindragEvent = begindragEvent;
            };
            if (dblclkEvent || trplclkEvent) {
                m_timer1 = setTimeout(Event_Mouse_Timer1, DOUBLECLICKTIME);
            };
            break;
        case 2:
            // doubleclick event arrived
            if (but != m_buttonID)
                break;
            if (m_timer1 > 0) {
                clearTimeout(m_timer1);
                m_timer1 = 0;
            };
            if (dblclkEvent && trplclkEvent == 0) {
                m_mouseStatus = 0;
                if (MouseInHotspot(m_p1, dblclkEvent)) {
                    BDblClk(event);
                }
                else {
                    FalseMouseEvent();
                };
                break;
            };
            m_mouseStatus = 3;
            m_p3 = new StoredEvent(GetMouseX(event), GetMouseY(event), GetShiftState(event), but);
            m_timer2 = setTimeout(Event_Mouse_Timer2, DOUBLECLICKTIME);
            break;
        case 3:
            // tripleclick event arrived
            if (but != m_buttonID)
                break;
            if (m_timer2 > 0) {
                clearTimeout(m_timer2);
                m_timer2 = 0;
            };
            m_mouseStatus = 0;
            if (trplclkEvent && MouseInHotspot(m_p1, trplclkEvent) &&
													MouseInHotspot(m_p3, trplclkEvent)) {
                BTrplClk(event);
            }
            else {
                FalseMouseEvent();
            };
            break;
        default:
            m_mouseStatus = 0;
            break;
    };
    return false;
};

function EventMouseUp(event) {
    if (m_mouseStatus == 2) {
        EventMouseDown(event);
    }
    if (playMode == "K" && KGuestDemoMode)
        return false;
    if (playMode == "K" && IsDragBegin())
        return false;
    if (playMode == "K" && (KConfirmDemo > 0))
        return false;
    if (event == null)
        event = window.event;
    var but = GetButton(event);
    if (but != m_buttonID)
        return false;
    if (screens[showScreen].actions.length > 0) {
        if (screens[showScreen].actions[0].type == "Decision")
            return true;
    };
    var clkEvent = ActionControl(but + "Click1", event);
    var dblclkEvent = ActionControl(but + "Click2", event);
    var trplclkEvent = ActionControl(but + "Click3", event);
    switch (m_mouseStatus) {
        case 1:
            // first up event arrived
            if (clkEvent == 0 && dblclkEvent == 0 && trplclkEvent == 0) {
                m_mouseStatus = 0;
                BUp(event);
                break;
            };
            if (clkEvent) {
                m_bClkEvent = MouseInHotspot(m_p1, clkEvent);
            };
            if (m_timer1 == 0) {
                if (clkEvent) {
                    m_mouseStatus = 0;
                    if (m_bClkEvent)
                        BClk(event)
                    else
                        BUp(event);
                }
                else {
                    m_mouseStatus = 0;
                    FalseMouseEvent();
                };
                break;
            };
            m_mouseStatus = 2;
            m_p2 = new StoredEvent(GetMouseX(event), GetMouseY(event), GetShiftState(event), but);
            break;
        default:
            break;
    };
    return false;
};

function Event_Mouse_Timer1() {
    m_timer1 = 0;
    if (m_mouseStatus == 2) {
        if (m_bClkEvent)
            BClk(m_p2)
        else
            BUp(m_p2);
        m_mouseStatus = 0;
    };
};

function Event_Mouse_Timer2() {
    m_timer2 = 0;
    if (m_mouseStatus == 3) {
        m_mouseStatus = 0;
        var dblEvent = ActionControl(m_buttonID + "Click2", m_p3);
        if (dblEvent) {
            if (MouseInHotspot(m_p1, dblEvent)) {
                BDblClk(m_p3);
            };
        }
        else {
            FalseMouseEvent();
        };
    };
};

var knowit_AltF4Pressed = false;

function BeforeUnload() {
    if (knowit_AltF4Pressed) {
        knowit_AltF4Pressed = false;
        try { event.returnValue = ""; } catch (e) { };
    };
    if (navigator.userAgent.indexOf("Firefox/") > 0) {
        UnLoad();
    }
    if (navigator.userAgent.indexOf("Safari") > 0) {
        UnLoad();
    }
};

var getCode = false;
//var fromInput=false;

function EventKeyPress(event) {
    if (showActObj.type == "Input")
        return true;
    //	if (fromInput)
    //	{
    //		fromInput=false;
    //		return false;
    //	};
    if (!getCode)
        return true;

    if (event == null)
        event = window.event;
    var code = event.which ? event.which : event.keyCode
    //	if (!(code>=112 && code<=123))
    if (code >= 65 && code <= 90) {
        var codes = String.fromCharCode(code);
        var upcodes = codes.toUpperCase();
        code = upcodes.charCodeAt(0);
    };

    if (playMode == "T") {
        if (act = ActionKeyControl(code, event, true))
            TeacherForward(true, act.nextFrame, act.id)
        else if (!IsLeadIn() && !IsLeadOut())
            TeacherWrong(event);
    }
    else	// playMode==K
    {
        if (act = ActionKeyControl(code, event, true))
            TeacherForward(true, act.nextFrame, act.id)
        else
            TeacherWrong(event)
    };
    getCode = false;
    return false;
};

var _tabsemaphore = false;

function EventKeyDown(event) {
    if (event == null) {
        event = window.event;
    }

    var code = event.which ? event.which : event.keyCode;

    if (IsExplorer()) {
        if (code == 9) {
            if (_tabsemaphore == true) {
                return false;
            }
            else {
                _tabsemaphore = true;
                setInterval("_tabsemaphore=false;", 10);
            }

        }
    }

    // NS: Disable function keys in "See It" mode
    if ((playMode == "S") && (code >= 112) && (code <= 123)) {
        if (showFrameIDToggle && CheckFrameIDKeys(event) == true) {
            ToggleShowFrameID();
        }
        return false;
    }

    if (playMode == "K") {
        if (KFinishClose == true) {
            return false;
        }
    }

    if (showActObj.type == "Input") {
        if (playMode == "S" || (playMode == "K" && KGuestDemoMode)) {
            if (code == 13)
                DemoForward();
            if (code == 27)
                ClosePlayer();
            if (code == 32)
                PauseToggle();
            return false;
        }
        if (code == 9 && PlayerConfig.StringInputLostFocusAutoadvanceEnabled) {
            if (AssessStringInput(true, true)) //complete
            {
                TeacherForward(true);
            }
            else {
                TeacherWrong(event);
            };
        };
        if (code == 13) {
            if (playMode == "T" && (UserPrefs.TryIt.EnableSkipping || IsTouchEvent())) {
                TeacherForward(true);
            }
            else if (AssessStringInput(true, true)) //complete
            {
                TeacherForward(true);
            }
            else {
                TeacherWrong(event);
            };
        }
        if (IsSafari() && code == 27) {
            OnClose();
            return false;
        }
        return true;
    }
    if (playMode == "K" && KGuestDemoMode)
        return false;
    if (playMode == "K" && IsDragBegin())
        return false;
    //	if (!(code>=112 && code<=123))
    if (code >= 65 && code <= 90) {
        var codes = String.fromCharCode(code);
        var upcodes = codes.toUpperCase();
        code = upcodes.charCodeAt(0);
    };
    if (code >= 16 && code <= 18)
        return true;
    if (code == 91 || code == 92)		//(windows key!)
        return true;

    if (code == 114 || code == 116 || code == 117 || code == 121)		// F3, F5, F6 and F10 keys
    {
        if (document.all && !IsFF3()) {
            event.originalCode = code;
            event.keyCode = 0;
        }
        if (playMode == "S")
            return false;
    };

    var act;
    if (playMode == "S") {
        if (code == 27) {
            ClosePlayer();
            return false;
        }
        else if (code == 32) {
            PauseToggle()
            return false;
        }
        else if (code == 13) {
            //			if(isTabbed)
            //				return true
            if (actionMenu) {
                if (actionMenu.IsOnScreen()) {
                    actionMenu.Close();
                    return true;
                }
            }
            DemoForward(showActObj.delay != DELAY_INFINITE);
            return false;
        }
        //		else if(code==9)
        //		{
        //			isTabbed = true
        //			return false
        //		}
        return true;
    }
    else if (playMode == "T") {
        if (event.keyCode == 115 && event.altKey == true) {
            return false;
        };
        if (code == 13) {
            if (actionMenu) {
                if (actionMenu.IsOnScreen()) {
                    closedbyEnter = true;
                    actionMenu.Close();
                    return true;
                };
            }
            //			if (isTabbed)
            //				return true
            //			else
            if (act = ActionKeyControl(code, event)) {
                TeacherForward(true, act.nextFrame, act.id);
                return false;
            }
            else if (UserPrefs.TryIt.EnableSkipping || IsTouchEvent()) {
                TeacherForward(false)
                return false;
            }
            else if (screens[showScreen].actions[0].type == "None") {
                TeacherForward(true)
                return false;
            }
            if (!UserPrefs.TryIt.EnableSkipping && !IsTouchEvent()) {
                TeacherWrong(event);
                return false;
            }
            else
                return true;
        }
        /*		
        else if(act=ActionKeyControl(code,event))
        TeacherForward(true,act.nextFrame)
        else if(code==9)
        {
        isTabbed = true;
        return true;
        }
        else if(code==27)
        ClosePlayer()
        else if((code>=16 && code<=18) || showActObj.type=="Input")
        return true
        else if (!IsLeadIn() && !IsLeadOut())
        TeacherWrong()
        */
        else if (code == 27) {
            if (act = ActionKeyControl(code, event))
                TeacherForward(true, act.nextFrame, act.id)
            else
                ClosePlayer();
            return false;
        }
        else if (code == 9) {
            if (act = ActionKeyControl(code, event)) {
                TeacherForward(true, act.nextFrame, act.id);
                return false;
            }
            else {
                TeacherWrong(event);
                return false;
            };
        }
        else if ((code >= 16 && code <= 18) || showActObj.type == "Input")
            return true
        else if (act = ActionKeyControl(code, event)) {
            TeacherForward(true, act.nextFrame, act.id);
            return false;
        }
        else
        //        if (code >= 112 && code <= 123)	// function keys
        {
            TeacherWrong(event);
            return false;
        };
        //        getCode = true;
        //        return true;
    }
    else // playMode=="K"
    {
        if (event.keyCode == 115 && event.altKey == true)	// altF4
        {
            try { event.keyCode = 27; } catch (e) { };
            code = 27;
            knowit_AltF4Pressed = true;
        };
        if (code == 13) {
            if (actionMenu) {
                if (actionMenu.IsOnScreen()) {
                    actionMenu.Close();
                    return true;
                }
            }
            if (KScoringScreen)
                ClosePlayer(1)
            else if (IsLeadIn() || IsLeadOut())
                TeacherForward(true)
            else if (act = ActionKeyControl(code, event))
                TeacherForward(true, act.nextFrame, act.id)
            else if (screens[showScreen].actions[0].type == "None") {
                TeacherForward(true, act.nextFrame, act.id)
            }
            else
                TeacherWrong(event)
            return true;
        };
        /*		
        if(act=ActionKeyControl(code,event))
        TeacherForward(true,act.nextFrame)
        else if(code==27)
        OnClose()
        else if((code>=16 && code<=18) || showActObj.type=="Input")
        return true
        else
        TeacherWrong()
        */
        //		if(code==9)
        //		{
        //			TeacherWrong();
        //			return false;
        //		}
        //		else if(code==27) !!!!!
        if (code == 27) {
            if (act = ActionKeyControl(code, event))
                TeacherForward(true, act.nextFrame, act.id)
            else
                OnClose();
            return false;
        }
        else if (code == 9) {
            if (act = ActionKeyControl(code, event)) {
                TeacherForward(true, act.nextFrame, act.id);
                return false;
            }
            else {
                TeacherWrong(event);
                return false;
            };
        }
        else if ((code >= 16 && code <= 18) || showActObj.type == "Input")
            return true
        else if (act = ActionKeyControl(code, event)) {
            TeacherForward(true, act.nextFrame, act.id)
            return false;
        };
        if (code >= 112 && code <= 123)	// function keys
        {
            TeacherWrong(event);
            return false;
        };
        getCode = true;
        return true;
    };
    //return false;
}

function StrongAssess(complete, primary) {
    if (!complete)
        complete = false;
    if (!primary)
        primary = false;
    var v = showActInpObj.value;
    if (primary) {
        var s = showActObj.par1[1];
        if (matchString(s, v, showActObj.par3))
            return true;
        var s = DecodeInputString(showActObj.par1[1]);
        return matchString(s, v, showActObj.par3)
    };

    if (complete) {
        if (showActObj.par1[0] == "N" && v == "")
            return true;
        if (showActObj.par1[0] == "A" && v == "")
            return true;
    }

    for (var i = 1; i < showActObj.par1.length; i++) {
        var s = showActObj.par1[i];
        if (matchString(s, v, showActObj.par3))
            return true;
        s = DecodeInputString(showActObj.par1[i]);
        if (matchString(s, v, showActObj.par3))
            return true;
    };
    return false;
};

var _assessStr_counter = 0;

function AssessStringInput(complete, force) {
    if (!force) {
        _assessStr_counter++;
        if (_assessStr_counter == 3)
            _assessStr_counter = 0;
        if (_assessStr_counter != 0)
            return;
    }

    if (!complete)
        complete = false;

    var validatedoption = false;
    if (playMode == "K")
        validatedoption = true;

    if (!complete)
        return StrongAssess(false, !validatedoption);
    if (validatedoption) {
        if (showActObj.par1[0] == "N" || showActObj.par1[0] == "") {
            return StrongAssess(true, false);
        }
        else if (showActObj.par1[0] == "S") {
            return (showActInpObj.value.length > 0);
        }
        else {
            return true;
        };
    }
    else {
        return StrongAssess(complete, true);
    };

};

function EventInputKey(event) {
    if (playMode == "S") {
        var code = window.event ? window.event.keyCode : event.which ? event.which : event.keyCode;
        if (code == 27) {
            OnClose();
            return false;
        };
        setTimeout("showActInpObj.value=showActInpObj.original;", 10);
        return false;
    }
    if (playMode == "K" && KGuestDemoMode) {
        setTimeout("showActInpObj.value=showActInpObj.original;", 10);
        return false;
    };
    if (playMode == "K" && IsDragBegin()) {
        setTimeout("showActInpObj.value=showActInpObj.original;", 10);
        return false;
    };
    if (playMode == "T" || playMode == "K") {
        var code = window.event ? window.event.keyCode : event.which ? event.which : event.keyCode;
        if (code != 13)
            showActObj.par4 = true;
        if (code == 27) {
            showActInpObj.value = showActObj.par5;
            showActInpObj.original = showActInpObj.value;
            OnClose();
            return false;
        };
    }
    //return false;
    return true;
}

///////////////////////////////////////////////
// Trace for test
var tracewindow = null;

function Trace(s) {
    if (tracewindow == null) {
        tracewindow.open("", "", "");
    };
    tracewindow.document.writeln(s);
    tracewindow.document.writeln("<br>");
    tracewindow.scrollBy(0, 100);
}
///////////////////////////////////////////////

function EventPropertyChange()
// it works by non key based character input (japanese content, IME input)
{
    if (showActObj.type != "Input") {
        if (showActObj.par4 == false) {
            return true;
        }
    }
    if (playMode == "T" || playMode == "K") {
        if (PlayerConfig.StringInputAutoadvanceEnabled) {
            //            if (_backStep == true)
            //                return false;
            if (AssessStringInput(false) && showActObj.par4 == true)			// implicit
            {
                TeacherForward(true, showActObj.nextFrame, showActObj.id);
            }
        }
    }
    setTimeout("EventPropertyChange();", 100);
    return true;
}

function EventKeyUp(event) {
    return true
}

function EventCancel(event) {
    return false	// cancel popups
}

function UnLoad() {
    lms_ClosePage();
    if (playMode == "K") {
        trackScoreCompleted = GetResultInPercent(true);
        trackScoreRequired = KScoreNeeded;
        if (KTopicFinished || KScoringScreen || showActObj.nextFrame == 'end')
            trackComplete()
        else
            trackIncomplete();
    };
    if (playMode == "S" || playMode == "T" || playMode == "K") {
        ClosePlayer();
    }
    if (guidedParent) {
        guidedParent.GITMClosed();
    }
};

function StartFrameCorrection(frameID) {
    var originalFrameID = frameID;
    var frmPos = frameID;
    if (screens[frameID].backActions.length == 0) {
        StartScreen = "start";
        if (StartScreen != originalFrameID)
            StartAction = 0;
        return;
    };
    var fID = "";
    for (var i = 0; i < screens[frameID].backActions.length; i++) {
        if (i == 0)
            fID = screens[frameID].backActions[0].prevFrame
        else {
            if (fID != screens[frameID].backActions[0].prevFrame) {
                StartScreen = frameID;
                if (StartScreen != originalFrameID)
                    StartAction = 0;
                return;
            };
        };
    };
    frmPos = screens[frmPos].backActions[0].prevFrame;
    while (true) {
        if (screens[frmPos].backActions.length == 0) {
            StartScreen = "start";
            if (StartScreen != originalFrameID)
                StartAction = 0;
            return;
        };
        if (screens[frmPos].actions[0].type == "None") {
            frmPos = screens[frmPos].backActions[0].prevFrame;
            continue;
        };
        if (screens[frmPos].actions[0].type == "Decision") {
            StartScreen = frmPos;
            if (StartScreen != originalFrameID)
                StartAction = 0;
            return;
        };
        StartScreen = frameID;
        if (StartScreen != originalFrameID)
            StartAction = 0;
        return;
    };
};

function SetStartFrame(frameID) {
    if (frameID.length == 0)
        return;
    if (screens[frameID])
        StartScreen = frameID;
};

function SetStartContext(contextID) {
    if (contextID.length == 0)
        return;
    var ctxArray = new Array();
    ctxArray = contextID.split("+");

    for (var i = 0; i < ctxArray.length; i++) {
        ctxItem = ctxArray[i];
        for (var j = 0; j < screenNames.length; j++) {
            scrName = screenNames[j];
            scr = screens[scrName];
            for (var k = 0; k < scr.actions.length; k++) {
                act = scr.actions[k];
                if (act.ctx == ctxItem) {
                    SetStartFrame(scrName);
                    StartFrameCorrection(StartScreen);
                    return;
                };
            };
        };
    };
};

var ecidMatchingFrames = new Array();
var ecidStartDecisions = new Object();
var ecidDecisionStart = false;

function SetStartEcid(ecidexpression) {
    if (ecidexpression.length == 0)
        return;
    EcidComparer.Init(ecidexpression);
    SearchPathForEcid(screenNames[0]);
    if (ecidMatchingFrames.length == 1) {
        SetStartFrame(ecidMatchingFrames[0].frameid);
        StartAction = ecidMatchingFrames[0].altindex;
        StartFrameCorrection(StartScreen);
    }
    else if (ecidMatchingFrames.length >= 2) {
        ecidDecisionStart = true;
        StartScreen = FindEcidStartNextFrame(screenNames[0]);
        StartFrameCorrection(StartScreen);
    }
}

function SearchPathForEcid(frid) {
    var frameid = frid;
    while (true) {
        if (frameid == "end") {
            return false;
        }
        var frame = screens[frameid];
        frame.type = frame.actions[0].type.toLowerCase();
        if (frame.type == "decision") {
            var match = false;
            ecidStartDecisions[frameid] = { id: frameid, display: false, pathstoignore: new Array() };
            for (var i = 0; i < frame.actions.length; i++) {
                if (SearchPathForEcid(frame.actions[i].nextFrame)) {
                    if (match) {
                        ecidStartDecisions[frameid].display = true;
                    }
                    match = true;
                }
                else {
                    ecidStartDecisions[frameid].pathstoignore.push(frame.actions[i].id);
                }
            }
            return match;
        }
        for (var j = 0; j < frame.actions.length; j++) {
            var act = frame.actions[j];
            if (EcidComparer.Compare(act.ecidarray)) {
                ecidMatchingFrames.push({ frameid: frameid, altindex: j });
                return true;
            }
        }
        frameid = frame.actions[0].nextFrame;
    }
}

function FindEcidStartNextFrame(frid) {
    var frameid = frid;
    var frame = screens[frameid];
    frame.type = frame.actions[0].type.toLowerCase();
    if (frame.type == "decision") {
        if (ecidStartDecisions[frameid].display) {
            return frameid;
        }
    }
    for (var i = 0; i < ecidMatchingFrames.length; i++) {
        if (frameid == ecidMatchingFrames[i].frameid) {
            StartAction = ecidMatchingFrames[i].altindex;
            ecidDecisionStart = false;
            return frameid;
        }
    }
    for (var iii = 0; iii < frame.actions.length; iii++) {
        if (frame.actions[iii].nextFrame != "end") {
            var ret = FindEcidStartNextFrame(frame.actions[iii].nextFrame);
            if (ret) return ret;
        }
    }
}

function Skip() {
    return false;
};

function SetFlags() {
    for (var i = 0; i < screenNames.length; i++) {
        scrName = screenNames[i];
        var bcount = 0;
        for (var j = 0; j < screens[scrName].actions.length; j++) {
            var ie = screens[scrName].emptyinfo;
            var te = screens[scrName].actions[j].emptytext;
            var be = (ie && te);
            screens[scrName].actions[j].emptybubble = be;
            if (!be && screens[scrName].actions[j].realAction == true)
                bcount++;
        };
        for (var j = 0; j < screens[scrName].actions.length; j++) {
            screens[scrName].actions[j].showalternatives = (bcount > 1);
            if (screens[scrName].actions[j].type == "None" ||
				screens[scrName].actions[j].type == "Decision")
                screens[scrName].actions[j].showalternatives = false;
        };
    };
};

var bActionsBuilded = false;

function FrameContainer() {
    this.container = new Object();

    this.Clear = function () {
        this.container = new Object();
    }

    this.Contains = function (id) {
        try {
            var a = this.container[id];
            if (a != null)
                return true;
        }
        catch (e) { }
        return false;
    }

    this.Get = function (id) {
        if (this.Contains(id))
            return this.container[id];
        return null;
    }

    this.Add = function (id, nextid) {
        this.container[id] = nextid;
    }
}

var frameContainer = new FrameContainer();

function _isHiddenAction(a) {
    try {
        return (a.disabledmodes.indexOf(playMode) >= 0);
    }
    catch (e) {
        return false;
    }
}

function _isFrameToSkip(f) {
    if (playMode == "S") {
        var a = f.actions[0];
        if (!_isHiddenAction(a)) {
            return false;
        }
    }
    else {
        for (var i = 0; i < f.actions.length; i++) {
            var a = f.actions[i];
            if (!_isHiddenAction(a)) {
                return false;
            }
        }
    }
    return true;
}

// creates a new action array for a frame avoiding actions are hidden
function _createActionArray(fname) {
    var aa = new Array();
    var f = screens[fname];
    for (var i = 0; i < f.actions.length; i++) {
        var a = f.actions[i];
        if (!_isHiddenAction(a)) {
            aa[aa.length] = a;
        }
    }
    return aa;
}

function _buildActionsS() {
    // creating a map from the frames to skip
    for (var i = 0; i < screenNames.length; i++) {
        var f = screens[screenNames[i]];
        if (_isFrameToSkip(f)) {
            frameContainer.Add(f.actions[0].prevFrame, f.actions[0].nextFrame);
        }
    }
    // reducing map
    var changed = true;
    while (changed) {
        changed = false;
        for (var j in frameContainer.container) {
            var k = frameContainer.Get(j);
            var kn = frameContainer.Get(k);
            if (kn != null && k != kn) {
                frameContainer.Add(j, kn);
                changed = true;
            }
        }
    }
    // rebuild nextFrame pointers about the map
    for (var i = 0; i < screenNames.length; i++) {
        var fname = screenNames[i];
        var f = screens[fname];
        try {
            var next = f.actions[0].nextFrame;
            if (frameContainer.Contains(next)) {
                f.actions[0].nextFrame = frameContainer.Get(next);
            }
        }
        catch (e) { }
    }
}

function _buildActionsTK() {
    // creating a map from the frames to skip
    for (var i = 0; i < screenNames.length; i++) {
        var f = screens[screenNames[i]];
        if (_isFrameToSkip(f)) {
            for (var j = 0; j < f.backActions.length; j++)
                frameContainer.Add(f.backActions[j].nextFrame, f.actions[0].nextFrame);
        }
    }
    // reducing map
    var changed = true;
    while (changed) {
        changed = false;
        for (var j in frameContainer.container) {
            var k = frameContainer.Get(j);
            var kn = frameContainer.Get(k);
            if (kn != null && k != kn) {
                frameContainer.Add(j, kn);
                changed = true;
            }
        }
    }
    // rebuild nextFrame pointers about the map
    for (var i = 0; i < screenNames.length; i++) {
        var fname = screenNames[i];
        var f = screens[fname];
        f.actions = _createActionArray(fname);
        for (var j = 0; j < f.actions.length; j++) {
            var next = f.actions[j].nextFrame;
            if (frameContainer.Contains(next)) {
                f.actions[j].nextFrame = frameContainer.Get(next);
            }
        }
    }
}

function BuildActions() {
    if (bActionsBuilded)
        return;
    frameContainer.Clear();
    if (playMode == "S") {
        _buildActionsS();
    }
    else {
        _buildActionsTK();
    }
    bActionsBuilded = true;
}

var bBackActionsBuilded = false;

function BuildBackActions() {
    if (!bBackActionsBuilded) {
        for (var i = 0; i < screenNames.length; i++) {
            scr = screens[screenNames[i]];
            scr.backActions = new Array();
        };
        for (i = 0; i < screenNames.length; i++) {
            if (!frameContainer.Contains(screenNames[i])) {
                scr = screens[screenNames[i]];
                for (var j = 0; j < scr.actions.length; j++) {
                    scr.actions[j].prevFrame = screenNames[i];
                    s = scr.actions[j].nextFrame;
                    if (s != "end")
                        screens[s].backActions[screens[s].backActions.length] = scr.actions[j];
                }
            };
        };
    };
    bBackActionsBuilded = true;
};

var _deviceDPI = 0;

var swipe = new Swipe();
var screenwidth = 0;

function IsTouchEvent() {
    if (IsTouchDevice()) {
        if (UserPrefs.TryIt.EnableSkipping)
            return true;
        var t = showActObj.type.toLowerCase();
        if (t.indexOf('click') >= 0)
            return false;
        if (t.indexOf('input') >= 0)
            return false;
        return true;
    }
    return false;
}

function setiPadScreen() {
    if (window.innerWidth / window.innerHeight > $("#screen").width() / $("#screen").height()) {
        $("html").css({
            "margin": 0,
            "padding": 0
        });
        $("body").css({
            "position": "relative",
            "margin": 0,
            "padding": 0
        }).width(window.innerWidth / window.innerHeight * $("#screen").height());
        $("#screen").css("top", 0)
        $("#screen").css("left", (((window.innerWidth / window.innerHeight * $("#screen").height()) - $("#screen").width()) / 2))
        //alert(((window.innerWidth / window.innerHeight * $("#screen").height()) - $("#screen").width()) / 2)
        //shiftTo("screen", ((window.innerWidth / window.innerHeight * $("#screen").height()) - $("#screen").width()) / 2, 0)
    } else {
        $("body").width($("#screen").width());
        $("#screen").css("left", 0)
        $("#screen").css("top", (((window.innerHeight / window.innerWidth * $("#screen").width()) - $("#screen").height()) / 2))
    }


}

function SetVolumeLevel(v, m) {
    SoundPlayerObj.SetVolume(m ? 0 : v);
    UserPrefs.LoadCookie();
    UserPrefs.NavbarVolume = (m ? v + 1000 : v);
    UserPrefs.StoreCookie();
}

function UpdateHistoryFromTimeline(timelineindex) {
    var t = upk.Timeline.GetTimeline();
    showHistory = new Array();
    for (var i = 0; i < timelineindex; i++) {
        showHistory[showHistory.length] = t[i];
    }
}

function SetTimeLevel(t) {
    upk.Timeline.Lock(true);
    PlayStop();
    var fts = upk.Timeline.DeterminateCurrentFrameFromTime(t);
    timelineDescriptor = new TimelineDescriptor(true, fts.frameid, fts.timelineindex, fts.narration, fts.animation, fts.resttime)
    UpdateHistoryFromTimeline(fts.timelineindex);
    ShowScreen(fts.frameid, "", "back", true);
}

var navBar, fusionmode = false;
var showCursor = false;
function FirstScreen(restart) {

    template_pauselink = '<div align="right"><span id="prbr"><br /></span><a id="prdiv" class="InstructText" href="javascript:HLink(600)">' + R_interface_pause + '</a></div>'
    HideSplash();
    if (screenwidth == 0) {
        screenwidth = $("#screen").width() + 2;

        if (fusionmode) {
            navBar = new upk.player.navBar("navBar1", $(document.body), { ios: IsTouchDevice() })
            navBar.bind({
                "onnext": function () { DemoNext() },
                "onprev": function () { DemoPrev() },
                "onrefresh": function () { TeacherFastBack() },
                "onpausetoggle": function () { PauseToggle() },
                "onprefs": function () { SeeItPause(); OpenPreferences() },
                "onvolumechange": function (e) { SetVolumeLevel(e.volume, e.muted) },
                "onsliderchange": function (e) { SetTimeLevel(e.time) },
                "onhelp": function () { LaunchHelp("../../") }
            });
            UserPrefs.LoadCookie();
            var v = UserPrefs.NavbarVolume;
            var m = v > 1000;
            if (m) {
                navBar.setVolume(v - 1000);
                navBar.toggleMute(true);
            }
            else {
                navBar.setVolume(v);
            }
            if (IsTouchDevice()) {
                navBar.setKeepHidden(true);
            } else {
                navBar.show();
            }

        }
        if (IsTouchDevice()) {

            var clname = document["body"].className;
            if (clname.indexOf('ipad') < 0) {
                document["body"].className = clname + " ipad";
            }

            setiPadScreen();

            $("#screen").bind('orientationchange', function (e) {
                setTimeout("setiPadScreen(); binterf.RefreshPosition(); ScrollToAction()", 200);
            });

            $("#screen").bind('touchstart', function (e) {
                swipe.Init(screenwidth);
            });

            $("#screen").bind('touchmove', function (e) {
                try {
                    if (e.originalEvent.touches[1] || e.originalEvent.changedTouches[1]) {
                        swipe.DetectedMulti();
                    }
                    else if (swipe.IsNotZoomed()) {
                        e.preventDefault();
                    }
                }
                catch (e) { };
                var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
                swipe.Add(touch.pageY, touch.pageX);
            });

            $("#screen").bind('touchend', function (e) {

                var sensitivity = 30;
                if (swipe.IsMulti()) {
                    setTimeout("binterf.RefreshPosition();", 100);
                    return;
                }
                if (swipe.IsNotZoomed() == false) {
                    return;
                }
                var x = swipe.GetX();
                var y = swipe.GetY();
                if (Math.abs(x) > Math.abs(y)) {
                    return;
                }
                if (y > sensitivity) {
                    //                   alert("touch right swipe");
                    TeacherBack();
                }
                if (y < (0 - sensitivity)) {
                    //                    alert("touch left swipe");
                    if (IsDragBegin()) {

                        StartDemoInTryIt();
                        return;
                    }
                    var a = new Object();
                    a.keyCode = 13;
                    EventKeyDown(a);
                }
            });
        }

    }

    if (PlayerConfig.UseCursorShadow == true) {
        $("#cursor img").attr("src", "../../../img/cursor2.png");
        $("#bullseye img").attr("src", "../../../img/bullseye2.png");
    }

    // Get the current device DPI
    if (_deviceDPI == 0)
        _deviceDPI = getDpiInfo();


    if (_deviceDPI != 96) {
        if (getDPICookie() == false) {
            loader_dontclose = true;
            this.location.replace("../../../js/unsuppdpi.html?" + Escape.MyEscape(AbsUrl(this.location.href)));
            return;
        }
    }
    InitLmsMode("player");

    if (!restart && lms_initialized == false) {

        // edw
        SetUpProgressReporting();

        GetOpener();
        var lms_opener = (window.opener == undefined ? window.parent : window.opener);
        /*
        if (lms_inAssessment == true) {
        lms_opener = window.opener.parent;
        }
        */

        var k = soundModes.indexOf(playMode);
        if (k < 0)
            soundIsExported = false;
        if (location.hostname == "")
            soundIsExported = false;

        if (_lmsMode != null) {
            if (nosound == false) {
                if (Sound_Init(soundIsExported, UserPrefs.PlayAudio, null, false) == false) {
                    loader_dontclose = true;
                    return;
                }
            }
        }

        lms_InitPage((_lmsMode == null ? lms_childIndex : -1), (_lmsMode == null ? (gopener == null ? lms_opener : gopener) : null), "T_" + document.getElementById("TopicId").getAttribute("topicid"), "FirstScreen()");
        return;
    }

    if (nosound == true) {
        SetNoSound(true);
    }

    if (GetNoSound()) {
        soundIsExported = false;
    }

    BuildBackActions();
    BuildActions();
    bBackActionsBuilded = false;
    BuildBackActions();
    event_blocked = false;

    if (playMode != "K") {
        if (restart) {
            StartScreen = FirstScreenName;
        }
        else {
            SetStartFrame(param_frame);
            SetStartContext(param_ctx);
            SetStartEcid(param_ecid);
            FirstScreenName = StartScreen;
            SetFlags();
        };
        if (StartScreen == "start") {
            if (showLeadIn == 0) {
                StartScreen = screens["start"].actions[0].nextFrame;
            }
            else if (showLeadIn != 1) {
                if (UserPrefs.ShowLeadIn == "toc") {
                    StartScreen = screens["start"].actions[0].nextFrame;
                }
            }
        }
    }
    else {
        FirstScreenName = StartScreen;
        KWrongScreens = new Array();
    };

    var screenObj = getDIV("screen")

    scrH = getObjHeight("screen");
    scrW = getObjWidth("screen");

    window.onresize = HandleResize0;
    if (!IsTouchDevice()) {
        window.onscroll = HandleResize;
    }

    document.body.oncontextmenu = EventCancel;

    window.onhelp = Skip;
    document.onhelp = Skip;
    screenObj.onhelp = Skip;

    // Safety net in case onresize/onscroll is not processed properly
    if (navigator.appName.substring(0, 9) != "Microsoft" && !IsTouchDevice()) {
        setInterval("HandleResize()", 1000)
    }

    if (document.layers) {
        document.captureEvents(Event.KEYDOWN)
        if (playMode == "T" || playMode == "K") screenObj.captureEvents(Event.MOUSEMOVE)
        screenObj.captureEvents(Event.MOUSEDOWN)
        if (playMode == "T" || playMode == "K") screenObj.captureEvents(Event.MOUSEUP)
        screenObj.captureEvents(Event.DBLCLICK)
    }

    if (playMode == "T" || playMode == "K") screenObj.onmousemove = EventMouseMove
    screenObj.onmousedown = EventMouseDown;
    document.onmousedown = DocEventMouseDown;
    if (playMode == "T" || playMode == "K") screenObj.onmouseup = EventMouseUp
    screenObj.ondblclick = EventDblClk;

    if (screenObj.addEventListener)
        screenObj.addEventListener('DOMMouseScroll', EventWheel, false)
    else
        screenObj.onmousewheel = EventWheel;

    // ondblclick is also assigned statically in the HTML text to avoid a
    // bug in current Mozilla betas (0.9.4 at the time of writing)
    screenObj.oncontextmenu = EventCancel
    screenObj.ondragstart = EventCancel
    document.ondragstart = EventCancel

    document.onkeydown = EventKeyDown;
    document.onkeypress = EventKeyPress;

    document.onstop = null
    if (parent)
        parent.document.onstop = null;
    window.onunload = UnLoad;
    //    window.onbeforeunload = BeforeUnload;
    window.onfocus = OnFocus;

    curH = getObjHeight("cursor");
    curW = getObjWidth("cursor");
    sx = screenObj.offsetLeft;
    sy = screenObj.offsetTop;
    shiftTo("cursor", (scrW - curW - sx - cursor_alignment_x) / 2, (scrH - curH - sy - cursor_alignment_y) / 2);
    showCursor = false;

    var StartScreenSaved = StartScreen;
    StartScreen = "";
    HandleResize();
    StartScreen = StartScreenSaved;
    if (!restart) {
        binterf = new JSBubbleInterface("bubb01");
    };

    binterf.SetEnableCloseButton(1);

    if (playMode == "T") {
        binterf.SetMode(R_mode_tryit);
        binterf.SetActionText(R_interface_action);
        binterf.SetMoveable(false);
    };
    if (playMode == "S") {
        binterf.SetMode(R_mode_seeit);
        if (!fusionmode)
            binterf.SetActionText(R_interface_action);
        binterf.SetMoveable(false);
    };
    if (playMode == "K") {

        binterf.SetMode(R_mode_knowit);
        binterf.SetActionText(R_interface_action);
        binterf.SetPosition(-1, -1, -1, -1, true, 0, 0, 0);
        binterf.SetMoveable(true);
    };

    document.getElementById("frameidtext").innerHTML = R_frameid;

    switch (PlayerConfig.ShowFrameID.toLowerCase()) {
        case "on":
            document.getElementById("frameiddiv").style.display = "block";
            break;
        case "off":
            document.getElementById("frameiddiv").style.display = "none";
            break;
        case "shiftf1":
            showFrameIDToggle = 112;
            break;
        case "shiftf2":
            showFrameIDToggle = 113;
            break;
        case "shiftf3":
            showFrameIDToggle = 114;
            break;
        case "shiftf4":
            showFrameIDToggle = 115;
            break;
        case "shiftf5":
            showFrameIDToggle = 116;
            break;
        case "shiftf6":
            showFrameIDToggle = 117;
            break;
        case "shiftf7":
            showFrameIDToggle = 118;
            break;
        case "shiftf8":
            showFrameIDToggle = 119;
            break;
        case "shiftf9":
            showFrameIDToggle = 120;
            break;
        case "shiftf10":
            showFrameIDToggle = 121;
            break;
        case "shiftf11":
            showFrameIDToggle = 122;
            break;
        case "shiftf12":
            showFrameIDToggle = 123;
            break;
    }

    lms_topicStart(getMyGuid(), playMode);

    ShowScreen(StartScreen, StartAction)
    try {
        window.focus()
    }
    catch (e) { };

    /* edw */
    if (playMode == "S") {
        upk.Timeline.CalculateTimelineThrough("end");
    }
}

function SetSound(value) {
    soundIsExported = value;
};

function SetKScore(score) {
    KScoreNeeded = score;
};

function HexaToDec(hexa) {
    if (hexa.length == 0)
        return "";
    try {
        return hexa.substr(0, 1) + parseInt("0x" + hexa.substr(1));
    }
    catch (e) {
        return "";
    }
}

function ecidStr(s) {
    return replaceString("%27", "'", s);
}

function ParseArguments() {
    var strArgs;
    var strArg;

    // Call parameters can be seperated from the URL by either a "?"
    // or a "#" character...

    var ss = document.location.hash.substring(1);
    strArgs = ss.split("&");
    if (strArgs.length == 0 || strArgs[0] == "") {
        ss = document.location.search.substring(1);
        strArgs = ss.split("&");
    };

    if (strArgs.length == 1) {
        if (strArgs[0].toLowerCase().substr(0, 3) == "su=") {
            var s = Escape.SafeUriUnEscape(strArgs[0].substr(3));
            strArgs = s.split("&");
        }
    }

    for (var i = 0; i < strArgs.length; i++) {
        strArg = (strArgs[i]);

        if (strArg.substr(0, 5).toLowerCase() == "mode=") {
            playMode = strArg.substr(5, 1);
        }
        if (strArg.substr(0, 9).toLowerCase() == "framehex=") {
            param_frame = HexaToDec(strArg.substr(9));
        }
        if (strArg.substr(0, 6).toLowerCase() == "frame=") {
            param_frame = strArg.substr(6);
        }
        if (strArg.substr(0, 4).toLowerCase() == "ctx=") {
            param_ctx = strArg.substr(4);
        }
        if (strArg.substr(0, 6).toLowerCase() == "ctxex=") {
            param_ecid = ecidStr(strArg.substr(6));
        }
        if (strArg.substr(0, 8).toLowerCase() == "leadin=1") {
            showLeadIn = 1;
        }
        if (strArg.substr(0, 8).toLowerCase() == "leadin=0") {
            showLeadIn = 0;
        }
        if (strArg.substr(0, 12).toLowerCase() == "printitname=") {
            param_printitname = strArg.substr(12);
        }
        if (strArg.substr(0, 8).toLowerCase() == "windowed") {
            fusionmode = true;
        }
        if (strArg.substr(0, 11).toLowerCase() == "childindex=") {
            lms_childIndex = parseInt(strArg.substr(11));
        }
        if (strArg.substr(0, 10).toLowerCase() == "assessment") {
            lms_inAssessment = true;
        }
        if (strArg.substr(0, 7).toLowerCase() == "nosound") {
            nosound = true;
        }
    }
    if (playMode == "K") {
        trackArgList = strArgs;
        trackOnBegin();
    };
}

var clicknum = 1

function SoundToggle() {
    clicknum = clicknum + 1
    if (Math.floor(clicknum / 2) == clicknum / 2) {
        document.imgS.src = "sound_isoff.gif";
    }
    else {
        document.imgS.src = "sound_ison.gif";
    }
}

function OpenDialog(URL) {
    day = new Date();
    id = day.getTime();
    eval("page" + id + " = window.open(MakeAbsolute(URL), '" + id + "', 'toolbar=1,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=506,height=338,left = 147,top = 131');");
}

function PauseToggle() {
    try {
        isPaused = !isPaused;
        if (isPaused) {
            binterf.SetPRText(R_interface_resume);
            binterf.StartBlink();
            PlayPause();
        }
        else {
            binterf.EndBlink();
            binterf.SetPRText(R_interface_pause);
            if (!PlayResume()) {
                if (navBar)
                    navBar.togglePause(isPaused);
                TeacherFastBack();
                return;
            }
        }
        if (parent.setPauseStatus)
            parent.setPauseStatus(isPaused);
        if (navBar)
            navBar.togglePause(isPaused);
    }
    catch (e) {
        isPaused = !isPaused;
    }
}

function SeeItPause() {
    if (playMode == "S" && !isPaused)
        PauseToggle();
}

function SeeItResume() {
    if (playMode == "S" && isPaused)
        PauseToggle();
}

function IsPaused() {
    return isPaused;
}

function SetScrollbars() {
    var div = getDIV("screen");
    var w = div.offsetWidth;
    //	var ww=window.screen.width;
    var ww = document.body.clientWidth + 2;
    var h = div.offsetHeight;
    //	var hh=window.screen.height;
    var hh = document.body.clientHeight;
    if (w > ww || h > hh) {
        document.body.scroll = "auto";
    };
};

function SetScreenshotPath(s) {
    if (!s)
        s = "";
    if (s == "")
        screenshotPath = MakeAbsolute("")
    else
        screenshotPath = s;
    if (s != "")
        SoundPlayerObj.SetSoundPath(s);
};

function SetRemediationLevels(level1, level2, level3) {
    KRemediation1 = level1;
    KRemediation2 = level2;
    KRemediation3 = level3;
}

function SetTopicName(s) {
    if (!s)
        s = "";
    if (s.length > 0)
        topicName = unescape(s);
}

function SetTopicShowBubbles(s) {
    topicShowBubbles = s;
}

function fixHTMLString(strHTMLString) {
    strHTMLString = replaceString("<", "&lt;", strHTMLString);
    strHTMLString = replaceString(">", "&gt;", strHTMLString);
    strHTMLString = replaceString("'", "&#39;", strHTMLString);
    strHTMLString = replaceString('"', "&#34;", strHTMLString);

    return strHTMLString;
}

function DecodeInputString(s) {
    s = replaceString("&lt;", "<", s);
    s = replaceString("&gt;", ">", s);
    s = replaceString("&amp;", "&", s);
    return s;
}

//
// Initialization and preloads
//

ParseArguments()

//
// Mode-specific styles
//

document.writeln("<STYLE>")
if (playMode == "S") {
    document.writeln("A.textLink {text-decoration:none; color:black}")
    document.writeln(".infoblocks {display:none}")
}
else {
    document.writeln("A.textLink {color:#0033cc}")
}
document.writeln("</STYLE>")

//
// Force reload when Netscape 4 resizes window
//

if (NS4) {
    var loadWidth = window.innerWidth
    var loadHeight = window.innerHeight
}

function getMyGuid() {
    var l = this.location.href;
    var k = l.indexOf("?");
    if (k >= 0)
        l = l.substr(0, k);
    k = l.lastIndexOf("/");
    var g = l.substr(k - 36, 36);
    return g;
}

/********** swipe support ************************************************************************/

function Swipe() {
}

Swipe.prototype.Init = function (width) {
    this.x = 0;
    this.y = 0;
    this.dx = 0;
    this.dy = 0;
    this.width = width;
    this.multi = false;
}

Swipe.prototype.Add = function (x, y) {
    if (this.x == 0 && this.y == 0) {
        this.x = this.dx = x;
        this.y = this.dy = y;
    }
    else {
        this.dx = x;
        this.dy = y;
    }
}

Swipe.prototype.IsNotZoomed = function () {
    if (window.innerWidth > this.width)
        return true;
    return (Math.abs(window.innerWidth - this.width) < 5);
}

Swipe.prototype.DetectedMulti = function () {
    this.multi = true;
}

Swipe.prototype.IsMulti = function () {
    return this.multi;
}

Swipe.prototype.Result = function () {
    return ("" + (this.dx - this.x) + " " + (this.dy - this.y));
}

Swipe.prototype.GetX = function () {
    return (this.dx - this.x);
}

Swipe.prototype.GetY = function () {
    return (this.dy - this.y);
}

Swipe.prototype.GetPoint = function () {
    return ("" + this.dx + "," + this.dy);
}

/*************************************************************************************************/

var __myLogWnd = null;

function MYLOGOpen() {
    if (__myLogWnd == null)
        __myLogWnd = window.open();
}

function MYLOG(o) {
    MYLOGOpen();
    __myLogWnd.document.write("<hr/>");
    __myLogWnd.document.write(o + "<br/><br/>");
    for (var name in o) {
        __myLogWnd.document.write(name + ": " + o[name] + "<br/>");
    }
    __myLogWnd.document.write("<hr/>");
}

function MYLOGSimple(s) {
    MYLOGOpen();
    __myLogWnd.document.write(s + "<br/>");
}

/* navbar.js */ 
/*--
Copyright � 1998, 2012, Oracle and/or its affiliates.  All rights reserved.
--*/

//file version 1.0

var upk = upk || {};
///////////////////////////////////
//  +++ class upk.player.navBar  //
///////////////////////////////////

$.extend(true, upk, {
	player: {
		navBar: function (id, parentElement, opts) {
			/// <summary>navBar object, can be created using "new" keyword</summary>
			/// <param name="id" type="String">navBar id</param>
			/// <param name="parentElement" type="JQuery">The element that the navBar will be appended to</param>

			/// PUBLIC
			var _this = this;

			_this.bind = function (p1, p2) {
				_self.bind(p1, p2);
			}

			_this.show = function () {
				hideTimer = 28;
				_protected.scaleToWindow();
				_self.show();
				_protected.scaleToWindow();
			}

			_this.hide = function () {
				_self.hide();
			}

			_this.setOptions = function (opts) {
				$.extend(_protected.options, opts);
			}

			_this.setEndTime = function (t) {
				if (_timeSliderDragged) { return; }
				_endTime = t;
				_self.find(".endtime").text(getTime(_endTime));
				_self.find(".timeslider").slider("option", "max", _endTime);
				_this.setCurrentTime(_currentTime);
			}

			_this.setCurrentTime = function (t) {
				if (_timeSliderDragged) { return; }
				_currentTime = t;
				_self.find(".currenttime").text(getTime(_currentTime));
				_self.find(".timeslider").slider("value", _currentTime);
			}

			_this.setVolume = function (v) {
				_volume = v;
				_self.find(".volumeslider").slider("value", _volume);
			}

			_this.setKeepHidden = function (b) {
				_keepHidden = b;
				if (hideTimer > 0) { hideTimer = 28; }
				if (_keepHidden) { _keepVisible = false; _self.hide(); }
				else if (hideTimer > 0) { _this.show(); }
			}

			_this.setKeepVisible = function (b) {
				_keepVisible = b;
				if (_keepVisible) { _keepHidden = false; _this.show(); }
			}

			_this.toggleMute = function (m) {
				_volumeMuted = m;
				if (_volumeMuted) {
					_self.find(".volumeslider").slider("value", 0);
				}
			}

			var _isPaused = true;
			_this.togglePause = function (p) {
				_isPaused = p;
				if (_isPaused) {
					_self.find(".pauseresumebutton").removeClass("pause_butt" + classPostFix).addClass("play_butt" + classPostFix);
				} else {
					_self.find(".pauseresumebutton").removeClass("play_butt" + classPostFix).addClass("pause_butt" + classPostFix);
				}
			}

			/// PROTECTED

			var _protected = {};
			_protected.id = id;
			_protected.parentElement = parentElement;
			_protected.options = {
				ios: false
			};
			$.extend(_protected.options, opts);

			_protected.create = function () {
				/// <summary>Creates navbar DOM</summary>
				var self = $("<div>", {
					"class": "NavbarWrapper" + (_protected.options.ios ? "" : " small"),
					html: $("<div>", {
						"class": "NavbarOuter",
						html: $("<div>", {
							id: _protected.id,
							"class": "NavbarMain",
							html: $("<div>", {
								"class": "prevbutton previous_butt" + classPostFix,
								title: R_fusion_back,
								click: function () { _self.trigger("onprev"); }
							}).add("<div>", {
								"class": "pauseresumebutton pause_butt" + classPostFix,
								title: R_fusion_play_pause,
								click: function () { _self.trigger("onpausetoggle"); }
							}).add("<div>", {
								"class": "nextbutton next_butt" + classPostFix,
								title: R_fusion_forward,
								click: function () { _self.trigger("onnext"); }
							}).add("<div>", {
								"class": "refreshbutton refresh_butt" + classPostFix,
								title: R_fusion_restart,
								click: function () { _self.trigger("onrefresh"); }
							}).add("<div>", {
								"class": "slidercontainer",
								html: $("<div>", {
									"class": "sliderleft slider_leftbar" + classPostFix
								})
							}).add("<div>", {
								"class": "helpbutton help_butt" + classPostFix,
								title: R_fusion_help,
								click: function () { _self.trigger("onhelp"); }
							}).add("<div>", {
								"class": "prefsbutton prefs_butt" + classPostFix,
								title: R_fusion_preferences,
								click: function () { _self.trigger("onprefs"); }
							}).add("<div>", {
								"class": "timerdisplay",
								html: $("<span>", {
									"class": "currenttime",
									text: getTime(_currentTime)
								}).add("<span>", {
									text: " / "
								}).add("<span>", {
									"class": "endtime",
									text: getTime(_endTime)
								})
							}).add("<div>", {
								"class": "timerleft slider_leftbar" + classPostFix
							}).add("<div>", {
								"class": "volumebutton volume_butt" + classPostFix,
								html: $("<div>", {
									"class": "volumeslidercontainer",
									html: $("<div>", {
										"class": "volumeslider"
									})
								}),
								click: function () {
									_volumeMuted = !_volumeMuted;
									_self.trigger({
										type: "onvolumechange",
										volume: _volume,
										muted: _volumeMuted
									})
									_self.find(".volumeslider").slider("value", (_volumeMuted ? 0 : _volume));
								}
							})
						})
					}).add("<div>", {
						"class": "timeslider"
					})
				})
				self.appendTo(_protected.parentElement);
				self.find(".timeslider").slider({
					orientation: "horizontal",
					range: "min",
					change: function (event, ui) {
						_self.find(".currenttime").text(getTime(ui.value));
					},
					start: function (event, ui) { _timeSliderDragged = true },
					stop: function (event, ui) {
						_timeSliderDragged = false;
						_self.trigger({
							type: "onsliderchange",
							time: ui.value
						})
					},
					slide: function (event, ui) {
						_self.find(".currenttime").text(getTime(ui.value));
						_self.trigger({
							type: "onsliderslide",
							time: ui.value
						})
					}
				});
				if (_protected.options.ios) {
					self.find(".ui-slider .ui-slider-handle").addClass("sliderpointer");
					self.find(".volumebutton").remove();
					self.find(".helpbutton").remove();
				} else {
					self.find(".prevbutton, .pauseresumebutton, .nextbutton, .refreshbutton, .helpbutton, .prefsbutton, .volumebutton").bind({
						"mouseenter": function () { $(this).css("background-color", "#cacac9") },
						"mouseleave": function () { $(this).css("background-color", "") }
					})
					self.find(".volumeslider").slider({
						orientation: "horizontal",
						range: "min",
						max: 100,
						value: 100,
						change: function (event, ui) {
							if (!_volumeMuted) { _volume = ui.value; }
							_volumeMuted = (ui.value == 0);
							if (_volumeMuted) { _self.find(".volumebutton").removeClass("volumebutton" + classPostFix).addClass("volumemuted_butt" + classPostFix); }
							else { _self.find(".volumebutton").addClass("volumebutton" + classPostFix).removeClass("volumemuted_butt" + classPostFix); }
							_self.trigger({
								type: "onvolumechange",
								volume: _volume,
								muted: _volumeMuted
							})
						},
						slide: function (event, ui) {
							_volumeMuted = (ui.value == 0);
							_volume = ui.value;
							if (_volumeMuted) { _self.find(".volumebutton").removeClass("volumebutton" + classPostFix).addClass("volumemuted_butt" + classPostFix); }
							else { _self.find(".volumebutton").addClass("volumebutton" + classPostFix).removeClass("volumemuted_butt" + classPostFix); }
							_self.trigger({
								type: "onvolumechange",
								volume: _volume,
								muted: _volumeMuted
							})
						}
					});
					self.find(".ui-slider .ui-slider-handle").addClass("slider_pointer" + classPostFix);
					self.find(".volumeslider.ui-slider .ui-slider-handle").addClass("volumesliderbutton");
					self.find(".timeslider").appendTo(".NavbarOuter");
				}
				return self;
			}

			_protected.scaleToWindow = function () {
				if (_protected.options.ios) {
					var ww = (window.orientation == 0 || window.orientation == 180) ? 768 / 45 * 87 : 1024 / 45 * 87;
					var zoomfactor = window.innerWidth / ww;
					_self.find(".NavbarOuter").css({
						"height": 87 * zoomfactor,
						"top": window.pageYOffset + window.innerHeight - 87 * zoomfactor
					})
					_self.find(".NavbarMain").css({
						"transform": "scale(" + zoomfactor + ")",
						"-ms-transform": "scale(" + zoomfactor + ")",
						"-webkit-transform": "scale(" + zoomfactor + ")",
						"-o-transform": "scale(" + zoomfactor + ")",
						"-moz-transform": "scale(" + zoomfactor + ")"
					})
					_self.find(".NavbarMain").css({
						"left": window.pageXOffset - ((ww - window.innerWidth) / 2),
						"top": 0 - ((87 - 87 * zoomfactor) / 2),
						"width": ww
					})
					var dw = 0, dl = 0;
					_self.find(".NavbarMain > div").not(".slidercontainer").each(function () { dw += $(this).width() })
					_self.find(".slidercontainer").prevAll().each(function () { dl += $(this).width() })
					_self.find(".slidercontainer").css({
						"right": dw - dl
					})
					_self.find(".timeslider").css({
						"left": (dl + 40) * zoomfactor + window.pageXOffset,
						"top": window.pageYOffset + window.innerHeight - 61 * zoomfactor,
						"height": 35 * zoomfactor,
						"width": (ww - dw - 80) * zoomfactor
					})
					_self.find(".ui-slider .ui-slider-handle").css({
						"width": 45 * zoomfactor,
						"height": 45 * zoomfactor
					})
					_self.find(".ui-slider-horizontal .ui-slider-handle").css({
						"margin-left": -22 * zoomfactor,
						"top": -5 * zoomfactor
					})
				} else {
					var addHeight = 0;
					if (_self.find('.volumeslidercontainer').is(':visible')) { addHeight = 22; }
					_self.find(".NavbarOuter").css({
						"top": $(document).scrollTop() + $(window).height() - 45 - addHeight,
						"left": $(document).scrollLeft(),
						"width": $(window).width(),
						"height": 45 + addHeight
					})
					_self.find(".NavbarMain").css({
						"width": "100%"
					})
					var dw = 0, dl = 0;
					_self.find(".NavbarMain > div").not(".slidercontainer").each(function () { dw += $(this).width() })
					_self.find(".slidercontainer").prevAll().each(function () { dl += $(this).width() })
					_self.find(".slidercontainer").css({
						"left": dl,
						"width": $(window).width() - dw
					})
					_self.find(".timeslider").css({
						"top": 15 + addHeight,
						"left": dl + 25,
						"width": $(window).width() - dw - 50
					})
				}
				//alert(sw);
			}


			/// PRIVATE

			var _currentTime = 0, _endTime = 9999999, _volume = 100, _volumeMuted = false, _timeSliderDragged = false, hideTimer = 0, showVolume = false;
			var _keepHidden = false, _keepVisible = false;
			function getTime(t) {
				/// <summary>Converts time from ms to hh:mm:ss</summary>
				/// <param name="t" type="int">Time in milliseconds</param>
				/// <returns type="String" />
				var ret = "", seconds = 0, minutes = 0, hours = 0
				seconds = Math.floor((t / 1000) % 60);
				seconds = (seconds < 10 ? '0' : '') + seconds
				minutes = Math.floor((t / (1000 * 60)) % 60);
				//minutes = (minutes < 10 ? '0' : '') + minutes
				hours = Math.floor(t / (1000 * 60 * 60));
				//hours = (hours < 10 ? '0' : '') + hours
				if (hours || _endTime >= (1000 * 60 * 60)) { minutes = (minutes < 10 ? '0' : '') + minutes; }
				ret = ((hours || _endTime >= (1000 * 60 * 60)) ? hours + ':' : '') + minutes + ":" + seconds;
				return ret;
			}

			var classPostFix = _protected.options.ios ? '' : '_sm';
			var _self = _protected.create();
			_this.setEndTime(_endTime);
			//_this.setCurrentTime(444444)
			//_this.setEndTime(888888);
			_protected.scaleToWindow();
			//setTimeout(function () { _this.show(); }, 500)

			var scaleTimer = setInterval(function () { _protected.scaleToWindow() }, 100);

			/////////////////////////////////////////////////////////////////////////
			// ----------------------- Navbar auto hide --------------------------//
			/////////////////////////////////////////////////////////////////////////
			var hideTimerIV = setInterval(function () {
				if (_keepHidden) { return; }
				if (hideTimer <= 0 && !_keepVisible) {
					_self.hide();
				}
				else if (!_timeSliderDragged && !_keepVisible) { hideTimer--; }
				if (showVolume) { _self.find('.volumeslidercontainer').show(); }
				else { _self.find('.volumeslidercontainer').hide(); }
			}, 250);

			_self.find('.ui-slider-handle').removeAttr("href");
			_self.bind('touchmove', function (e) { e.stopPropagation(); e.preventDefault(); })

			_self.find('.volumebutton').bind({
				'mouseenter': function (e) {
					showVolume = true;
					_self.find('.volumeslidercontainer').show();
				},
				'mouseover': function (e) {
					showVolume = true;
					_self.find('.volumeslidercontainer').show();
				}
				//'mouseout': function (e) {
				//	showVolume = false;
				//}
			});
			var outHandler = function (e) {
				showVolume = false;
			}
			_self.find('.volumebutton').bind('mouseout', outHandler);

			_self.find('.volumeslidercontainer').bind({
				'mouseenter': function (e) {
					showVolume = true;
					_self.find('.volumeslidercontainer').show();
				},
				'mouseover': function (e) {
					showVolume = true;
					_self.find('.volumeslidercontainer').show();
				},
				'mousedown': function (e) {
					_self.find('.volumebutton').unbind('mouseout', outHandler);
					$(document).one("mouseup", function () {
						showVolume = false;
						_self.find('.volumebutton').bind('mouseout', outHandler);
					})
				}
			});

			var eX, eY;
			$(document).bind({
				'touchmove': function (e) {
					if (!_timeSliderDragged) { _self.hide(); }
				},
				'touchend': function (e) {
					if (_keepHidden || hideTimer <= 0) { return; }
					_this.show();
				},
				'click': function (e) {
					if (_keepHidden) { return; }
					_this.show();
				},
				'mousemove': function (e) {
					if (eX == e.clientX && eY == e.clientY || _keepHidden) { return; }
					_this.show();
					eX = e.clientX;
					eY = e.clientY;
				}
			});

			if (!_protected.options.ios) {
			_self.bind({
				'mouseenter': function () {
					_this.setKeepVisible(true);
				},
				'mouseleave': function () {
					_this.setKeepVisible(false);
				}
			})
			}

			/////////////////////////////////////////////////////////////////////////
			// ----------------- Fix for jquery ui touch events ------------------//
			/////////////////////////////////////////////////////////////////////////
			if (_protected.options.ios) {
				var _touchStarted = false, _moved = false;

				function simulateEvent(event, newType) {
					if (event.originalEvent.touches.length > 1) {
						return;
					}
					event.preventDefault();

					var touch = event.originalEvent.changedTouches[0], newEvent = document.createEvent('MouseEvents');
					newEvent.initMouseEvent(newType, true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
					event.target.dispatchEvent(newEvent);
				}

				function touchStart(event) {

					if (_touchStarted) {
						return;
					}
					_touchStarted = true;
					_moved = false;

					simulateEvent(event, 'mouseover');
					simulateEvent(event, 'mousemove');
					simulateEvent(event, 'mousedown');
				};

				function touchMove(event) {

					if (!_touchStarted) {
						return;
					}
					_moved = true;

					simulateEvent(event, 'mousemove');
				};

				function touchEnd(event) {

					if (!_touchStarted) {
						return;
					}

					simulateEvent(event, 'mouseup');
					simulateEvent(event, 'mouseout');
					if (!_moved) {
						simulateEvent(event, 'click');
					}
					_touchStarted = false;
				};

				_self.find('.ui-slider, .ui-slider *')
					.bind('touchstart', function (e) { touchStart(e) })
					.bind('touchmove', function (e) { touchMove(e) })
					.bind('touchend', function (e) { touchEnd(e) });
			}

			return _this;
		}
	}
})

upk.player.navBar.prototype = {
	/* event types: 
		onprev,
		onpausetoggle,
		onnext,
		onrefresh,
		onhelp,
		onprefs,
		onvolumeclick,
		onvolumechange (event.volume),
		onsliderchange (event.time),
		onsliderslide (event.time)
	*/
}
