/*
 * Javascript functionality for Starlight Development Guide.
 *
 * This powers the dynamic parts of the guide.
 *
 * This requires jquery Javascript framework. The examples in the guide do
 * not require jquery - the examples only use the generic utility functions
 * below.
 *
 */
function main() {
    $("div#container > table tr:odd").addClass("odd");

    $("div.case").each(function(){
        var t = $(this);
        var html = $("div.html textarea", t).val();
        if (t.hasClass("frame"))
            var elem = $('<div class="usecase"></div>');
        else
            var elem = $('<div class="playground"></div>');
        elem.append(html);

        t.append(elem);
        if (t.hasClass("frame"))
            elem.wrap('<div class="phoneframe"></div>');
    });

    $("div.case div.css").each(function(){
        var t = $(this);
        var elem = '<input type="button" class="run apply" value="Apply" />';
        t.append(elem);
        var elem = '<input type="button" class="run remove" value="Remove" />';
        t.append(elem);
        var elem = '<input type="button" class="run edit" value="Edit" />';
        t.append(elem);
    });

    $("div.case div.javascript").each(function(){
        var t = $(this);
        var elem = '<input type="button" class="apply" value="Apply" />';
        t.append(elem);
        var elem = '<input type="button" class="edit" value="Edit" />';
        t.append(elem);
    });

    // green "active" title in code without action
    $("div.code").each(function(){
        var t = $(this);
        if ($("input", t).length == 0)
            t.addClass("active");
    });

    $("div.code input.edit").click(function() {
        var div = $(this).closest("div.code");
        var h = $("pre:first", div).height();
        $("table, input.edit", div).hide();
        $("textarea", div).height(h+25).show();
    });
    $("div.code input.apply").click(function() {
        var div = $(this).closest("div.code");
        div.addClass("active");
        var divCase = $(this).closest("div.case");
        var val = $("textarea", div).val();
        if (div.hasClass("css")) {
            applyCSS(val, div);
        } else {
            applyJS2(val, divCase);
        }
    });
    $("div.css input.remove").click(function() {
        var div = $(this).closest("div.code");
        div.removeClass("active");
        removeCSS(div);
    });

    $("div.playground, div.phoneframe").each(function(){
        var t = $(this);
        t.before("<br/>");

        setTimeout(function() {
            // some images may be larger, enlarge playground
            var img = $("img", t);
            var h1 = t.height();
            var h2 = img.height();
            if (h2 > h1)
                t.height(h2+10);
        }, 1000);
    });

    $("a.teaserlink").click(function() {
        startGame();
        return false;
    });

    detectBrowser();
}

function applyCSS(cssStr, divCode) {

    var thiscase = divCode.closest("div.case");

    // remove all other styles in the doc first!
    $("div.case").each(function(){
        if (this != thiscase.get(0)) {
            $("style", this).remove();
        }
    });

    // remove comments, can't have comments!
    cssStr = cssStr.replace(/\/\/.*/g, "");

    var style = $('<style type="text/css">'+cssStr+'</style>');

    $("style", divCode).remove();
    divCode.append(style);
}
function removeCSS(divCode) {
    $("style", divCode).remove();
}
function applyJS2(js, divCase) {
    // first unbind all events, so they don't cumulate
    // unbinding is done by refilling playground with fresh html
    var html = $("div.html textarea", divCase).val();
    var play = $("div.playground, div.usecase", divCase);
    play.html(html);

    // then load new javascript
    load_js(js);
}

// load javascript
function load_js(code) {
  var dj_global = this; // global scope reference
  if (window.execScript) {
    window.execScript(code); // eval in global scope for IE
    return null; // execScript doesn't return anything
  }
  return dj_global.eval ? dj_global.eval(code) : eval(code);
}

// detect browser and display some messages
function detectBrowser() {
    // find the paragraphs from doc
    var cssok = $("a#browsercssok").parent();
    var touchok = $("a#browsertouchok").parent();
    var bad = $("a#browsernotok").parent();

    var isCssOk = false;
    var isTouchOk = false;
    var agent = navigator.userAgent;

    if (/WebKit/.test(agent) && /Version\/4/.test(agent))
        isCssOk = true;
    else if (/Chrome/.test(agent))
        isCssOk = true;
    else if (/WebKit/.test(agent) && /QtLauncher/.test(agent))
        isTouchOk = true;
    else if (/WebKit/.test(agent) && /Starlight/.test(agent))
        isTouchOk = true;

    // alert(agent);

    if (!isCssOk && !isTouchOk) {
        cssok.hide();
        touchok.hide();
        bad.addClass("browsernotok");
    } else if (isCssOk) {
        bad.hide();
        touchok.hide();
        cssok.addClass("browsercssok");
    } else {
        bad.hide();
        cssok.hide();
        touchok.addClass("browsertouchok");
    }

}


/* util funcs, used by examples and documented in guide */
//--------------------------------------------------------------------------
// show and hide an elem
function show(elem) {
    elem.style.display = 'block';
}
function hide(elem) {
    elem.style.display = 'none';
}
// adds a class to an element
function addClass(elem, className) {
    if (!hasClass(elem, className)) {
        var cl = ""+elem.className;
        elem.className += (cl.length>0 ? " " : "") + className;
    }
}
// removes a class from an element
function removeClass(elem, className) {
    if (hasClass(elem, className)) {
        var reg = new RegExp('(\\s|^)'+className+'(\\s|$)');
        elem.className = elem.className.replace(reg, ' ');
    }
}
// does elem has a class?
function hasClass(elem, className) {
    var reg = new RegExp("(^|\\s)" + className + "(\\s|$)");
    return reg.test(elem.className);
}
// get next elem
function nextelem(elem) {
    var sib = elem.nextSibling;
    while (sib && sib.nodeType != 1)
        sib = sib.nextSibling;
    return sib;
}
// get previous elem
function prevelem(elem) {
    var sib = elem.previousSibling;
    while (sib && sib.nodeType != 1)
        sib = sib.previousSibling;
    return sib;
}
// finds an element of desired type above
function parentElem(elem, tagtype) {
    var p = elem.parentNode;
    tagtype = tagtype.toUpperCase();
    while (p && p.nodeName != tagtype)
        p = p.parentNode;
    return p;
}
// returns position of element, CSS left and top
function getPos(elem) {
    var o = {};
    var computedStyle = document.defaultView.getComputedStyle(elem, null);
    o.left = parseInt(computedStyle.getPropertyValue("left"));
    o.top = parseInt(computedStyle.getPropertyValue("top"));
    o.height = parseInt(computedStyle.getPropertyValue("height"));
    o.width = parseInt(computedStyle.getPropertyValue("width"));
    return o;
}

