I'm new to Plunker so this may be a noob question...But I really struggled a long time and haven't figured it out yet.
I tried to test the example code published on Skulpt's main site in Plunker but it just didn't work. But it did work in local server.
Here's my plunker link
Here's the code:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" type="text/javascript"></script>
<script src="http://www.skulpt.org/static/skulpt.min.js" type="text/javascript"></script>
<script src="http://www.skulpt.org/static/skulpt-stdlib.js" type="text/javascript"></script>
</head>
<body>
<script type="text/javascript">
// output functions are configurable. This one just appends some text
// to a pre element.
function outf(text) {
var mypre = document.getElementById("output");
mypre.innerHTML = mypre.innerHTML + text;
}
function builtinRead(x) {
if (Sk.builtinFiles === undefined || Sk.builtinFiles["files"][x] === undefined)
throw "File not found: '" + x + "'";
return Sk.builtinFiles["files"][x];
}
// Here's everything you need to run a python program in skulpt
// grab the code from your textarea
// get a reference to your pre element for output
// configure the output function
// call Sk.importMainWithBody()
function runit() {
var prog = document.getElementById("yourcode").value;
var mypre = document.getElementById("output");
mypre.innerHTML = '';
Sk.pre = "output";
Sk.configure({output:outf, read:builtinRead});
(Sk.TurtleGraphics || (Sk.TurtleGraphics = {})).target = 'mycanvas';
var myPromise = Sk.misceval.asyncToPromise(function() {
return Sk.importMainWithBody("<stdin>", false, prog, true);
});
myPromise.then(function(mod) {
console.log('success');
},
function(err) {
console.log(err.toString());
});
}
</script>
<h3>Try This</h3>
<form>
<textarea id="yourcode" cols="40" rows="10">import turtle
t = turtle.Turtle()
t.forward(100)
print "Hello World"
</textarea><br />
<button type="button" onclick="runit()">Run</button>
</form>
<pre id="output" ></pre>
<!-- If you want turtle graphics include a canvas -->
<div id="mycanvas"></div>
</body>
</html>
Your code requests http resources and is being run from the https version of Plunker. Plunker's editor can be opened either in https or in http though I encourage the former.
Modern browsers will now block the loading of http resources from an https website (such as the preview of your Plunk). You can observe this by opening the developer console where you will see messages about blocked requests.
You have two options:
Open your saved Plunk via http (your plunk over http)
Adjust the resources that your plunk requests to come from an https:// scheme:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" type="text/javascript"></script>
<script src="https://www.skulpt.org/static/skulpt.min.js" type="text/javascript"></script>
<script src="https://www.skulpt.org/static/skulpt-stdlib.js" type="text/javascript"></script>
Related
So I am trying to do a python interpreter on my website using skulpt.
But im running to some issues and dont know how to fix them. The error will be probably in the js script which is shown below
Error:
Uncaught ReferenceError: Sk is not defined at runit (portfolio:33) at HTMLButtonElement.onclick (portfolio:57)
HTML CODE:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" type="text/javascript"></script>
<script src="http://www.skulpt.org/js/skulpt.min.js" type="text/javascript"></script>
<script src="http://www.skulpt.org/js/skulpt-stdlib.js" type="text/javascript"></script>
</head>
<body>
<script type="text/javascript">
function outf(text) {
var mypre = document.getElementById("output");
mypre.innerHTML = mypre.innerHTML + text;
}
function builtinRead(x) {
if (Sk.builtinFiles === undefined || Sk.builtinFiles["files"][x] === undefined)
throw "File not found: '" + x + "'";
return Sk.builtinFiles["files"][x];
}
function runit() {
var prog = document.getElementById("yourcode").value;
var mypre = document.getElementById("output");
mypre.innerHTML = '';
Sk.pre = "output";
Sk.configure({output:outf, read:builtinRead});
(Sk.TurtleGraphics || (Sk.TurtleGraphics = {})).target = 'mycanvas';
var myPromise = Sk.misceval.asyncToPromise(function() {
return Sk.importMainWithBody("<stdin>", false, prog, true);
});
myPromise.then(function(mod) {
console.log('success');
},
function(err) {
console.log(err.toString());
});
}
</script>
<h3>Try This</h3>
<form>
<textarea id="yourcode" cols="40" rows="10">import turtle
t = turtle.Turtle()
t.forward(100)
print "Hello World"
</textarea><br />
<button type="button" onclick="runit()">Run</button>
</form>
<pre id="output" ></pre>
<!-- If you want turtle graphics include a canvas -->
<div id="mycanvas"></div>
</body>
</html>
I ran out of ideas how to fix this. Here is the documentation > https://skulpt.org/using.html
Just remove www. from script urls.
You should use http://skulpt.org/js/skulpt.min.js instead of http://www.skulpt.org/js/skulpt.min.js
I know this has been asked a lot on here, but all the answers work only with jQuery and I need a solution without it.
So after I do something, my Servlet leads me to a JSP page. My JS function should populate a drop down list when the page is loaded. It only works properly when the page is refreshed tho.
As I understand this is happening because I want to populate, using innerHTML and the JS function gets called faster then my HTML page.
I also get this error in my Browser:
Uncaught TypeError: Cannot read property 'innerHTML' of null
at XMLHttpRequest.xmlHttpRequest.onreadystatechange
I had a soulution for debugging but I can't leave it in there. What I did was, every time I opened that page I automatically refreshed the whole page. But my browser asked me every time if I wanted to do this. So that is not a solution that's pretty to say the least.
Is there something I could do to prevent this?
Edit:
document.addEventListener("DOMContentLoaded", pupulateDropDown);
function pupulateDropDown() {
var servletURL = "./KategorienHolen"
let xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.onreadystatechange = function () {
if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status === 200) {
console.log(xmlHttpRequest.responseText);
let katGetter = JSON.parse(xmlHttpRequest.responseText);
JSON.stringify(katGetter);
var i;
for(i = 0; i <= katGetter.length -1; i++){
console.log(katGetter[i].id);
console.log(katGetter[i].kategorie);
console.log(katGetter[i].oberkategorie);
if (katGetter[i].oberkategorie === "B") {
document.getElementById("BKat").innerHTML += "" + katGetter[i].kategorie + "</br>";
} else if (katGetter[i].oberkategorie === "S") {
document.getElementById("SKat").innerHTML += "" + katGetter[i].kategorie + "</br>";
} else if (katGetter[i].oberkategorie ==="A") {
document.getElementById("ACat").innerHTML += "" + katGetter[i].kategorie + "</br>";
}
// document.getElementsByClassName("innerDiv").innerHTML = "" + katGetter.kategorie + "";
// document.getElementById("test123").innerHTML = "" + katGetter.kategorie + "";
}
}
};
xmlHttpRequest.open("GET", servletURL, true);
xmlHttpRequest.send();
}
It can depend on how + when you're executing the code.
<html>
<head>
<title>In Head Not Working</title>
<!-- WILL NOT WORK -->
<!--<script>
const p = document.querySelector('p');
p.innerHTML = 'Replaced!';
</script>-->
</head>
<body>
<p>Replace This</p>
<!-- Will work because the page has finished loading and this is the last thing to load on the page so it can find other elements -->
<script>
const p = document.querySelector('p');
p.innerHTML = 'Replaced!';
</script>
</body>
</html>
Additionally you could add an Event handler so when the window is fully loaded, you can then find the DOM element.
<html>
<head>
<title>In Head Working</title>
<script>
window.addEventListener('load', function () {
const p = document.querySelector('p');
p.innerHTML = 'Replaced!';
});
</script>
</head>
<body>
<p>Replace This</p>
</body>
</html>
Define your function and add an onload event to body:
<body onload="pupulateDropDown()">
<!-- ... -->
</body>
Script needs to be loaded again, I tried many options but <iframe/> works better in my case. You may try to npm import for library related to your script or you can use the following code.
<iframe
srcDoc={`
<!doctype html>
<html>
<head>
<style>[Style (If you want to)]</style>
</head>
<body>
<div>
[Your data]
<script type="text/javascript" src="[Script source]"></script>
</div>
</body>
</html>
`}
/>
Inside srcDoc, it's similar to normal HTML code.
You can load data by using ${[Your Data]} inside srcDoc.
It should work :
document.addEventListener("DOMContentLoaded", function(){
//....
});
You should be using the DOMContentLoaded event to run your code only when the document has been completely loaded and all elements have been parsed.
window.addEventListener("DOMContentLoaded", function(){
//your code here
});
Alternatively, place your script tag right before the ending body tag.
<body>
<!--body content...-->
<script>
//your code here
</script>
</body>
I'm attempting to pull "webId%22:%22" var string from a script tag using JS for a Chrome extension. The example I'm currently working with allows me to pull the page title.
// payload.js
chrome.runtime.sendMessage(document.title);
// popup.js
window.addEventListener('load', function (evt) {
chrome.extension.getBackgroundPage().chrome.tabs.executeScript(null, {
file: 'payload.js'
});;
});
// Listen to messages from the payload.js script and write to popout.html
chrome.runtime.onMessage.addListener(function (message) {
document.getElementById('pagetitle').innerHTML = message;
});
//HTML popup
<!doctype html>
<html>
<head>
<title>WebID</title>
<script src="popup.js"></script>
<script src="testButton.js"></script>
</head>
<body>
<button onclick="myFunction()">Try it</button>
<p id="body"></p>
<h3>It's working</h1>
<p id='pagetitle'>This is where the webID would be if I could get this stupid thing to work.</p>
</body>
</html>
What I am trying to pull is the webID from below:
<script if="inlineJs">;(function() { window.hydra = {}; hydra.state =
JSON.parse(decodeURI("%7B%22cache%22:%7B%22Co.context.configCtx%22:%7B%22webId%22:%22gmps-salvadore%22,%22locale%22:%22en_US%22,%22version%22:%22LIVE%22,%22page%22:%22HomePage%22,%22secureSiteId%22:%22b382ca78958d10048eda00145edef68b%22%7D,%22features%22:%7B%22directivePerfSwitch%22:true,%22enable.directive.localisation%22:true,%22enable.directive.thumbnailGallery%22:true,%22enable.new.newstaticmap%22:false,%22disable.forms.webId%22:false,%22use.hydra.popup.title.override.via.url%22:true,%22enable.directive.geoloc.enableHighAccuracy%22:true,%22use.hydra.theme.service%22:true,%22disable.ajax.options.contentType%22:false,%22dealerLocator.map.use.markerClustering%22:true,%22hydra.open.login.popup.on.cs.click%22:false,%22hydra.consumerlogin.use.secure.cookie%22:true,%22use.hydra.directive.vertical.thumbnailGallery.onpopup%22:true,%22hydra.encrypt.data.to.login.service%22:true,%22disable.dealerlocator.fix.loading%22:false,%22use.hydra.date.formatting%22:true,%22use.hydra.optimized.style.directive.updates%22:false,%22hydra.click.pmp.button.on.myaccount.page%22:true,%22use.hydra.fix.invalid.combination.of.filters%22:true,%22disable.vsr.view.from.preference%22:false%7D%7D,%22store%22:%7B%22properties%22:%7B%22routePrefix%22:%22/hydra-graph%22%7D%7D%7D")); }());</script>
You have inline code in onclick attribute which won't work, see this answer.
You can see an error message in devtools console for the popup: right-click it, then "Inspect".
The simplest solution is to attach a click listener in your popup.js file.
The popup is an extension page and thus it can access chrome.tabs.executeScript directly without chrome.extension.getBackgroundPage(), just don't forget to add the necessary permissions in manifest.json, preferably "activeTab".
For such a simple data extraction you don't even need a separate content script file or messaging, just provide code string in executeScript.
chrome.tabs.executeScript({
code: '(' + (() => {
for (const el of document.querySelectorAll('script[if="inlineJs"]')) {
const m = el.textContent.match(/"([^"]*%22webId%22[^"]*)"/);
if (m) return m[1];
}
}) + ')()',
}, results => {
if (!chrome.runtime.lastError && results) {
document.querySelector('p').textContent = decodeURI(results[0]);
}
});
I'm using QUnit for unit testing js and jquery.
My HTML looks like this:
<!DOCTYPE html>
<html>
<head>
<title>QUnit Test Suite</title>
<script src="../lib/jquery.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.16.0.css" type="text/css" media="screen">
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.16.0.js"></script>
<!--This is where I may have to add startPage.html--->
<script src="../login.js"></script>
<script src="../test/myTests.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
</html>
Currently, I'm adding login.js as shown and I'm getting references correctly to objects defined in login.js.
However, functions in login.js contains references to some dom elements defined in startPage.html which is located elsewhere.
So, if I say $('#login-btn'), it is throwing an error. Is there any way to fix this?
Can I
(a) refer to startPage.html to my qunit page given above?
(b) refer to or load startPage.html in the file where I'm running tests (myTests.js):
QUnit.test( "a test", function( assert ) {
assert.equal( 1, "1", "String '1' and number 1 have the same value" );//works
assert.equal( login.abc, "abc", "Abc" );//works with attributes
assert.equal(($("#userid").val()),'', 'Userid field is present');//fails
assert.equal( login.ValidUserId(), true, "ValidUserId" );//fails with functions
});
Does QUnit provide any method to load Html/php files so they'll be defined prior to testing. Like 'fixtures' in jasmine?
EDIT: Please also tell what to do in case I have startPage.php
There are a couple of ways you can do this. The simplest is just to use the built-in QUnit "fixtures" element. In your QUnit HTML file, simply add any HTML you want in the div with the id of qunit-fixture. Any HTML you put in there will be reset to what it was on load before each test (automatically).
<html>
...
<body>
<div id='qunit'></div>
<div id='qunit-fixture'>
<!-- everything in here is reset before each test -->
<form>
<input id='userid' type='text'>
<input id='login-btn' type='submit'>
</form>
</div>
</body>
</html>
Note that the HTML in the fixture doesn't really have to match what you have in production, but obviously you can do that. Really, you should just be adding the minimal necessary HTML so that you can minimize any side effects on your tests.
The second option is to actually pull in the HTML from that login page and delay the start of the QUnit tests until the HTML loading is complete:
<html>
<head>
...
<script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.16.0.js"></script>
<script>
// tell QUnit you're not ready to start right away...
QUnit.config.autostart = false;
$.ajax({
url: '/path/to/startPage.html',
dataType: 'html',
success: function(html) {
// find specific elements you want...
var elem = $(html).find(...);
$('#qunit-fixture').append(elem);
QUnit.start(); // ...tell QUnit you're ready to go
}
});
</script>
...
</head>
...
</html>
Another way to do this without using jquery is as follows
QUnit.config.autostart = false;
window.onload = function() {
var xhr = new XMLHttpRequest();
if (xhr) {
xhr.onloadend = function () {
if(xhr.status == 200) {
var txt = xhr.responseText;
var start = txt.indexOf('<body>')+6;
var end = txt.indexOf('</body>');;
var body_text = txt.substring(start, end);
var qunit_fixture_body = document.getElementById('qunit-fixture');
qunit_fixture_body.innerHTML = body_text;
}
QUnit.start();
}
xhr.open("GET", "index.html");
xhr.send();
} else {
QUnit.start(); //If getting the html file from server fails run tests and fail anyway
}
}
Using Addon SDK I am trying to inject script to page on every page load. To test things, plugin is trying to add variable to window object and page should read it. When I run this, I can see "injecting" alert, but page gives me error "undefined property window.myVar". What am I doing wrong? Btw I don't want to use unsafeWindow.
main.js:
var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");
pageMod.PageMod({
include: "*",
contentScriptFile: data.url("inject.js"),
contentScriptWhen: "start",
onAttach: function(worker) {
worker.port.emit("inject", "unused param");
}
});
inject.js
function inject(arg) {
var script = document.createElement("script");
script.innerHTML = 'alert("injecting"); window.myVar=54564;';
document.head.appendChild(script);
}
self.port.on("inject", inject);
page.html
<html>
<head>
</head>
<body>
<script>
alert(window.myVar);
</script>
</body>
</html>
EDIT:
I tried canuckistani's code and it shows some weird behavior. Btw I am on Firefox 31. Here is my code
function inject(arg) {
var myVar = 123;
unsafeWindow.myVar = cloneInto(myVar, unsafeWindow);
}
self.port.on("inject", inject);
and page
<html>
<head>
</head>
<body>
<script>
alert(window.myVar); <!--This shows empty alert box-->
alert(window.myVar); <!--This shows alert box with right value (123)-->
</script>
</body>
</html>
Starting with Firefox 30 ( almost 2 versions ago! ) you can use some new apis to do this. This would look like:
let myVar = {1:2};
self.port.on("inject", function() {
unsafeWindow.myVar = cloneInto(myVar, unsafeWindow);
});
For more information, see this blog post: