Live reloading iframe script on change - javascript

I'm setting up some editors with HTML, CSS and JS code. The code of each of them is reloaded in an iframe when it's change. HTML and CSS code reloads perfectly, bus the JS code that is injected inside of a script in the body of the iframe is not working, possible because it's not rerunning once it's updated, but I don't know how to do it...
Any idea?
Here's an example in Plunker http://plnkr.co/edit/tpl:8rFfZljYNl3z1A4LKSL2?p=preview
HTML
<div class="result">
<!-- RESULT -->
<style id="style"></style>
<script id="script"></script>
<script id="jQ" type="text/javascript" src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
<iframe id="view" class="view"></iframe>
</div>
JS
var app = angular.module('plunker', []);app.controller('MainCtrl', function($scope) {
var style = document.getElementById('style');
var script = document.getElementById('script');
var jQ = document.getElementById('jQ');
var view = document.getElementById('view');
var viewDocument = view.contentDocument || view.contentWindow.document;
var body = viewDocument.getElementsByTagName('body')[0];
var head = viewDocument.getElementsByTagName('head')[0];
var widgets = [];
var loadScript = document.createElement('script');
loadScript.innerHTML = "var $ = parent.$; console.log('loaded');";
$scope.html = '<div id="test">Testing</div>';
$scope.js = 'console.log("More test");';
head.appendChild(jQ);
head.appendChild(loadScript);
head.appendChild(style);
body.appendChild(script);
$scope.$watch('html', function(nv){
body.innerHTML = nv;
body.appendChild(script);
});
$scope.$watch('js', function(nv){
script.innerHTML = nv;
});});
Note: Code seems to run fine when is set by hand
SOLVED:
I found a way around. Here's the code in case someone else need it
setTimeout(updatePreview(codeHTML, codeCSS, codeJS), 300);
function updatePreview(codeHTML, codeCSS, codeJS) {
var view = document.getElementById('view');
var viewDocument = view.contentDocument || view.contentWindow.document;
var codeHTML = (codeHTML === undefined) ? '' : codeHTML;
var codeCSS = (codeCSS === undefined) ? '' : codeCSS;
var codeJS = (codeJS === undefined) ? '' : codeJS;
viewDocument.open();
viewDocument.write('<style type="text/css">' + codeCSS + '</style>');
viewDocument.write('<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.0.min.js"></script>');
viewDocument.write(codeHTML);
viewDocument.write('<script type="text/javascript">' + codeJS + '</script>');
viewDocument.close();
}
This is called in $scope.$watch of de editors passing the updated value.

Weave: http://kodeweave.sourceforge.net/editor/#b6b39c95ec91f42950957a1ac8dc707f
I see you were able to solve your problem however I have a minor suggestion.
If a user uses setTimeout or setInterval like so...
setInterval((function() {
return $('body').css('background', newGradient())
}), 1000)
The problem you have in your code is it will add to the original literation and your setInterval function in this case will be added to the previous one.
Thus a good idea is to create the iframe dynamically and add the code within that. This way you have more control over what's being added to the iFrame and how to handle it.
document.querySelector(".preview").innerHTML = ""
var frame = document.createElement("iframe")
frame.setAttribute("id", "preview")
frame.setAttribute("sandbox", "allow-forms allow-modals allow-pointer-lock allow-popups allow-same-origin allow-scripts")
document.querySelector(".preview").appendChild(frame)

Related

Display complete Javascript tag in div

I need to place an entire javascript function in a div and show it for testing purposes, how can I accomplish this? I am doing this from code behind in asp.net
EDIT
<!-- Facebook Conversion Code for Website Purchase -->
<script type='text/javascript'>
(function() {
var _fbq = window._fbq || (window._fbq = []);
if (!_fbq.loaded) {
var fbds = document.createElement('script');
fbds.async = true;
fbds.src = '//connect.facebook.net/en_US/fbds.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(fbds, s);
_fbq.loaded = true;
}
})();
window._fbq = window._fbq || [];
</script>
Edit: You need to do some trickery: How to show <div> tag literally in <code>/<pre> tag? Which says that you need to escape your < and > characters in your tag to < and > for them to show in the <pre>. The example below has been modified to show this.
You should try using the html <pre> tag, it's commonly supported and does exactly what you're asking for:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre
<pre>
<script type="text/javascript">
console.log('hi');
</script>
</pre>
should show something like
<script type="text/javascript">
console.log('hi');
</script>

