File size: 10,138 Bytes
7bed60d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
// Create a variable to track if the code has been run yet
var rsen_init = false;

// Icon
var rsen_extra_networks_symbol = '🎴';

// Keep track of toggle state
var rsen_toggleState = false;

var rsen_lastTxt2imgTabButton;
var rsen_lastImg2imgTabButton;

var rsen_lastGenerationTabGridTemplateTxt2img = {
  saved: "1fr 16px 1fr"
}
var rsen_lastGenerationTabGridTemplateImg2img = {
  saved: "1fr 16px 1fr"
};

// This function is automatically called by automatic1111 when the UI is loaded
onUiLoaded(function() {
  // This code should only be run once, so if init is true dont do anything. Init is set after we complete this the first time.
  if(!rsen_init) {
    // Get all the elements you are interested in and put them into an object to make the later code a bit cleaner
    let settingsObjects = [
      { // Text2Image elements
        tools: document.getElementById('txt2img_tools'),
        last_button:  document.getElementById('txt2img_style_apply'),
        generation_tab: document.getElementById('txt2img_settings').parentNode.parentNode,
        generation_tab_att_id: 'txt2img_generation_tab',
        new_id: 'txt2img_toggle_extra'
      },
      { // Image2Image elements
        tools: document.getElementById('img2img_tools'),
        last_button:  document.getElementById('deepbooru'),
        generation_tab: document.getElementById('img2img_settings').parentNode.parentNode,
        generation_tab_att_id: 'img2img_generation_tab',
        new_id: 'img2img_toggle_extra'
      }
    ];
    if(typeof settingsObjects[0].last_button != "undefined" && typeof settingsObjects[1].last_button != "undefined") {
      // Loop through each object in the array we created earlier
      settingsObjects.forEach(obj => {
        // Do init code
        let newButton = obj.last_button.cloneNode(false); // Duplicate the last_button
        newButton.id = obj.new_id; // Change the id to new_id
        newButton.title = "Toggle Extra Networks."; // Change the title
        newButton.innerHTML = rsen_extra_networks_symbol; // Change the innerHTML

        obj.last_button.parentNode.insertBefore(newButton, obj.last_button.nextSibling); // Insert the new button after the last_button

        newButton.onclick = () => rsen_toggleExtraNetworks(); // Add new click event

        // Set an id for the inner generation tab div and parent div
				obj.generation_tab.setAttribute("sd-enr-id", obj.generation_tab_att_id);
				obj.generation_tab.parentNode.setAttribute("sd-enr-id", obj.generation_tab_att_id + "_parent");
      });
      
      // Now that we are done, set init to true so that it doesn't run more than once
      rsen_init = true;
    }
  }
});

function getText_ExtraNetworksSidePanel(text) {
    let tl = getTranslation(text);
    return tl !== undefined ? tl.trim() : text.trim();
}

