Inject HTML mit JavaScript nur top level element angezeigt?
Ich möchte einen Download Button in Youtube einfügen, der ein XML-Get Request an meinen Download-Server schickt und das Video herunterlädt. Der Einfachheit halber will ich den schon vorhandenen YT-Download Button nutzen. Dazu hole ich mir das Element aus dem Dokument und entferne das "is-hidden" Attribut. Soweit alles gut, das Element wird angezeigt. Auch wenn ich einen EventListener für den Request hinzufüge ist noch alles in Ordnung. Nur der bestehende YT-Eventlistener zeigt einen Fehler an, dass Downloads nicht aktiviert sind bei meinem Account. Und um den zu entfernen habe ich das Element geclont und ersetzt, leider wird nur das äußerste Html-Element eingefügt, die inneren Elemente gehen verloren. Das gleiche Problem habe ich bei innerHtml. Alles was verschachtelt ist wird nicht eingefügt.
Mein Code:
var downloadIntegrated = document.querySelector(
"ytd-download-button-renderer"
);
downloadIntegrated.removeAttribute("is-hidden");
downloadIntegrated = downloadIntegrated.replaceWith(
downloadIntegrated.cloneNode(true)
);
downloadIntegrated.onclick = function () {
downloadURL(currentURL);
return false;
};
Der Originale Button:
<ytd-download-button-renderer class="style-scope ytd-menu-renderer style-default size-default force-icon-button" use-keyboard-focused="" is-hidden="" button-renderer="true" style-action-button="" is-icon-button=""><a class="yt-simple-endpoint style-scope ytd-download-button-renderer" tabindex="-1"><yt-icon-button id="button" class="style-scope ytd-download-button-renderer style-default size-default" touch-feedback=""><!--css-build:shady--><button id="button" class="style-scope yt-icon-button" aria-label="Herunterladen"><yt-icon class="style-scope ytd-download-button-renderer"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope yt-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope yt-icon"><path d="M17 18V19H6V18H17ZM16.5 11.4L15.8 10.7L12 14.4V4H11V14.4L7.2 10.6L6.5 11.3L11.5 16.3L16.5 11.4Z" class="style-scope yt-icon"></path></g></svg><!--css-build:shady--></yt-icon></button><yt-interaction id="interaction" class="circular style-scope yt-icon-button"><!--css-build:shady--><div class="stroke style-scope yt-interaction"></div><div class="fill style-scope yt-interaction"></div></yt-interaction></yt-icon-button><yt-formatted-string id="text" class="style-scope ytd-download-button-renderer style-default size-default">Herunterladen</yt-formatted-string></a></ytd-download-button-renderer>
Der geclonte und eingefügte Button:
<ytd-download-button-renderer class="style-scope ytd-menu-renderer style-default size-default force-icon-button" use-keyboard-focused="" button-renderer="true" style-action-button="" is-icon-button=""></ytd-download-button-renderer>
1 Antwort
In diesem Fall klappt es so:
const node = document.querySelector("ytd-download-button-renderer");
const dolly = node.cloneNode(false);
node.parentNode.insertBefore(dolly, node);
dolly.innerHTML = node.innerHTML;
node.remove();
Statt die Kindelemente mit innerHTML zu holen, könnte man auch alle direkten Kinder des Originalknotens via appendChild an den Klon hängen.
for (const child of Array.from(node.childNodes)) {
dolly.appendChild(child);
}
Auf diese Weise würde man die Event-Listener, die an diesen Elementen hängen, nicht verlieren.
Werde ich probieren und melde mich dann nochmal. Wenn ich meinen jetzigen Code auf einer anderen Website ausführe, wird das Element wie gewünscht eingefügt mit allen Unterelementen, nur auf YT geht es nicht.
Das hat begrenzt funktioniert. Die Unterelemente werden eingefügt, aber 2 Elemente darunter Fehlen das svg Element und der Text "Herunterladen" ist zwar in area-label enthalten, fehlt allerdings in yt-formatted-string. Muss ich da den textContent noch manuell setzen?
<ytd-download-button-renderer class="style-scope ytd-menu-renderer style-default size-default force-icon-button" use-keyboard-focused="" button-renderer="true" style-action-button="" is-icon-button="" loadeddl="true"><a class="yt-simple-endpoint style-scope ytd-download-button-renderer" tabindex="-1"><yt-icon-button id="button" class="style-scope ytd-download-button-renderer style-default size-default" touch-feedback=""><!--css-build:shady--><button id="button" class="style-scope yt-icon-button"><!--css-build:shady--><button id="button" class="style-scope yt-icon-button" aria-label="Herunterladen"><yt-icon class="style-scope ytd-download-button-renderer"><!--css-build:shady--></yt-icon></button><yt-interaction id="interaction" class="circular style-scope yt-icon-button"><!--css-build:shady--><div class="stroke style-scope yt-interaction"></div><div class="fill style-scope yt-interaction"></div></yt-interaction></button><yt-interaction id="interaction" class="circular style-scope yt-icon-button"><!--css-build:shady--><div class="stroke style-scope yt-interaction"></div><div class="fill style-scope yt-interaction"></div></yt-interaction></yt-icon-button><yt-formatted-string id="text" class="style-scope ytd-download-button-renderer style-default size-default">
<!--css-build:shady--></yt-formatted-string></a></ytd-download-button-renderer>
Habe es jetzt mit folgendem Code hinbekommen, das Icon ist zwar nicht dort wo es original war aber es wird richtig angezeigt:
const node = document.querySelector("ytd-download-button-renderer");
const dolly = node.cloneNode(false);
dolly.removeAttribute("is-hidden");
dolly.setAttribute("loadeddl", "true");
node.removeAttribute("is-hidden");
node.setAttribute("loadeddl", "true");
node.parentNode.insertBefore(dolly, node);
dolly.innerHTML = node.innerHTML;
node.remove();
dolly.setAttribute("loadeddl", "true");
dolly.removeAttribute("is-hidden");
dolly.querySelector("yt-formatted-string").textContent = "Herunterladen";
dolly.querySelector(
"yt-icon-button"
).innerHTML = `<svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope yt-icon" style="pointer-events: none; display: block; width: 100%; height: 100%; color:#ffffff"><g class="style-scope yt-icon"><path fill="#ffffff" d="M17 18V19H6V18H17ZM16.5 11.4L15.8 10.7L12 14.4V4H11V14.4L7.2 10.6L6.5 11.3L11.5 16.3L16.5 11.4Z" class="style-scope yt-icon"></path></g></svg>`;
dolly.onclick = function () {
downloadURL(currentURL);
return false;
};