Download javascript/colab_sd_models.js from prolapse/dl_models_addon: direct link, hf CLI and curl.
- Browser
- Download file 15 kB
-
https://huggingface.co/prolapse/dl_models_addon/resolve/main/javascript/colab_sd_models.js
- Command line
-
hf download hf://prolapse/dl_models_addon/javascript/colab_sd_models.js
-
curl -L -o colab_sd_models.js https://huggingface.co/prolapse/dl_models_addon/resolve/main/javascript/colab_sd_models.js
15 kB
| document.addEventListener('DOMContentLoaded', () => { | |
| const observer = new MutationObserver((mutations) => { | |
| mutations.forEach((mutation) => { | |
| if (mutation.addedNodes) { | |
| mutation.addedNodes.forEach((node) => { | |
| if (node.id === 'tab_models_list') { | |
| // запуск кода после загрузки элементов | |
| Array.from(document.querySelectorAll('#tabs > div.tab-nav > button')).find(button => button.textContent.includes('модели')).click(); | |
| // получение инфы по кд о свободном пространтсве из скрытого уродского текстбокса в красивый элементик в шапочке | |
| const freespacetextarea = document.querySelector("#free_space_area > label > textarea"); | |
| const frespace_out = document.querySelector("#frespace_out"); | |
| let prevValue = freespacetextarea.value; | |
| setInterval(function () { | |
| const currentValue = freespacetextarea.value; | |
| if (currentValue !== prevValue) { | |
| frespace_out.innerHTML = `${currentValue}`; | |
| prevValue = currentValue; | |
| } | |
| }, 100); | |
| // скликивание реальной, но скрытой уродской кнопки с обработчиком проверки свободного места при нажатии на фейковую но красивую кнопочку | |
| const freespace_getButton = document.querySelector("#freespace_get"); | |
| const free_spaceOrigButton = document.querySelector("#free_space_button"); | |
| freespace_getButton.addEventListener("click", function () { | |
| free_spaceOrigButton.click(); | |
| }); | |
| // небольшой css-фикс | |
| const ModelDLHeaderContainer = document.querySelector('.models_dl_header').closest('div').parentNode; | |
| ModelDLHeaderContainer.style.cssText = `display: flex; flex-direction: row; align-items: center; justify-content: flex-start; flex-wrap: wrap;`; | |
| document.querySelector('.models_dl_header').parentNode.marginRight = "50px"; | |
| // автоматическое скликивание скрытых кнопок для подгрузки установленных моделей и свободного места после загрузки дополнения через 1 сек | |
| setTimeout(() => document.querySelector("#files_button").click(), 1000); | |
| setTimeout(() => document.querySelector("#free_space_button").click(), 1000); | |
| // файловый менеджер на тексбоксах | |
| setTimeout(() => { | |
| const filesArea = document.querySelector("#files_area > label > textarea"); | |
| const filesCheckbox = document.querySelector("#files_checkbox"); | |
| const deleteArea = document.querySelector("#delete_area > label > textarea"); | |
| // обновление списка чекбоксов с файлами при изменении списка путей в текстбоксе | |
| function addCheckboxEventListeners() { | |
| const delete_checkboxes = document.querySelectorAll("#files_checkbox > label > input[type=checkbox]"); | |
| delete_checkboxes.forEach(checkbox => { | |
| checkbox.addEventListener("change", event => { | |
| // отмеченные на удаление делаем красными и зачеркнутыми | |
| const delete_span = event.target.parentElement.querySelector("span"); | |
| if (event.target.checked) { | |
| delete_span.style.textDecoration = "line-through"; | |
| delete_span.style.color = "#ed5252"; | |
| } else { | |
| delete_span.style.textDecoration = "none"; | |
| delete_span.style.color = ""; | |
| } | |
| }); | |
| }); | |
| } | |
| // функция для обновления чекбоксов с файлами почти в реальном времени | |
| function updateCheckboxes() { | |
| while (filesCheckbox.firstChild) { | |
| filesCheckbox.removeChild(filesCheckbox.firstChild); | |
| } | |
| const fileNames = filesArea.value.split("\n").map(path => path.split("/").pop()); | |
| if (fileNames.length === 0 || (fileNames.length === 1 && fileNames[0] === "")) { | |
| const message = document.createElement("p"); | |
| message.textContent = "ничего не найдено"; | |
| filesCheckbox.appendChild(message); | |
| } else { | |
| fileNames.forEach(fileName => { | |
| const checkbox = document.createElement("input"); | |
| checkbox.type = "checkbox"; | |
| checkbox.id = fileName; | |
| checkbox.addEventListener("change", event => { | |
| if (event.target.checked) { | |
| deleteArea.value += (deleteArea.value ? "\n" : "") + fileName; | |
| } else { | |
| const lines = deleteArea.value.split("\n"); | |
| const index = lines.indexOf(fileName); | |
| if (index !== -1) { | |
| lines.splice(index, 1); | |
| deleteArea.value = lines.join("\n"); | |
| } | |
| } | |
| deleteArea.dispatchEvent(new Event('input')); // имитация ввода, это самая важная часть кода | |
| }); | |
| const label = document.createElement("label"); | |
| label.htmlFor = fileName; | |
| label.className = "filecheckbox"; | |
| const span = document.createElement("span"); | |
| span.textContent = fileName; | |
| label.appendChild(checkbox); | |
| label.appendChild(span); | |
| filesCheckbox.appendChild(label); | |
| }); | |
| } | |
| deleteArea.value = deleteArea.value.trim(); | |
| deleteArea.dispatchEvent(new Event('input')); // имитация ввода, без этого не работает | |
| addCheckboxEventListeners() | |
| } | |
| // наблюдаем за скрытым тексбоксом с путями до моделей и обновлям чекбоксы | |
| const observer = new MutationObserver(updateCheckboxes); | |
| observer.observe(filesArea, { characterData: true, subtree: true }); | |
| updateCheckboxes(); | |
| // скликивание реальной, но скрытой уродской кнопки с обработчиком обновления списка файлов при нажатии на фейковую но красивую кнопочку | |
| const RefreshFilesButton = document.querySelector("#refresh_files_button"); | |
| RefreshFilesButton.addEventListener("click", () => { | |
| document.querySelector("#files_button").click(); | |
| // задержки по 3 секунды необходимы, чтобы колаб одуплился | |
| setTimeout(function () { updateCheckboxes(); }, 3000); | |
| }); | |
| // при клике на фейковую кнопочку удаления - произойдет и обновление списка файлов с задержкой 3 сек | |
| document.querySelector("#delete_button").addEventListener("click", function () { | |
| setTimeout(function () { | |
| document.querySelector("#files_button").click(); | |
| // задержки по 3 секунды необходимы, чтобы колаб одуплился | |
| setTimeout(function () { updateCheckboxes(); }, 3000); | |
| }, 3000); | |
| }); | |
| // скликивание реальной, но скрытой уродской кнопки с обработчиком удаления моделей при нажатии на фейковую но красивую кнопочку | |
| const OrigDelButton = document.querySelector("#delete_button"); | |
| const CustomDelButton = document.querySelector("#delete_files_button"); | |
| CustomDelButton.addEventListener("click", () => { | |
| OrigDelButton.click(); | |
| }); | |
| // проверка выхлопа из функции загрузки в скрытом текстбоксе | |
| setInterval(function () { | |
| const DLresultText = document.querySelector("#downloads_result_text > span.finish_dl_func"); | |
| DLresultText.textContent = document.querySelector("#dlresultbox > label > textarea").value; | |
| // функция скрытия прогрессбара | |
| function checkDLresult(element, text) { | |
| if (element.textContent.includes(text)) { | |
| document.querySelector("div.downloads_result_container > div.models_porgress_loader").style.removeProperty("display"); | |
| document.querySelector("#downloads_start_text").style.removeProperty("display"); | |
| document.querySelector("#downloads_result_text > span.dl_progress_info").textContent = "чтобы новые файлы появились в выпадающем списке моделей, нужно обновить их список по соответсвующей кнопке"; | |
| } | |
| } | |
| // просто скрываем прогрессбар если в выхлопе есть фраза о завершении или предупреждение | |
| checkDLresult(DLresultText, "заверш"); | |
| checkDLresult(DLresultText, "слишком"); | |
| checkDLresult(DLresultText, "ОШИБКА"); | |
| // раскрашиваем текст сообщения о результате выполнения, если что-то пошло не так | |
| if (DLresultText) { | |
| if (DLresultText.textContent.includes("слишком")) { | |
| DLresultText.style.setProperty("color", "#ff4f8b", "important"); | |
| } else if (DLresultText.textContent.includes("ОШИБКА")) { | |
| DLresultText.style.setProperty("color", "#de2f2f", "important"); | |
| } else if (DLresultText.textContent.includes("заверш")) { | |
| DLresultText.style.setProperty("color", "#99fb99", "important"); | |
| } | |
| } | |
| }, 200); | |
| // действия по клику на фейковую, но видимую кнопку для скачивания | |
| document.querySelector("#general_download_button").addEventListener("click", function () { | |
| // очистка текстбокса от выхлопа предыдущего выполнения | |
| const resultTextareaDL = document.querySelector("#dlresultbox > label > textarea"); | |
| resultTextareaDL.value = ""; | |
| const resultClearOut = new Event("input", {bubbles: true}); // без этого не будет работать обноволение .value | |
| resultTextareaDL.dispatchEvent(resultClearOut); | |
| // делаем прогрессбар и место для результирующего текста видимыми | |
| const DLprogressBar = document.querySelector("div.downloads_result_container > div.models_porgress_loader"); | |
| DLprogressBar.style.setProperty("display", "block", "important"); | |
| const DLresultText = document.querySelector("#downloads_result_text"); | |
| DLresultText.style.setProperty("display", "block", "important"); | |
| document.querySelector("#downloads_start_text").style.setProperty("display", "block", "important"); | |
| // скликивание реальных, но скрытых кнопок с обработчиками загрузки файлов по чекбоксам и кастомных ссылок при нажатии на фейковую но кнопочку | |
| // формирование списка из кастомных ссылок | |
| document.querySelector("#ownlinks_download_button").click(); | |
| setTimeout(function () { | |
| // через 3 сек. добавим его к списку ссылок из чекбоксов и отправим на загрузку вместе | |
| document.querySelector("#checkboxes_download_button").click(); | |
| }, 3000); // задержка, чтобы колаб успел одуплиться | |
| }); | |
| // если кнопка загрузки уже нажата, запрещаем кликать еще раз пока функция загрузки не выплюнет ответ | |
| const GendownloadButton = document.querySelector("#general_download_button"); | |
| const DLprogressBar = document.querySelector("div.downloads_result_container > div.models_porgress_loader"); | |
| if (GendownloadButton && DLprogressBar) { | |
| const DLobserver = new MutationObserver(function (mutations) { | |
| mutations.forEach(function (mutation) { | |
| if (mutation.type === "attributes" && mutation.attributeName === "style") { // отслеживание видимости прогрессбара | |
| if (DLprogressBar.style.display === "block") { | |
| GendownloadButton.setAttribute("disabled", "disabled"); | |
| } else { | |
| setTimeout(function () { | |
| GendownloadButton.removeAttribute("disabled"); | |
| }, 3000); // не сразу даем кликнуть снова, а после ожидания 3 секунды, чтобы не закликали | |
| } | |
| } | |
| }); | |
| }); | |
| DLobserver.observe(DLprogressBar, { attributes: true }); | |
| } | |
| }, 9000); // запуск скриптов через 9 секунд после загрузки вебуи, чтобы успели отработать скрипты других дополнений и градио | |
| } | |
| }); | |
| } | |
| }); | |
| }); | |
| observer.observe(document.body, { childList: true, subtree: true }); | |
| }); |