// ***************************************** // menu.js : dynamic hierarchical menu system // // (c) by E.F. de Moor (Creagraphy) ernst@creagraphy.nl // // date: april 8th 2002 // // // Following function are used for interfacing // // my_menu_sel(id) : called when the user clicks a menu item in our own frame. // This function must call menu_sel in all frames! // my_menu_over(id) : called when the mouse moves over a menu item of our own frame. // This function must call menu_over in all frames! // my_menu_out(id) : called when the mouse moves out a menu item of our own frame. // This function must call menu_out in all frames! // // menu_sel(id) : called when the user clicks a menu item in any frame. // menu_over(id) : called when the mouse moves over a menu item in any frame. // menu_out(id) : called when the mouse moves out a menu item in any frame. // set_page_info(sel, info) : called by the content frame, if the content changes. // // cms_onload(sel) : called once when this frame is loaded // // // Note about the my_menu... functions: // These functions are implemented in ../menu.inc. // // Note about the menu_sel, menu_over and menu_out functions: // Any frame is allowed to implement these (not just menu frames). This can be used // To give helpinformation (e.g. popup notes, textual explanations) in other frames // Whenever something happens with a menu button or whenever a new page is loaded // in the content frame. // // Note: Also new is that the content frame is now allowed to have a menu itself. This is // Handy to have a popup menu to appear over the content itself. // Remember the last selection // ------ Interface Functions ------- add_onload(onload_menu_folding); add_page_info(page_info_folding); add_menu_sel(menu_sel_folding); add_menu_over(menu_over_folding); add_menu_out(menu_out_folding); function onload_menu_folding(sel) { if(sel) set_states_from_sel(sel); else if(typeof(parent.selection) != "undefined") set_states_from_sel(parent.selection); else if(typeof(top.selection) != "undefined") set_states_from_sel(top.selection); else set_states_from_sel(sel); check_pos(0); //Solve the IE6 bug: Force a refresh refresh_menu(); } function page_info_folding(sel, info) { set_states_from_sel(sel); check_pos(0); //Solve the IE6 bug: Force a refresh refresh_menu(); } function menu_sel_folding(id, item_x, item_y) { check_pos(1); //Solve the IE6 bug: Force a refresh refresh_menu(); } function menu_over_folding(id, item_x, item_y) { window.status = menu_tree[id].explanation; show_menu_item(id,1,menu_tree[id].visible,100); } function menu_out_folding(id, item_x, item_y) { window.status = ''; show_menu_item(id,0,menu_tree[id].visible,100); } // ------ Menu functions ------- function check_pos(animate) { if(typeof(menu_tree) == "undefined") // No tree available, skip processing return; var i; var menu_width = 0; // Determine the width of the menu. for(i=0; i= menu_settings_folding.min_menu_level && menu_tree[i].level <= menu_settings_folding.max_menu_level) { if(menu_tree_parms[i].width > menu_width) menu_width = menu_tree_parms[i].width; } for(i=0; i= menu_settings_folding.min_menu_level && menu_tree[i].level <= menu_settings_folding.max_menu_level) { menu_tree_parms[i].x = calc_x(menu_settings_folding.x_pos[menu_tree[i].level], menu_settings_folding.x_align[menu_tree[i].level], 0, menu_width); set_all_x(i, menu_tree_parms[i].x, 0); } } if(animate && menu_settings_folding.animation_speed) do_animate(0); else show_tree(menu_settings_folding.min_menu_level,0); } var animating = false; function do_animate(from_timer) { var i; if(animating && !from_timer) return; animating = true; moved = 0; // First finish all items we were already animating for(i=0; i= menu_settings_folding.min_menu_level && menu_tree[i].level <= menu_settings_folding.max_menu_level) { if(menu_tree_parms[i].desired_y != menu_tree_parms[i].y) { set_y_pos(i,menu_settings_folding.animation_speed); moved++; } } } // If none: then check if we should collapse parent menu items if(!moved) { for(i=0; i= menu_settings_folding.min_menu_level && menu_tree[i].level <= menu_settings_folding.max_menu_level) { // if(menu_tree_parms[i].prev_expanded == menu_tree[i].expanded) // show_menu_item(i,0,1,100); if(menu_tree_parms[i].prev_expanded && !menu_tree[i].expanded) { menu_tree_parms[i].prev_expanded = menu_tree[i].expanded; level = menu_tree[i].level; parent_y = menu_tree_parms[i].desired_y; cur_y = parent_y + menu_tree_parms[i].height; i++ while(i < menu_tree.length) { if(menu_tree[i].level <= level) break; moved++; menu_tree_parms[i].visible = false; menu_tree_parms[i].desired_y = parent_y; i++; } // Also move the menu items below the collapsed menu while(i < menu_tree.length) { if( menu_tree_parms[i].visible) { menu_tree_parms[i].desired_y = cur_y; parent_y = cur_y; cur_y += menu_tree_parms[i].height; } else { menu_tree_parms[i].desired_y = parent_y; } i++; } do_animate(1); return; } } } } // If none: then check if we should expand parent menu items if(!moved) { for(i=0; i= menu_settings_folding.min_menu_level && menu_tree[i].level <= menu_settings_folding.max_menu_level) { if(!menu_tree_parms[i].prev_expanded && menu_tree[i].expanded) { menu_tree_parms[i].prev_expanded = menu_tree[i].expanded; level = menu_tree[i].level; parent_y = menu_tree_parms[i].desired_y; cur_y = parent_y + menu_tree_parms[i].height; i++; while(i < menu_tree.length) { if(menu_tree[i].level <= level) break; if(menu_tree[i].level - level == 1) { moved++; menu_tree_parms[i].visible = true; menu_tree_parms[i].desired_y = cur_y; parent_y = cur_y; cur_y += menu_tree_parms[i].height; show_menu_item(i,0,1,100); } else { menu_tree_parms[i].desired_y = parent_y; } i++; } // Also move the menu items below the expanded menu while(i < menu_tree.length) { if( menu_tree_parms[i].visible) { menu_tree_parms[i].desired_y = cur_y; parent_y = cur_y; cur_y += menu_tree_parms[i].height; } else { menu_tree_parms[i].desired_y = parent_y; } i++; } do_animate(1); return; } } } } if(moved) setTimeout('do_animate(1)', 50); else { for(i=0; i= menu_settings_folding.min_menu_level && menu_tree[i].level <= menu_settings_folding.max_menu_level) { show_menu_item(i,0,menu_tree_parms[i].visible,100); } } animating = false; } } function set_y_pos(index, stepsize) { // Calculate the necessary stepsize diff_y = menu_tree_parms[index].desired_y - menu_tree_parms[index].y; if(diff_y > stepsize) diff_y = stepsize; if(diff_y < -stepsize) diff_y = -stepsize; // Calculate the new position menu_tree_parms[index].y += diff_y; // Move all states set_all_y(index, menu_tree_parms[index].y, 0); } // Immediately show the entire tree. var cur_y; function show_tree(level, idx) { var i; var menu_height=0; // Make sure we start with a sensible value if(level == menu_settings_folding.min_menu_level) { // Determine the tree height for(i=idx; i= menu_settings_folding.min_menu_level && menu_tree[i].level <= menu_settings_folding.max_menu_level) { menu_height += menu_tree_parms[i].height; } } cur_y = calc_y(menu_settings_folding.y_pos[level], menu_settings_folding.y_align[level], 0, menu_height); parent_y = cur_y; } for(i=idx; i= menu_settings_folding.min_menu_level && menu_tree[i].level <= menu_settings_folding.max_menu_level) { menu_tree_parms[i].visible = menu_tree[i].visible; if(menu_tree_parms[i].visible) { menu_tree_parms[i].desired_y = cur_y; parent_y = cur_y; cur_y += menu_tree_parms[i].height; } else { menu_tree_parms[i].desired_y = parent_y; } // Store the desired position into the current position too menu_tree_parms[i].y = menu_tree_parms[i].desired_y; // And place it there immediately (10000 forces animation off) set_y_pos(i,10000); show_menu_item(i,0,menu_tree_parms[i].visible,100); // Store the stati menu_tree_parms[i].prev_parent = menu_tree[i].parent; menu_tree_parms[i].prev_expanded = menu_tree[i].expanded; menu_tree_parms[i].prev_selected = menu_tree[i].selected; } } }