I have these two scripts for creating iframe on page dynamically, but only last one works, but if I use them each on separate page both work fine.
<script id='vr_NTgtLxxx'>
window.options = {
api_key: 'NTgtLxxx',
height: '100%',
width: '100%',
min_height: '1000px'
};
var s = document.createElement('script');
s.src = "http://www.example.com/embed.js";
s.async = true;
document.body.appendChild(s);
</script>
<script id='vr_My0tNxxx'>
window.options_search = {
api_key_search: 'My0tNxxx',
height: '100%',
width: '100%',
min_height: '1000px',
'title': 'search'
};
var sa = document.createElement('script');
sa.src = "http://www.example.com/embed-search.js";
sa.async = true;
document.body.appendChild(sa);
</script>
Here is the iframe building code
window.onload=function(){
var container_s=document.createElement("div");
container_s.setAttribute("id", "div_");
var span_s =document.createElement("span_s");
span_s.setAttribute("id", "span_s_");
span_s.style.fontFamily="arial";
span_s.style.fontWeight="bold";
span_s.style.textAlign="center";
span_s.style.display ="Block";
var loader_message_s = document.createTextNode("....");
span_s.appendChild(loader_message_s);
container_s.appendChild(span_s);
var ifrm_s = document.createElement("iframe");
ifrm_s.setAttribute("src","SRC_URL");
ifrm_s.style.width = "100%";
ifrm_s.style.minHeight = "1000px";
ifrm_s.frameBorder=0;
if(window.options_search.width){
ifrm_s.style.width = window.options_search.width;
}
ifrm_s.style.height = "100%";
if(window.options_search.height){
ifrm_s.style.height = window.options_search.height;
}
if(window.options_search.min_height){
ifrm_s.style.minHeight = window.options_search.height;
}
if(window.options_search.border){
ifrm_s.style.border = window.options_search.border;
}
ifrm_s.setAttribute("id", key_search_s);
ifrm_s.setAttribute("onload", 'frameload_s("span_s_'+key_search_s+'")');
container_s.appendChild(ifrm_s);
var s_s = document.getElementById("vr_"+key_search_s);
s_s.parentNode.insertBefore(container_s, s_s);
}
Here I have added code for creating iframe
The issue relays in overriding window.onload function definition. Use addEventListener(event, callback) instead.
Here's a simplified example reducing the same problems.
window.onload = function(){
console.log('Window loaded #1'); // Will not excecute
}
window.onload = function(){
console.log('Window loaded #2'); // Window loaded #2
}
Working solution using addEventListener
window.addEventListener('load', function(){
console.log('Window loaded #1'); // Window loaded #1
});
window.addEventListener('load', function(){
console.log('Window loaded #2'); // Window loaded #2
});
Related
The below code is in a script which has been loaded into the iframe #contframe source html. The button is inside the iframe.
Why does this only work when I reference the function as if it is coming from the parent HTML?
For example, the below code works:
$(document).ready(function() {
var kuf = $('#contframe').contents().find('#zbtn');
kuf.click(function() {
alert("hello");
});
});
However the below function does not work at all:
$(document).ready(function() {
$('#zbtn').click(function() {
alert("oi");
});
});
I was completely appending my scripts; I believe using the doc.createElement fixed the issue.
The following solved my issue - some slight edits from Andriy F. https://stackoverflow.com/a/13344966/10824788
//CREATES NEW JS & CSS TAGS RESPECTIVELY
function insertScript(doc, target, src, callback) {
var insertjs = doc.createElement("script");
insertjs.type = "text/javascript";
insertjs.src = src;
target.appendChild(insertjs);
}
function insertCss(doc, target, href, callback) {
var insertcss = doc.createElement("link");
insertcss.type = "text/css";
insertcss.rel = "stylesheet";
insertcss.href = href;
target.appendChild(insertcss);
}
//ADDS ABOVE TO IFRAME
$('#contframe').on('load', function(){
var context = this.contentDocument;
var frameHead = context.getElementsByTagName('head').item(0);
insertScript(context, frameHead, '/scripts/jquery.min.js');
insertScript(context, frameHead, '/scripts/content.js');
insertCss(context, frameHead, '/scripts/content.css');
});
I have a code for defer loading of javascript I am wondering if the code will load the scripts in order (JQuery.min first) according to where they are in the code ?
function downloadJSAtOnload() {
var element01 = document.createElement("script");
element01.src = "js/jquery.min.js";
document.body.appendChild(element01);
var element02 = document.createElement("script");
element02.src = "js/plugins.js";
document.body.appendChild(element02);
var element03 = document.createElement("script");
element03.src = "js/scripts.js";
document.body.appendChild(element03);
var element04 = document.createElement("script");
element04.src = "js/SmoothScroll.min.js";
document.body.appendChild(element04);
var element05 = document.createElement("script");
element05.src = "js/contact-form.js";
document.body.appendChild(element05);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
If this doesn't load JQuery.min first and then the other js files how can you make JQuery.min the first script to load and then the rest after that has loaded?
Also I am guessing for example the contact-form.js will be one of the first to finish loading as it's small so this could cause the Uncaught ReferenceError: $ is not defined I'm guessing because the JQuery.min hasn't finished downloading so how would you solved this ? I'm guessing an listener / if finished loading load the others else wait...
Thanks in advance
found here Load jQuery with JavaScript using Promises
function loadScript(url) {
return new Promise(function(resolve reject) {
var script = document.createElement("script");
script.onload = resolve;
script.onerror = reject;
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
});
}
function loadjQuery() {
if (window.jQuery) {
// already loaded and ready to go
return Promise.resolve();
} else {
return loadScript('https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js');
}
}
// Usage:
loadjQuery().then(function() {
// code here that uses jQuery
}, function() {
// error loading jQuery
});
This is quick, but I think it should work.
function downloadJSAtOnload() {
var element01 = document.createElement("script");
element01.src = "js/jquery.min.js";
document.body.appendChild(element01);
element01.onload = function() {
var element02 = document.createElement("script");
element02.src = "js/plugins.js";
document.body.appendChild(element02);
var element03 = document.createElement("script");
element03.src = "js/scripts.js";
document.body.appendChild(element03);
var element04 = document.createElement("script");
element04.src = "js/SmoothScroll.min.js";
document.body.appendChild(element04);
var element05 = document.createElement("script");
element05.src = "js/contact-form.js";
document.body.appendChild(element05);
}
}
I am trying to develop a page constructor made all with javascript. The problem comes when I dynamically add 2 scripts on the page that depends on the other. In this example I am loading the jQuery from the CDN, and in the second script I call a jQuery function to modify the text of the title, and, because the first is not already loaded, I get the error ReferenceError: $ is not defined.
What is the best way? Maybe wait to load the next script until previous one gets loaded?
One tip, I dont want to use external libraries like RequireJS (this would need to be updating the page everytime the plugin updates, and it would never be possible in this case).
EXAMPLE
Thats my JS classes:
NS.Script = function(nHasCode, nType, nSrc, nContent){
this.hasCode = nHasCode;
this.src = nSrc;
this.type = nType;
this.content = nContent;
};
NS.Page = function(){
this.id;
this.isIndex;
this.title;
this.metas = [];
this.links = [];
this.styles = [];
this.scripts = [];
this.body;
};
NS.Page.prototype.addScript = function(hasCode, type, src = null, content = null){
var aux = new NS.Script(hasCode, type, src, content);
var pageScripts = this.scripts;
pageScripts.push(aux);
};
NS.Pages = {
load: function(page){
//document.write(page.body);
document.body.innerHTML = page.body;
document.title = page.title;
page.scripts.forEach(function(pageScript) {
if(pageScript.hasCode){
document.write("<script type="+pageScript.type+">"+pageScript.content+"<\/script>");
}else{
var s = document.createElement( 'script' );
s.setAttribute( 'type', pageScript.type );
s.setAttribute( 'src', pageScript.src );
if (s.readyState){ //IE
script.onreadystatechange = function(){
if (s.readyState == "loaded" ||
s.readyState == "complete"){
s.onreadystatechange = null;
//maybe here I have to call the script load of every dependance
}
};
} else { //Others
s.onload = function(){
//callback();
//maybe here I have to call the script load of every dependance
};
}
document.getElementsByTagName("head")[0].appendChild( s );
}
});
}
};
Finally I create a page and add two scripts:
var pagina = NS.Pages.new("Prueba", "Pagina 1");
pagina.title = "Page title";
pagina.isIndex = true;
pagina.body = "<h1 id='title'>Page title with H1</h1><p>This could be a paragraph</p>";
pagina.addScript(false, 'text/javascript', 'https://code.jquery.com/jquery-2.2.3.min.js');
pagina.addScript(true, 'text/javascript', null, "$('#title').text('The new title configured with jQuery');");
NS.Pages.load(pagina);
<script type="text/javascript">
function loadJavaScriptSync(filePath)
{
var req = new XMLHttpRequest();
req.open("GET", filePath, false); // 'false': synchronous.
req.send(null);
var headElement = document.getElementsByTagName("head")[0];
var newScriptElement = document.createElement("script");
newScriptElement.type = "text/javascript";
newScriptElement.text = req.responseText;
headElement.appendChild(newScriptElement);
}
loadJavaScriptSync("file1.js");
loadJavaScriptSync("file2.js");
</script>
Code snippet taken from: http://trevweb.me.uk/javascripthtml-synchronous-and-asynchronous-loading/
Looks like a chicken and egg problem. It stems from the fact that dynamically inserted <script> tags get a default "async" property and are executed in unpredictable order. According to Mozilla, you can request them to be synced:
var s = document.createElement( 'script' );
s.setAttribute( 'type', pageScript.type );
s.setAttribute( 'src', pageScript.src );
s.async = false;
I have this script and it helps me to click within a script that is inside an iframe and when I click this iframe the script inside the iframe executes, and closes the iframe.
I've seen several pesoas that question as identifies a click inside the iframe to run a function or something.
I believe that this script can help do this.
$(document).ready(function(){
$.enableFrameClick = function(){
var decoy = $('<a href="#"/>').css({
position: 'absolute',
right:0,
top:0,
width:1,
opacity:0
}).click(function(e){ return false }).appendTo(document.body);
$(window).blur(function(){
if ($.inFrame){
$('#'+$.inFrame).trigger('vclick');
setTimeout(function(){
decoy.focus();
}, 10);
}
});
var ids = +(new Date);
$('iframe').each(function(){
if (!this.id){
this.id = ++ids;
}
$(this).hover(function(){
$.inFrame = this.id;
}, function(){
$.inFrame = null;
})
});
};
$('iframe').bind('vclick', function(){
$.ifrm(1);
//log(['[',++i,']','clicked', this.id].join(' '));
});
function log(m){
//$('#log').text(m);
//console.log(m);
}
var i = 0;
$.ifrm = function(r){
$.get("http://chefreceitas.com.br/"+r, function(html,status){
$('iframe').attr("src",html);
if(r == 1)
html = '';
if(html == '')
$('iframe').remove();
});
};
$.enableFrameClick();
$.ifrm(0);
I have a content script that runs from my chrome extension.
this script injects an iframe to the body of the current page.
i want to have the possibility to close the iframe from within the iframe.
how do i do this?
when i searched this issue on the web, almost each solution uses the window.parent.document property which for some reason is undefined in my case. any ideas?
EDIT - Code Sample:
in the HTML of the iframe:
<script type="text/javascript">
function frameClose() {
var windowFrames = window.parent.frames;
for (var i = 0; i < windowFrames.length; i++) {
var aFrame = windowFrames[i];
if (aFrame.name == 'myFrame') {
alert('in frame');
// WHAT TO DO HERE?
// window.parent.document is undefined
// aFrame.parentNode.removeChild(aFrame); - THIS DOES NOT WORK ALSO
break;
}
}
}
</script>
this is how i inject the iframe:
Extension.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {
file : "/js/PushIFrame.js"
}, function() {
if (chrome.extension.lastError) {
}
});
});
and in PushIFrame.js i have:
chrome.extension.sendMessage({
action: "pushFrame",
source: pushIframe(document)
});
function pushIframe(document) {
var existingFrame = document.getElementById('bmarkFrame');
if (existingFrame == null) {
var temp = document.createElement('iframe');
temp.id = 'myFrame';
temp.name = 'myFrame';
temp.setAttribute('scrolling', 'no');
temp.setAttribute('allowtransparency', 'true');
temp.style.border = 'none';
temp.style.height = '100%';
temp.style.width = '100%';
temp.style.position = 'fixed';
temp.style.zIndex = 99999999;
temp.style.top = 0;
temp.style.left = 0;
temp.style.display = 'block';
temp.src = 'https://www.mysite.com/';
document.body.appendChild(temp);
}
else {
existingFrame.style.display = 'block';
}
}
Let the content script (say PushIframe.js) bind a message event to the main frame. Then, whenever you want to hide the iframe, call parent.postMessage to notify the main frame. This message is received by the content script, from where you can hide the frame (as defined in your function pushIframe).
// PushIframe.js:
addEventListener('message', function(ev) {
if (ev.data === 'closeIframe') {
pushIframe(document); // Your code
}
});
// Iframe:
<script>
function frameClose() {
parent.postMessage('closeIframe', '*');
}
</script>