//this is the main function call. This function is the first to be run. async function make_main_menu() { //alert("View Menu"); var is_editable = null; var top_menu_container = null; var top_menu_HTML_object = null; var sub_menu_HTML_object = null; var item_ids = null; var item_id_array = null; var item_id = null; var array_len = null; var i = null; var show_centered_box = null; var submenus = null; var sub_menu_objects = null; top_menu_container = make_top_menu_container(); //create div container for all of the top menu's objects top_menu_HTML_object = await place_top_menu(0); //place the tier 0, or top menu bar's menu options at the top of the window. These menu options are organized as inline, not as a stack menus top_menu_container.appendChild(top_menu_HTML_object); //place the top menu bar items into the div container that holds the main menu //top menu fades into view when mouse enters its space //2023-08-22: commented this out and added a mousemove event listener which //makes the menu top menu bar visible. top_menu_HTML_object.addEventListener("mouseover", function () { //quick_fade_in(top_menu_HTML_object.id); }); //2023-08-22: //when the mouse cursor moves up near the top menu by 100 pixels Y, //if the top menu bar is visisble window.addEventListener("mousemove", function (event) { return; var client_y = null; client_y = parseFloat(event.clientY); if (client_y >= 0 && client_y <= 100) { quick_fade_in(top_menu_HTML_object.id); } }); item_ids = await get_all_menu_item_ids(1, 1); //grabs all menu id numbers from the database using http according to the two arguments. The first argument is the user id, the second argument is the desktop id. These arguments can be changed to fetch a specific main menu from the database item_id_array = item_ids.split("|"); //make the list of menu id numbers into an array from a pipe (i.e. "|") delimited string array_len = item_id_array.length; //get the number of items in the array. If this is not set to a variable before running the counting loop, the loop won't work. //adds an event listener for a window click. This way when the user clicks outside a menu, all the sub menus hide. window_body_onclick(); //listens for a mousedown event in the body element, //and determines if that event occurred over an inline menu item. //If it occurred over an inline menu item, activate menu. //If event target was not an inline menu item, deactivate the menu set_window_body_onmousedown_event_listeners(); //By default, set the menu's active mode to false set_is_menu_active_false(); ////be sure to place the array item count into a variable BEFORE running the counting loop. Don't use "array.length" as the number of times the counter loops. It won't work. for (i = 0; i < array_len; i++) { //alert(item_id_array[i]); item_id = item_id_array[i]; //designate a single menu id in the array using the counter variable (i.e. i) //if the array is a legitimate array and has one item or more if (item_id.length > 0) { //the id of the menu item is greater than 0. All valid menu item ids are an integer greater than 1. if (item_id > 0) { //alert(item_id); sub_menu_HTML_object = await get_subMenus(item_id); //creates each stack menu //alert(sub_menu_HTML_object.innerHTML); //if the menu object is not empty, then it will contain html. Valid menu objects contain html as a string. Invalid, or blank menu items contain no html. The number of html characters in the menu item is counted to check for validity //alert("HTML Object: " + sub_menu_HTML_object.innerHTML); if (sub_menu_HTML_object) { if (sub_menu_HTML_object.innerHTML.length !== undefined) { if (sub_menu_HTML_object.innerHTML.length > 0) { top_menu_container.appendChild(sub_menu_HTML_object); //place the valid menu object into the div container for the entire main menu //the parent menu id can only be added to the stack menu after the stack menu is created and wrapped inside a parent div container add_parent_menu_id_attribute(sub_menu_HTML_object, item_id); //places an attribute into the menu's html specifying the parent menu's id according to the child menu's id //this function is located in progress_bar_2.js //start_progress_bar(1, array_len - 1, i + 1, ("Loading Menu Item: " + (i + 1).toString())); most_customizable_config_elem_for_animation(sub_menu_HTML_object.id, "opacity", "0.25", "0.001"); //set up the fade-in CSS transform function if ((i + 1) === array_len) { // document.getElementById("top_menu_container").style.display = "block"; //alert("done"); //var html = await get_top_menu_html(); // }); } } } } } } } } //This function determines what HTML element was clicked upon. //If it's the body, then deactivate the main menu. If the click //occurred on an inline item, activate the main menu. //Otherwise, the click occurred somewhere else. //In such a case, this deactivates the menu. function window_body_onmousedown_set_active_menu_mode(event) { var event_target_is_inline_menu_item = null; if (event) { event_target_is_inline_menu_item = event.target.getAttribute("data-is_inline_menu_item"); if (event_target_is_inline_menu_item !== null) { if (event_target_is_inline_menu_item === "true") { //the click event was over an inline menu item. Set main menu mode to "active = true" set_is_menu_active_true(); ////console.log("MENU ACTIVE: TRUE"); } else { //deactive the main menu. The target that was clicked is not an inline menu item set_is_menu_active_false(); ////console.log("MENU ACTIVE: FALSE"); } } else { //event target is null set_is_menu_active_false(); ////console.log("MENU ACTIVE: FALSE"); } } else { //event object doesn't seem valid set_is_menu_active_false(); ////console.log("MENU ACTIVE: FALSE"); } } //sets an onmousedown event listener of the window. //depending on if the user clicked outside of an inline menu item, //the mode can be turned on or off function set_window_body_onmousedown_event_listeners() { window.addEventListener("mousedown", function () { window_body_onmousedown_set_active_menu_mode(); }); } //Adds an event listener that depending on what event target //was clicked in the window, the submenus are all set to hidden //except for certain target elements designated by id function window_body_onclick() { var target_elem_id = null; var in_string_1 = null; var in_string_2 = null; var in_string_3 = null; var in_string_4 = null; var inline_menu_item_id = null; var submenu_arrow_id = null; var no_arrow_td_id = null; var no_arrow_img_id = null; //When the user clicks anywhere in the window, do this. window.addEventListener("click", function () { //Get the id of the element that was clicked upon. target_elem_id = event.target.getAttribute("id"); //If the target element has this text inside it's id attribute //We can identify what the target element is inline_menu_item_id = "menu_label_span"; submenu_arrow_id = "menu_hasChildren_arrow_"; no_arrow_td_id = "menu_has_NO_Children_blank_"; no_arrow_img_id = "menu_hasChildren_arrow_icon_"; //Do these strings contain any of the id strings? //If so, where? The value of -1 is returned if //the text is not found within the string. //If the id string exists in the target element's id attribute, //Then its index returns an integer greater than -1. //If target element has a null id, then these variables //cannot be assigned. Only strings are allowed. if (target_elem_id !== null) { in_string_1 = target_elem_id.indexOf(inline_menu_item_id); in_string_2 = target_elem_id.indexOf(submenu_arrow_id); in_string_3 = target_elem_id.indexOf(no_arrow_td_id); in_string_4 = target_elem_id.indexOf(no_arrow_img_id); } else { //the target element has a null value //for its id attribute. Default to -1 so that //we know the id text is not within //the target element's id attribute in_string_1 = -1; in_string_2 = -1; in_string_3 = -1; in_string_4 = -1; } //If the target element's id attribute contains //the id text declared above if (in_string_1 > -1) { //An inline menu item was clicked upon. Do nothing. //Continue to display the tier 1 submenu return; } if (in_string_2 > -1) { //The submenu display arrow was clicked upon. Do nothing. //Continue to display the menu item's submenu. return; } if (in_string_3 > -1) { //clicked on the blank image. //This is not the image containing the 'show submenu' arrow icon) //*** NOTE ***: the CSS display property of this element is //already set to "none" by default. //This element does NOT interact with the end user. //hide all visible submenus all_stack_menus_allow_hide(); hide_all_stack_menus(); //event.stopImmediatePropagation(); //event.stopPropagation(); //event.preventDefault(); return; } if (in_string_4 > -1) { //clicked on the blank image (not the 'show submenu' arrow) //*** NOTE ***: the CSS display property of this element is //already set to "none" by default. //This element does NOT interact with the end user. all_stack_menus_allow_hide(); hide_all_stack_menus(); //event.stopImmediatePropagation(); //event.stopPropagation(); //event.preventDefault(); return; } //if no conditions have resulted in this function's exit, //then by default, hide all stack menus. Whatever //the target element cicked upon may be, this ensures that //clicking on any object in the window hides all stack menus. all_stack_menus_allow_hide(); hide_all_stack_menus(); //event.stopImmediatePropagation(); //event.stopPropagation(); //event.preventDefault(); return; }); } //start by getting the root menu (pid=0). Wrap the top menu output into a div container, and place it at the top of the window as a grey strip async function place_top_menu(parent_menu_id) { //return; var pid = null; var base_path = null; var menu_data = null; var show_menu = null; pid = parent_menu_id; //start out by grabbing root menu (root parent id is 0) //if pid isn't a valid number, exit function. Otherwise proceed. if (pid !== NaN && pid !== null && pid !== "") { if (typeof pid === "number") { //continue } else { return; } } //base_path = get_base_path(); //grabs the base url (this protocol, host, and port number) base_path = "/chromosphere/scripts/js/ui/topmenu/view_menu/Default?pid="; //add folder path for making the top menu menu_data = await getData3(base_path + pid); //grab the menu items' HTML with http menu_data = top_menu_divWrapper(menu_data, pid); //wrap the top tier (i.e. tier level 0) into a div container menu_data.style.position = "fixed"; //allow the menu to position itself on the page menu_data.style.top = "0"; //place it at the very top menu_data.style.left = "0"; //place it at the very left menu_data.style.width = "100%"; //make it span the entire width of the window menu_data.style.height = "31px"; //make its height thin, so it appears as a strip along the top of the page menu_data.style.overflow = "hidden"; //if the window is reconstrained, or resized, hide the overlapping menu contents //menu_data.style.display = "none"; //menu_data.style.backgroundColor = "rgb(153,153,153)"; //give the menu strip a grey color menu_data.style.backgroundColor = "rgba(90,90,90,1.0)"; //give the menu strip a grey color ////menu_data.style.backgroundColor = "rgba(255,255,0,1.0)"; //give the menu strip a grey color menu_data.style.borderBottom = "0.5px solid rgba(0,0,0,1.0)"; //menu_data.style.backgroundColor = "rgb(255,255,0)"; //give the menu strip a grey color ////menu_data.style.opacity = 0.0; //menu_data.style.display = "none"; return menu_data; //return the menu html data } //creates the container that will hold the main menu function make_top_menu_container() { var top_menu_container = null; var exists = null; var output = null; exists = document.getElementById("top_menu_container"); //check to see if the main menu's container already exists if (exists !== null) { //object already exists output = document.getElementById("top_menu_container"); } else { //main menu container does not exist. Make container and append it to the document's body. top_menu_container = document.createElement("div"); //make a new div to act as the main menu's container top_menu_container.setAttribute("id", "top_menu_container"); //give the container an id top_menu_container.style.zIndex = 10000000; //make sure to set the top menu as the top-most layer on the page //top_menu_container.style.backgroundColor = "#ffa"; //checking the background. So, making it yellow. document.body.appendChild(top_menu_container); top_menu_container.setAttribute("data-is_menu_active", "false"); //initially set the top menu to be inactive. //trying to make the frame stay fixed on the page. //window.addEventListener("scroll", function () { //top_menu_container.style.top = (parseFloat(top_menu_container.style.top) + document.body.scrollHeight) + "px";// parseFloat(document.body.style.top) + "px"; //top_menu_container.style.left = (parseFloat(top_menu_container.style.left) + document.body.scrollWidth) + "px";// parseFloat(document.body.style.top) + "px"; //top_menu_container.style.left = document.body.scrollWidth + "px";//parseFloat(document.body.style.left) + "px"; //top_menu_container.style.width = "inherit"; //99.999%"; //parseFloat(document.body.style.width) + "px"; //top_menu_container.style.height = "inherit"; //99.999%"; //parseFloat(document.body.style.height) + "px"; //}); output = top_menu_container; } return output; } //gets the sub-menus by parent_id async function get_subMenus(parent_menu_id) { var pid = null; var base_path = null; var menu_data = null; var menu_exists = null; var stack_menu_id = null; var stack_menu = null; pid = parseFloat(parent_menu_id); //get parent menu id //if pid isn't a valid number, exit function. Otherwise proceed. if (pid !== NaN && pid !== null && pid !== "") { if (typeof pid === "number") { //continue } else { return; } } //Get the base url, append the path string //base_path = get_base_path(); //grabs the base url (this protocol, host, and port number) base_path = "/chromosphere/scripts/js/ui/topmenu/view_menu/Default?pid="; //add folder path for making the top menu menu_exists = menu_object_exists(pid); //check to see if the menu already exists if (menu_exists !== true) { menu_data = await getData3(base_path + pid); //grab the menu items' HTML menu_data = stack_menu_divWrapper(menu_data, pid); //wrap the stack menu table items into a div container menu_data.style.position = "fixed"; //these menus will change location on the screen, so set the position to absolute menu_data.style.backgroundColor = "#d0d0d0"; //set the background to light grey menu_data.style.display = "none"; return menu_data; //return the menu html data } } //function to grab an URL and return its response data async function getData3_OLD(url) { let d = await fetch(url, { headers: { Cookie: 'SameSite=Strict' } }).then().catch(); let t = await d.text(); return t; } //function to grab an URL and return its response data async function getData3(url) { //let d = await fetch(url); let d = await fetch(url, { method: "GET", headers: { //"Origin": "", "Content-Type": "text/plain;charset=UTF-8" //"Cache-Control": "no-cache" //"Set-Cookie": make_sameSite_cookie(), //"Access-Control-Allow-Origin": "" } //referrerPolicy: "no-referrer-when-downgrade", // no-referrer, origin, same-origin... //mode: "no-cors", // same-origin, no-cors //credentials: "same-origin", // omit, include //}).then().catch(); }); let t = await d.text(); return t; } function cookie_expires_date() { var dateToday = null; var dateExpires = null; var nextYearsDate = null; dateToday = new Date(Date.now()); dateExpires = new Date(Date.now()); nextYearsDate = parseInt(dateExpires.getFullYear()) + 1; //cookie expires in 1 year dateExpires.setFullYear(nextYearsDate); dateExpires = dateExpires.toUTCString(); return dateExpires; } function make_sameSite_cookie() { var expireDate = null; var cookieDomainName = null; var sameSite = null; var cookieText = null; var cookieName = null; var urlPath = null; //var origin = null; sameSite = "SameSite=None; Secure; HttpOnly; "; cookieDomainName = "Domain=" + window.location.hostname + "; "; expireDate = "Expires=" + cookie_expires_date() + "; "; urlPath = "Path=/; "; //urlPath = "Path=" + window.location.pathname + "; "; //origin = "Origin=" + window.location.origin + "; "; cookieText = sameSite + cookieDomainName + expireDate + urlPath; // + origin; return cookieText; } function set_sameSite_cookie() { var cookie_text = null; cookie_text = make_sameSite_cookie(); //document.headers("Cookie") = cookie_text; /*if (document.cookie("CORSSameSite")) { document.cookie("CORSSameSite") = ""; document.cookie("CORSSameSite") = cookie_text; } else { document.cookie("CORSSameSite") = cookie_text; } return document.cookie("CORSSameSite"); */ return cookie_text; } //gets the child menu items of a menu item. Places all items into the main menu's div container. All top menu items are displayed within this container. async function display_sub_menu_items(id_val) { var obj_id = null; var base_path = null; var url = null; var submenu = null; var new_div_node = null; var new_div_child_node = null; var menu_container = null; var menu_exists = null; //alert("c0w"); obj_id = parseFloat(id_val); //the id of the folder which contains the submenu items menu_exists = menu_object_exists(obj_id.toString()); //if the menu exists if (menu_exists !== true) { submenu = await get_subMenus(obj_id); //gets the menu items' html from the server new_div_node = document.createElement("div"); //make a container div as a node object to hold the html //new_div_node.innerHTML = submenu.; //place menu html into container div new_div_node.appendChild(submenu); new_div_child_node = new_div_node.firstChild; //now that we have the html in the form of an html node object, remove the container div menu_container = document.getElementById("top_menu_container"); //gets the container that holds the entire main menu //if the main menu container exists if (menu_container !== null) { menu_container.appendChild(new_div_child_node); //add the new menu items into the main menu's container new_div_child_node.style.zIndex = parseFloat(document.getElementById("top_menu_container").style.zIndex) + (number_menu_items() + 1); } } return id_val; } //displays the first stack submenu of a top inline menu item. Called only by tier 0 inline menu items, not other submenus (i.e tiers > 0). async function display_tier1_submenu(menu_item_obj) { var pid = null; var menu_container = null; var sub_menu_HTML_object = null; var menu_exists = null; pid = menu_item_obj.getAttribute("data-item_number"); // the id for this menu item. Use it to create the sub-menu of child objects for this menu item pid = parseFloat(pid); if (typeof pid === "number") { menu_exists = menu_object_exists(pid); //check to see if the menu exists. menu_container = document.getElementById("top_menu_container"); //get the menu container object in the DOM if (menu_container !== null) { //if the menu does not exist in the DOM if (!menu_exists) { sub_menu_HTML_object = await get_subMenus(pid); //make new sub-menu menu_container.appendChild(sub_menu_HTML_object); //add new sub-menu to DOM container position_stack_menu_1st_tier(menu_item_obj, pid); //sets the location on the screen where a first tier stack menu is to be placed for display } else { //bring existing sub-menu into view position_stack_menu_1st_tier(menu_item_obj, pid); //sets the location on the screen where a first tier stack menu is to be placed for display } } else { //the menu container for the entire main/top menu does not exist in the DOM. Nowhere to place the node object. //no menu container } } else { //pid is not numeric } } //this ONLY checks for stack menu objects. The object referenced is the div wrapping container of a stack menu by the pid argument function menu_object_exists(pid) { var stack_menu_id = null; var stack_menu = null; stack_menu_id = "stack_menu_div_wrapper_" + pid; //make the DOM id of the stack menu stack_menu = document.getElementById(stack_menu_id); //grab the stack menu by its id //if the stack menu already exists...return true if (stack_menu !== null) { return true; //the menu exists. output true. } else { return false; //the referenced menu does not exist. output false. } } //this creates a div wrap container for the top menu bar function top_menu_divWrapper(txt_html, pid_value) { //return; var div_wrap = null; div_wrap = document.createElement("div"); //make a new div container div_wrap.setAttribute("id", "div_wrapper_" + pid_value); //set the id of the div container div_wrap.style.position = "fixed"; //the position of the div container will change, so set its position to absolute. //div_wrap.style.overflow = "hidden"; //div_wrap.style.position = "fixed" //the position of the div container will change, so set its position to absolute. div_wrap.style.paddingTop = "4px"; //add a little space to the top of the menu bar div_wrap.style.boxShadow = "1px 3px 6px 1px rgba(0,0,0,0.5)"; //set the shadow effect of the top menu bar div_wrap.style.borderBottom = "1px solid rbg(51,51,51)"; //set the background color of the top menu bar to grey ////div_wrap.style.backgroundColor = "#ff0"; //checking to see the background, so turning it yellow div_wrap.innerHTML = txt_html; //wrap the html input into its div container return div_wrap; } //creates the stack menu with menu items within a div wrapping container function stack_menu_divWrapper(txt_html, pid_value) { var div_wrap = null; var stack_menu_div = null; //alert(pid_value); stack_menu_div = document.getElementById("stack_menu_div_wrapper_" + pid_value); //if the stack menu exists if (stack_menu_div !== null) { stack_menu_div.parentNode.removeChild(stack_menu_div); //remove it to prevent duplicate stack menus being added } //The menu does not exist. create it div_wrap = document.createElement("div"); div_wrap.setAttribute("id", "stack_menu_div_wrapper_" + pid_value); div_wrap.setAttribute("name", "stack_menu"); div_wrap.setAttribute("data-pid", pid_value); div_wrap.setAttribute("data-stay_visible", "false"); div_wrap.setAttribute("data-is_displayed", "false"); //2024-03-21: //adding an even handler for when the mouse is over (moving over) //a stack menu, keep that submenu visible. div_wrap.setAttribute("onmousemove", "submenu_mouseover(" + pid_value + ");stack_menu_stay_visible(" + pid_value + ");//console.log('mousemove over stack menu');"); //2024-04-16: //commenting out the line below to use a 'mousemove' event instead of a 'mouseover' event ////div_wrap.setAttribute("onmouseover", "submenu_mouseover(" + pid_value + ");stack_menu_stay_visible(" + pid_value + ");"); div_wrap.setAttribute("onmousedown", "this.style.zIndex=get_stack_menu_top_zIndex();"); //div_wrap.setAttribute("onmouseenter", "show_submenu(" + pid_value + ");stack_menu_stay_visible("+ pid_value +")"); div_wrap.style.position = "fixed"; div_wrap.style.boxShadow = "1px 3px 6px 1px rgba(0,0,0,0.5)"; div_wrap.style.border = "0.5px solid #111"; div_wrap.style.borderRadius = "3px"; //div_wrap.style.borderBottomLeftRadius = "3px"; //div_wrap.style.borderBottomRightRadius = "3px"; div_wrap.style.overflow = "hidden"; div_wrap.style.backgroundColor = "#d0d0d0"; div_wrap.style.padding = "0"; //div_wrap.style.paddingBottom = "1px"; div_wrap.style.zIndex = increment_zIndex(); div_wrap.innerHTML = txt_html; return div_wrap; } //gets the number of stack menus that exist function number_menu_items() { return document.getElementsByName("stack_menu").length; //get the items by referencing the name attribute. It returns an array, so add the .length property to return the number of objects in the array } function hide_stack_menu(pid) { var stack_menu = null; var stay_visible = null; stack_menu = document.getElementById("stack_menu_div_wrapper_" + pid); if (stack_menu !== null) { stay_visible = stack_menu.getAttribute("data-stay_visible"); if (stay_visible === "false") { stack_menu.style.display = "none"; } } return stay_visible; } function delay_hide_stack_menu(pid, delay) { global_hide_menu_timer_ID = setTimeout(function () { hide_stack_menu(pid); clearTimeout(global_hide_menu_timer_ID); } , delay); } function hide_all_stack_menus() { var all_sm = null; var num_sm = null; var i = null; var sm = null; all_sm = document.getElementsByName("stack_menu"); num_sm = all_sm.length; //2023-08-25: //Allow all stack menus to hide. //If allowed to hide, you can //set the CSS display on all to "none". all_stack_menus_allow_hide(); for (i = 0; i < num_sm; i++) { sm = all_sm[i]; hide_stack_menu(sm.getAttribute("data-pid")); } } function show_stack_menu(pid) { var stack_menu = null; stack_menu = document.getElementById("stack_menu_div_wrapper_" + pid); if (stack_menu !== null) { //stack_menu.style.opacity = 0.0; stack_menu.style.display = "block"; //quick_fade_in(stack_menu.id); //set its zIndex to the top layer //stack_menu.style.zIndex = increment_zIndex(); } return "show_block"; } function stack_menu_stay_visible(pid) { var stack_menu = null; var stay_visible = null; stack_menu = document.getElementById("stack_menu_div_wrapper_" + pid); if (stack_menu !== null) { stay_visible = stack_menu.setAttribute("data-stay_visible", "true"); stack_menu.style.display = "block"; } } function stack_menu_allow_hide(pid) { var stack_menu = null; stack_menu = document.getElementById("stack_menu_div_wrapper_" + pid); if (stack_menu !== null) { stack_menu.setAttribute("data-stay_visible", "false"); } } function all_stack_menus_allow_hide() { var stack_menus = null; var stack_menu = null; var stack_menu_count = null; var i = null; stack_menus = document.getElementsByName("stack_menu"); stack_menu_count = stack_menus.length; for (i = 0; i < stack_menu_count; i++) { stack_menu = stack_menus[i]; if (stack_menu !== null) { stack_menu.setAttribute("data-stay_visible", "false"); } } } //set the position of the first stack menu items. Only requires an X coordinate. The Y coordinate never changes. function position_stack_menu_1st_tier(menu_item_obj, pid) { var stack_menu = null; stack_menu = document.getElementById("stack_menu_div_wrapper_" + pid); if (stack_menu !== null) { stack_menu.style.left = menu_item_obj.offsetLeft + "px"; set_offset_X(stack_menu, menu_item_obj.offsetLeft); stack_menu.style.top = (menu_item_obj.offsetTop + 33) + "px"; set_offset_Y(stack_menu, menu_item_obj.offsetTop + 33); //stack_menu.style.zIndex = parseFloat(document.getElementById("top_menu_container").style.zIndex) + parseFloat(number_menu_items()) + 1 stack_menu.style.zIndex = increment_zIndex(); } } //sets the position of all stack menus except for the first stack menus. Adjusts both X and Y coordinates of the stack menu function position_stack_menu_other_tiers(arrow_expand_obj, pid) { var stack_menu = null; var parent_menu_offset_X = null; var parent_menu_offset_Y = null; var X = null; var Y = null; X = parseFloat(arrow_expand_obj.offsetWidth) + parseFloat(arrow_expand_obj.offsetLeft); //Y = parseFloat(arrow_expand_obj.offsetHeight) + Y = parseFloat(arrow_expand_obj.offsetTop); stack_menu = document.getElementById("stack_menu_div_wrapper_" + pid); if (stack_menu !== null) { parent_menu_offset_X = parseFloat(get_parent_offset_X(stack_menu)); X = parseFloat(X) + parent_menu_offset_X; X = X - 11; X = X.toString(); set_offset_X(stack_menu, X); parent_menu_offset_Y = parseFloat(get_parent_offset_Y(stack_menu)); Y = parseFloat(Y) + parent_menu_offset_Y; //Y = Y + 1; Y = Y.toString(); set_offset_Y(stack_menu, Y); stack_menu.style.left = X + "px"; stack_menu.style.top = Y + "px"; //stack_menu.style.zIndex = parseFloat(document.getElementById("top_menu_container").style.zIndex) + parseFloat(number_menu_items()) + 1 stack_menu.style.zIndex = increment_zIndex(); } } //gets the stack menu table. Iterates through each row in the table. Hide any visible stack menus corresponding to the designated row. The row id number can be passed in as an argument and used to reference the corresponding stack menu function submenu_mousedown(stack_tbl, pid, id) { //get stack_tbl var tbl = null; var tbl_rows = null; var tbl_row = null; var tbl_row_id = null; var num_rows = null; var stack_sub_menu_id = null; var stack_sub_menu = null; var i = null; var row_id_number = null; var row_parent_id_number = null; stack_sub_menu_id = "stack_menu_div_wrapper_" + id; stack_sub_menu = document.getElementById(stack_sub_menu_id); tbl = stack_tbl; if (tbl !== null) { tbl_rows = tbl.getElementsByTagName("tr"); if (tbl_rows !== null) { num_rows = tbl_rows.length; for (i = 0; i < (num_rows - 1); i++) { //for (i = 0; i < num_rows; i++) { tbl_row = tbl_rows[i]; row_id_number = tbl_row.getAttribute("data-row_id_num"); stack_menu_allow_hide(row_id_number); hide_stack_menu(row_id_number); } } } } function increment_zIndex() { var zIndex = null; //gets the top most stack menu layer position (zIndex) and increments up one layer zIndex = Math.floor(parseFloat(get_stack_menu_top_zIndex()) + 1); return zIndex; } function get_stack_menu_top_zIndex() { var stack_menus = null; var stack_menu = null; var stack_menu_count = null; var zIndex = null; var top_zIndex = null; var i = null; top_zIndex = 0; stack_menus = document.getElementsByName("stack_menu"); if (stack_menus !== null) { stack_menu_count = stack_menus.length; for (i = 0; i < stack_menu_count; i++) { stack_menu = stack_menus[i]; zIndex = parseFloat(stack_menu.style.zIndex); if (zIndex >= top_zIndex) { top_zIndex = zIndex; } } } return top_zIndex; } function submenu_mouseup(arrow, pid) { var parent_id = null; var parent = null; parent_id = parseFloat(get_parent_menu_id(pid)); if (parent_id !== null) { if (typeof parent_id === "number") { if (parent_id > 0) { parent = document.getElementById(parent_id); if (parent !== null) { position_stack_menu_other_tiers(arrow, parent_id); show_stack_menu(parent_id); stack_menu_stay_visible(parent_id); } } } } position_stack_menu_other_tiers(arrow, pid); show_stack_menu(pid); } function submenu_mouseover(pid) { show_stack_menu(pid); //return; } //This function grabs a delimited list of menu ids from the database. It preloads the menu items when the page loads, as apposed to on-call menu display which creates an unwanted pause. It caches the menu objects to eliminate latency when menus are placed on the screen. The querystring variables "user_id" and "desktop_id" are set to a default value of 1. Change the querystring parameters to choose a specific custom main menu. async function get_all_menu_item_ids(user_id, desktop_id) { var url = null; var base_url = null; var output = null; //base_url = get_base_path(); //gets the protocol, host, port url = "/chromosphere/scripts/js/ui/topmenu/get_top_menu?user_id=" + get_user_id_val(self.location.href, 'user_id').toString() + "&desktop_id=" + get_desktop_id_val(self.location.href, 'desktop_id').toString(); //adds the path string that gets the menu output = await getData3(url); //await return results return output; //pass result back } //This function gets the PARENT ID of the PARENT STACK MENU ID. //It essentially gets the parent of the parent. function get_parent_menu_id(pid) { var stack_menu_item_id = null; var stack_menu_item = null; var parent_menu_id = null; var output = 0; //default to 0 when there are no parent menu items. 0 is the top tier menu level stack_menu_item_id = "stack_menu_item_" + pid; //get the id for the "show the sub menu" box containing the tiny arrow stack_menu_item = document.getElementById(stack_menu_item_id); //grab the object by the id //if the stack menu exists //alert(stack_menu_item); if (stack_menu_item !== null) { parent_menu_id = stack_menu_item.getAttribute("data-parent_folder_id"); //grabs the parent's parent id of the stack menu //if the parent menu id exists if (parent_menu_id !== null) { output = parent_menu_id; //sets the output of the function to the parent's parent id } } return output; //default output is null. If the operation is a success, the output will have been changed to a valid value (a number) } //This function is called to add the parent of the parent ID to an individual stack menu. The attribute is stored inside the div container for the stack menu. function add_parent_menu_id_attribute(menu_obj, pid) { var parent_menu_id = null; parent_menu_id = get_parent_menu_id(pid); //This actually gets the parent id of the parent menu menu_obj.setAttribute("data-parent_folder_menu_id", parent_menu_id); //add the parent id of the parent to the menu stack div as an attribute } //this function causes the parent menu to remain visible when a sub menu is displayed function show_parent_menu(pid) { var parent_menu_id = null; var parent_menu = null; parent_menu_id = get_parent_menu_id(pid); //gets the parent menu id of the sub menu if (parent_menu_id > 0) { //only apply this function to stack menu items. Stack menu items have a id value greater than 0. The inline menu items at the top teir menu bar have a value of 0. parent_menu = document.getElementById(parent_menu_id); //get the parent menu object if (parent_menu !== null) { //if a valid parent menu object exists parent_menu.style.display = "block"; //make the menu visible stack_menu_stay_visible(parent_menu_id); //keep the menu visible until it is time to hide it. } } return parent_menu_id; //returns the parent menu id value } //hides a specific stack menu item according to its id (i.e. pid) function hide_submenu(pid) { var submenu = null; submenu = document.getElementById("stack_menu_item_" + pid); //get the sub menu object by id (i.e. pid) if (submenu !== null) { //if the sub menu exists stack_menu_allow_hide(pid); //give permisssion to the stack menu item to become hidden hide_stack_menu(pid); //hide the stack menu } } //this hides all visible stack menu items that are children of the given parent menu item (i.e. menu_item_obj argument) function hide_all_submenus(menu_item_obj) { var menu_item = null; var menu_items_name = null; var all_submenu_items = null; var menu_item_count = null; var i = null; var pid = null; menu_item = menu_item_obj; //assigns the menu item object to a local variable menu_items_name = menu_item.getAttribute("name"); //get the name attribute of the stack menu items if (menu_items_name !== null) { //if the menu items have a valid name all_submenu_items = document.getElementsByName(menu_items_name); //get the stack menu items according to their name if (all_submenu_items !== null) { //if sub menu items exist menu_item_count = all_submenu_items.length; //get the number of sub menus within the array for (i = 0; i < menu_item_count; i++) { submenu_item = all_submenu_items[i]; //get the individual sub menu item in the array according to its index if (submenu_item !== null) { //if the sub menu item exists pid = submenu_item.getAttribute("data-id_number"); //get the id number of the specified sub menu item hide_submenu(pid); //hide the sub menu item via reference of its pid (i.e. data-id_number) attribute within the sub menu item } } } } } function clear_away_any_visible_stack_menus() { var stack_menus = []; var len = null; var i = null; var stack_menu = null; stack_menus = document.getElementsByName("stack_menu"); if (stack_menus !== null) { len = stack_menus.length; for (i = 0; i < len; i++) { stack_menu = stack_menus[i]; } } } function set_offset_X(stack_menu, offsetLeft) { stack_menu.setAttribute("data-offset_X", offsetLeft.toString()); } function get_offset_X(stack_menu) { var offset_X = null; offset_X = stack_menu.getAttribute("data-offset_X"); offset_X = offset_X.toString(); return offset_X; } function get_parent_offset_X(stack_menu) { var offset_X = null; var stack_menu_id = null; var parent_stack_menu_id = null; var parent_stack_menu = null; offset_X = "0"; stack_menu_id = stack_menu.getAttribute("data-pid").toString(); //get the id number of the specified sub menu item parent_stack_menu_id = get_parent_menu_id(stack_menu_id).toString(); parent_stack_menu = document.getElementById("stack_menu_div_wrapper_" + parent_stack_menu_id); if (parent_stack_menu !== null) { offset_X = parseFloat(get_offset_X(parent_stack_menu)); offset_X = offset_X.toString(); } return offset_X; } function set_offset_Y(stack_menu, offsetTop) { stack_menu.setAttribute("data-offset_Y", offsetTop.toString()); } function get_offset_Y(stack_menu) { var offset_Y = null; offset_Y = stack_menu.getAttribute("data-offset_Y"); offset_Y = offset_Y.toString(); return offset_Y; } function get_parent_offset_Y(stack_menu) { var offset_Y = null; var stack_menu_id = null; var parent_stack_menu_id = null; var parent_stack_menu = null; offset_Y = "0"; stack_menu_id = stack_menu.getAttribute("data-pid").toString(); //get the id number of the specified sub menu item parent_stack_menu_id = get_parent_menu_id(stack_menu_id).toString(); parent_stack_menu = document.getElementById("stack_menu_div_wrapper_" + parent_stack_menu_id); if (parent_stack_menu !== null) { offset_Y = parseFloat(get_offset_Y(parent_stack_menu)); offset_Y = offset_Y.toString(); } return offset_Y; } function onmousedown_change_style(menu_item_obj) { if (menu_item_obj !== null) { menu_item_obj.style.color = "rgb(255,255,255)"; menu_item_obj.style.backgroundColor = "rgba(102,102,102,1.0)"; } } function onmouseup_change_style(menu_item_obj) { if (menu_item_obj !== null) { menu_item_obj.style.color = "rgb(0,0,0)"; menu_item_obj.style.backgroundColor = "rgba(205,205,205,0.5)"; } } async function preload_menu_item(pid, tier) { var id = null; var obj = null; var menu_items = null; var top_menu_container_id = null; var top_menu_container = null; var base_path = null; if (pid !== NaN && pid !== null && pid !== "") { if (typeof pid === "number") { //continue //alert(pid); } else { //alert(pid); return; } } base_path = "/chromosphere/scripts/js/ui/topmenu/view_menu/?pid="; id = "stack_menu_div_wrapper_" + pid; obj = document.getElementById(id); if (obj !== null) { if (typeof tier === "number") { if (tier > -1) { if (tier === 0) { //all_stack_menus_allow_hide(); //hide_all_stack_menus(); //position_stack_menu_1st_tier(obj, pid); //display_tier1_submenu(obj); //show_stack_menu(pid); //stack_menu_stay_visible(pid); } else if (tier > 0) { //all_stack_menus_allow_hide(); //hide_all_stack_menus(); //position_stack_menu_other_tiers(document.getElementById("menu_hasChildren_arrow_" + pid), pid); //display_sub_menu_items(id); //show_stack_menu(pid); //stack_menu_stay_visible(pid); } } } return; } else { menu_items = await getData3(base_path + pid); //grab the menu items' HTML menu_items = stack_menu_divWrapper(menu_items, pid); menu_items.style.position = "fixed"; //these menus will change location on the screen, so set the position to absolute menu_items.style.backgroundColor = "#d0d0d0"; //set the background to light grey menu_items.style.display = "none"; ////run this function again in 300 ms to check if ////requested menu items have been loaded and exist. //setTimeout(function () { // console.log("preloading: " + pid); // id = "stack_menu_div_wrapper_" + pid; // obj = document.getElementById(id); // if (obj === null) { // preload_menu_item(pid, tier); // } //}, 300); if (menu_items.childNodes.length > 0) { if (menu_items.tagName.toLowerCase() === "div") { top_menu_container_id = "top_menu_container"; top_menu_container = document.getElementById(top_menu_container_id); ////console.log("Menu Items Preloaded: " + menu_items.getAttribute("id")); //console.log("Menu Items Inner HTML: " + menu_items.innerHTML); if (top_menu_container !== null) { top_menu_container.appendChild(menu_items); } else { top_menu_container = make_top_menu_container(); if (top_menu_container !== null) { top_menu_container.appendChild(menu_items); } else { //error finding top_menu_container object } } id = "stack_menu_div_wrapper_" + pid; obj = document.getElementById(id); if (obj === null) { setTimeout(function () { console.log("preloading: " + pid); preload_menu_item(pid, tier); }, 100); } } } } return id; } async function inline_menu_item_mouseenter(inline_menu_item, pid, tier) { var menu_item = null; var stack_menu_exists = null; var menu_item_id = null; var is_active = null; is_active = is_menu_active(); menu_item = inline_menu_item; if (menu_item !== null) { stack_menu_exists = object_exists("stack_menu_div_wrapper_" + pid); if (stack_menu_exists === true) { all_stack_menus_allow_hide(); hide_all_stack_menus(); if (is_active === true) { display_tier1_submenu(menu_item); show_stack_menu(pid); stack_menu_stay_visible(pid); } } else if (stack_menu_exists === false) { menu_item_id = await preload_menu_item(pid, tier); if (document.getElementById(menu_item_id) !== null) { all_stack_menus_allow_hide(); hide_all_stack_menus(); if (is_active === true) { display_tier1_submenu(menu_item); show_stack_menu(pid); stack_menu_stay_visible(pid); } } } } } async function inline_menu_item_mousedown(inline_menu_item, pid, tier) { var menu_item = null; var stack_menu_exists = null; var menu_item_id = null; var is_active = null; //When the top menu is being interacted with, //place blank images over every web window's //content to avoid interacting with it. //function is located in file: ui_interaction_window_content_block.js block_all_window_content_containers(); is_active = is_menu_active(); menu_item = inline_menu_item; if (menu_item !== null) { stack_menu_exists = object_exists("stack_menu_div_wrapper_" + pid); if (stack_menu_exists === true) { if (is_active === true) { display_tier1_submenu(menu_item); show_stack_menu(pid); stack_menu_stay_visible(pid); } } else if (stack_menu_exists === false) { menu_item_id = await preload_menu_item(pid, tier); if (document.getElementById(menu_item_id) !== null) { if (is_active === true) { display_tier1_submenu(menu_item); show_stack_menu(pid); stack_menu_stay_visible(pid); } } } } } async function inline_menu_item_mouseup(inline_menu_item, pid, tier) { var menu_item = null; var stack_menu_exists = null; var menu_item_id = null; var is_active = null; set_is_menu_active_true(); menu_item = inline_menu_item; if (menu_item !== null) { stack_menu_exists = object_exists("stack_menu_div_wrapper_" + pid); if (stack_menu_exists === true) { display_tier1_submenu(menu_item); show_stack_menu(pid); stack_menu_stay_visible(pid); } else if (stack_menu_exists === false) { menu_item_id = await preload_menu_item(pid, tier); if (document.getElementById(menu_item_id) !== null) { display_tier1_submenu(menu_item); show_stack_menu(pid); stack_menu_stay_visible(pid); } } } } function object_exists(id) { var obj = null; var exists = null; obj = document.getElementById(id); if (obj !== null) { exists = true; } else { exists = false; } return exists; } async function get_top_menu_html() { var url = null; var content_holder = null; var responseText = null; var body_obj = null; var html = null; url = "/chromosphere/scripts/js/ui/topmenu/Default"; responseText = await getData3(url); content_holder = document.createElement("div"); content_holder.innerHTML = responseText; body_obj = content_holder.getElementsByTagName("body")[0]; html = body_obj.innerHTML; //alert(html); return null; } /* The following functions deal with the main menu MODES (e.g. data-is_menu_active="true"). * The menu is either active, or inactive. When clicking on a top inline menu item, * the main menu is set to active (i.e. "data-is_menu_active='true';"). When the user clicks on * anything other than the main menu iteself, the menu's "active mode" turns to false. This * prevents the menu items from popping up when the user is not making use of the main menu. */ function set_is_menu_active_true() { var main_menu_container = null; main_menu_container = document.getElementById("top_menu_container"); if (main_menu_container !== null) { main_menu_container.setAttribute("data-is_menu_active", "true"); } } function set_is_menu_active_false() { var main_menu_container = null; main_menu_container = document.getElementById("top_menu_container"); if (main_menu_container !== null) { main_menu_container.setAttribute("data-is_menu_active", "false"); } } //find out if the menu is in an active more, or not function is_menu_active() { var main_menu_container = null; var is_menu_active = null; main_menu_container = document.getElementById("top_menu_container"); if (main_menu_container !== null) { is_menu_active = main_menu_container.getAttribute("data-is_menu_active"); if (is_menu_active === "true") { return true; } else if (is_menu_active === "false") { return false; } } }