Javascript write html to iframe

How to Load HTML, CSS, and JS Code into an iFrame

If you’re just here for the answer, not the story, the solution is at the bottom. If you’ve ever used JSFiddle, Codepen, or others, this problem will be familiar to you: The goal is to take some HTML, CSS, and JS (stored as strings) and create an iframe with the code loaded inside. This problem should be easy, but it isn’t. At least. It wasn’t, until I found the golden ticket I had been waiting for all along. But more on that later. Let’s start with all the things that didn’t work, because that’s more fun.

Attempt #1: Using srcdoc

After doing a bit of research, I was thrilled to discover that it’s possible to add a srcdoc attribute to iframes. If you pass in an HTML string, the iframe will load with that HTML content inside:

 srcdoc="

This text will appear in the iframe!

"
>

1. Browser Support for srcdoc is not great

If we want to support IE or Edge, we’ll need a different approach (or a polyfill).

2. It’s possible to «escape» from CSS/JS

function setIframeContent(iframe,  html, css, js >)  const source = `  $css>  $html> $js>   ` iframe.srcdoc = source > 

The problem? When writing CSS or JS, it’s possible to «escape» out into HTML land, simply by including

or in the code, respectively. This bug is actually quite common; both JSFiddle and Codepen are affected:

Attempt #2: Serverless Boomerang

To fix the browser support issue, let’s replace srcdoc with a regular src attribute. In order to do this, we’ll need to pass a real URL instead of just code. Perhaps we can set up a page which takes HTML, CSS, and JS «GET» parameters and spits out the same type of page as before, but this time loaded from an actual URL. This is a perfect time to use a serverless architecture, because we just want a single endpoint that does one thing. Here’s my attempt:

module.exports = (req, res) =>  // Code comes from GET params in URL const  html = '', css = '', js = '' > = req.query // Generate and send HTML page return res.send(`  $css>  $html> $js>   `) > 
  1. «Escaping» from CSS/JS into HTML is still a problem
  2. The entire source code is passed in a URL, which isn’t ideal.

Attempt #3: Serverless Boomerang (redux)

Our first boomerang solved the browser support problem, but still has the «escaping» issue to deal with.

Fortunately, due to the way that we pass in the code, this can actually be solved. Rather than inserting the CSS and JS into the page on the server, we can do it on the client! This works because the URL GET parameters are still accessible to the client’s computer.

The source here is a bit longer, but it does work:

module.exports = (req, res) =>  return res.send(`     $req.query.html || ''>  `) > 

Now, if a script or style includes scary HTML characters, the browser will handle them for us when inserting said script/style into the document.

This solution is. fine. It works, technically. But we still have the soft URL length limit to consider. Plus, we’re now dealing with something server-side that feels like it should happen on the client.

There must be a better way.

Solution: Blob URLs

This entire time, we’ve been trying to simulate loading data from a URL:

  • First we used srcdoc to load data instead of loading from a URL
  • Then we used the boomerang to load code from a URL
  • Next we updated our boomerang to attempt to simulate the «loading CSS/JS from an external URL» behavior, despite every resource coming from one URL.

It turns out that Javascript has a feature to do just this: Blob URLs.

Blobs

We can use the Blob constructor to create a pseudo-file. It’s not a real file loaded from disk or from a URL — it’s just stored in memory. But in many ways, it functions just like a real loaded file.

Then, we can use URL.createObjectURL(blob) to create a URL that can be used to load the contents of the blob.

Here’s how that works in practice:

