One of the most difficult problems in my javascript experience has been the correct (that is "cross-browser") computing of a iframe height.
In my applications I have a lot of dynamically generated iframe and I want them all do a sort of autoresize at the end of the load event to adjust their height and width.
In the case of height computing my best solution is the following (with the help of jQuery):
function getDocumentHeight(doc) {
var mdoc = doc || document;
if (mdoc.compatMode=='CSS1Compat') {
return mdoc.body.offsetHeight;
}
else {
if ($.browser.msie)
return mdoc.body.scrollHeight;
else
return Math.max($(mdoc).height(), $(mdoc.body).height());
}
}
I searched the internet without success. I also tested Yahoo library that has some methods for document and viewport dimensions, but it's not satisfactory.
My solution works decently, but sometimes it calculates a taller height.
I've studied and tested tons of properties regarding document height in Firefox/IE/Safari: documentElement.clientHeight, documentElement.offsetHeight, documentElement.scrollHeight, body.offsetHeight, body.scrollHeight, ...
Also jQuery doesn't have a coherent behavior in various browser with the calls $(document.body).height(), $('html', doc).height(), $(window).height()
I call the above function not only at the end of load event, but also in the case of dynamically inserted DOM elements or elements hidden or shown. This is a case that sometimes breaks the code that works only in the load event.
Does someone have a real cross-browser (at least Firefox/IE/Safari) solution? Some tips or hints?
Although I like your solution, I've always found IFRAMEs to be more trouble than they're worth.
Why ? 1. The sizing issue. 2. the iframe has that src attribute to worry about. i.e. absolute path. 3. the extra complexity with the pages.
My solution - DIVs which are dynamically loaded through AJAX calls. DIVs will auto size. Although the AJAX code requires javascript work (which can be done through frameworks) they are relative to where the site is. 3 is a wash, you're trading complexity in pages up to javascript.
Instead of <IFRAME ...> use <DIV id="mystuff" />
Do the ajax call to fill the mystuff div with data and let the browser worry about it.
This has been without an accepted answer for awhile, so I wanted to contribute the solution I ended up going with after some research. This is cross-browser and cross-domain (e.g. when the iframe points to content from a different domain)
I ended up using html5's message passing mechanism wrapped in a jQuery pluging that makes it compatible with older browsers using various methods (some of them described in this thread).
The end solution is very simple.
On the host (parent) page:
// executes when a message is received from the iframe, to adjust
// the iframe's height
$.receiveMessage(
function( event ){
$( 'my_iframe' ).css({
height: event.data
});
});
// Please note this function could also verify event.origin and other security-related checks.
On the iframe page:
$(function(){
// Sends a message to the parent window to tell it the height of the
// iframe's body
var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);
$.postMessage(
$('body').outerHeight( true ) + 'px',
'*',
target
);
});
I've tested this on Chrome 13+, Firefox 3.6+, IE7, 8 and 9 on XP and W7, safari on OSX and W7. ;)
Since in your example you're accessing the document inside the IFRAME I guess you're talking about knowing the height of the document and not of the frame itself. Also, that means that the content comes from your own website and you have control over it's contents.
So, why don't you simply place a DIV around your content and then use the clientHeight of that DIV?
Code you load in your IFRAME:
...
<body>
<div id="content">
...
</div>
</body>
The parent document:
function getDocumentHeight(mdoc) {
return mdoc.getElementById("content").clientHeight;
}
BTW, this part of your example function does not make sense as "document" does not refer to the IFRAME:
var mdoc = doc || document;
Here is a solution that seems to work. Basically, the scrollHeight is the correct value in most cases. However, in IE (specifically 6 and 7), if the content is simply contained in text nodes, the height is not calculated and just defaults to the height set in CSS or on the "height" attribute on the iframe. This was found through trial and error, so take it for what it is worth.
function getDocumentHeight(doc) {
var mdoc = doc || document;
var docHeight = mdoc.body.scrollHeight;
if ($.browser.msie) {
// IE 6/7 don't report body height correctly.
// Instead, insert a temporary div containing the contents.
var child = $("<div>" + mdoc.body.innerHTML + "</div>", mdoc);
$("body", mdoc).prepend(child);
docHeight = child.height();
child.remove();
}
return docHeight;
}
I have found this solution to work in ie 6+, ff 3.5+, safari 4+. I am creating and appending an iframe to the document. The following code is executed at the end of jQuery's load event after some other dom manipulation. The timeout is needed for me because of the additional dom manipulation taking place in the load event.
// sizing - slight delay for good scrollheight
setTimeout(function() {
var intContentHeight = objContentDoc.body.scrollHeight;
var $wrap = $("#divContentWrapper", objContentFrameDoc);
var intMaxHeight = getMaxLayeredContentHeight($wrap);
$this.height(intContentHeight > intMaxHeight ? intMaxHeight : intContentHeight);
// animate
fireLayeredContentAnimation($wrap);
}, 100);
I have some sizing constraints to consider, which is what the getMaxLayeredContentHeight call is checking for me. Hope that helps.
Here's a script that resizes the iFrame depending on the body inside it's height.
Related
I have some swf embedded in iframe but only if the page is refreshed the iframe is resized, then if I select other one then will show as all swf not only the animation the background as well. This is what I am using
if ( 'resizeIframe' === $('#onPlayAction').val() ) {
var ifrEl = $('div.player-container iframe.page-iframe')[0];
$(ifrEl).show();
ifrEl.src = htmlPageBrowserUri;
ifrEl.onload = function() {
ifrEl.width = ifrEl.contentWindow.document.body.scrollWidth;
ifrEl.height = ifrEl.contentWindow.document.body.scrollHeight;
}
}
There are three ways to do this.
You can change the size on every window resize
$(window).on('resize', function (){
ifrEl.width = ... ;
ifrEl.height = ... ;
})
You can use some jQuery plugins like iFrame Resizer
You can use some nifty css tricks. Go search for responsive iframes using css and you will find a ton of good answers.
I hope this all helps you.
I suspect the issue with your code might be thses two lines :
ifrEl.src = htmlPageBrowserUri;
ifrEl.onload = function() {
The problem being that the first line set s the frame address, but second line sets the onload event immediately, probably before the page has loaded ? So when the page does load, the line setting onload event has already run & so doens't get set.
I don't quite understand the text in your question (sorry!) but the code below successfully resizes an iframe - it's run 'onload' in the frame's page:
<body onload="setParent()">
In case it's relevant, the iframe itself has attributes:
<iframe id="neckfinishframe" style="width:100%;overflow-x:hidden" src=".. etc">
In my case I'm only concerned about height. Width is 100%.
In the iFrame page, this code runs from the onload event to amend the iframe height to be whatever the height of the page is, plus a bit. This is intended to avoid showing a set of scroll bars within the iframe.
function setParent() {
// runs onload in iframe page
// in my case I have to run it from the frame page because I need to know the page rendered height in order to set the iframe height
var f;
try {f = parent.getElementById("neckfinishframe")} catch (e) {};
if (f != null) f.style.height=(this.document.body.scrollHeight+30)+"px";
}
Note - I haven't tried this cross- browser but I know it works in IE.
I have an iframe as you can see on the following link;-
http://one2onecars.com
The iframe is the online booking in the centre of the screen. The problem I have is that although the height of the iframe is okay as the page loads, I need it to somehow auto adjust the height as the page content adjusts. For example, if I do a postcode search in the online booking it creates a dropdown menu and then makes the 'Next Step' button not viewable.
What I need to happen is that when the content of the online booking changes, the iframe auto adjusts to the new height of the iframe (dynamically) as it is not loading any other pages.
I have tried several different scripts using jquery to try resolving this issue, but they all only seem to auto adjust the height of the iframe when the page first loads and not as the contents of the iframe changes.
Is this even possible to do?
The code I have at the moment is with a set height at the moment:-
<div id="main-online-booking">
<iframe id="main-online-frame" class="booking-dimensions" src="http://www.marandy.com/one2oneob/login-guest.php" scrolling="no" frameborder="0"></iframe>
</div>
#main-online-booking {
height: 488px;
border-bottom: 6px #939393 solid;
border-left: 6px #939393 solid;
border-right: 6px #939393 solid;
z-index: 4;
background-color: #fff;
}
.booking-dimensions {
width: 620px;
height: 488px;
}
If anybody can help me with this I would be much appreciated!
setInterval
The only (corrected due to advances in browser tech, see David Bradshaw's answer) backwards compatible way to achieve this with an iframe is to use setInterval and keep an eye on the iframe's content yourself. When it changes its height, you update the size of the iframe. There is no such event you can listen out for that will make it easy unfortunately.
A basic example, this will only work if the iframe content that has changed in size is part of the main page flow. If the elements are floated or positioned then you will have to target them specifically to look for height changes.
jQuery(function($){
var lastHeight = 0, curHeight = 0, $frame = $('iframe:eq(0)');
setInterval(function(){
curHeight = $frame.contents().find('body').height();
if ( curHeight != lastHeight ) {
$frame.css('height', (lastHeight = curHeight) + 'px' );
}
},500);
});
Obviously depending on what you want you can modify the perspective of this code so that it works from the iframe, on itself, rather than expecting to be part of the main page.
cross-domain issue
The problem you will find is that due to browser security it wont let you access the content of the iframe if it is on a different host to the main page, so there isn't actually anything you can do unless you have a way of adding any script to the html that appears in the iframe.
ajax
Some others are suggesting trying to use the third-party service via AJAX, unless the service supports this method it will be very unlikely you'll be able to get it to work -- especially if it is a booking service that will most likely need to operate over https/ssl.
As it appears you have full control over the iframe content, you have full options open to you, AJAX with JSONP would be an option. However, one word of warning. If your booking system is multistepped you need to make sure you have a well designed UI -- and possibly some history/fragment management code -- if you are to go down the AJAX route. All because you can never tell when a user will decide to navigate forward or back in their browser (which an iframe would automatically handle, within reason). A well designed UI can detract users from doing this.
cross-domain communication
If you have control of both sides (which it sounds like you do) you also have the cross domain communication option using window.postMessage - see here for more information https://developer.mozilla.org/en-US/docs/DOM/window.postMessage
Modern browser and in part IE8 have some new features that make this task easier than it use to be.
PostMessage
The postMessage API provides a simple method for comunicating between an iFrame and it's parent.
To send a message to the parent page you call it as follows.
parent.postMessage('Hello parent','http://origin-domain.com');
In the other direction we can send the message to the iFrame with the following code.
var iframe = document.querySelector('iframe');
iframe.contentWindow.postMessage('Hello my child', 'http://remote-domain.com:8080');
To recevie a message create an event listerner for the message event.
function receiveMessage(event)
{
if (event.origin !== "http://remote-domain.com:8080")
return;
console.log(event.data);
}
if ('addEventListener' in window){
window.addEventListener('message', receiveMessage, false);
} else if ('attachEvent' in window){ //IE
window.attachEvent('onmessage', receiveMessage);
These examples uses the origin property to limit where the message is sent to and to check where it came from. It is possible to specify * to allow sending to any domain and you may in some cases you may want to accept messages from any domain. However, if you do this you need to consider the security implications and implement your own checks on the incoming message to ensure it contains what your expecting. In this case the iframe can post it's height to '*', as we might have more than one parent domain. However, it's a good idea to check incoming messages are from the iFrame.
function isMessageFromIFrame(event,iframe){
var
origin = event.origin,
src = iframe.src;
if ((''+origin !== 'null') && (origin !== src.substr(0,origin.length))) {
throw new Error(
'Unexpect message received from: ' + origin +
' for ' + iframe.id + '. Message was: ' + event.data
);
}
return true;
}
MutationObserver
The other advance in more modern broswers is MutationObserver which allows you to watch for changes in the DOM; so it is now possible to detect changes that could effect the size of the iFrame without having to constantly poll with setInterval.
function createMutationObserver(){
var
target = document.querySelector('body'),
config = {
attributes : true,
attributeOldValue : false,
characterData : true,
characterDataOldValue : false,
childList : true,
subtree : true
},
observer = new MutationObserver(function(mutations) {
parent.postMessage('[iframeResize]'+document.body.offsetHeight,'*');
});
log('Setup MutationObserver');
observer.observe(target, config);
}
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if (MutationObserver){
createMutationObserver();
}
Working out an accurate height
Getting an accurate height for the iFrame is not as simple as it should be, as you have a choice of six different properties that you can check and none of them give a constantly right answer. The best solution I've come up with is this function that works so long as you don't use CSS to overflow the body tag.
function getIFrameHeight(){
function getComputedBodyStyle(prop) {
return parseInt(
document.defaultView.getComputedStyle(document.body, null),
10
);
}
return document.body.offsetHeight +
getComputedBodyStyle('marginTop') +
getComputedBodyStyle('marginBottom');
}
This is the IE9 version, for the much long IE8 version see this answer.
If you do overflow the body and you can't fix your code to stop this, then using either the offsetHeight or scrollHeight properties of document.documentElement are your best options. Both have pros and cons and it best just to test both and see which works for you.
Other issues
Other things to consider include, having more than one iFrame on the page, CSS :Checkbox and :Hover events causing page resize, avoiding the use of height auto in the iFrames' body and html tags and lastly the window being resized.
IFrame Resizer Library
I've wrapped all this up in a simple dependancy free library, that also provides some extra functions not discussed here.
https://github.com/davidjbradshaw/iframe-resizer
This works with IE8+.
I wrote this script and it's working perfectly for me. Feel free to use it!
function ResizeIframeFromParent(id) {
if (jQuery('#'+id).length > 0) {
var window = document.getElementById(id).contentWindow;
var prevheight = jQuery('#'+id).attr('height');
var newheight = Math.max( window.document.body.scrollHeight, window.document.body.offsetHeight, window.document.documentElement.clientHeight, window.document.documentElement.scrollHeight, window.document.documentElement.offsetHeight );
if (newheight != prevheight && newheight > 0) {
jQuery('#'+id).attr('height', newheight);
console.log("Adjusting iframe height for "+id+": " +prevheight+"px => "+newheight+"px");
}
}
}
You can call the function inside a loop:
<script>
jQuery(document).ready(function() {
// Try to change the iframe size every 2 seconds
setInterval(function() {
ResizeIframeFromParent('iframeid');
}, 2000);
});
</script>
ResizeObserver allows your code to remain encapsulated inside the iframe and decoupled from the outer scope (i.e., versus postMessage), and it is ligher weight than the general-purpose MutationObserver.
Simple example below (or good example at Mozilla):
const myElement = document.getElementById('my-element');
const resizeObserver = new ResizeObserver((entries) => {
const dims = myElement.getBoundingClientRect(); // or see Mozilla for `entries` example
console.log(`new height (${dims.height}) and width (${dims.width})`);
});
resizeObserver.observe(myElement);
use this script:
$(document).ready(function () {
// Set specific variable to represent all iframe tags.
var iFrames = document.getElementsByTagName('iframe');
// Resize heights.
function iResize() {
// Iterate through all iframes in the page.
for (var i = 0, j = iFrames.length; i < j; i++) {
// Set inline style to equal the body height of the iframed content.
iFrames[i].style.height = iFrames[i].contentWindow.document.body.offsetHeight + 'px';
}
}
// Check if browser is Safari or Opera.
if ($.browser.safari || $.browser.opera) {
// Start timer when loaded.
$('iframe').load(function () {
setTimeout(iResize, 0);
});
// Safari and Opera need a kick-start.
for (var i = 0, j = iFrames.length; i < j; i++) {
var iSource = iFrames[i].src;
iFrames[i].src = '';
iFrames[i].src = iSource;
}
} else {
// For other good browsers.
$('iframe').load(function () {
// Set inline style to equal the body height of the iframed content.
this.style.height = this.contentWindow.document.body.offsetHeight + 'px';
});
}
});
Note : use it on webserver.
So I am trying to find the height of my images then add a top margin this enables me to impose a a vertical center.
I'm running this code, and on an F5 refresh I get correct height but on CTRL+F5 refresh it gives me a much smaller height. I kind of assume this is a loading/delay thing, but I am using document ready so not really sure whats going on. I tried using a php function but it slows the site down amazingly so have to stick with jquery.
you can see it working here. www.mzillustration.com
jQuery(document).ready(function() {
if (jQuery('.imagedisplay').length != 0) {
jQuery('.imagedisplay').each(function(){
var imgheight = jQuery(this).find('img').height();
var topmarg = ((240 - imgheight) / 2) ;
jQuery(this).find('img').css({'margin-top':topmarg+'px'});
});
});
any ideas/help/explanation much appreciated.
thanks
There is a difference between onload and onready.
ready will wait until the actual DOM-tree is done, while onload will wait until ALL of the content displayed on the page is finnished loading. So an explanation would be that when clearing the cache and refreshing, the dom tree finishes much faster than the images, hence giving the wrong heigh.
Try using the onload-event instead and see if you get a different result.
You need to insure the image has loaded before asking the browser for its height. If that image path is living in the html you will unfortunately need a jquery pluggin to handle this in a cross browser manner.
https://github.com/alexanderdickson/waitForImages
http://desandro.github.com/imagesloaded/
Or you will have to wait for the window.onload event which in jquery looks like this:
$(window).on('load', function(){....
However if you use the window load event, it will wait until ALL resources have loaded and depending on your site that can be a serious delay when compared to measuring just the image itself.
Or if you are comfortable with loading the image from javascript, simply ordering your code properly will handle this:
var loadTester = new Image(),
imgH;
$(loadTest).on('load',function(){
imgH = $('#image').attr('src',loadTester.src).height();
}
loadTester.src = "paht/to/image.jpg";
The reason you are seeing a difference in the manner you reload the page, is that a simple refresh does not clear the cache, so the image is already loaded. When you hit ctrl+f5 it clears the cache and so the image is not yet loaded when you ask the browser for the height.
For cache control durring development consider getting the firefox web-developer toolbar.
Try this approach:
jQuery(function() {
jQuery('.imagedisplay img').each(function() {
var $this = jQuery(this),
height = $this.height();
if (height) {
$this.css('margin-top', ((240 - height) / 2) + 'px');
} else {
$this.on('load', function() {
$this.css('margin-top', ((240 - $this.height()) / 2) + 'px');
});
}
});
});
images are/can be cached/loaded separately from the actual page content. the document being ready can (and in my experience usually) occurs before everything is loaded.
try adding an event listener to the actual element being loaded.
You need to make sure the image has loaded before extracting a height. You can easily check this using the complete property on the image. Try this:
var setH = function() {
$(this).css('margin-top', (240 - this.height) / 2);
}
$('.imagedisplay img').each(function() {
if( this.complete ) {
setH.call(this); // apply height straight away
return;
}
$(this).load(setH); // apply height when the image has loaded
});
I use the following code to dynamically create an iframe.
var iframe_jquery = $("<iframe>")
.addClass("foo")
.appendTo(container); // container is a jQuery object containing a <div> which already exists
Then, I want to access its contentWindow, but it's null:
var iframe = iframe_jquery.get(0);
if (iframe){ // iFrame exists
console.log(iframe.contentWindow); // Prints "null"
var doc = iframe.contentWindow.document; // NullpointerException
}
So I thought: "Maybe the iframe isn't ready yet?" So I tried:
iframe_jquery.ready(function(){
var iframe = iframe_jquery.get(0);
console.log(iframe.contentWindow); // Prints "null"
var doc = iframe.contentWindow.document; // NullpointerException
});
Same result.
What's wrong?
I had this problem last week while playing with iframes (building an rtf editor), and yeah it's not ready yet.
I thought if I put it in a .ready(), it would work, but .ready() is when the DOM is ready, not when the iframe has loaded its contents, so I ended up wrapping my code with jQuery .load().
So try this:
$(function () {
$("#myiframe").load(function () {
frames["myframe"].document.body.innerHTML = htmlValue;
});
});
Hope this helps
The problem is that your <iframe> won't be "real" until it's really added to the actual DOM for the page. Here is a fiddle to demonstrate..
Depending on the browser, accessing the document or an <iframe> may vary.
Here is an example of how to handle it:
if (iframe.contentDocument) // FF Chrome
doc = iframe.contentDocument;
else if ( iframe.contentWindow ) // IE
doc = iframe.contentWindow.document;
You can also make a function that will be executed when the iframe has finished loading by setting it's onload attribute.
Bookmarklet version
Just out of curiosity I thought I'd put this together. Remembering that iframes and load events don't play well together on different browsers (mainly older, falling apart, should-be-dead browsers)... plus not being entirely sure how jQuery gets around this problem... my brain decided that this would be better supported (whether it is or not is neither here nor there):
$(function(){
/// bind a listener for the bespoke iframeload event
$(window).bind('iframeload', function(){
/// access the contents of the iframe using jQuery notation
iframe.show().contents().find('body').html('hello');
});
/// create your iframe
var iframe = $('<iframe />')
/// by forcing our iframe to evaluate javascript in the path, we know when it's ready
.attr('src', 'javascript:(function(){try{p=window.parent;p.jQuery(p).trigger(\'iframeload\');}catch(ee){};})();')
/// insert the iframe into the live DOM
.appendTo('body');
});
The reason for taking this approach is that it is normally far better to trigger your load event from inside the iframe itself. But this means having a proper document loaded in to the iframe, so for dynamic iframes this is a little tedious. This is kind of a mixture between having a document loaded, and not.
The above works on everything I have tested so far - and yes you are correct - it is a little ridiculous, non-future-proof and propably other things that have negative connotations ;)
One positive thing I'll say about this post is that introduces the use of .contents() to access the document of the iframe, which is at least a little bit useful...
Working on a Mobile First design and want to conditional load and execute some JavaScript based on the browser width.
UPDATE: (more info on what I'm doing)
I'm looking to conditionally load different size Google DFP ads depending on the width of the browser window. So a desktop/iPad might see a 720 pixel wide ad, a wide mobile might see a 480px ad and a basic mobile might see a 320px ad.
Google DFP has an asynchronous method which has the main code in the head. Ad calls are then made via a combination of a div with a numbered id and a function call that has the same number.
So in what I'm trying to accomplish, I need to insert both a numbered div and a specific numbered function call into the div where I want the specific ad call to appear.
Looked around for conditional examples and this worked in my test:
<div id="ad"></div>
<script type="text/javascript">
var ad = document.getElementById("ad");
if (document.documentElement.clientWidth > 640) {
ad.innerHTML = "big";
}
if (document.documentElement.clientWidth < 640) {
ad.innerHTML = "small";
}
</script>
Obviously just a test of the width checking and not the ad call.
If I understand correctly, innerHTML won't work if I need to dynamically load and execute some JavaScript.
Basically, when I test for the size I have to enter an ad call like this into the #ad div:
<div id='div-gpt-ad-xxxxxxxxxxx-2'
style='width:728px;height:90px;margin:auto'><script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-xxxxxxxxxxx-2'); });
</script></div>
Notice the "-2" in both the div and function. That will be different for the different ad sizes.
Completely new to DOM manipulation so any help is greatly appreciated.
You are correct that script elements inserted using the innerHTML property aren't executed.
A simple solution is to collect the script elements that were inserted and replace them with new elements where the code will be executed, e.g.
function insertAndExecute(id, markup) {
var sOld, sNew, scripts;
var s;
var el = document.getElementById(id);
if (el) {
s = document.createElement('script');
el.innerHTML = markup;
scripts = el.getElementsByTagName('script');
for (var i=0, iLen=scripts.length; i<iLen; i++) {
sOld = scripts[i];
sNew = s.cloneNode(true);
sNew.type = sOld.type;
if (sOld.src) {
sNew.src = sOld.src;
} else {
sNew.text = sOld.text;
}
sOld.parentNode.replaceChild(sNew, sOld);
}
}
}
It is much better if the scripts have a src attribtue and load an external file.
As jfriend00 says, if you can determine the markup to be inserted during page load, document.write is a viable alternative as it will cause included scripts to be executed. But you can't use it after the page has finished loading.
Edit
As for getting the width of the window:
var width = window.innerWidth || document.body.clientWidth;
should do. Note that in IE, clientWidth is 20px less than the window width because it allows for a vertical scroll bar. But that shouldn't matter here.
Also, clientWidth shouldn't be measured until the document has finished loading so the layout is complete (use onload or something later), and make sure documents have a DOCTYPE so that IE is in standards mode (or "almost standards mode" or whatever).
You might also be interested in How to Measure the Viewport.
If you're new to DOM manipulation, then stop right now and find a JavaScript library that you like. The DOM is by far the most frustrating part of using JavaScript in the browser, so don't ruin your first experience with the language by not using a library that helps you with it. Two good options are YUI and jQuery. This is important because you can't get the width of the screen reliably with document.documentElement.clientWidth. Different browsers use different properties for it.
Regarding your question, in this case it's just a matter of running the code in your script after inserting the content into the ad container.
<div id="ad"></div>
<script>
document.getElementById('ad').innerHTML = '<div id="div-gpt-ad-xxxxxxxxxxx-2" style="width:728px;height:90px;margin:auto"></div>';
if (screenWidth > 640) {
googletag.cmd.push(function() {
googletag.display('div-gpt-ad-xxxxxxxxxxx-2');
});
} else {
// do something else
}
</script>