Javascript in my Meteor app still not working

I originally posted this How can I load js into my templates with Meteor/handlebars.js?
and thought I had a solution to my issue. I was wrong. I have some external js I want to load as well as an internal script. I tried placing the scripts in a template alone for example:
<template name="myscripts">
<script src="myexternalscript"></script>
<script src="anotherexternalscript></script>
<script src="anotherexternalscript"></script>
<script>
//internal script code here
</script>
</template>
then on the template with the html I want those scripts to affect, which contains html named "myothertemplate", I added
{{myscripts}}
to the bottom of those elements where I wanted it to load. Then that template which contains the html elements and the {{myscripts}} which I want to load the JavaScript, is loaded on my main page in the body {{>myothertemplate}}. I run my project, localhost:3000 and get no errors. I see the scripts I wanted there on the page where I wanted them as well but they don't work. They have no affect on the page. I tried taking the internal JavaScript and saving it as a JavaScript file as well as the external JavaScript files however this is not working either. This is an example of what I want:
<!--HTML here-->
<!--some elements here
after the last div on this template page, I wanted to add my scripts.-->
<div>
</div>
<script src="some external script"></script>
<script src="some external script"></script>
<!--Now my internal script-->
<script>
(function() {
// Base template
var base_tpl =
"<!doctype html>\n" +
"<html>\n\t" +
"<head>\n\t\t" +
"<meta charset=\"utf-8\">\n\t\t" +
"<title>Test</title>\n\n\t\t\n\t" +
"</head>\n\t" +
"<body>\n\t\n\t" +
"</body>\n" +
"</html>";
var prepareSource = function() {
var html = html_editor.getValue(),
css = css_editor.getValue(),
js = js_editor.getValue(),
src = '';
src = base_tpl.replace('</body>', html + '</body>');
css = '<style>' + css + '</style>';
src = src.replace('</head>', css + '</head>');
js = '<script>' + js + '<\/script>';
src = src.replace('</body>', js + '</body>');
return src;
};
var render = function() {
var source = prepareSource();
var iframe = document.querySelector('#output iframe'),
iframe_doc = iframe.contentDocument;
iframe_doc.open();
iframe_doc.write(source);
iframe_doc.close();
};
var cm_opt = {
mode: 'text/html',
gutter: true,
lineNumbers: true,
};
var html_box = document.querySelector('#html textarea');
var html_editor = CodeMirror.fromTextArea(html_box, cm_opt);
html_editor.on('change', function (inst, changes) {
render();
});
cm_opt.mode = 'css';
var css_box = document.querySelector('#css textarea');
var css_editor = CodeMirror.fromTextArea(css_box, cm_opt);
css_editor.on('change', function (inst, changes) {
render();
});
cm_opt.mode = 'javascript';
var js_box = document.querySelector('#js textarea');
var js_editor = CodeMirror.fromTextArea(js_box, cm_opt);
js_editor.on('change', function (inst, changes) {
render();
});
var cms = document.querySelectorAll('.CodeMirror');
for (var i = 0; i < cms.length; i++) {
cms[i].style.position = 'absolute';
cms[i].style.top = '30px';
cms[i].style.bottom = '0';
cms[i].style.left = '0';
cms[i].style.right = '0';
cms[i].style.height = '100%';
}
/*cms = document.querySelectorAll('.CodeMirror-scroll');
for (i = 0; i < cms.length; i++) {
cms[i].style.height = '100%';
}*/
}());
</script>
$.getScript('/myscript.js') worked.

Add external file to head - one for Staging and one for Production