function rsen_toggleExtraNetworks() {
	// Get all the elements you are interested in and put them into an object to make the later code a bit cleaner
	let settingsObjects = [
		{ // Text2Image elements
			all_tabs: document.getElementById('txt2img_extra_tabs'),
			generation_tab_parent: document.querySelector('[sd-enr-id="txt2img_generation_tab_parent"]'),
			generation_tab: document.querySelector('[sd-enr-id="txt2img_generation_tab"]'),
			generation_tab_resize: document.getElementById('txt2img_generation_tab_resize'),
			generation_tab_resize_id: 'txt2img_generation_tab_resize',
			tab_nav: document.querySelector('#txt2img_extra_tabs > .tab-nav'),
      lastTabButton: rsen_lastTxt2imgTabButton,
      lastGridTemplate: rsen_lastGenerationTabGridTemplateTxt2img
		},
		{ // Image2Image elements
			all_tabs: document.getElementById('img2img_extra_tabs'),
			generation_tab_parent: document.querySelector('[sd-enr-id="img2img_generation_tab_parent"]'),
			generation_tab: document.querySelector('[sd-enr-id="img2img_generation_tab"]'),
			generation_tab_resize: document.getElementById('img2img_generation_tab_resize'),
			generation_tab_resize_id: 'img2img_generation_tab_resize',
			tab_nav: document.querySelector('#img2img_extra_tabs > .tab-nav'),
      lastTabButton: rsen_lastImg2imgTabButton,
      lastGridTemplate: rsen_lastGenerationTabGridTemplateImg2img
		}
	];

	if (typeof settingsObjects[0].generation_tab != "undefined" && typeof settingsObjects[1].generation_tab != "undefined") {
		// Loop through each object in the array we created earlier
		settingsObjects.forEach(obj => {
			// Find the tab buttons with the text for the default tab and "Generation" tab
      let tabButtons = Array.from(obj.tab_nav.querySelectorAll('button'))
			let defaultTabButton = tabButtons.find(button => button.innerHTML.trim() === getText_ExtraNetworksSidePanel(opts.extra_networks_side_panel_default_tab));
			let generationButton = tabButtons.find(button => button.innerHTML.trim() === getText_ExtraNetworksSidePanel("Generation"));
      
			let lastTabButton;
      if (typeof obj.lastTabButton !== "undefined") {
        lastTabButton = Array.from(obj.tab_nav.querySelectorAll('button')).find(button => button.innerHTML.trim() === obj.lastTabButton.innerHTML.trim());
      }

			if (generationButton) {
				if (!rsen_toggleState) {
          if (defaultTabButton && typeof lastTabButton === "undefined") {
					  // Click the default tab button
					  defaultTabButton.click();
          } else {
            // Switch to the last tab open
            lastTabButton.click();
          }

          obj.all_tabs.parentNode.setAttribute("restore-separate-extra-network","");

					// Move the generation_tab node to be before the all_tabs node
					obj.all_tabs.parentNode.insertBefore(obj.generation_tab, obj.all_tabs);

          let resizeDiv = document.createElement('div');
          resizeDiv.setAttribute('id', obj.generation_tab_resize_id);

					obj.all_tabs.parentNode.insertBefore(resizeDiv, obj.all_tabs);

          // on mouse down (drag start)
          resizeDiv.onmousedown = function dragMouseDown(e) {
            // get position of mouse
            let dragX = e.clientX;
            // register a mouse move listener if mouse is down
            document.onmousemove = function onMouseMove(e) {
              // e.clientX will be the position of the mouse as it has moved a bit now
              let newWidth = obj.generation_tab.offsetWidth + e.clientX - dragX;
              let maxWidth = obj.all_tabs.parentNode.offsetWidth - 400;
              
              if (newWidth > 200 && newWidth < maxWidth) {
                // offsetWidth is the width of the block-1
                obj.generation_tab.style.width = newWidth  + "px";
                // update variable - till this pos, mouse movement has been handled
                dragX = e.clientX;
              }
            }
            // remove mouse-move listener on mouse-up (drag is finished now)
            document.onmouseup = () => document.onmousemove = document.onmouseup = null;
          }

          // Find the index of the generationButton within its parent node
					let generationButtonIndex = Array.from(obj.tab_nav.children).indexOf(generationButton) + 1;

					// Hide the "Generation" tab button
					obj.tab_nav.setAttribute("important-hide", generationButtonIndex.toString());

          // Allow the generation tab to be resized horizontally
          obj.generation_tab.style.overflowX = 'auto';
          obj.generation_tab.style.width = '';

          // Reset the grid columns for the generation tab incase user made the columns too large
          if(obj.generation_tab.firstElementChild) {
            let tempVal = obj.generation_tab.firstElementChild.style.gridTemplateColumns;
            obj.generation_tab.firstElementChild.style.gridTemplateColumns = obj.lastGridTemplate.saved;
            obj.lastGridTemplate.saved = tempVal;
          }
				} else {
					// Show the "Generation" button
					obj.tab_nav.removeAttribute("important-hide");

          obj.all_tabs.parentNode.removeAttribute("restore-separate-extra-network","");

					// Move the generation_tab node back to its parent
					obj.generation_tab_parent.appendChild(obj.generation_tab);

          // Allow the generation tab to be resized horizontally
          obj.generation_tab.style.overflowX = '';
          obj.generation_tab.style.width = '';

          obj.generation_tab_resize.remove();

          // Restore the grid columns for the generation tab incase user made the columns
          if(obj.generation_tab.firstElementChild) {
            let tempVal = obj.generation_tab.firstElementChild.style.gridTemplateColumns;
            obj.generation_tab.firstElementChild.style.gridTemplateColumns = obj.lastGridTemplate.saved;
            obj.lastGridTemplate.saved = tempVal;
          }

					// Click the "Generation" tab button
					generationButton.click();
				}
			}
		});
		// Toggle the state
		rsen_toggleState = !rsen_toggleState;
	}
}

onUiUpdate(function(args) {
  const lastTxt2imgTabButton = document.querySelector("#txt2img_extra_tabs > .tab-nav > .selected");
  const lastImg2imgTabButton = document.querySelector("#img2img_extra_tabs > .tab-nav > .selected");
  // onUiUpdate runs between localization so you have to check for both english and localized versions of the text
  let generationText = ["Generation", getText_ExtraNetworksSidePanel("Generation")];
  if(lastTxt2imgTabButton != null && typeof lastTxt2imgTabButton !== "undefined" && !generationText.includes(lastTxt2imgTabButton.innerHTML.trim())) {
    rsen_lastTxt2imgTabButton = lastTxt2imgTabButton;
  }
  if(lastImg2imgTabButton != null && typeof lastImg2imgTabButton !== "undefined" && !generationText.includes(lastImg2imgTabButton.innerHTML.trim())) {
    rsen_lastImg2imgTabButton = lastImg2imgTabButton;
  }
});


// for compact ui layout we need to hijack the method that moves the prompt box to the extra network tabs

// save the original method
const extraNetworksMovePromptToTabOriginal = extraNetworksMovePromptToTab;

// override the original to not operate when the side panel is open
extraNetworksMovePromptToTab = (...args) => { 
  if(rsen_toggleState) return;
  return extraNetworksMovePromptToTabOriginal(...args);
};