var returnTo;

//var winningPanelTimeoutId;
var signInPanelTimeoutId;
//var winningTickerTimeoutId;
var selectedTab;

$(document).ready(function() {

    //global functions
    subResHover();
    disableLink();
    clearInputs();
    clearPassInputs();
    windowResize();

    // flash are size calculationssssssssaaaaa

    $(window).resize(function() {
        windowResize();
    });

    $('.jsHide').show();

    //page specific functions

    /*$("a.popUp[rel]").overlay({	
    expose: "#000",
    closeOnClick: false,
    closeOnEsc: false
    });*/

    initNavItem();

    //Setup all the update timers
    updateSignInPanelStart();
    //updateWinningPanelStart();
});


function parentGuard() {
    if ($('#guardianName').val() == "") {
        $('li.pGuard').hide();
    }
    $('#yearOfBirth').change(function()
    {
        var currVal = parseInt($(this).val());

        var d = new Date();
        var currYear = d.getFullYear();
        var diffYear = currYear - 17;

        if (currVal <= diffYear)
        {
            $('#guardianName').val("");
            $('li.pGuard').hide();
            return false;
        }
        else
        {
            $('li.pGuard').show();
        }
        return true;
    });
}

function countryShow() {
    if ($('#state').val() != "") {
        $('li.pCountry').hide();
        $('#country').val("");
    }
    else
        $('li.pCountry').show();

    $('#state').change(function() {
        var stateVal = $(this).val();
        if (stateVal == "")
            $('li.pCountry').show();
        else {
            $('li.pCountry').hide();
            $('#country').val("");
        }
    });
}

function infoOverlay(message, isGood) {
    if (isGood) {
        infoOverlay2(message, "/images/elements/img_overlayHeadGood.png");
    }
    else {
        infoOverlay2(message, "/images/elements/img_overlayHeadBad.png");
    }
}

function infoOverlay2(message, imageUrl)
{
    $("#infoOverlayImage").attr("src", imageUrl)
    $("#infoOverlayMessage").html(message.replace(/&lt;/g, "<").replace(/&gt;/g, ">"));
    Cufon.refresh();
    $("#infoOverlay").overlay({
		mask: {
		    color: "#000",
		    maskId: "exposeInfoMask"
		},
		speed: "fast",
		left: "center",
		top: "center",
		load: true,
		onLoad: function(){
		    //Hide the flash as this is an overlay and the flash is running in windowed mode.
		    $(".flashWrapper").css("height", "0px");
		},
		onClose: function(){
		    //Show the flash and then call the callbackFunction
		    $(".flashWrapper").css("height", "596px");
		}
	}).load();
}

function confirmOverlay(message, imageUrl, confirmFunction)
{
    //Hide the flash as this overlay is modal and the flash is running in windowed mode.
    $("#confirmOverlayImage").attr("src", (imageUrl != null && imageUrl != "" ? imageUrl : "/images/elements/img_overlayHeadGood.png"));
    if (imageUrl != null && imageUrl != "") {
			$("#confirmOverlayImage").addClass("acessories");
    } else {
			$("#confirmOverlayImage").removeClass("acessories");
    }
		$("#confirmOverlayMessage").html(message.replace(/&lt;/g, "<").replace(/&gt;/g, ">"));
    $("#confirmOverlay .confirmLink").unbind("click").click(function(e){
        if(e.preventDefault)
        {
            e.preventDefault();
        }
        
        $("#confirmOverlay").overlay().close();
        try
        {
            confirmFunction();
        }
        catch(err)
        {
        }
    });
    
    Cufon.refresh();
    $("#confirmOverlay").overlay({
		mask: {
		    color: "#000",
		    maskId: "exposeConfirmMask"
		},
		speed: "fast",
		left: "center",
		top: "center",
		load: true,
		onLoad: function(){
		    //Hide the flash as this overlay is modal and the flash is running in windowed mode.
		    $(".flashWrapper").css("height", "0px");
		},
		onClose: function(){
		    //Show the flash and then call the callbackFunction
		    $(".flashWrapper").css("height", "596px");
		}
	}).load();
}

//function winningTickerStart()
//{
//	winningTickerStop();
//    winningTickerTimeoutId = window.setTimeout(doTicker, 3000);
//}

//function winningTickerStop()
//{
//	window.clearTimeout(winningTickerTimeoutId);
//}