I need to add an external javascript file to the <head> section of a website - one file when on the Staging server, and a different one for production.
So far I have this, but I get an error: 'return' outside of function
<script type="text/javascript">
var pathOrigin = window.location.origin;
var headtg = document.getElementsByTagName('head')[0];
if (!headtg) {
return;
}
var linktg = document.createElement('script');
if (pathOrigin.toLowerCase().indexOf("staging.server.com") >= 0) {
linktg.src = '/script-staging.js';
} else {
linktg.src = '/script-production.js';
}
headtg.appendChild(linktg);
</script>
What am I missing?
Thanks.
Return - Specifies the value to be returned by a function.
That means the error you got from the browser is correct. Your returnstatement is not part of a function, but of the global scope. You wil either have to skip using the return statement and use simple variable assingment like in #Azzy's answer, or encapsulate it in a function like so:
function getHead() {
var headtg = document.getElementsByTagName('head')[0];
if (typeof headtg === 'undefined') {
return; // will break the function
} else {
var linktg = document.createElement('script');
if (pathOrigin.toLowerCase().indexOf("staging.server.com") >= 0) {
linktg.src = '/script-staging.js';
} else {
linktg.src = '/script-production.js';
}
headtg.appendChild(linktg);
};
};
getHead(); // don't forget to initialize the function
//or you could do:
element.onload/onclick/on<whatever_event> = getHead();
To me it is also not clear what you want to return, unless you simply want to stop script execution; citing from MDN:
If the expression in return [expression] is omitted, undefined is returned instead.
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return
NB: Check this why it is safer to use the typeofstatement than a simple !mark to check if something exists: Check if object exists in JavaScript.
EDIT: For a very simple use case of the return statement, you can check out this fiddle I made which is basically a counter that will output an error when it reaches 100.
Where place this code? Are you sure that the path is correct?
Another method to add js file into head is this method:
<head>
....
<script type="text/javascript">
var pathOrigin = window.location.origin;
var path = "";
if (pathOrigin.toLowerCase().indexOf("staging.server.com") >= 0) {
path = '/script-staging.js';
} else {
path = '/script-production.js';
}
document.write( '<script type="text/javascript" src="' + path + '"><\/script>' );
</script>
.....
</head>
<html>
<head>
<script type='text/javascript'>
var path = window.location.origin
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
if (path == 'local'){
fileref.setAttribute("src", 'file:///D:/JS/jquery.js')
}
else{
fileref.setAttribute("src", 'file:///D:/JS/jquery.js')
}
document.getElementsByTagName("head")[0].appendChild(fileref)
//list all the js loaded dynamically
var scripts = document.getElementsByTagName('script');
console.log(scripts);
</script>
</head>
<body>
<p>test</p>
</body>
</html>
To load script dynamically, you can try out this..
The javascript error "return statement outside of function" means you've created a code fragment that is not allowed to exist outside of a function definition.

Replace a script with another using Js and checkbox?

I'm creating a page which is suppose to be a little interactive. The user is suppose to be able to change a bunch of information by checking off an checkbox.
Index.php:
<span id="changeIt">Deactivated! - [ChangeMod]<img src="pic/deactivated.png"></span>
<form action="">
<input type="checkbox" id="checkboxChange" onclick="ChangeEverything();">Change Everything!</input>
</form>
<script TYPE="text/javascript" SRC="script/map_checkbox.js"></script>
map_checkbox.js:
var checkbox6 = document.getElementById("checkboxChange");
var posting6 = document.getElementById("changeIt");
var script = document.createElement("scriptChange");
function ChangeEverything(){
if (checkbox6.checked){
posting6.innerHTML="Activated! - [ChangeMod]<img src='pic/activated.png'>" ;
script.src = 'scriptMain.js';
var head = document.getElementsByTagName("head")[0];
head.appendChild(scriptChange);
}
else{
posting6.innerHTML="Deactivated! - [ChangeMod]<img src='pic/deactivated.png'>" ;
script.src = 'scriptSec.js';
var head = document.getElementsByTagName("head")[0];
head.appendChild(scriptChange);
}
}
Is it possible to overwrite the script like this, or do I have to use another method?
i think you have a problem with the
var script = document.createElement("scriptChange");
tou have to put the tag NAME
var script = document.createElement("script");

How to add script code using javascript?

I want to add script tag using javascript, but I am not able to get it work. Below is code. I want to add this code in bigcommerce cart page.
var duration = document.getElementsByName("cartdata");
var cartstr = '<!-- MyBuys Page Parameters – Place in <body> element -->';
cartstr += '<script type="text/javascript">';
cartstr += 'mybuys.setPageType("SHOPPING_CART");';
cartstr += 'mybuys.set("email","consumer#example.com"); <!--consumer email can be blank if not known-->';
cartstr += 'mybuys.set("amount","99.34");';
for (var i = 0; i < duration.length; i++) {
str = duration[i].value;
var n = str.split('|');
cartstr += 'mybuys.addCartItemQtySubtotal("'+n[0]+'","'+n[1]+'","'+n[2]+'");'+'<br>';
}
cartstr += '</script>';
cartstr += '<!-- End MyBuys Page Parameters -->';
//alert(cartstr);
var script = document.createElement("script");
script.type = "text/javascript";
script.text = cartstr; // use this for inline script
document.body.appendChild(script);
I want below code added to page:
<!-- MyBuys Page Parameters – Place in <body> element -->
<script type="text/javascript">
mybuys.setPageType("SHOPPING_CART");
mybuys.set("email","consumer#example.com"); <!--consumer email can be blank if not known-->
mybuys.set("amount","99.34");
mybuys.addCartItemQtySubtotal("12345","1","54.34");
mybuys.addCartItemQtySubtotal("56789","3","45.00");
</script>
<!-- End MyBuys Page Parameters -->
This demonstrates how to dynamically add JavaScript:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
var optionalFunctionLoaded = false;
var commonFunction = function() {
console.log("test button clicked " + (new Date()).toLocaleString());
if (!optionalFunctionLoaded) {
// get optionalSrc e.g. via AJAX, eventually providing actual input values
var optionalSrc = 'function optFun(){console.log("optional function");}';
// if optionalSrc is not empty
var script = document.createElement("script");
script.innerHTML = optionalSrc;
document.head.appendChild(script);
optionalFunctionLoaded = true;
}
if(optionalFunctionLoaded) optFun();
}
</script>
</head>
<body>
<button id ="testButton">test</button>
<script type="text/javascript">
document.getElementById("testButton").onclick = commonFunction;
</script>
</body>
</html>
Tested with Firefox 24.0 / Linux.
The solution is to just add the code to the page:
<!-- MyBuys Page Parameters – Place in <body> element -->
<script type="text/javascript">
mybuys.setPageType("SHOPPING_CART");
mybuys.set("email","consumer#example.com"); <!--consumer email can be blank if not known-->
mybuys.set("amount","99.34");
mybuys.addCartItemQtySubtotal("12345","1","54.34");
mybuys.addCartItemQtySubtotal("56789","3","45.00");
</script>
<!-- End MyBuys Page Parameters -->
Why use JavaScript to put it there? Just add it to the page. You might have to adjust it a bit with your loop:
for (var i = 0; i < duration.length; i++) {
str = duration[i].value;
var n = str.split('|');
mybuys.addCartItemQtySubtotal(n[0],n[1],n[2]);
}
You should just be executing the code, there is no need to build the string. In the end, what you are trying to do is the same thing as running the code! Just execute it.
mybuys.setPageType("SHOPPING_CART");
mybuys.set("email","consumer#example.com");
mybuys.set("amount","99.34");
for (var i = 0; i < duration.length; i++) {
str = duration[i].value;
var n = str.split('|');
mybuys.addCartItemQtySubtotal(n[0],n[1],n[2]);
}
I don't know why would you want to do that. But if you really want to, here is a way you could try.
$('body').append("console.log('blah');")
OR
$('body').html($('body').html()+"console.log('blah');")
Replace console.log('blah') with your code
Note this is assuming you are using JQuery.
If not, you can still use Native Javascript to do something similar. Just search for creating an element and adding it to another using vanila javascript and you'll get lots of information on google.
Although, as epascarello says, its not a good idea to do this. Its basically a code smell and you can improve your code.
Hope this helps.

Categories

Resources