Synchronize with Etiquette.
This commit is contained in:
		
							parent
							
								
									ec19301bcc
								
							
						
					
					
						commit
						76b1504353
					
				
					 3 changed files with 238 additions and 203 deletions
				
			
		|  | @ -201,17 +201,26 @@ button:active | ||||||
| 
 | 
 | ||||||
| #message_area | #message_area | ||||||
| { | { | ||||||
|     display: flex; |     display: grid; | ||||||
|     flex-direction: column; |     grid-auto-flow: row; | ||||||
|     align-items: center; |     grid-auto-rows: min-content; | ||||||
|  |     grid-gap: 8px; | ||||||
|  |     padding: 8px; | ||||||
|     overflow-y: auto; |     overflow-y: auto; | ||||||
|     background-color: var(--color_transparency); |     background-color: var(--color_transparency); | ||||||
| } | } | ||||||
|  | #message_area > :last-child | ||||||
|  | { | ||||||
|  |     /* | ||||||
|  |     For some reason, the message_area's 8px padding doesn't apply to the bottom | ||||||
|  |     when the container is scrolled. | ||||||
|  |     */ | ||||||
|  |     margin-bottom: 8px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .message_bubble | .message_bubble | ||||||
| { | { | ||||||
|     width: 80%; |     padding: 2px; | ||||||
|     margin: 4px; |  | ||||||
| 
 |  | ||||||
|     word-wrap: break-word; |     word-wrap: break-word; | ||||||
| } | } | ||||||
| .message_bubble * | .message_bubble * | ||||||
|  |  | ||||||
|  | @ -1,12 +1,12 @@ | ||||||
| var common = {}; | const common = {}; | ||||||
| 
 | 
 | ||||||
| common.INPUT_TYPES = new Set(["INPUT", "TEXTAREA"]); | common.INPUT_TYPES = new Set(["INPUT", "TEXTAREA"]); | ||||||
| 
 | 
 | ||||||
| common._request = | common._request = | ||||||
| function _request(method, url, callback) | function _request(method, url, callback) | ||||||
| { | { | ||||||
|     let request = new XMLHttpRequest(); |     const request = new XMLHttpRequest(); | ||||||
|     let response = { |     const response = { | ||||||
|         "completed": false, |         "completed": false, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  | @ -29,7 +29,7 @@ function _request(method, url, callback) | ||||||
|         } |         } | ||||||
|         callback(response); |         callback(response); | ||||||
|     }; |     }; | ||||||
|     let asynchronous = true; |     const asynchronous = true; | ||||||
|     request.open(method, url, asynchronous); |     request.open(method, url, asynchronous); | ||||||
|     return request; |     return request; | ||||||
| } | } | ||||||
|  | @ -61,7 +61,7 @@ function bind_box_to_button(box, button, ctrl_enter) | ||||||
|     Thanks Yaroslav Yakovlev |     Thanks Yaroslav Yakovlev | ||||||
|     http://stackoverflow.com/a/9343095
 |     http://stackoverflow.com/a/9343095
 | ||||||