//function doTicker()
//{
//    if ($("ol.slider li").length > 1 )
//    {
//        $('<div class="tickerTrans"></div>').insertAfter('li.navItem3 div.navContent h2');
//        $("div.tickerTrans").animate({ opacity: '1' }, 500, function() {
//            $("ol.slider li").hide().addClass("hide");
//            $("ol.slider li:last").insertBefore("ol.slider li:first")
//            $("ol.slider li:first").show().removeClass("hide");
//            $("div.tickerTrans").animate({ opacity: "0" }, function() {
//                $(this).remove();
//                winningTickerStart();
//            });
//        });
//    }
//}

function initNavItem()
{
    //navHover();
    
    //$(".navItem > a").unbind("click", navClick);
    //$(".navItem > a").click(navClick);
    $("input.loginButton").unbind("click", login);
    $("input.loginButton").click(login);
    $(".signOutLink").unbind("click", signOut);
    $(".signOutLink").click(signOut);
	
	//login fadeIn
	$(".loginButton").live("click", function(){
		$(".loginForm .login").fadeIn("fast");
    });

    $("a.loginBackButton").live("click", function() {
        $(".loginForm .login").fadeOut("fast");
    });

    ajax.init();
}


//clear inputs


function windowResize() {

		var windowWidth = $(window).width();
		var windowPx = windowWidth + "px";
		if (windowWidth <= 1440) {
			$("div.flashWrapper").css({
				"width": windowPx,
				"left": "auto",
				"marginLeft": "0px"
			})
		}
		else {
			$("div.flashWrapper").removeAttr("style");
		}

}



function clearInputs() {
	$("input#packCode:text,input#stfEmail:text,input#search:text,input.defaultText:text, #ajaxFormDiv input").focus(function() {
			if( this.value == this.defaultValue ) {
					this.value = "";
			}
	 }).blur(function() {
			if( !this.value.length ) {
					this.value = this.defaultValue;
			}
	 });
}


function clearPassInputs() {

	$('div.login div.password').append('<p>Password</p>');

	$('div.login div.password p').click(function(){
		$(this).hide();
		$("input.password").focus();
	});
	
	$('div.login div.password input').focus(function(){
		$(this).next('p').hide();
	});
	
	$("input.password").blur(function() {
			if( !this.value.length ) {
				$('div.login div.password p').show();
			}
	});	

}


//nav hover function

//function navHover() {
//  $(".navItem a.hoverNav").unbind("mouseenter").unbind("mouseleave");
//	$(".navItem a.hoverNav:not('li.active a.hoverNav')").hover(function(){
//	    $(this).parents('li.navItem').addClass("hover");
//	},
//	function(){
//			$(this).parents('li.navItem').removeClass("hover");
//	});
//}

//function navClick() {
//    $(".navItem").removeClass("active");
//    $(".navItem").removeClass("hover");
//    $(this).parent('li').addClass("active");
//    //Cufon.refresh();
//    navHover();
//}

//subRes hover function

function subResHover() {
    $('input.subRes').unbind("mouseenter").unbind("mouseleave");
		$(this).addClass("activeInput");
$('input.subRes').hover(function(){
	},
	function() {
		$(this).removeClass("activeInput");
	});
}

//disable link function

function disableLink() {
   $('a.disabled').unbind("click");
	$('a.disabled').click(function(e){
		e.preventDefault();
	});
}

function scrollToValue(scrollValue, postScrollFunction)
{
    if($.isFunction(postScrollFunction))
    {
        //$('html').animate({scrollTop:scrollValue}, "slow", postScrollFunction);
        $.scrollTo(scrollValue, 600, { axis: 'y', onAfter: postScrollFunction });
	}
	else
	{
	    //$('html').animate({scrollTop:scrollValue}, "slow");
	    //$.scrollTo(scrollValue);
	    $.scrollTo(scrollValue, 600, { axis: 'y' });
	}
}

function setPageTitle(title)
{
    if(title != null && title != "")
    {
        document.title = title;
    }
}

function setMetaTag(name, content)
{
    if(content != null && content != "")
    {
        var mt = $("meta[name=" + name + "]");
        mt = mt.length ? mt : $("<meta name='" + name + "' />").appendTo("head");
        mt.attr("content", content);
    }
}

function setMetaFacebook(imageurl)
{
    if(imageurl != null && imageurl != "")
    {
        var mt = $("link[rel=image_src]");
        mt = mt.length ? mt : $("<link rel='image_src' />").appendTo("head");
        mt.attr("href", imageurl);
    }
}

function getNavItem()
{
    return selectedTab;
}

function getSelectedTabForFlash()
{
    return getNavItem() - 1;
}

function setNavItem(itemNumber)
{
    //$(".navItem").removeClass("active");
	//$(".navItem").removeClass("hover");
	//$(".navItem" + itemNumber).addClass("active");
	//navHover();

    selectedTab = itemNumber;
    // selectedTab - 1 because flash will search its 0 based array
    try { document.getElementById("YogoWorld").selectTabFromJS(getSelectedTabForFlash()); } catch (err) { }
}

function loadAppInWorld(appName)
{
    document.getElementById("YogoWorld").LoadApp(appName);
    if (appName != 'avatareditor')
    {
        gaTrackEvent('Play_games', 'Play', appName);
    }
}

var classicGameLoadedName = "";

function closeClassicGame()
{
    if ($('#classicGameWrapper div.close').css('visibility') != 'hidden')
    {
        // unmute flash world
        document.getElementById("YogoWorld").onBottomPageGameClose();

        classicGameLoadedName = "";
        $('#classicGameWrapper div.close').css('visibility', 'hidden');
        $('#classicGameFlash').remove();
        $('#classicGameWrapper').append("<div id=\"classicGameFlash\"/>").animate({
            height: 0
        }, 750, function()
        {
            $('#classicGameWrapper').css('display', 'none');
            //refreshAjaxPage();
        });
    }
}

function loadClassicGame(appName, appId, version, frameRate, width, height, bgcolor, scrollToContent)
{
	// mute flash world
	document.getElementById("YogoWorld").onBottomPageGameOpen();

	if (classicGameLoadedName == appName)
        return;

    classicGameLoadedName = appName;
    gaTrackEvent('Play_games', 'Play', appName);

    $('#classicGameWrapper').css('display', 'block');
    $('#classicGameWrapper').css('height', '0').animate({
        height: height + 25
    }, 750, function()
    {

        $('#classicGameWrapper div.close').css('visibility', 'visible');
        $('#classicGameWrapper div.close').css('margin-left', (width / 2) - 10);

        var flashVars = {
            appID: appId,
            appPath: "/content/apps/" + appName + "/" + version + "/",
            frameRate: frameRate
        };

        var params = {
            allowScriptAccess: "sameDomain",
            allowFullScreen: "true",
            menu: "false",
            scale: "noscale",
            base: "flash/",
            bgcolor: bgcolor
        };

        var attributes = {
            id: "classicGameFlash",
            name: "classicGameFlash"
        };

        // Version numbers:
        //	Flash 8: 8.0.42.0
        //	Flash 9: 9.0.260.0
        // 	Flash 10: 10.0.45.2
        swfobject.embedSWF("../flash/oldgameloader.swf", "classicGameFlash", width, height, "10.0.45.2", false, flashVars, params, attributes);

        scrollToValue(626, function()
        {
        });
    });
    
}

function loadAvatarEditor()
{
    loadAppInWorld('avatareditor');
    gaTrackPageView('/profile/avatar/');
}

function notifyFlashOfLogin(data)
{
    var strData = data.xml ? data.xml : (new XMLSerializer()).serializeToString(data);
    document.getElementById("YogoWorld").NotifyLogin(strData);
}

function notifyFlashOfLogout()
{
    document.getElementById("YogoWorld").NotifyLogout();
}

function notifyFlashOfGameUnlock(gameName)
{
    document.getElementById("YogoWorld").UnlockGame(gameName);
}

function notifyFlashOfAssetUnlock(assetName) {
    document.getElementById("YogoWorld").UnlockAsset(assetName);
}

function notifyFlashOfYoGoldUpdate(amount) {
    document.getElementById("YogoWorld").UpdateYoGold(amount);
}

function updateSignInPanelStart()
{
    //updateSignInPanelStop();
    signInPanelTimeoutId = window.setTimeout(function(){updateSignInPanel(); updateSignInPanelStart();}, 30000);
}

function updateSignInPanelStop()
{
   window.clearTimeout(signInPanelTimeoutId);
}

function updateSignInPanel() 
{
    ajax.ajaxClickWithCallback("/ajax/signinpaneltop.aspx",
    function(xhr) {
        return true;
    },
    function(o) {
        $("#headerSignIn").html(o);
        //signInPanelInit();
        /*Cufon.replace('.profileBox span.userName ', {
            fontFamily: 'frutigerBC'
        });*/
    },
    function() {
        return;
    });    
}

function signInPanelInit() {
    //console.log('signInPanelInit()');
    //navHover();

    //$(".navitem1 a.hoverNav").unbind("click", navClick);
    //$(".navitem1 a.hoverNav").click(navClick);
    $("#headerSignIn input.loginButton").unbind("click", login);
    $("#headerSignIn input.loginButton").click(login);
    $(".signOutLink").unbind("click", signOut);
    $(".signOutLink").click(signOut);

    $("input#loginEmail").unbind("keydown");
    $("input#loginEmail").keydown(function(e) {
        if (e.which == 13) {
            login();
        }
    });

    $("input#loginPassword").unbind("keydown");
    $("input#loginPassword").keydown(function(f) {
        if (f.which == 13) {
            login();
        }
    });

    var topMessage = $("#headerSignIn div.headerMessage").clone();
    $("#headerTopBar").empty(); 
    $("#headerTopBar").append(topMessage);
    if ($("#headerTopBar div.headerMessage").children().size() > 0) {
        $("#headerTopBar div.headerMessage").css('display', 'block');
    }
    else {
        $("#headerTopBar div.headerMessage").css('display', 'none');
    }

    clearInputs();
    
    ajax.init();
}

//function updateWinningPanelStart()
//{
//    updateWinningPanelStop();
//    winningPanelTimeoutId = window.setTimeout(function() {updateWinningPanel(); updateWinningPanelStart();}, 60000);
//}

//function updateWinningPanelStop()
//{
//    window.clearTimeout(winningPanelTimeoutId);
//}

//function updateWinningPanel(restartTimeout)
//{
//    var restart = true;
//    
//    if(restartTimeout)
//    {
//        restart = restartTimeout;
//    }
//    
//    ajax.ajaxClickWithCallback("/ajax/latestgameplays.aspx",
//    function(xhr){
//        return true;
//    },
//    function(o){
//        $(".navItem3").html(o);
//        initNavItem();
//        if(restart)
//        {
//            updateWinningPanelStart();
//        }
//    },
//    function(){
//        return;
//    });
//}

//function winningPanelInit()
//{
//    navHover();
//    
//    $(".navItem2 a.hoverNav").unbind("click", navClick);
//    $(".navItem2 a.hoverNav").click(navClick);
//    
//    ajax.init();
//}

function login(e)
{
    if(e && e.preventDefault)
    {
        e.preventDefault();
    }
    
    gaTrackPageView('/login/');
    
    var email = $("#loginEmail").val();
    var password = $("#loginPassword").val();
    var remember = $("#loginRemember").is(':checked');
    
    //Validate email and password
    if(email != null && email != "" && email != "Email" &&
        password != null && password != "") {

        var data = {email: email, password: password, remember: remember};
        ajax.ajaxClickWithCallback("/flashscripts/login.aspx"/*?email="+email+"&password="+password*/, function(xhr){return true;}, loginSuccess, loginError, null, data);
    }
    else
    {
        infoOverlay("Please enter a valid email address and password to login.");
        gaTrackEvent('Login', 'Login', 'Validation_error');
    }
}

function loginSuccessDo(data, status, xhr, register) 
{
    var statusCode = $("status", data).text();

    if (statusCode == "1") {
        updateSignInPanel();
        try { notifyFlashOfLogin(data); } catch (err) { }
        var shortNickname = $("shortnickname", data).text();
        var activated = !!(parseInt($("hasactivated", data).text()));
        var haseveractivated = !!(parseInt($("haseveractivated", data).text()));
        var profileUrl = "/profile/" + shortNickname + "/";
        profileUrl = unescape(profileUrl);
        var ajaxUrl = getCurrentAjaxUrl();
        jQuery.history.load(profileUrl, ajax.defaultContainer);

        if (!activated && !register) 
        {
            if (!haseveractivated)
                loginShowNeverActivatedMessage();
            else
                loginShowNotActivatedMessage();
        }
    }
    else {
        var errorMessage = "";
        var errorList = $("error", data);
        errorList.each(function() {
            errorMessage += $(this).text() + "\n";
        });
        infoOverlay(errorMessage);
    }
}