const getBlobURL = (code, type) =>  const blob = new Blob([code],  type >) return URL.createObjectURL(blob) > console.log(getBlobURL('

My webpage

', 'text/html')) // blob:https://dev.to/9ca05e31-05ea-48f8-838d-cc1ad0949ec8

Try running the above code in the console to see it for yourself! It will log a URL. If you paste the URL into a new tab (including the blob: bit at the beginning), it will load a page containing the HTML.

Notice the ‘text/html’ passed to getBlobURL ? We can change that too. Generating a CSS or JS blob is easy: Just pass text/css or text/javascript respectively.

Another benefit of blob URLs is that they stick around, and can be accessed any way that you would access a regular URL. Which means that we can actually load our CSS and JS files from a separate URL, so the «escaping» trick is no longer a problem.

Here’s a bare-bones implementation of this in practice:

const getGeneratedPageURL = ( html, css, js >) =>  const getBlobURL = (code, type) =>  const blob = new Blob([code],  type >) return URL.createObjectURL(blob) > const cssURL = getBlobURL(css, 'text/css') const jsURL = getBlobURL(js, 'text/javascript') const source = ` $css && `$cssURL>" />`> $js && ``> $html || ''>  ` return getBlobURL(source, 'text/html') > const url = getGeneratedPageURL( html: '

Hello, world!

', css: 'p ', js: 'console.log("hi")' >) const iframe = document.querySelector('#iframe') iframe.src = url

Oh, and browser support for Blob URLs is much better than srcdoc. 😉

The Moral?

Don’t fight the language, I guess.

I knew what I wanted to do: Load data from URLs. It just never occurred to me to look for a non-hacky way to do just that!

Источник

Общение между окнами и фреймами

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/cross-window-communication.

Элемент iframe является обычным узлом DOM, как и любой другой. Существенное отличие – в том, что с ним связан объект window внутреннего окна. Он доступен по ссылке iframe.contentWindow .

Таким образом, iframe.contentWindow.document будет внутренним документом, iframe.contentWindow.document.body – его и так далее.

В старых браузерах использовались другие свойства, такие как iframe.contentDocument и даже iframe.document , но они давно не нужны.

Переход внутрь ифрейма

В примере ниже JavaScript получает документ внутри ифрейма и модифицирует его:

  var iframe = document.getElementsByTagName('iframe')[0]; var iframeDoc = iframe.contentWindow.document; if (iframeDoc.readyState == 'complete') < iframeDoc.body.style.backgroundColor = 'green'; >iframe.onload = function() 

Атрибут src может использовать протокол javascript , как указано выше: src=»javascript:код» . При этом код выполняется и его результат будет содержимым ифрейма. Этот способ описан в стандарте и поддерживается всеми браузерами.

Атрибут src является обязательным, и его отсутствие может привести к проблемам, вплоть до игнорирования ифрейма браузером. Чтобы ничего не загружать в ифрейм, можно указать пустую строку: src=»javascript:»» или специальную страницу: src=»about:blank» .

В некоторых браузерах (Chrome) пример выше покажет iframe зелёным. А в некоторых (Firefox) – оранжевым.

Дело в том, что, когда iframe только создан, документ в нём обычно ещё не загружен.

При обычных значениях iframe src=»https://learn.javascript.ru/» , которые указывают на HTML-страницу (даже если она уже в кеше), это всегда так. Документ, который в iframe на момент срабатывания скрипта iframeDoc – временный, он будет заменён на новый очень скоро. И работать надо уже с новым документом iframeDoc2 – например, по событию iframe.onload .

В случае с javascript -протоколом, по идее, ифрейм уже загружен, и тогда onload у него уже не будет. Но здесь мнения браузеров расходятся, некоторые (Firefox) всё равно «подгрузят» документ позже. Поэтому факт «готовности» документа в скрипте проверяется через iframeDoc.readyState .

Ещё раз заметим, что при обычных URL в качестве src нужно работать не с начальным документом, а с тем, который появится позже.

Кросс-доменность: ограничение доступа к окну

Элемент является «двуличным». С одной стороны, это обычный узел DOM, с другой – внутри находится окно, которое может иметь совершенно другой URL, содержать независимый документ из другого источника.

Внешний документ имеет полный доступ к как к DOM-узлу. А вот к окну – если они с одного источника.

Это приводит к забавным последствиям. Например, чтобы узнать об окончании загрузки , мы можем повесить обработчик iframe.onload . По сути, это то же самое что iframe.contentWindow.onload , но его мы можем поставить лишь в случае, если окно с того же источника.

  

Если бы в примере выше был с текущего сайта, то оба обработчика сработали бы.

Иерархия window.frames

Альтернативный способ доступа к окну ифрейма – это получить его из коллекции window.frames .

Обратим внимание: в коллекции хранится именно окно ( contentWindow ), а не DOM-элемент.

Демонстрация всех способов доступа к окну:

   

Внутри ифрейма могут быть свои вложенные ифреймы. Всё это вместе образует иерархию.

Ссылки для навигации по ней:

  • window.frames – коллекция «детей» (вложенных ифреймов)
  • window.parent – содержит ссылку на родительское окно, позволяет обратиться к нему из ифрейма. Всегда верно:
// (из окна со фреймом) window.frames[0].parent === window; // true
window.frames[0].frames[0].frames[0].top === window

Свойство top позволяет легко проверить, во фрейме ли находится текущий документ:

Песочница sandbox

Атрибут sandbox позволяет построить «песочницу» вокруг ифрейма, запретив ему выполнять ряд действий.

  • Заставляет браузер считать ифрейм загруженным с другого источника, так что он и внешнее окно больше не могут обращаться к переменным друг друга.
  • Отключает формы и скрипты в ифрейме.
  • Запрещает менять parent.location из ифрейма.

Пример ниже загружает в документ с JavaScript и формой. Ни то ни другое не сработает:

Источник

JavaScript write to IFrame

The tag defines an inline frame which allows to embed an HTML document inside another HTML document. In the given example, we have created a simple HTML page adding a div element and a function writeToIFrame() which is called when the page is loaded. The method createElement() of document object creates a html iframe element. The variable div grabs the id of the div element which is added to the iframe?s document element by using the method appendChild().

Following code allows to display the iframe’s document on Firefox:

if (iframe.contentDocument)
doc = iframe.contentDocument ;

Following code allows to display the iframe’s document on Internet Explorer:

else if(iframe.contentWindow)
doc = iframe.contentWindow.document;

Write to IFrame using JavaScript



Output will be displayed as:

Tutorials

  1. Clear cookie example
  2. JavaScript getElementById innerHTML
  3. JavaScript getElementById Style
  4. Javascript Examples
  5. JavaScript add row dynamically to table
  6. New Page 1
  7. JavaScript Change link
  8. JavaScript Checkbox getElementById
  9. javascript clear textarea
  10. JavaScript Clock Timer
  11. JavaScript Cookies
  12. JavaScript Date Difference
  13. JavaScript duplicate string
  14. JavaScript Email Validation
  15. javascript focus input
  16. JavaScript get excel file data
  17. JavaScript getAttribute Href
  18. JavaScript getAttribute Style
  19. JavaScript getElementById div
  20. JavaScript getElementById Iframe
  21. JavaScript getElementById select
  22. JavaScript Hide Button
  23. JavaScript Hide Div
  24. JavaScript hide image
  25. JavaScript Hide Table Column
  26. JavaScript Hide Table Rows
  27. JavaScript Key Event
  28. JavaScript link
  29. JavaScript method location
  30. JavaScript move div
  31. JavaScript move file
  32. JavaScript move image
  33. JavaScript Navigate Back
  34. JavaScript navigate to page
  35. JavaScript Navigate to URL
  36. JavaScript indexOf substring
  37. JavaScript onkeypress event
  38. JavaScript Open file
  39. JavaScript Open link in new window
  40. JavaScript Open Modal Window

Источник

Читайте также:  Css div positioning example
Оцените статью