window.state = window.state || {}; window.state.extensions = window.state.extensions || {}; state = window.state; function general_ext(tab_name, extension_name, root_container) { let container = root_container; let store = null; let cnTabs = []; let root_not_tabs = null; let cur_tab_name = tab_name; let ext_name = extension_name let LS_PREFIX = 'ext-'+ ext_name.replace(" ","-").toLowerCase() + "-" function handleToggle(addEvtLsner=true) { let value = store.get('toggled'); let toggleBtn = container.querySelector('div.cursor-pointer, .label-wrap'); //for(let toggleBtn of toggleBtns){ //if(!toggleBtn){continue} if(toggleBtn && toggleBtn.className.split(' ').pop() != "open"){ if (value && value === 'true') { state.utils.triggerEvent(toggleBtn, 'click'); //load(); } if(addEvtLsner) { toggleBtn.addEventListener('click', function () { let span = this.querySelector('.transition, .icon'); store.set('toggled', span.style.transform !== 'rotate(90deg)'); //load(); }); } } //} } function bindTabEvents(addEvtLsner=true) { const tabs = container.querySelectorAll('.tabs > div > button'); if(addEvtLsner) { tabs.forEach(tab => { // dirty hack here tab.removeEventListener('click', onTabClick); tab.addEventListener('click', onTabClick); }); } return tabs; } function handleTabs(addEvtLsner=true) { let tabs = bindTabEvents(addEvtLsner); let value = store.get('tab'); if (value) { for (var i = 0; i < tabs.length; i++) { let translations = state.utils.reverseTranslation(tabs[i].textContent) if (value in translations) { //if (tabs[i].textContent === value) { state.utils.triggerEvent(tabs[i], 'click'); break; } } } } function onTabClick() { store.set('tab', state.utils.reverseTranslation(this.textContent)[0]); bindTabEvents(); } function handleCheckbox(checkbox, store, addEvtLsner=true) { let label = checkbox.nextElementSibling; let translations = state.utils.reverseTranslation(label.textContent) for (var text of translations){ var id = state.utils.txtToId(text); var value = store.get(id); if (value) {break} } if (value) { state.utils.setValue(checkbox, value, 'change'); } if(addEvtLsner){ checkbox.addEventListener('change', function () { let label = checkbox.nextElementSibling; let translations = state.utils.reverseTranslation(label.textContent) for (var text of translations){ var id = state.utils.txtToId(text); store.set(id, this.checked); } }); } } function handleCheckboxes(addEvtLsner=true) { let root_checkboxes = root_not_tabs.container.querySelectorAll('input[type="checkbox"]'); root_checkboxes.forEach(function (root_checkbox) { if(cnTabs.length == 0){ handleCheckbox(root_checkbox, root_not_tabs.store, addEvtLsner) } else{ let needsHandle = true for(let tab of cnTabs){ if(tab.container.contains(root_checkbox)){ needsHandle = false break } } if(needsHandle){handleCheckbox(root_checkbox, root_not_tabs.store, addEvtLsner)} } // else }); cnTabs.forEach(({ container, store }) => { let checkboxes = container.querySelectorAll('input[type="checkbox"]'); checkboxes.forEach(function (checkbox) { handleCheckbox(checkbox, store, addEvtLsner) }); }); } function handleTextArea(textarea, index, store, addEvtLsner=true) { var id = state.utils.txtToId(`textarea_${index}`); var value = store.get(id); if (value) { state.utils.setValue(textarea, value, 'change'); } if(addEvtLsner){ textarea.addEventListener('change', function () { let text = this.value; store.set(id, text); //console.log(`id = ${id} value = ${text}`) }); } } function handleTextAreas(addEvtLsner=true) { let textArea_index = 0; // 因为文本框的顺序不会变,所以命名直接使用序号区分 "textarea_0" let root_textareas = root_not_tabs.container.querySelectorAll('textarea'); root_textareas.forEach(function (root_textarea) { if(cnTabs.length == 0){ handleTextArea(root_textarea, textArea_index, root_not_tabs.store, addEvtLsner) textArea_index += 1 } else{ let needsHandle = true for(let tab of cnTabs){ if(tab.container.contains(root_textarea)){ needsHandle = false break } } if(needsHandle){ handleTextArea(root_textarea, textArea_index, root_not_tabs.store, addEvtLsner) textArea_index += 1 } } // else }); cnTabs.forEach(({ container, store }) => { container.querySelectorAll('textarea').forEach(textarea => { handleTextArea(textarea, textArea_index, store, addEvtLsner) textArea_index += 1 }); }); } function handleSelect(select, store, addEvtLsner=true) { let translations = state.utils.reverseTranslation(select.querySelector('label').firstChild.textContent) for (var text of translations){ var id = state.utils.txtToId(text); var value = store.get(id); if (value) {break} } //id = state.utils.txtToId(translations[0]); //if (value) { //前面不需要判断是否有值,因为需要执行handleSelect绑定onchange事件 state.utils.handleSelect(select, id, store, force=true, addEvtLsner); //} // let id = state.constants.LS_PREFIX+LS_PREFIX+"dropdown_"+index // state.utils.onContentChange(select, function (el) { // console.log(`onContentChange ${id}`) // let selected = el.querySelector('span.single-select'); // if (selected) { // store.setWithNoPrefix(id, selected.textContent); // } else { // // new gradio version... // let input = el.querySelector('input'); // if (input) { // store.setWithNoPrefix(id, input.value); // } // } // }); if (id === 'preprocessor' && value && value.toLowerCase() !== 'none') { state.utils.onNextUiUpdates(handleSliders); // update new sliders if needed } } function handleSelects(addEvtLsner=true) { // let root_selects = root_not_tabs.container.querySelectorAll('.gradio-dropdown'); // root_selects.forEach(function (root_select) { // if(cnTabs.length == 0){ // handleSelect(root_select, global_dropdown_index[ext_name], root_not_tabs.store) // global_dropdown_index[ext_name] += 1 // console.log(`global_dropdown_index = ${global_dropdown_index[ext_name]}`) // } // else{ // let needsHandle = true // for(let tab of cnTabs){ // if(tab.container.contains(root_select)){ // needsHandle = false // break // } // } // if(needsHandle){ // handleSelect(root_select, global_dropdown_index[ext_name], root_not_tabs.store) // global_dropdown_index[ext_name] += 1 // console.log(`global_dropdown_index = ${global_dropdown_index[ext_name]}`) // } // } // else // }); // cnTabs.forEach(({ container, store }) => { // container.querySelectorAll('.gradio-dropdown').forEach(select => { // handleSelect(select, global_dropdown_index[ext_name], store) // global_dropdown_index[ext_name] += 1 // console.log(`global_dropdown_index = ${global_dropdown_index[ext_name]}`) // }); // }); let root_selects = root_not_tabs.container.querySelectorAll('.gradio-dropdown'); root_selects.forEach(function (root_select) { if(cnTabs.length == 0){ handleSelect(root_select, root_not_tabs.store, addEvtLsner) } else{ let needsHandle = true for(let tab of cnTabs){ if(tab.container.contains(root_select)){ needsHandle = false break } } if(needsHandle){handleSelect(root_select, root_not_tabs.store, addEvtLsner)} } // else }); cnTabs.forEach(({ container, store }) => { container.querySelectorAll('.gradio-dropdown').forEach(select => { handleSelect(select, store, addEvtLsner) }); }); } function handleSlider(slider, store, addEvtLsner=true) { let label = slider.previousElementSibling.querySelector('label span'); let translations = state.utils.reverseTranslation(label.textContent) for (var text of translations){ var id = state.utils.txtToId(text); var value = store.get(id); if (value) {break} } if (value) { state.utils.setValue(slider, value, 'change'); } if(addEvtLsner){ slider.addEventListener('change', function () { //store.set(id, state.utils.reverseTranslation(this.value)[0]); let label = slider.previousElementSibling.querySelector('label span'); let translations = state.utils.reverseTranslation(label.textContent) for (var text of translations){ var id = state.utils.txtToId(text); store.set(id, state.utils.reverseTranslation(this.value)[0]); } }); } } function handleSliders(addEvtLsner=true) { let root_sliders = root_not_tabs.container.querySelectorAll('input[type="range"]'); root_sliders.forEach(function (root_slider) { if(cnTabs.length == 0){ handleSlider(root_slider, root_not_tabs.store, addEvtLsner) } else{ let needsHandle = true for(let tab of cnTabs){ if(tab.container.contains(root_slider)){ needsHandle = false break } } if(needsHandle){handleSlider(root_slider, root_not_tabs.store, addEvtLsner)} } // else }); cnTabs.forEach(({ container, store }) => { let sliders = container.querySelectorAll('input[type="range"]'); sliders.forEach(function (slider) { handleSlider(slider, store, addEvtLsner) }); }); } function handleRadioButton(fieldset, store, addEvtLsner=true) { let label = fieldset.firstChild.nextElementSibling; let radios = fieldset.querySelectorAll('input[type="radio"]'); let translations = state.utils.reverseTranslation(label.textContent) for (var text of translations){ var id = state.utils.txtToId(text); var value = store.get(id); if (value) {break} } if (value) { radios.forEach(function (radio) { state.utils.setValue(radio, value, 'change'); }); } if(addEvtLsner){ radios.forEach(function (radio) { radio.addEventListener('change', function () { let label = fieldset.firstChild.nextElementSibling; let translations = state.utils.reverseTranslation(label.textContent) for (var text of translations){ var id = state.utils.txtToId(text); store.set(id, state.utils.reverseTranslation(this.value)[0]); } }); }); } } function handleRadioButtons(addEvtLsner=true) { let root_fieldsets = root_not_tabs.container.querySelectorAll('fieldset'); root_fieldsets.forEach(function (root_fieldset) { if(cnTabs.length == 0){ handleRadioButton(root_fieldset, root_not_tabs.store, addEvtLsner) } else{ let needsHandle = true for(let tab of cnTabs){ if(tab.container.contains(root_fieldset)){ needsHandle = false break } } if(needsHandle){handleRadioButton(root_fieldset, root_not_tabs.store, addEvtLsner)} } // else }); cnTabs.forEach(({ container, store }) => { let fieldsets = container.querySelectorAll('fieldset'); fieldsets.forEach(function (fieldset) { handleRadioButton(fieldset, store, addEvtLsner) }); }); } function load(addEvtLsner=true) { setTimeout(function () { handleTabs(addEvtLsner); handleCheckboxes(addEvtLsner); handleTextAreas(addEvtLsner); if(state.utils.target_is_newer_version(state.core.actions.get_sd_version(), "v1.6.0")){ //console.log("-----------general handleSelects-------") handleSelects(addEvtLsner); } handleSliders(addEvtLsner); handleRadioButtons(addEvtLsner); }, 500); } function init(addEvtLsner=true) { store = new state.Store(LS_PREFIX + cur_tab_name); if (! container) { return; } let tabnav = container.getElementsByClassName('tabs'); let tabs = [] if(tabnav.length > 0 ){ tabs = Array.from(tabnav[0].childNodes).filter(item => item.className && item.className.indexOf("tabitem") !== -1) } cnTabs = []; if (tabs.length) { tabs.forEach((tabContainer, i) => { cnTabs.push({ container: tabContainer, store: new state.Store(LS_PREFIX + cur_tab_name + "_" + i) }); }); } //else { root_not_tabs = { container: container, store: new state.Store(LS_PREFIX + cur_tab_name) } //} handleToggle(addEvtLsner); load(addEvtLsner); } return { init,LS_PREFIX }; } function general_ext_main(tab){ let cur_tab_name = tab let general_ext_list = [] // 遍历第一级子节点 每个节点选出一个层级最小且innerText不为空的子节点 function walks_element(element, cur_gen){ if(element.innerText != "" && element.innerText != undefined && element.children.length == 0){ return [[element.innerText,cur_gen]] } let res = [] for(child of element.children){ res = res.concat(walks_element(child,cur_gen+1,res)) } return res } function init(core_mode = true, addEvtLsner=true) { console.log(`------------${cur_tab_name}----init--- addEvtLsner=${addEvtLsner} ----`) if(addEvtLsner==false) { for (let obj of general_ext_list) { obj.init(addEvtLsner); } return } let container = gradioApp().getElementById(cur_tab_name+'_script_container'); // main container let extensions_root = container.children if(extensions_root.length > 0 && extensions_root[0].className.split(' ')[0] != "gr-group" && extensions_root[0].className.split(' ')[0] != "gradio-group"){ extensions_root = extensions_root[0].children // webui v1.6.0 版本,UI结构有变更 } //console.log(extensions_root) for (child of extensions_root){ let root_container = child res = walks_element(child, 0) let min_gen = 99 let title = undefined for(pair of res){ if(pair[1] < min_gen){ min_gen = pair[1] title = pair[0] } } if(title == undefined || title.toLowerCase() == "lightdiffusionflow" // 自己存自己就不用了 ){continue} let translations = state.utils.reverseTranslation(title) title = translations[0] // 标题翻译一般只会有一个? if(title.toLowerCase() == 'script'){break} // script后面的面板暂时不考虑 console.log(title) reg = /(.+) v[0-9\.]+/ if(reg.test(title)){title = RegExp.$1} // 匹配 xxx v0.0.0 格式的标题,把后半部分的版本号去掉 if(title == "ControlNet"){title = "Control Net"} // 兼容旧命名 else{ if(core_mode){continue} } let ext_name = title.replace(" ","-").toLowerCase() console.log(ext_name) // if(!global_dropdown_index[ext_name]){ // global_dropdown_index[ext_name] = 0 // } general_ext_obj = general_ext(cur_tab_name, ext_name, root_container) general_ext_list.push(general_ext_obj) general_ext_obj.init(addEvtLsner); } } return {init} } //global_dropdown_index = {} // py里是不分txt2img和img2img的,但是这里是需要区分的。。 const TABS = ['txt2img', 'img2img']; for (tab of TABS){ state.extensions[`${tab}-ext-general`] = general_ext_main(tab); }