function loginShowNotActivatedMessage() {
    setTimeout(function() {
        infoOverlay2("Please click the link we emailed you to confirm your email address.", "/images/elements/img_overlayHeadBad.png")
    }, 1000);
}

function loginShowNeverActivatedMessage() {
    setTimeout(function() {
        infoOverlay2("If you activate your account you can earn bonus YoGold!", "/images/elements/img_overlayYoGold.png")
    }, 1000);
}

function loginSuccess(data, status, xhr) 
{
    gaTrackPageView("/login/successful/");
    loginSuccessDo(data, status, xhr, false)
}

function loginRegister(data, status, xhr) 
{
    gaTrackPageView("/signup/thankyou/");
    loginSuccessDo(data, status, xhr, true)
}

function loginError(xhr, status, errorThrown)
{
    infoOverlay("Sorry, we couldn't log you in. Please try again later.");
}

function signOut(e)
{
    if(e.preventDefault)
    {
        e.preventDefault();
    }

    gaTrackPageView('/logout/');
    
    $.get("/flashscripts/logout.aspx", function(){
            updateSignInPanel();
            try{notifyFlashOfLogout();}catch(err){}
        });
}

function unlockGame(gameShortName)
{
    //Insert the loading panel into the target container
    /*var parentElement = jQuery(ajax.defaultContainer).parent();
    var parentHeight = parentElement.height() + "px";
    parentElement.append("<div class='trans' style='padding-top:" + ((parentElement.height()/2) - 50) + "px;'><p align='center'><img src='/images/elements/ajax-loader.gif' align='center' /></p></div>");
    jQuery("div.trans").css("height", parentHeight);
    jQuery("div.trans").animate({opacity: 1}, 300, function() {*/
        ajax.ajaxClickWithCallback("/flashscripts/unlockgame.aspx?game="+gameShortName, function(xhr){return true;}, unlockGameSuccess, unlockGameError, gameShortName);
    //});
}

function unlockGameSuccess(data, status, xhr, sender)
{
    var statusCode = $("status", data).text();
    if (statusCode == "1")
    {
        var transaction = $("transaction", data);
        var gameName = transaction.attr("gamename");
        infoOverlay("This game is now unlocked.", true);
        try{notifyFlashOfGameUnlock(sender);}catch(err){}
        refreshAjaxPage();
        gaTrackEvent('Play_games', 'Unlocked', gameName);
    }
    else
    {
        var errorMessage = "";
        var errorList = $("error", data);
        errorList.each(function(){
            errorMessage += $(this).text() + "\n";
        });
        infoOverlay(errorMessage);
    }
}

function unlockGameError(xhr, status, errorThrown, sender)
{
    infoOverlay("Sorry, there was an error while trying to unlock this game. Please try again later.");
}

