//
// Copyright (c) 2002,2003 ComponentOne L.L.C. All rights reserved.
// Version 1.0.20041.28, 23-Feb-2004.
//
// Implementation notes:
//
// Two kinds of elements are involved in menu tracking logic: menus
// and menu items. Both kinds are HTML elements, menu items are
// contained in menus in HTML (in the current realization menu items
// are immediate children of menus, and that fact is significant for
// the functioning of the system). Menu items may contain nested
// elements but these are opaque to the menu tracking. Submenus are
// NOT nested inside their parent items or menus in HTML.
//
// A form may contain several root (always shown) menus. Only one root
// menu can be active at a time (an active menu is the one with a
// selected item and/or an open submenu; if there is a selected item
// and an open menu, both must belong to the same root). At any given
// moment, the global c1c_active_menu variable contains the currently
// active root menu, or null if there is none.
//
// A menu can have zero or one selected item. In each menu, the member
// c1_sel_item points to that item, or is null if the menu does not
// have a selected item at the moment.
//
// A menu can have at most one item with an open submenu. Most often,
// this is the selected item, but that need not be true always. In
// each menu, c1_menu_item points to the item with the currently open
// submenu, or is null if there is none.
//
// Items with associated submenus have c1_submenu_id specified in HTML
// which does not change and contains the id of the submenu element.
// If an item has a submenu open, it has a member c1_submenu pointing
// to that menu. In the menu, menu.c1_parent_item points back to the
// item.
//
// List of custom element attributes used by this code:
//
// Static (should be present in html):
//   - menu.c1_horz (true/false)
//   - menu.c1_sel_item_styles
//   - menu.c1_item_styles
//   - menu.c1_sel_item_styles_class
//   - menu.c1_item_styles_class
//   - item.c1_submenu_id
//   - item.c1_sel_item_styles
//   - item.c1_item_styles
//   - item.c1_sel_item_styles_class
//   - item.c1_item_styles_class
//   - item.c1_img_src
//   - item.c1_img_sel_src
//   - item.c1_status
//
// Dynamic (created at runtime):
//   - menu.c1_menu_item
//   - menu.c1_sel_item
//   - menu.c1_parent_item
//   - item.c1_submenu
//   - item.c1_img
//   - item.c1_img_sel
//

// the currently active root menu
var c1c_active_menu = null;
// true if we are tracking menus
var c1c_tracking_menus = false;
// menu pop down delay (ms); change as needed
var c1c_menu_popdown_delay = 500;
// arbitrary large z-index for popup menus (set to 0 to disable)
var c1c_submenu_zindex = 32000;
// initialization code was executed
var c1c_initialized = false;


// mousedown handler for outside of menus clicks
function c1c_doc_onmousedown(ev)
{
    c1c_init();
    var src = null;
    if (ev.srcElement)
        src = ev.srcElement;
    else if (ev.target)
        src = ev.target;
    // ignore mouse down on menus (handled by c1c_onmousedown)
    while (src && src.parentNode) {
        if (src.c1_submenu || c1c_getattr(src, 'c1_submenu_id'))
            return;
        if (src.c1_sel_item)
            return;
        src = src.parentNode;
    }
    // remove any popup menus, unselect items
    popdown_and_unselect(c1c_active_menu);
    c1c_active_menu = null;
}

// mouseup fires after the click (which is when the menu action
// is run), and we hide menus here unless we've clicked a menu
// with a submenu
function c1c_doc_onmouseup(ev)
{
    c1c_init();
    var src = null;
    if (ev.srcElement)
        src = ev.srcElement;
    else if (ev.target)
        src = ev.target;
    // ignore mouse up on items with submenus
    while (src && src.parentNode) {
        if (src.c1_submenu || c1c_getattr(src, 'c1_submenu_id'))
            return;
        src = src.parentNode;
    }
    popdown_and_unselect(c1c_active_menu);
    c1c_active_menu = null;
}

// this function is attached to mousedown of menu items
// that do not have other handlers (postback or script)
function c1c_onmousedown(ev, item)
{
    c1c_onmouseover(ev, item);
}

function c1c_onclick(ev, item)
{
    c1c_onmouseover(ev, item);
}

// mouseover for menu items
function c1c_onmouseover(ev, item)
{
    c1c_init();
    var src = null;
    if (ev.srcElement)
        src = ev.srcElement;
    else if (ev.target)
        src = ev.target;
    if (src != item && !c1c_object_contains(item, src))
        return;
    c1c_select_item(item);
}