|     */ |     */ | ||||||
|     let bound_box_hook = function(event) |     const bound_box_hook = function(event) | ||||||
|     { |     { | ||||||
|         if (event.key !== "Enter") |         if (event.key !== "Enter") | ||||||
|             {return;} |             {return;} | ||||||
|  | @ -83,9 +83,9 @@ function create_message_bubble(message_area, message_positivity, message_text, l | ||||||
|     { |     { | ||||||
|         lifespan = 8000; |         lifespan = 8000; | ||||||
|     } |     } | ||||||
|     let message = document.createElement("div"); |     const message = document.createElement("div"); | ||||||
|     message.className = "message_bubble " + message_positivity; |     message.className = "message_bubble " + message_positivity; | ||||||
|     let span = document.createElement("span"); |     const span = document.createElement("span"); | ||||||
|     span.innerHTML = message_text; |     span.innerHTML = message_text; | ||||||
|     message.appendChild(span); |     message.appendChild(span); | ||||||
|     message_area.appendChild(message); |     message_area.appendChild(message); | ||||||
|  | @ -168,13 +168,13 @@ function entry_with_history_hook(event) | ||||||
| common.html_to_element = | common.html_to_element = | ||||||
| function html_to_element(html) | function html_to_element(html) | ||||||
| { | { | ||||||
|     let template = document.createElement("template"); |     const template = document.createElement("template"); | ||||||
|     template.innerHTML = html; |     template.innerHTML = html.trim(); | ||||||
|     return template.content.firstChild; |     return template.content.firstElementChild; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| common.init_atag_merge_params = | common.init_atag_merge_params = | ||||||
| function init_atag_merge_params() | function init_atag_merge_params(a) | ||||||
| { | { | ||||||
|     /* |     /* | ||||||
|     To create an <a> tag where the ?parameters written on the href are merged |     To create an <a> tag where the ?parameters written on the href are merged | ||||||
|  | @ -195,42 +195,47 @@ function init_atag_merge_params() | ||||||
|         href: "?orderby=date" |         href: "?orderby=date" | ||||||
|         Result: "?filter=hello&orderby=date" |         Result: "?filter=hello&orderby=date" | ||||||
|     */ |     */ | ||||||
|     function ingest(params, new_params) |  | ||||||
|     { |  | ||||||
|         for (const [key, value] of params) { new_params.set(key, value); } |  | ||||||
|     } |  | ||||||
|     const page_params = Array.from(new URLSearchParams(window.location.search)); |     const page_params = Array.from(new URLSearchParams(window.location.search)); | ||||||
|     let as = Array.from(document.getElementsByClassName("merge_params")); |     let to_merge; | ||||||
|  | 
 | ||||||
|  |     if (a.dataset.mergeParams) | ||||||
|  |     { | ||||||
|  |         const keep = new Set(a.dataset.mergeParams.split(/[\s,]+/)); | ||||||
|  |         to_merge = page_params.filter(key_value => keep.has(key_value[0])); | ||||||
|  |         delete a.dataset.mergeParams; | ||||||
|  |     } | ||||||
|  |     else if (a.dataset.mergeParamsExcept) | ||||||
|  |     { | ||||||
|  |         const remove = new Set(a.dataset.mergeParamsExcept.split(/[\s,]+/)); | ||||||
|  |         to_merge = page_params.filter(key_value => (! remove.has(key_value[0]))); | ||||||
|  |         delete a.dataset.mergeParamsExcept; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         to_merge = page_params; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     to_merge = to_merge.concat(Array.from(new URLSearchParams(a.search))); | ||||||
|  |     const new_params = new URLSearchParams(); | ||||||
|  |     for (const [key, value] of to_merge) | ||||||
|  |         { new_params.set(key, value); } | ||||||
|  |     a.search = new_params.toString(); | ||||||
|  |     a.classList.remove("merge_params"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | common.init_all_atag_merge_params = | ||||||
|  | function init_all_atag_merge_params() | ||||||
|  | { | ||||||
|  |     const page_params = Array.from(new URLSearchParams(window.location.search)); | ||||||
|  |     const as = Array.from(document.getElementsByClassName("merge_params")); | ||||||
|     for (const a of as) |     for (const a of as) | ||||||
|     { |     { | ||||||
|         const a_params = new URLSearchParams(a.search); |         setTimeout(() => common.init_atag_merge_params(a), 0); | ||||||
|         const new_params = new URLSearchParams(); |  | ||||||
| 
 |  | ||||||
|         if (a.dataset.mergeParams) |  | ||||||
|         { |  | ||||||
|             let keep = new Set(a.dataset.mergeParams.split(/[\s,]+/)); |  | ||||||
|             ingest(page_params.filter(key_value => keep.has(key_value[0])), new_params); |  | ||||||
|             delete a.dataset.mergeParams; |  | ||||||
|         } |  | ||||||
|         else if (a.dataset.mergeParamsExcept) |  | ||||||
|         { |  | ||||||
|             let remove = new Set(a.dataset.mergeParamsExcept.split(/[\s,]+/)); |  | ||||||
|             ingest(page_params.filter(key_value => (! remove.has(key_value[0]))), new_params); |  | ||||||
|             delete a.dataset.mergeParamsExcept; |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             ingest(page_params, new_params); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         ingest(a_params, new_params); |  | ||||||
|         a.search = new_params.toString(); |  | ||||||
|         a.classList.remove("merge_params"); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| common.init_button_with_confirm = | common.init_button_with_confirm = | ||||||
| function init_button_with_confirm() | function init_button_with_confirm(button) | ||||||
| { | { | ||||||
|     /* |     /* | ||||||
|     To create a button that requires a second confirmation step, assign it the |     To create a button that requires a second confirmation step, assign it the | ||||||
|  | @ -262,192 +267,213 @@ function init_button_with_confirm() | ||||||
| 
 | 
 | ||||||
|         data-holder-class: CSS class for the new span that holds the menu. |         data-holder-class: CSS class for the new span that holds the menu. | ||||||
|     */ |     */ | ||||||
|     let buttons = Array.from(document.getElementsByClassName("button_with_confirm")); |     button.classList.remove("button_with_confirm"); | ||||||
|  | 
 | ||||||
|  |     const holder = document.createElement("span"); | ||||||
|  |     holder.className = "confirm_holder " + (button.dataset.holderClass || ""); | ||||||
|  |     button.parentElement.insertBefore(holder, button); | ||||||
|  | 
 | ||||||
|  |     const holder_stage1 = document.createElement("span"); | ||||||
|  |     holder_stage1.className = "confirm_holder_stage1"; | ||||||
|  |     holder_stage1.appendChild(button); | ||||||
|  |     holder.appendChild(holder_stage1); | ||||||
|  | 
 | ||||||
|  |     const holder_stage2 = document.createElement("span"); | ||||||
|  |     holder_stage2.className = "confirm_holder_stage2 hidden"; | ||||||
|  |     holder.appendChild(holder_stage2); | ||||||
|  | 
 | ||||||
|  |     let prompt; | ||||||
|  |     let input_source; | ||||||
|  |     if (button.dataset.isInput) | ||||||
|  |     { | ||||||
|  |         prompt = document.createElement("input"); | ||||||
|  |         prompt.placeholder = button.dataset.prompt || ""; | ||||||
|  |         input_source = prompt; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         prompt = document.createElement("span"); | ||||||
|  |         prompt.innerText = (button.dataset.prompt || "Are you sure?") + " "; | ||||||
|  |         input_source = undefined; | ||||||
|  |     } | ||||||
|  |     prompt.className = button.dataset.promptClass || ""; | ||||||
|  |     holder_stage2.appendChild(prompt) | ||||||
|  |     delete button.dataset.prompt; | ||||||
|  |     delete button.dataset.promptClass; | ||||||
|  | 
 | ||||||
|  |     const button_confirm = document.createElement("button"); | ||||||
|  |     button_confirm.innerText = (button.dataset.confirm || button.innerText).trim(); | ||||||
|  |     if (button.dataset.confirmClass === undefined) | ||||||
|  |     { | ||||||
|  |         button_confirm.className = button.className; | ||||||
|  |         button_confirm.classList.remove("button_with_confirm"); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         button_confirm.className = button.dataset.confirmClass; | ||||||
|  |     } | ||||||
|  |     button_confirm.input_source = input_source; | ||||||
|  |     holder_stage2.appendChild(button_confirm); | ||||||
|  |     holder_stage2.appendChild(document.createTextNode(" ")); | ||||||
|  |     if (button.dataset.isInput) | ||||||
|  |     { | ||||||
|  |         common.bind_box_to_button(prompt, button_confirm); | ||||||
|  |     } | ||||||
|  |     delete button.dataset.confirm; | ||||||
|  |     delete button.dataset.confirmClass; | ||||||
|  |     delete button.dataset.isInput; | ||||||
|  | 
 | ||||||
|  |     const button_cancel = document.createElement("button"); | ||||||
|  |     button_cancel.innerText = button.dataset.cancel || "Cancel"; | ||||||
|  |     button_cancel.className = button.dataset.cancelClass || ""; | ||||||
|  |     holder_stage2.appendChild(button_cancel); | ||||||
|  |     delete button.dataset.cancel; | ||||||
|  |     delete button.dataset.cancelClass; | ||||||
|  | 
 | ||||||
|  |     // If this is stupid, let me know.
 | ||||||
|  |     const confirm_onclick = ` | ||||||
|  |         let holder = event.target.parentElement.parentElement; | ||||||
|  |         holder.getElementsByClassName("confirm_holder_stage1")[0].classList.remove("hidden"); | ||||||
|  |         holder.getElementsByClassName("confirm_holder_stage2")[0].classList.add("hidden"); | ||||||
|  |     ` + button.dataset.onclick;
 | ||||||
|  |     button_confirm.onclick = Function(confirm_onclick); | ||||||
|  | 
 | ||||||
|  |     button.removeAttribute("onclick"); | ||||||
|  |     button.onclick = function(event) | ||||||
|  |     { | ||||||
|  |         const holder = event.target.parentElement.parentElement; | ||||||
|  |         holder.getElementsByClassName("confirm_holder_stage1")[0].classList.add("hidden"); | ||||||
|  |         holder.getElementsByClassName("confirm_holder_stage2")[0].classList.remove("hidden"); | ||||||
|  |         const input = holder.getElementsByTagName("input")[0]; | ||||||
|  |         if (input) | ||||||
|  |         { | ||||||
|  |             input.focus(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     button_cancel.onclick = function(event) | ||||||
|  |     { | ||||||
|  |         const holder = event.target.parentElement.parentElement; | ||||||
|  |         holder.getElementsByClassName("confirm_holder_stage1")[0].classList.remove("hidden"); | ||||||
|  |         holder.getElementsByClassName("confirm_holder_stage2")[0].classList.add("hidden"); | ||||||
|  |     } | ||||||
|  |     delete button.dataset.onclick; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | common.init_all_button_with_confirm = | ||||||
|  | function init_all_button_with_confirm() | ||||||
|  | { | ||||||
|  |     const buttons = Array.from(document.getElementsByClassName("button_with_confirm")); | ||||||
|     for (const button of buttons) |     for (const button of buttons) | ||||||
|     { |     { | ||||||
|         button.classList.remove("button_with_confirm"); |         setTimeout(() => common.init_button_with_confirm(button), 0); | ||||||
| 
 |  | ||||||
|         let holder = document.createElement("span"); |  | ||||||
|         holder.classList.add("confirm_holder"); |  | ||||||
|         holder.classList.add(button.dataset.holderClass || "confirm_holder"); |  | ||||||
|         button.parentElement.insertBefore(holder, button); |  | ||||||
|         button.parentElement.removeChild(button); |  | ||||||
| 
 |  | ||||||
|         let holder_stage1 = document.createElement("span"); |  | ||||||
|         holder_stage1.classList.add("confirm_holder_stage1"); |  | ||||||
|         holder_stage1.appendChild(button); |  | ||||||
|         holder.appendChild(holder_stage1); |  | ||||||
| 
 |  | ||||||
|         let holder_stage2 = document.createElement("span"); |  | ||||||
|         holder_stage2.classList.add("confirm_holder_stage2"); |  | ||||||
|         holder_stage2.classList.add("hidden"); |  | ||||||
|         holder.appendChild(holder_stage2); |  | ||||||
| 
 |  | ||||||
|         let prompt; |  | ||||||
|         let input_source; |  | ||||||
|         if (button.dataset.isInput) |  | ||||||
|         { |  | ||||||
|             prompt = document.createElement("input"); |  | ||||||
|             prompt.placeholder = button.dataset.prompt || ""; |  | ||||||
|             input_source = prompt; |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             prompt = document.createElement("span"); |  | ||||||
|             prompt.innerText = (button.dataset.prompt || "Are you sure?") + " "; |  | ||||||
|             input_source = undefined; |  | ||||||
|         } |  | ||||||
|         prompt.className = button.dataset.promptClass || ""; |  | ||||||
|         holder_stage2.appendChild(prompt) |  | ||||||
|         delete button.dataset.prompt; |  | ||||||
|         delete button.dataset.promptClass; |  | ||||||
| 
 |  | ||||||
|         let button_confirm = document.createElement("button"); |  | ||||||
|         button_confirm.innerText = (button.dataset.confirm || button.innerText).trim(); |  | ||||||
|         if (button.dataset.confirmClass === undefined) |  | ||||||
|         { |  | ||||||
|             button_confirm.className = button.className; |  | ||||||
|             button_confirm.classList.remove("button_with_confirm"); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             button_confirm.className = button.dataset.confirmClass; |  | ||||||
|         } |  | ||||||
|         button_confirm.input_source = input_source; |  | ||||||
|         holder_stage2.appendChild(button_confirm); |  | ||||||
|         holder_stage2.appendChild(document.createTextNode(" ")); |  | ||||||
|         if (button.dataset.isInput) |  | ||||||
|         { |  | ||||||
|             common.bind_box_to_button(prompt, button_confirm); |  | ||||||
|         } |  | ||||||
|         delete button.dataset.confirm; |  | ||||||
|         delete button.dataset.confirmClass; |  | ||||||
|         delete button.dataset.isInput; |  | ||||||
| 
 |  | ||||||
|         let button_cancel = document.createElement("button"); |  | ||||||
|         button_cancel.innerText = button.dataset.cancel || "Cancel"; |  | ||||||
|         button_cancel.className = button.dataset.cancelClass || ""; |  | ||||||
|         holder_stage2.appendChild(button_cancel); |  | ||||||
|         delete button.dataset.cancel; |  | ||||||
|         delete button.dataset.cancelClass; |  | ||||||
| 
 |  | ||||||
|         // If this is stupid, let me know.
 |  | ||||||
|         let confirm_onclick = button.dataset.onclick + ` |  | ||||||
|             ; |  | ||||||
|             let holder = event.target.parentElement.parentElement; |  | ||||||
|             holder.getElementsByClassName("confirm_holder_stage1")[0].classList.remove("hidden"); |  | ||||||
|             holder.getElementsByClassName("confirm_holder_stage2")[0].classList.add("hidden"); |  | ||||||
|         ` |  | ||||||
|         button_confirm.onclick = Function(confirm_onclick); |  | ||||||
|         button.removeAttribute("onclick"); |  | ||||||
|         button.onclick = function(event) |  | ||||||
|         { |  | ||||||
|             let holder = event.target.parentElement.parentElement; |  | ||||||
|             holder.getElementsByClassName("confirm_holder_stage1")[0].classList.add("hidden"); |  | ||||||
|             holder.getElementsByClassName("confirm_holder_stage2")[0].classList.remove("hidden"); |  | ||||||
|             let input = holder.getElementsByTagName("input")[0]; |  | ||||||
|             if (input) |  | ||||||
|             { |  | ||||||
|                 input.focus(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         button_cancel.onclick = function(event) |  | ||||||
|         { |  | ||||||
|             let holder = event.target.parentElement.parentElement; |  | ||||||
|             holder.getElementsByClassName("confirm_holder_stage1")[0].classList.remove("hidden"); |  | ||||||
|             holder.getElementsByClassName("confirm_holder_stage2")[0].classList.add("hidden"); |  | ||||||
|         } |  | ||||||
|         delete button.dataset.onclick; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| common.init_enable_on_pageload = | common.init_enable_on_pageload = | ||||||
| function init_enable_on_pageload() | function init_enable_on_pageload(element) | ||||||
| { | { | ||||||
|     /* |     /* | ||||||
|     To create an input element which is disabled at first, and is enabled when |     To create an input element which is disabled at first, and is enabled when | ||||||
|     the DOM has completed loading, give it the disabled attribute and the |     the DOM has completed loading, give it the disabled attribute and the | ||||||
|     class "enable_on_pageload". |     class "enable_on_pageload". | ||||||
|     */ |     */ | ||||||
|     let elements = Array.from(document.getElementsByClassName("enable_on_pageload")); |     element.disabled = false; | ||||||
|  |     element.classList.remove("enable_on_pageload"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | common.init_all_enable_on_pageload = | ||||||
|  | function init_all_enable_on_pageload() | ||||||
|  | { | ||||||
|  |     const elements = Array.from(document.getElementsByClassName("enable_on_pageload")); | ||||||
|     for (const element of elements) |     for (const element of elements) | ||||||
|     { |     { | ||||||
|         element.disabled = false; |         setTimeout(() => common.init_enable_on_pageload(element), 0); | ||||||
|         element.classList.remove("enable_on_pageload"); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| common.init_entry_with_history = | common.init_entry_with_history = | ||||||
| function init_entry_with_history() | function init_entry_with_history(input) | ||||||
|  | { | ||||||
|  |     input.addEventListener("keydown", common.entry_with_history_hook); | ||||||
|  |     input.classList.remove("entry_with_history"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | common.init_all_entry_with_history = | ||||||
|  | function init_all_entry_with_history() | ||||||
| { | { | ||||||
|     const inputs = Array.from(document.getElementsByClassName("entry_with_history")); |     const inputs = Array.from(document.getElementsByClassName("entry_with_history")); | ||||||
|     for (const input of inputs) |     for (const input of inputs) | ||||||
|     { |     { | ||||||
|         input.addEventListener("keydown", common.entry_with_history_hook); |         setTimeout(() => common.init_entry_with_history(input), 0); | ||||||
|         input.classList.remove("entry_with_history"); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| common.init_tabbed_container = | common.init_tabbed_container = | ||||||
| function init_tabbed_container() | function init_tabbed_container(tabbed_container) | ||||||
| { | { | ||||||
|     let switch_tab = |     const button_container = document.createElement("div"); | ||||||
|     function switch_tab(event) |     button_container.className = "tab_buttons"; | ||||||
|  |     tabbed_container.prepend(button_container); | ||||||
|  |     const tabs = Array.from(tabbed_container.getElementsByClassName("tab")); | ||||||
|  |     for (const tab of tabs) | ||||||
|     { |     { | ||||||
|         let tab_button = event.target; |         tab.classList.add("hidden"); | ||||||
|         if (tab_button.classList.contains("tab_button_active")) |         const tab_id = tab.dataset.tabId || tab.dataset.tabTitle; | ||||||
|             { return; } |         tab.dataset.tabId = tab_id; | ||||||
|  |         tab.style.borderTopColor = "transparent"; | ||||||
| 
 | 
 | ||||||
|         let tab_id = tab_button.dataset.tabId; |         const button = document.createElement("button"); | ||||||
|         let tab_buttons = tab_button.parentElement.getElementsByClassName("tab_button"); |         button.className = "tab_button tab_button_inactive"; | ||||||
|         let tabs = tab_button.parentElement.parentElement.getElementsByClassName("tab"); |         button.onclick = common.tabbed_container_switcher; | ||||||
|         for (const tab_button of tab_buttons) |         button.innerText = tab.dataset.tabTitle; | ||||||
|         { |         button.dataset.tabId = tab_id; | ||||||
|             if (tab_button.dataset.tabId === tab_id) |         button_container.append(button); | ||||||
|             { |  | ||||||
|                 tab_button.classList.remove("tab_button_inactive"); |  | ||||||
|                 tab_button.classList.add("tab_button_active"); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 tab_button.classList.remove("tab_button_active"); |  | ||||||
|                 tab_button.classList.add("tab_button_inactive"); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         for (const tab of tabs) |  | ||||||
|         { |  | ||||||
|             if (tab.dataset.tabId === tab_id) |  | ||||||
|                 { tab.classList.remove("hidden"); } |  | ||||||
|             else |  | ||||||
|                 { tab.classList.add("hidden"); } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |     tabs[0].classList.remove("hidden"); | ||||||
|  |     button_container.firstElementChild.classList.remove("tab_button_inactive"); | ||||||
|  |     button_container.firstElementChild.classList.add("tab_button_active"); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     let tabbed_containers = Array.from(document.getElementsByClassName("tabbed_container")); | common.init_all_tabbed_container = | ||||||
|  | function init_all_tabbed_container() | ||||||
|  | { | ||||||
|  |     const tabbed_containers = Array.from(document.getElementsByClassName("tabbed_container")); | ||||||
|     for (const tabbed_container of tabbed_containers) |     for (const tabbed_container of tabbed_containers) | ||||||
|     { |     { | ||||||
|         let button_container = document.createElement("div"); |         setTimeout(() => common.init_tabbed_container(tabbed_container), 0); | ||||||
|         button_container.className = "tab_buttons"; |     } | ||||||
|         tabbed_container.prepend(button_container); | } | ||||||
|         let tabs = Array.from(tabbed_container.getElementsByClassName("tab")); |  | ||||||
|         for (const tab of tabs) |  | ||||||
|         { |  | ||||||
|             tab.classList.add("hidden"); |  | ||||||
|             let tab_id = tab.dataset.tabId || tab.dataset.tabTitle; |  | ||||||
|             tab.dataset.tabId = tab_id; |  | ||||||
|             tab.style.borderTopColor = "transparent"; |  | ||||||
| 
 | 
 | ||||||
|             let button = document.createElement("button"); | common.tabbed_container_switcher = | ||||||
|             button.className = "tab_button tab_button_inactive"; | function tabbed_container_switcher(event) | ||||||
|             button.onclick = switch_tab; | { | ||||||
|             button.innerText = tab.dataset.tabTitle; |     const tab_button = event.target; | ||||||
|             button.dataset.tabId = tab_id; |     if (tab_button.classList.contains("tab_button_active")) | ||||||
|             button_container.append(button); |         { return; } | ||||||
|  | 
 | ||||||
|  |     const tab_id = tab_button.dataset.tabId; | ||||||
|  |     const tab_buttons = tab_button.parentElement.getElementsByClassName("tab_button"); | ||||||
|  |     const tabs = tab_button.parentElement.parentElement.getElementsByClassName("tab"); | ||||||
|  |     for (const tab_button of tab_buttons) | ||||||
|  |     { | ||||||
|  |         if (tab_button.dataset.tabId === tab_id) | ||||||
|  |         { | ||||||
|  |             tab_button.classList.remove("tab_button_inactive"); | ||||||
|  |             tab_button.classList.add("tab_button_active"); | ||||||
|         } |         } | ||||||
|         tabs[0].classList.remove("hidden"); |         else | ||||||
|         button_container.firstElementChild.classList.remove("tab_button_inactive"); |         { | ||||||
|         button_container.firstElementChild.classList.add("tab_button_active"); |             tab_button.classList.remove("tab_button_active"); | ||||||
|  |             tab_button.classList.add("tab_button_inactive"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     for (const tab of tabs) | ||||||
|  |     { | ||||||
|  |         if (tab.dataset.tabId === tab_id) | ||||||
|  |             { tab.classList.remove("hidden"); } | ||||||
|  |         else | ||||||
|  |             { tab.classList.add("hidden"); } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -460,10 +486,10 @@ function refresh() | ||||||
| common.on_pageload = | common.on_pageload = | ||||||
| function on_pageload() | function on_pageload() | ||||||
| { | { | ||||||
|     common.init_atag_merge_params(); |     common.init_all_atag_merge_params(); | ||||||
|     common.init_button_with_confirm(); |     common.init_all_button_with_confirm(); | ||||||
|     common.init_enable_on_pageload(); |     common.init_all_enable_on_pageload(); | ||||||
|     common.init_entry_with_history(); |     common.init_all_entry_with_history(); | ||||||
|     common.init_tabbed_container(); |     common.init_all_tabbed_container(); | ||||||
| } | } | ||||||
| document.addEventListener("DOMContentLoaded", common.on_pageload); | document.addEventListener("DOMContentLoaded", common.on_pageload); | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| var spinner = {}; | const spinner = {}; | ||||||
| 
 | 
 | ||||||
| /* | /* | ||||||
| In general, spinners are used for functions that launch a callback, and the | In general, spinners are used for functions that launch a callback, and the | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue