File size: 6,233 Bytes
b5ba7a5 |
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 |
(function () {
async function checkEditorAvailable() {
const EDITOR_PATH = '/openpose_editor_index';
const res = await fetch(EDITOR_PATH);
return res.status === 200;
}
const cnetOpenposeEditorRegisteredElements = new Set();
function loadOpenposeEditor() {
// Simulate an `input` DOM event for Gradio Textbox component. Needed after you edit its contents in javascript, otherwise your edits
// will only visible on web page and not sent to python.
function updateInput(target) {
let e = new Event("input", { bubbles: true })
Object.defineProperty(e, "target", { value: target })
target.dispatchEvent(e);
}
function navigateIframe(iframe) {
function getPathname(rawURL) {
try {
return new URL(rawURL).pathname;
} catch (e) {
return rawURL;
}
}
return new Promise((resolve) => {
const EDITOR_PATH = '/openpose_editor_index';
const darkThemeParam = document.body.classList.contains('dark') ?
new URLSearchParams({ theme: 'dark' }).toString() :
'';
window.addEventListener('message', (event) => {
const message = event.data;
if (message['ready']) resolve();
}, { once: true });
if (getPathname(iframe.src) !== EDITOR_PATH) {
iframe.src = `${EDITOR_PATH}?${darkThemeParam}`;
// By default assume 5 second is enough for the openpose editor
// to load.
setTimeout(resolve, 5000);
} else {
// If no navigation is required, immediately return.
resolve();
}
});
}
const imageRows = gradioApp().querySelectorAll('.cnet-image-row');
imageRows.forEach(imageRow => {
if (cnetOpenposeEditorRegisteredElements.has(imageRow)) return;
cnetOpenposeEditorRegisteredElements.add(imageRow);
const generatedImageGroup = imageRow.querySelector('.cnet-generated-image-group');
const editButton = generatedImageGroup.querySelector('.cnet-edit-pose');
editButton.addEventListener('click', async () => {
const inputImageGroup = imageRow.querySelector('.cnet-input-image-group');
const inputImage = inputImageGroup.querySelector('.cnet-image img');
const downloadLink = generatedImageGroup.querySelector('.cnet-download-pose a');
const modalId = editButton.id.replace('cnet-modal-open-', '');
const modalIframe = generatedImageGroup.querySelector('.cnet-modal iframe');
await navigateIframe(modalIframe);
modalIframe.contentWindow.postMessage({
modalId,
imageURL: inputImage.src,
poseURL: downloadLink.href,
}, '*');
// Focus the iframe so that the focus is no longer on the `Edit` button.
// Pressing space when the focus is on `Edit` button will trigger
// the click again to resend the frame message.
modalIframe.contentWindow.focus();
});
window.addEventListener('message', (event) => {
const message = event.data;
const downloadLink = generatedImageGroup.querySelector('.cnet-download-pose a');
const renderButton = generatedImageGroup.querySelector('.cnet-render-pose');
const poseTextbox = generatedImageGroup.querySelector('.cnet-pose-json textarea');
const modalId = editButton.id.replace('cnet-modal-open-', '');
const closeModalButton = generatedImageGroup.querySelector('.cnet-modal .cnet-modal-close');
if (message.modalId !== modalId) return;
/*
* Writes the pose data URL to an link element on input image group.
* Click a hidden button to trigger a backend rendering of the pose JSON.
*
* The backend should:
* - Set the rendered pose image as preprocessor generated image.
*/
downloadLink.href = message.poseURL;
poseTextbox.value = message.poseURL;
updateInput(poseTextbox);
renderButton.click();
closeModalButton.click();
});
});
}
function loadPlaceHolder() {
const imageRows = gradioApp().querySelectorAll('.cnet-image-row');
imageRows.forEach(imageRow => {
if (cnetOpenposeEditorRegisteredElements.has(imageRow)) return;
cnetOpenposeEditorRegisteredElements.add(imageRow);
const generatedImageGroup = imageRow.querySelector('.cnet-generated-image-group');
const editButton = generatedImageGroup.querySelector('.cnet-edit-pose');
const modalContent = generatedImageGroup.querySelector('.cnet-modal-content');
modalContent.classList.add('alert');
modalContent.innerHTML = `
<div>
<p>Openpose editor not found. Please make sure you have an openpose
editor available on /openpose_editor_index. To hide the edit button,
you can check "Disable openpose edit" in Settings.<br>
Following extension(s) provide integration with ControlNet:</p>
<ul style="list-style-type:none;">
<li><a href="https://github.com/huchenlei/sd-webui-openpose-editor">
huchenlei/sd-webui-openpose-editor</a></li>
</ul>
</div>
`;
editButton.innerHTML = '<del>' + editButton.innerHTML + '</del>';
});
}
checkEditorAvailable().then(editorAvailable => {
onUiUpdate(() => {
if (editorAvailable)
loadOpenposeEditor();
else
loadPlaceHolder();
});
});
})(); |