How to use Javascript to search and substitute text within the "srcdoc" attribute of an HTML iframe

tldr: I want to update the stylesheet link in an iframe's srcdoc attribute using vanilla Javascript without affecting the rest of the content.

More detailed version:

I am customizing a blog template from Publii and adding a comment widget from Cusdis using their hosted JS SDK.

The template includes HTML, CSS, Javascript, and Handlebars.

To embed the Cusdis widget, you need to insert the following code snippet into your html document:

<div id="cusdis_thread"
  data-host="https://cusdis.com"
  data-app-id="{{ APP_ID }}"
  data-page-id="{{ PAGE_ID }}"
  data-page-url="{{ PAGE_URL }}"
  data-page-title="{{ PAGE_TITLE }}"
>
<script async src="https://cusdis.com/js/cusdis.es.js"></script>

The Cusdis SDK will locate the element with id cusdis_thread and display the iframe widget inside it:

<iframe srcdoc='<!DOCTYPE html>
 <html>
  <head>
    <link rel="stylesheet" href="https://cusdis.com/js/style.css">
    <base target="_parent" />
    <link>
    <script>
      window.CUSDIS_LOCALE = undefined
      window.__DATA__ = {"host":"https://cusdis.com","appId":"...","pageId":"...","pageUrl":"...","pageTitle":"..."}
    </script>
  </head>
  <body>
    <div id="root"></div>
    <script src="https://cusdis.com/js/iframe.umd.js" type="module"
    </script>
  </body>
 </html>'
style="width: 100%; border: 0px none; height: 323px;">
  #document
</iframe>

The challenge I face is as follows:

  • I aim to customize the appearance of the Cusdis widget by altering its CSS.
  • Although I've tried modifying my own stylesheet to target Cusdis's classes, the changes do not show up in the output (even when using !important). This could be due to the fact that the widget generates an iframe where the elements I wish to adjust reside.
  • A potential solution is to replace the stylesheet link within the iframe's "srcdoc" attribute with a link to another external stylesheet.

Since the iframe is dynamically generated by Cusdis's SDK, I lack control over that portion of the HTML. My goal is to find a way to swap out the stylesheet in the generated iframe's srcdoc solely through the use of vanilla Javascript.

Here are my attempts:

Using setAttribute to target and replace only the stylesheet link:

document.querySelector("#cusdis_thread iframe").setAttribute('srcdoc', '<!DOCTYPE html><html><head><link rel="stylesheet" href="..."><base target="_parent" /><link><script> window.CUSDIS_LOCALE = undefined window.__DATA__ = {"host":"https://cusdis.com", appId":"...","pageId":"{{id}}","pageUrl":"{{url}}","pageTitle":"{{title}}"} </script> </head> <body> <div id="root"></div> <script src="https://cusdis.com/js/iframe.umd.js" type="module"> </script></body></html>');

Outcome: Although the operation was successful in theory, the comments section did not appear. Upon inspection, I noticed that the handlebars expressions {{}} remained unchanged within the srcdoc contents, causing issues with dynamic content rendering.

Hence, I seek a method that will preserve the existing content within the srcdoc attribute while updating only the stylesheet link. Below are my endeavors towards achieving this:

Applying .replace to identify and swap the URL of Cusdis's stylesheet:

document.querySelector("#cusdis_thread iframe").replace("https://cusdis.com/js/style.css", "...");

Outcome: The attempt went unnoticed

Utilizing setAttribute specifically for the stylesheet:

document.querySelector("#cusdis_thread iframe").setAttribute('srcdoc', '<link rel="stylesheet" href="...">');

Outcome: The action was disregarded

Answer №1

When this iframe loads through its srcdoc attribute, you have the ability to access its inner document from your own document (thanks to the mystical powers of about:srcdoc).

The optimal approach would be to wait for the iframe to finish loading and then inject your own <link> or adjust the StyleSheets to your liking.

const iframe = document.querySelector("iframe");
iframe.addEventListener("load", (evt) => {
  const link = document.createElement("link");
  link.rel = "stylesheet";
  link.href = "your-stylesheet.css";
  iframe.contentDocument.head.append(link);
}, { once: true });

See Live Demo (hosted on jsfiddle because StackSnippets with null-origin iframes can cause issues with same-origin policy).

Detecting when the iframe is inserted into the document may pose a challenge. If you are unable to accomplish this, consider checking for events fired by the library or utilizing a MutationObserver as a last resort.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a Node.js application using Express requires careful consideration of file structure and communication methods

Struggling to pass login form credentials to existing JavaScript files for logic and info retrieval. Login page contains a form with POST method. main.js handles the login: main.js module.exports = { returnSessionToken: function(success, error) { ...

Is there a way to adjust the default width of a button before toggling it?

Can anyone offer guidance on how to reduce the width of the Chat button in this demo when it is not clicked? I've been struggling to find a solution but haven't had any success so far. JS function showChat() { jQuery("#blk-collaboration .c ...

Position the sidebar next to the dashboard content

Objective: Move the sidebar class to be positioned next to the dashboard content. Issue: The Sidebar is currently overlapping with the dashboard instead of being positioned beside it. What class should replace 'col-sm-2'? () jsbin: http ...

Addressing three visual problems with an html form input, dropdown menu, and clickable button

Currently, the output of my code looks like this: https://i.stack.imgur.com/pl5CJ.jpg The first box (squared) represents an <input>, while the second box (rectangled) is a <select>. There are several issues that I am facing: The text entered ...

What is the proper way to utilize a function from a library?

I need to implement a noise function from the Noise.js library into my code. How can I properly add this library to my file for it to be utilized? Below is the snippet of code that involves calling the noise function: // Utilizing the noise.js library to ...

Tips for properly showcasing images on a webpage after ensuring all other content has loaded

Is there a way to have an image load last on a webpage after all other content has been loaded? I have an image that is retrieved from a database when a button is pressed, but I would prefer for the entire page to load first and then display the image. C ...

Struggling with Bootstrap 4 - need help with navbar and flexbox alignment issues

My goal is to recreate a navigation bar similar to this design: navbar I initially attempted to use the grid system for my navbar, but it didn't work out as expected. After some research, I found that using the grid system for navbars is not recomme ...

Where could one possibly find the destination of the mysterious <circle>?

I want to implement a simple pulsating animation on a circle svg element. I attempted using a transform: scale(..,..) animation, but it seems to be shifting the entire circle within its container instead of just scaling the element itself. This is the cur ...

The overflow:hidden property prevents me from being able to scroll down the rest of my webpage

@import url('https://fonts.googleapis.com/css?family=Indie+Flower|Lobster|Open+Sans+Condensed:300|Roboto+Condensed&display=swap'); * { margin: 0; padding: 0; } html,body { height: 100%; width: 100%; margin: 0px; padding: 0px; ...

Import MDX metadata in Next.js on the fly

I am currently utilizing Next.js to create a static blog site. Following the guidelines in Next.js documentation, I set up @next/mdx and successfully imported MDX statically using import MDXArticle from "@/app/(article)/2023/test-article/page.mdx&quo ...

Is there a way to determine if a user has interacted with a scrollbar on a website?

Is there a Jquery function available to determine if a user is currently holding onto a scrollbar on my website? I need to return a Boolean value based on whether the user has control of the scrollbar or not. Additionally, I am encountering a specific iss ...

Error: Element type is invalid: a string was anticipated, but not found

I recently experimented with the example provided in React's documentation at this link and it functioned perfectly. My objective now is to create a button using material-ui. Can you identify what is causing the issue in this code? import * as R ...

The footer is being covered by the section, despite my attempts to address the issue with

I have noticed a section overlapping issue and I am struggling to figure out the cause. I have attempted using margins and padding to adjust the footer with my .div-wrap, but so far it has not been effective. After searching around, I am still uncertain ...

What is the best approach to interact with a single hoverable element?

I am in the process of creating a list with multiple sublists nested inside. My goal is to modify the style of an individual <li> element when it is hovered over, without affecting its parent elements. If you want to see the code and demonstration, ...

Which library should be connected in order to utilize JSONLoader, OrbitControls, and AnimationAction?

When looking for a Three.js library that supports JSONLoader, OrbitControls, and AnimationAction simultaneously, the choice can be challenging due to the variety of options available. The code snippet below showcases an attempt to incorporate these three f ...

ReportViewer Web Form sending page into a frozen state

Recently, I was tasked with investigating a seemingly simple issue on one of our web pages within a small dashboard web application. This particular app displays basic state information for the backend apps that I am heavily involved in working on. Here is ...

What is the best way to place an <a> tag and a <p> tag side by side in an HTML

I have a question on organizing this HTML code: <ol class="results-list"> <% @results.sort_by { rand }.each do |result| %> <li class="<%= 'checked-out' if result.catalog_item.library_status == 'Checked out&apos ...

The loading of Google maps occurs simultaneously with ongoing AJAX requests

I am currently working with the Google Maps API in combination with rails 5.0.4. My goal is to have the map center on the user's location and populate the latitude and longitude fields with the corresponding coordinates. Right now, the lat, lng field ...

Modifying Bootstrap Grid Layouts

I need to reorganize the columns for better responsiveness as the current order is not ideal. Below is the code snippet: <div class="tab-content" id="pills-tabContent"> <div class="tab-pane fade show active" id="pills-home" role="tabpanel" ari ...

Could the wizard control sidebar be customized to have a similar appearance?

Can I make my asp.net wizard side bar look like the one shown here: I'm not sure if it's possible since SideBarStyle usually only allows for basic styling like changing font color and size. ...