// mouseout for menu items
function c1c_onmouseout(ev, item)
{
    c1c_init();
    var tgt;
    if (ev.relatedTarget)
        tgt = ev.relatedTarget;
    else if (ev.toElement)
        tgt = ev.toElement;
    if (!tgt || (tgt != item.c1_submenu && !c1c_object_contains(item.c1_submenu, tgt))) {
        c1c_unselect_item(item);
    }
}

// close any open menus if we moused out of a menu
// (the arg is one for a "mouseout" of a menu event)
function c1c_popdown_if_out()
{
    if (!c1c_tracking_menus && c1c_active_menu) {
        popdown_and_unselect(c1c_active_menu);
        c1c_active_menu = null;
    }
}

// mouseout for submenus
function c1c_onmouseout_submenu(ev, submenu)
{
    // Find out where to the mouse's gone. If it has moved out
    // of the menus altogether, register a timed handler which
    // will pop down all menus after a while.
    var tgt;
    if (ev.relatedTarget)
        tgt = ev.relatedTarget;
    else if (ev.toElement)
        tgt = ev.toElement;
    // do nothing if we still are in a menu
    while (tgt && tgt.parentNode) {
        if (tgt == c1c_active_menu || c1c_getattr(tgt, 'c1_parent_item'))
            return;
        tgt = tgt.parentNode;
    }
    // if we got here, we are not in a menu
    c1c_tracking_menus = false;
    if (window.setTimeout)
        window.setTimeout('c1c_popdown_if_out()', c1c_menu_popdown_delay);
    else
        c1c_popdown_if_out();
}

function c1c_select_item(item)
{
    c1c_tracking_menus = true;
    var menu = item.parentNode;
    // if the currently selected item is the same as the new selection, nothing to do
    if (menu.c1_sel_item == item)
        return;
    // otherwise, if there is a selected item, unselect it
    if (menu.c1_sel_item) {
        c1c_unselect_item(menu.c1_sel_item);
        c1c_tracking_menus = true;
    }
    // if there is an open submenu, hide it
    if (menu.c1_menu_item && menu.c1_menu_item != item)
        c1c_popdown_item_menu(menu.c1_menu_item)
    // show item status message
    var st = c1c_getattr(item, 'c1_status');
    if (st)
        window.status = st;
    // if we're selecting an item in a root menu,
    if (!menu.c1_parent_item) {
        // ..and there is a selected item in another root menu, unselect it and hide any menus
        if (c1c_active_menu && c1c_active_menu != menu) {
            popdown_and_unselect(c1c_active_menu);
            c1c_active_menu = null;
        }
    }
    else {
        // make sure the parent item is selected
        if (menu.c1_parent_item.parentNode.c1_sel_item != menu.c1_parent_item)
            c1c_select_item(menu.c1_parent_item);
    }
    // if the item to be selected has a submenu, show it
    c1c_popup_item_menu(item);
    // redraw the item to be selected using selected style
    c1c_hilite_item(item, true);
    // store the new selected item in its menu
    menu.c1_sel_item = item;
    // update the global c1c_active_menu var if needed.
    if (c1c_active_menu == null)
        c1c_active_menu = menu;
    c1c_tracking_menus = true;
}

function c1c_unselect_item(item)
{
    // if the item has an open submenu, hide it
    if (c1c_getattr(item, 'c1_submenu_id')) {
        if (window.setTimeout)
            window.setTimeout('c1c_popdown_item_menu_delayed("' + item.id + '")', c1c_menu_popdown_delay);
        else
            c1c_popdown_item_menu(item);
    }
    // redraw item in normal style
    c1c_hilite_item(item, false);
    // remove status
    if (c1c_getattr(item, 'c1_status'))
        window.status = '';
    // store the fact that there is no selection in the menu
    if (item.parentNode.c1_sel_item == item)
        item.parentNode.c1_sel_item = null;
    // update the global c1c_active_menu var if needed.
    if (c1c_active_menu == item.parentNode && !c1c_active_menu.c1_menu_item)
        c1c_active_menu = null;
}

// pops up item's submenu
function c1c_popup_item_menu(item)
{
    var submenu_id = c1c_getattr(item, 'c1_submenu_id');
    if (submenu_id) {
        var submenu = document.getElementById(submenu_id);
        if (submenu) {
            c1c_show_submenu(item, submenu);
            item.c1_submenu = submenu;
            submenu.c1_parent_item = item;
            item.parentNode.c1_menu_item = item;
        }
    }
}

function c1c_popdown_item_menu_delayed(id)
{
    var item = document.getElementById(id);
    if (item && item.parentNode.c1_sel_item != item)
        c1c_popdown_item_menu(item);
}

// pops down item's submenu
function c1c_popdown_item_menu(item)
{
    var submenu = item.c1_submenu;
    if (submenu) {
        // recursively unselect and pop down all nested menus
        if (submenu.c1_menu_item)
            c1c_popdown_item_menu(submenu.c1_menu_item);
        if (submenu.c1_sel_item)
            c1c_unselect_item(submenu.c1_sel_item);
        c1c_hide_submenu(submenu);
        submenu.c1_parent_item = null;
        item.c1_submenu = null;
        item.parentNode.c1_menu_item = null;
        // update the global c1c_active_menu var if needed.
        if (c1c_active_menu == item.parentNode && !c1c_active_menu.c1_sel_item)
            c1c_active_menu = null;
    }
}

function popdown_and_unselect(menu)
{
    // remove any popup menus, remove selection.
    if (menu) {
        if (menu.c1_menu_item)
            c1c_popdown_item_menu(menu.c1_menu_item);
        if (menu.c1_sel_item)
            c1c_unselect_item(menu.c1_sel_item);
    }
}

// ---- none of the functions below deal with menu tracking logic ----

function c1c_hilite_item(item, on)
{
    if (on) {
        // styles
        if (c1c_getattr(item, 'c1_sel_item_styles_class'))
        	c1c_set_style_class(item, c1c_getattr(item, 'c1_sel_item_styles_class'))
        else {
        	c1c_add_styles(item, c1c_getattr(item.parentNode, 'c1_sel_item_styles'));
        	c1c_add_styles(item, c1c_getattr(item, 'c1_sel_item_styles'));
        }
        // image
        if (!item.c1_img && c1c_getattr(item, 'c1_img_src') && c1c_getattr(item, 'c1_img_sel_src')) {
            item.c1_img = new Image;
            item.c1_img.src = c1c_getattr(item, 'c1_img_src');
            item.c1_img_sel = new Image;
            item.c1_img_sel.src = c1c_getattr(item, 'c1_img_sel_src');
        }
        if (item.c1_img) {
            if (item.childNodes)
                item.childNodes[0].src = item.c1_img_sel.src;
            else {
                item.getElementsByTagName('IMG')[0].src = item.c1_img_sel.src;
            }
        }
    }
    else {
        // styles
        if (c1c_getattr(item, 'c1_item_styles_class'))
        	c1c_set_style_class(item, c1c_getattr(item, 'c1_item_styles_class'))
        else {
            c1c_remove_styles(item, c1c_getattr(item, 'c1_sel_item_styles'));
            c1c_remove_styles(item, c1c_getattr(item.parentNode, 'c1_sel_item_styles'));
            c1c_add_styles(item, c1c_getattr(item.parentNode, 'c1_item_styles'));
            c1c_add_styles(item, c1c_getattr(item, 'c1_item_styles'));
        }
        // image
        if (item.c1_img) {
            if (item.childNodes)
                // item.childNodes[0].childNodes[0].src = item.c1_img.src;
                item.childNodes[0].src = item.c1_img.src;
            else
                item.getElementsByTagName('IMG')[0].src = item.c1_img.src;
        }
    }
}

function c1c_show_submenu(item, submenu)
{
    if (c1c_submenu_zindex)
        submenu.style.zIndex = c1c_submenu_zindex;
    var tx, ty;
    if (c1c_getattr(item.parentNode, 'c1_horz')) {
        tx = c1c_offset_x(item) - c1c_offset_x(submenu.offsetParent);
        ty = c1c_offset_y(item) - c1c_offset_y(submenu.offsetParent) + item.offsetHeight;
    }
    else {
        tx = c1c_offset_x(item) - c1c_offset_x(submenu.offsetParent) + item.offsetWidth;
        ty = c1c_offset_y(item) - c1c_offset_y(submenu.offsetParent);
    }
    submenu.style.left = tx;
    submenu.style.top = ty;
    c1c_set_item_visibility(submenu.id, 'visible');


    var ifr_id = 'ifr_'+submenu.id;
    if (c1c_need_to_cover_dropdowns())
    {
        var ifr = document.getElementById(ifr_id);
        if (!ifr) 
        {
		    c1c_innerText = submenu.innerHTML;
		    var iframe_text = 
		    '<iframe id=' + ifr_id + ' src="about:blank"'+
		    ' style="position:absolute;left:'+submenu.style.left+';top:'+submenu.style.top;
            iframe_text += ';Z-INDEX:' + submenu.style.zIndex;
		    iframe_text += '" ' + 'frameborder=no scrolling=no width=' + submenu.scrollWidth + 
		    'px height=' + submenu.scrollHeight + 'px noresize marginheight=0 marginwidth=0"></iframe>';
    		   
		    submenu.insertAdjacentHTML('beforeBegin', iframe_text);
        } else 
            c1c_set_item_visibility(ifr_id, 'visible');
            // ifr.style.visibility = 'visible';
    }        
    
}

