// $Id: moxow.js 2688 2012-01-25 12:50:08Z sdalu $
// Requires: jquery, jquery.task, jquery.cookie
//


//
// Copyright (c)  Stephane D'Alu  2008-2012
// http://www.sdalu.com/
//

;
var MoXoW = (typeof module !== "undefined" && module.exports) || {};

(function(exports) {
exports.name       		= "moxow.js";
exports.version    		= "0.5.0";
exports.setOptions 		= setOptions;
exports.lang_switch_by_cookie 	= lang_switch_by_cookie;
exports.make_button		= make_button;
exports.message			= message;
exports.menutab			= menutab;
exports.toc			= toc;
exports.closable_box		= closable_box;
exports.getLang                 = getLang;
exports.cookie			= cookie;

var options = { cookie : { domain  : null,
			   expires : null,
			   path    : null },
		lang   : null 
	      };


function cookie(key, val, opts) {
    return arguments.length > 1
	? $.cookie(key, val, $.extend({}, options.cookie, opts))
        : $.cookie(key);
}

function getLang() {
    return options.lang;
}

//----------------------------------------------------------------------
// Set options for:
//  - cookie (expires, path, domain)
//  - lang
//----------------------------------------------------------------------
function setOptions(opts) {
    if (!opts) return;
    $.extend(true, options, opts)
};



//----------------------------------------------------------------------
// Language switching by cookie
//   => In menu language, don't follow links but set cookie for
//      language preference and reload current page
//----------------------------------------------------------------------
function lang_switch_by_cookie(id) {
    if (! $.cookie) return;
    $('#'+id + ' a').on('click', function(evt) {
	evt.preventDefault();

	var key  = 'language';
	var lang = $(evt.target).closest('a').attr('hreflang');
	if (lang.length) $.cookie(key, lang, {
		             domain : options.cookie.domain,
		             path   : '/',
		             expires: options.cookie.expires });
	else
	    $.cookie(key, null);
	window.location.reload();
 });
};



//----------------------------------------------------------------------
// Mark all button (.m-button) as unselectable
//----------------------------------------------------------------------
function make_button() {
    $('.m-button').each(function() { this.unselectable = 'on'; });
};


//----------------------------------------------------------------------
// Display short messages
//----------------------------------------------------------------------
function message() {
    var msgs   = [];
    var msg, active;

    var update  = function() {
	if (active.rel) 
	    msg.attr('rel', active.rel);
	msg.attr('href', active.url).html(active.text).fadeIn();
    };

    var showmsg = function(idx) {
	if (msg.hasClass('hover')) return;
	active = msgs[idx];
	if (msg.is(':visible')) msg.fadeOut(update);
	else update(); 
    };

    return {
    init  : function(id) {
	msg = $('<a/>')
	    .on('mouseenter', function() { msg.addClass('hover');    })
	    .on('mouseleave', function() { msg.removeClass('hover'); })
	    .appendTo($('#' + id));					  },
    start : function(msec) {
        var index = 0;
	showmsg(0);
	setInterval(function() {
	   showmsg(index = msgs[index+1] ? index+1 : 0); }, msec);        },
    add   : function(cfgs) {
        cfgs.forEach(function(cfg) {
	    if (options.lang && cfg.lang && (options.lang != cfg.lang))
		return false;
	    if (cfg == '-') msgs = [];
	    else            msgs.push(cfg); });  			  },
    clear : function() {
	msgs = [];                                                        }
    };
};



//----------------------------------------------------------------------
// Handle menu
//----------------------------------------------------------------------
function menutab() {
    var shown    = null;	
    var hideMenu = function() { 
	if (shown) { shown.hide(); shown = null; } };
    var later    = $.task();

    return {
    attach: function(name){
	var tab  = $('#menu-tab-'+name);
	var sub  = $('#menu-sub-'+name);
	if (!tab.length || !sub.length) return;

        tab.on('mouseenter', function() {
	    later.cancel(); 
	    if (shown == sub) return;
	    hideMenu();
	    shown = sub.css({ left: 0, top: '2px' }).show();
	    var off = sub.offset().left + sub.outerWidth(true)
		    - $(window).width();
	    if (off > 0)
		sub.offset({ left :$(window).width() - sub.outerWidth(true) });
	});
	tab.on('mouseleave', function() {
	    later.cancel().task(hideMenu).delay(); 
	});
    }
    };
};



//----------------------------------------------------------------------
// Closable box
//----------------------------------------------------------------------
function toc(box_id, toggler_id, opts) {
    var idcount = 0;
    var content = $('#main-content');
    
    var root    = ol = $('<ol/>');
    var stack   = [ root ];
    var current = 1;
    
    content.find('h1,h2,h3').each(function() {
	var lvl;
	
	// Which level? (XXX: IE doesn't support toLowerCaser())
	switch(this.nodeName) {
	case 'H1': case 'h1': lvl = 1; break;
	case 'H2': case 'h2': lvl = 2; break;
	case 'H3': case 'h3': lvl = 3; break;
	}
	
	// Build link
	if (!this.id) 
	    this.id = 'toc-gen-' + idcount++;
	var a    = $('<a/>' ).attr('href', '#' + this.id)
                             .append($(this).html());
	var link = $('<li/>').append(a);
	
	if        (current > lvl) {
	    for ( ; current > lvl ; current-- ) {
		stack.pop();
		ol = stack[stack.length-1];
	    }
	} else if (current < lvl) {
	    for ( ; current < lvl ; current++ ) {
		var n = $('<ol/>');
		stack.push(n);
		var c = ol.children();
		var count = c.length;
		if (count > 0) {
		    $(c[count-1]).append(n);
		} else {
		    ol.addClass('m-toc-nodata')
		    ol.append($('<li/>').append(n));
		}
		ol = n;
	    }
	}
	// Add
	ol.append(link);	
    });

    toc = $('#' + box_id);
    root.attr('id', toc.attr('id'));
    toc.replaceWith(root);
    toc = $('#' + box_id);

    $('#' + toggler_id)
	.css({ cursor: 'pointer' })
	.on('click', function() { toc.parent().toggleClass('collapsed'); });
};



//----------------------------------------------------------------------
// Closable box
//----------------------------------------------------------------------

/*
 * box_id   : id of the element container
 * close_id : id of the element used as close button
 * opts     : options
 *   - key      : cookie key (global if starting with '/')
 *   - reset    : cookie expiration in hours
 *   - start    : only show notify after 'start' seconds
 *   - autoclose: secondes before automatically closing
 *   - show     : hover = when hovering box_id
 *                *     = always on
 */
function closable_box(box_id, close_id, opts) {
    opts = $.extend({
	    key       : null,
	    reset     : null,
	    start     : 0,
	    autoclose : 0,
	    show      : 'always' }, opts || {});

    var box          = $('#' + box_id  );
    var btn          = $('#' + close_id);

    if ($.cookie && opts.key && 
	$.cookie(opts.key[0] == '/' ? opts.key.substring(1) : opts.key)) {
	box.remove();
	return;
    }
    var remaining = null;
    var closer    = $.task(function() {
        if (remaining) { remaining.cancel();
			 remaining = null;	}
	box.hide();
       
	if ($.cookie && opts.key) {
	    var cookie_opts = {};
	    var key         = opts.key;
	    if (opts.reset) {
		cookie_opts.expires = new Date(new Date().getTime() +
					       opts.reset*60*60*1000);
	    }
	    if (key && (key[0] == '/')) {
		cookie_opts.path = '/';
		key              = key.substring(1);
	    }
	    cookie_opts = $.extend({}, options.cookie, cookie_opts);
	    $.cookie(key, false, cookie_opts);
	}
    });
    
    if (btn.length) {
	btn.on('click', function() { closer.now() });

	switch(opts.show) {
	case 'hover':
	    btn.hide();
	    box.removeClass('m-hidden');
	    box.on('mouseenter',  function() { btn.fadeIn() });
	    box.on('mouseleave',  function() { btn.fadeOut() });
	    break;
	}
    }

    function do_autoclose() {
	if (opts.autoclose <= 0) return;
	if (btn.length) {
	    remaining = $.task.repeated(function() {
		var sec = opts.autoclose - this.count();
                btn.find('.m-autoclose-value').html(sec.toString()) });
	    remaining.start(1000, opts.autoclose);
	}
	closer.delay(opts.autoclose * 1000);
    }

    if (opts.start > 0) {
	box.hide().removeClass('m-hidden');
	$.task(function() { box.fadeIn(do_autoclose); })
	 .delay(opts.start * 1000);
    }  else {
	do_autoclose();
    }
};

})(MoXoW);