function getCurrentAjaxUrl()
{
    var ajaxUrl = location.hash.replace(/^.*#/, "");

    if (ajaxUrl == "")
    {
        //We don't have an ajax url, so try to grab only the path and query of the current url
        var fullUrl = location.href.replace("http://", "").replace("https://", "");
        var pathIndex = fullUrl.indexOf("/");
        if (pathIndex >= 0)
        {
            ajaxUrl = fullUrl.substring(pathIndex);
        }
    }

    if (ajaxUrl == "#" || ajaxUrl == "/#")
    {
        ajaxUrl = "/";
    }

    ajaxUrl = unescape(ajaxUrl);

    return ajaxUrl;
}

function refreshAjaxPage() {
    var ajaxUrl = getCurrentAjaxUrl();

    if (ajaxUrl)
    {
        loadAjaxPage(ajaxUrl, false);
    }
}

function loadAjaxPage(url, scrollToContent)
{
    unescapedUrl = unescape(url);
    
    if (scrollToContent) {
        scrollToValue(626, function() {
            jQuery.history.load(unescapedUrl, ajax.defaultContainer);
        });
    }
    else
    {
        jQuery.history.load(unescapedUrl, ajax.defaultContainer);
    }
}

function raiseFlashEvent(nickname, eventName, eventLabel)
{
    if (!eventName)
    {
        return;
    }

    var ajaxUrl = getCurrentAjaxUrl();
    var refresh = false;
    var refreshSignIn = false;
    nickname = hexEncode(nickname);
    

    if (eventName == "avatarsaved")
    {
        if (nickname)
        {
            if (ajaxUrl == "/profile/" + nickname + "/")
            {
                //The avatar has been saved by the flash and we are on a page that shows avatars.
                refresh = true;
            }
        }
        refreshSignIn = true;
    }
    else if (eventName == "accessorybought")
    {
        if (nickname)
        {
            if (ajaxUrl == "/profile/" + nickname + "/")
            {
                //An accessory has been bought in the flash and we are on that player's profile page.
                refresh = true;
            }
        }
        refreshSignIn = true;
    }
    else if (eventName == "awardachieved" || eventName == "gameunlocked" || eventName == "gamesaved")
    {
        if (eventLabel)
        {
            if (ajaxUrl == "/profile/" + nickname + "/" || ajaxUrl == "/games/" + eventLabel + "/")
            {
                refresh = true;
            }
        }
        refreshSignIn = true;
    }

    if (refresh)
    {
        refreshAjaxPage();
    }

    if (refreshSignIn) 
    {
        updateSignInPanel();
    }
}

function loadPopupPage(url)
{
    var popup = window.open(url, "popup", "width=700,height=510,status=0,resizable=0,menubar=0,location=0,scrollbars=1");
    popup.focus();
}


function listPaging(listClass) {
	$("ul." + listClass + " li:gt(5)").hide();

	$("div." + listClass + "_paging a").click(function()
	{
		if ($(this).hasClass("disabled")){
			return false;
		} 
		if ($(this).hasClass("prev"))  {

		    var numberVis = $("ul." + listClass + " > li:visible").length;

		    var lastVis = $("ul." + listClass + " > li:visible").last().index() + 1;
			var firstVis = 	lastVis - numberVis;
			var firstHidden = firstVis - 6; 
			
			//alert(lastVis);
			//alert(firstVis);
			//alert(firstHidden);

			$("ul." + listClass).find('li').slice(firstVis, lastVis).hide();
			$("ul." + listClass).find('li').slice(firstHidden, firstVis).show();		
			
			disabledCheck(listClass)
		} 
		else if ($(this).hasClass("next")) {

		    var firstVis = $("ul." + listClass + " li:visible").first().index();
		    var lastVis = $("ul." + listClass + " li:visible").last().index() + 1;
			var lastHidden = lastVis + 6

			$("ul." + listClass).find('li').slice(firstVis, lastVis).hide();
			$("ul." + listClass).find('li').slice(lastVis, lastHidden).show();

			disabledCheck(listClass);
        }
        return false;
	});
}

function disabledCheck(listClass)
{
    $("div." + listClass + "_paging > a.disabled").removeClass("disabled");

    if ($("ul." + listClass + " > li:last").is(':visible'))
    {
        $("div." + listClass + "_paging > a.next").addClass("disabled");
	}
	if ($("ul." + listClass + " > li:first").is(':visible'))
	{
	    $("div." + listClass + "_paging > a.prev").addClass("disabled");
	}
}

/* Hexadecimal conversion methods.
* Copyright (c) 2006 by Ali Farhadi.
* released under the terms of the Gnu Public License.
* see the GPL for details.
*
* Email: ali[at]farhadi[dot]ir
* Website: http://farhadi.ir/
*/

//Encodes data to Hex(base16) format
function hexEncode(data)
{
    var b16_digits = '0123456789abcdef';
    var b16_map = new Array();
    for (var i = 0; i < 256; i++)
    {
        b16_map[i] = b16_digits.charAt(i >> 4) + b16_digits.charAt(i & 15);
    }

    var result = new Array();
    for (var i = 0; i < data.length; i++)
    {
        result[i] = b16_map[data.charCodeAt(i)];
    }

    return result.join('');
}

//Decodes Hex(base16) formated data
function hexDecode(data)
{
    var b16_digits = '0123456789abcdef';
    var b16_map = new Array();
    for (var i = 0; i < 256; i++)
    {
        b16_map[b16_digits.charAt(i >> 4) + b16_digits.charAt(i & 15)] = String.fromCharCode(i);
    }
    if (!data.match(/^[a-f0-9]*$/i)) return false; // return false if input data is not a valid Hex string

    if (data.length % 2) data = '0' + data;

    var result = new Array();
    var j = 0;
    for (var i = 0; i < data.length; i += 2)
    {
        result[j++] = b16_map[data.substr(i, 2)];
    }

    return result.join('');
}