function c1c_set_item_visibility(item_id, value)
{
   var item = document.getElementById(item_id);
   if (item)
      if (window.setTimeout)
          window.setTimeout("c1c_set_item_visibility_delayed('"+item_id+"','"+value+"')",0);
      else
          item.style.visibility = value;
   
}

function c1c_set_item_visibility_delayed(item_id, value)
{
   var item = document.getElementById(item_id);
   if (item)
      item.style.visibility = value;
}

function c1c_hide_submenu(submenu)
{
    c1c_set_item_visibility(submenu.id, 'hidden');
    if (c1c_iframes_supported())
    {
        var ifr_id = 'ifr_'+submenu.id;
        c1c_set_item_visibility(ifr_id, 'hidden');
    }
}

// function c1c_menu_contains(menu, el)
// {
//     if (!menu || !el)
//         return false;
//     else if (c1c_object_contains(menu, el))
//         return true;
//     else if (menu.c1_sel_item)
//         return c1c_menu_contains(menu.c1_sel_item.c1_submenu, el)
//     else
//         return false;
// }

function c1c_getattr(obj, att)
{
    if (obj.getAttribute)
        return obj.getAttribute(att);
    if (obj.attributes) {
        var a = obj.attributes[att];
        if (a) return a.value;
    } else
        return obj[att];
}

// returns true if obj contains elem inside its tree
function c1c_object_contains(obj, elem)
{
    if (!obj)
        return null;
    else if (obj.contains)
        return obj.contains(elem);
    else
        return _c1c_object_contains(obj, elem);
}

function _c1c_object_contains(obj, elem)
{
    if (!obj)
        return null;
    var i;
    if (!obj.childNodes)
        return false;
    for (i = 0; i < obj.childNodes.length; ++i) {
        var child = obj.childNodes[i];
        if (elem == child)
            return true;
        else if (_c1c_object_contains(child, elem))
            return true;
    }
    return false;
}

function c1c_offset_x(o, relto)
{
    if (typeof(o) != 'object' || o == null)
        return 0;
    else
        return o.offsetLeft + c1c_offset_x(o.offsetParent, relto);
}

function c1c_offset_y(o)
{
    if (typeof(o) != 'object' || o == null)
        return 0;
    else
        return o.offsetTop + c1c_offset_y(o.offsetParent);
}

function c1c_add_styles(el, style_str)
{
    if (!style_str)
        return;
    var kvs = style_str.split(';');
    for (var i = 0; i < kvs.length; ++i) {
        var kv = kvs[i].split(':');
        if (kv.length == 2) {
            if (kv[0] == 'className')
                el.className = kv[1];
            else
                el.style[kv[0]] = kv[1];
        }
    }
}

function c1c_remove_styles(el, style_str)
{
    if (!style_str)
        return;
    var kvs = style_str.split(';');
    for (var i = 0; i < kvs.length; ++i) {
        var kv = kvs[i].split(':');
        if (kv.length == 2) {
            if (kv[0] == 'className')
                el.className = '';
            else
                el.style[kv[0]] = '';
        }
    }
}

function c1c_set_style_class(item, className)
{
    item.className = className;
}

// true if dropdowns is present on the page
function c1c_dropdowns_present()
{
    return (document.all.tags('SELECT').length > 0);
}

// true if embed or objects is present on the page
function c1c_embed_present()
{
    return ((document.all.tags('OBJECT').length > 0) || (document.all.tags('EMBED').length > 0));
}

// true if user agent support property scripting with iframes
function c1c_iframes_supported()
{
    var ua = window.navigator.userAgent;
    var msie = ua.indexOf('MSIE');
    var opera = ua.indexOf('Opera');
    return ((msie > 0) && (opera < 0));
}

// true if need to cover dropdowns in IE by submenus
function c1c_need_to_cover_dropdowns()
{
	return (c1c_iframes_supported() && (c1c_dropdowns_present() || c1c_embed_present())); 
}

function c1c_mnu_check_mouse_out(ev, item)
{
    var tgt;
    if (ev.relatedTarget)
        tgt = ev.relatedTarget;
    else if (ev.toElement)
        tgt = ev.toElement;
    return  (!tgt || !c1c_object_contains(item, tgt));
}

function c1c_init()
{
    if (!c1c_initialized)
    { 
        if (!document.expando)
            document.expando = true;
        if (document.attachEvent)
        {
            document.attachEvent('onmousedown',c1c_doc_onmousedown);
            document.attachEvent('onmouseup',c1c_doc_onmouseup);
        }
        else
        {
            c1c_menu_popdown_delay = 200;
        }
        c1c_initialized = true;
    }
}


// ---- end of file. ----
