Playing around with this javascript library
https://www.w3.org/TR/webmidi/#introduction I got some basic functionality working and I was happily able to send midi notes to my syntheseizer and hear it working!..
However, when I wanted to try out the exact same javascript code, but hosted remotely, I got this error:
Uncaught TypeError: window.navigator.requestMIDIAccess is not a function
My code can be boiled down to following:
<html>
<body>
<h1 id="test-result">MIDI test</h1>
<script>
window.onload = function(){
window.navigator.requestMIDIAccess().then(
x => document.getElementById("test-result").innerHTML = "success!",
x => document.getElementById("test-result").innerHTML = "fail!"
);
};
</script>
</body>
</html>
Why does it work locally but not remote?
I am using google-chrome and it is my impression that webmidi should be supported, although experimental https://developer.mozilla.org/en-US/docs/Web/API/MIDIAccess
navigator.requestMIDIAccess() is only available in a secure context, which means your remote host must serve your resources via HTTPS.
Resources served from localhost are considered to be in a secure context, whether delivered via HTTPS or HTTP.
Connect to your remote host using HTTPS instead of HTTP and that should resolve the problem.
Related
Please tell me, why local javascript cannot open a local file?
I'm trying to create a simple javascript/html app that shall run on the local machine from local filesystem. This app is trying to read the configuration file (json) using different methods, but gets the following errors (Chrome):
In case of XMLHttpRequest, method open("GET", filename, true) throws an exception:
XMLHttpRequest cannot load file:///bla-bla-bla. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
In case of document.createElement("iframe").src=filename I have another exception:
VM596:1 Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "null" from accessing a cross-origin frame."
In case of var f=new File([], filename, { type: "text/plain" }); I've got the File object with the zero size and no errors at all. FileReader returns an empty result then.
So, my questions are:
Why is it "cross-origin"? These files are stored in the same directory!
And how could I open the local file from the same origin/directory I run the script?
Please help.
P.S.: Yes, I know about --allow-file-access-from-files but I need to run this by customers.
Why is it "cross-origin"? These files are stored in the same directory!
Because Chrome considers all file:// URLs to be cross-origin to each other.
And how could I open the local file from the same origin/directory I run the script?
From Chrome? You don't. Not unless you disable CORS entirely with a command-line option (which is a bad idea, as it's trivially easy to forget you've set that command-line option and go surf the web, leaving yourself wide open to exploits cashing in on the fact you've disabled web security).
Other browsers may treat origin null differently.
Instead, run a local web server and make the files available via the local web server. Then you can access them because it'll be a same-origin http URL, not a file URL. Or use any of the dozen or so frameworks that let you write apps in JavaScript (rather than using the browser). Or a simple NodeJS script serving the files (it's about 10 lines long). Etc.
What you can do to read your .json file, is to declare it a .js.
data.js
var data = `{"value1": 10, "value2": "hello"}`
index.html
<script src="data.js"></script>
<script>
console.log(JSON.parse(data))
</script>
This will print
Object {value1: 10, value2: "hello"}
Both of them have to be in the same directory, otherwise you've to change the import of data.js.
A little late for this party, but I had the same issue and this was how I got around the problem
Create a js template such as this:
template.js
(function(global, factory) {
"use strict";
factory(global);
})(typeof window !== "undefined" ? window : this, function(window) {
"use strict";
var myObjectJson = '<JSONREPLACE>';
var myObject = JSON.parse(myObjectJson);
window.myObject = myObject;
});
Then, have your json replace the tag either by your program that could generate the exported js itself, or create a batch script file that does that for you. I'm using C# so I just build the template directly from there. If the language you're working on is half-decent, you should be able to generate and export your file.
Make sure you use a minified json string.
Then you use your generated file just like you'd use jQuery
<script src="generated.js"></script>
and access your object with
window.myObject;
It's slightly more complicated to set-up, but once you do, you completely remove the cross-origin issue.
I'm new at nodejs and I want to write to a serial port using node but now I want it to be triggered by a button. And the data is coming from a textbox.
My node script is doing fine when I run it in the console/terminal. But can't do it with a button in a webpage.
Here's my nodejs embedded in html
<!DOCTYPE html>
<html>
<head>
<title>Node x HTML</title>
</head>
<body>
<script>
function write_serial()
{
var serialport = require("serialport");
var SerialPort = serialport.SerialPort;
var sp = new SerialPort("/dev/ttyACM0", {
baudrate: 9600,
parser: serialport.parsers.readline("\n")
});
var text = document.getElementById("textbox1").value;
sp.on('open', function()
{
sp.on('data', function (data)
{
sp.write(name);
});
});
}
</script>
<Input Type = "text" id = "textbox1" >
<BR>
<br><button onclick="write_serial();" href="javascript:;">Go!</button>
</body>
</html>
Here's the error I got when I open the console of the page (F12)
ReferenceError: require is not defined
Thanks in advance for your help. :)
Node.js is a hosting environment, that can execute JS and provides Node.js specific API. Browser, is a different hosting environment, with different API's. You can't use Node's specific API in a browser, and JS that uses Node API will result in an error in a browser.
For example, your script is using global require function, which is not available in a browser API's. And that's why:
ReferenceError: require is not defined
Conversely, your script can't be executed on Node as well, since it uses browser API:
document.getElementById("textbox1")
You've mixed API's from different environments in one script.
However, if your JS script doesn't use Node or browser specific API, it can be executed in both Node and a browser without an error. But it's not the case with your script.
The solution to your problem can be to split your script into two separate scripts, run one in a browser, and the other in Node.js, and to exchange data between them using XMLHttpRequest.
NodeJS is a non-browser JavaScript environment. You can't use most NodeJS features in a browser environment, because they aren't designed for it.
Instead, you'd have a local NodeJS process providing a web endpoint (e.g., a web server; perhaps using Express, but you don't have to) and run that NodeJS process so it's listening for web requests. Then you'd have a button on your web page that makes an ajax call to the NodeJS server, which performs the work.
Naturally, this would only allow you to perform the work on the machine where the server process is running.
Maybe import the serialport module from https://wzrd.in/standalone/serialport#latest
In other hand, try to seperate the logic from the view, i don't know if your app will grow or if it's just a POC, but use a messageBroker or sockets to bind your actions'view with the engine ?
Hope it helps
I am just getting myself acquainted with Soundcloud's API and I am having some trouble. As far as I can tell, all I need in SC.initialize is a client_id. I have used the tutorials at Code Academy to get started and it was great. Now that I am actually trying to implement something I am running into some trouble.
When I ran my code in Code Academy, it did exactly what I wanted it to do. Now that I am trying to run it in a browser, I am getting a blank screen and this error:
NS_ERROR_DOM_BAD_URI: Access to restricted URI denied # http://connect.soundcloud.com/sdk
After doing some research, I have found that those errors are related to domain prefixes. So I tried changing it to http://www.connect.soundcloud.com/sdk. But when I do that, I get a different error:
SC is not defined
AHHHH What am I doing wrong?!
I am new to using API's, and any help at all would be very greatly appreciated.
Here is what I am doing:
(JavaScript)
SC.initialize({
client_id: 'hidden for privacy',
});
$(document).ready(function() {
SC.get('/users/5577686/tracks', {limit:7}, function(tracks) {
$(tracks).each(function(index, track) {
$('#tracktitle').append($('<li></li>').html(track.title));
$('#trackimage').append("<img src='" + track.artwork_url + "' />");
$('#play').append("<a href='" + track.permalink_url + "' >" + "Play" + "</a>");
});
});
});
(HTML)
<!DOCTYPE HTML>
<html>
<head>
<script src="http://connect.soundcloud.com/sdk.js"></script>
<script src="soundcloud.js"></script>
</head>
<body>
<div id="tracktitle"></div>
<div id="trackimage"></div>
<div id="play"></div>
</body>
</html>
I don't really think there is anything wrong with the code, as everything seemed to be working fine in Code Academy. I think it is more of an issue with familiarizing myself with the API. Do I need to do some further authentication? Do I need something more than just the client ID? Again I am very stuck and would appreciate any amount of help on this. Thanks for reading.
(I also followed along with Coding for GOOD's Soundcloud API Integration tutorial step-by-step and I am getting the same exact errors, so this further confirms that the code is probably not the problem, but connecting to the API may be)
The problem here is that when connecting to an API which is being hosted on another server, you must be using the same protocol. For local files, you use the file protocol (file://), wheres soundcloud uses: http:// or https://
Follow these steps:
Get a server (XAMPP/LAMPP/WAMPP for PHP/Regular HTML, NodeJS for JS server, or Tornado for Python)
Find the protocol which your server uses
If you server uses the http protocol, then your domain must be http://soundcloud.com/..., but if your server uses the https protocol, then the domain for the API must be https://..... So once you get the protocols to match, then you will be able to pass data through the API.
I am having a tough time figuring out how to access a page loaded in an iframe from the outer page. Both pages are local files, and I'm using Chrome.
I have an outer page, and many inner pages. The outer page should always display the page title for the inner page (it makes sense in my application, perhaps less so in this stripped-down example). This works without any problem in AppJS, but I've been requested to make this app work directly in the browser. I'm getting the error "Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match.".
I think this is due to Chrome's same origin policy regarding local files, but that hasn't helped me fix the problem directly. I can work around the issue in this stripped-down example by using the window.postMessage method per Ways to circumvent the same-origin policy. However, going beyond this example, I also want to manipulate the DOM of the inner page from the outer page, since this will make my code much cleaner - so posting messages won't quite do the job.
Outer Page
<!DOCTYPE html>
<html>
<head>
<meta name="viewport">
</head>
<body>
This text is in the outer page
<iframe src="html/Home.html" seamless id="PageContent_Iframe"></iframe>
<script src="./js/LoadNewPage.js"></script>
</body>
</html>
Inner Page
<!DOCTYPE html>
<html>
<head>
<title id="Page_Title">Home</title>
<meta name="viewport">
</head>
<body>
This text is in the inner page
</body>
</html>
JavaScript
var iFrameWindow = document.getElementById("PageContent_Iframe").contentWindow;
var pageTitleElement = iFrameWindow.$("#Page_Title");
Per Is it likely that future releases of Chrome support contentWindow/contentDocument when iFrame loads a local html file from local html file?, I tried launching Chrome with the flag
--allow-file-access-from-files
But there was no change in the results.
Per Disable same origin policy in Chrome, I tried launching Chrome with the flag
--disable-web-security
But again there was no change in the results.
Per What does document.domain = document.domain do?, I had both pages run the command
document.domain = document.domain;
This resulted in the error "Blocked a frame with origin "null" from accessing a frame with origin "null". The frame requesting access set "document.domain" to "", but the frame being accessed did not. Both must set "document.domain" to the same value to allow access."
For fun, I had both pages run the command
document.domain = "foo.com";
This resulted in the error "Uncaught Error: SecurityError: DOM Exception 18".
I'm floundering. Any help from more knowledgeable people would be fantastic! Thanks!
I'm sorry to say you that I've tried during weeks to solve this issue (I needed it for a project) and my conclusion is that it's not possible.
There are a lot of problems arround local access through javascript with chrome, and some of them can be solved using --allow-file-access-from-files and --disable-web-security, including some HTML5 offline features, but I definitely think there's no way to access local files.
I recomend you not to lose your time trying to circunvend this and to try to post messages wich you can interpret into the inner pages, so you can do the DOM modifications there.
Per our discussion in my cube just a minute ago :)
I hit this same problem (Ajax post response from express js keeps throwing error) trying to get an AJAX post request to work correctly.
What got me around it is not running the file directly off the file system but instead running it from a local server. I used node to run express.js. You can install express with the following command: npm install -g express
Once that is accomplished, you can create an express project with the following command: express -s -e expressTestApp
Now, in that folder, you should see a file named app.js and a folder named public. Put the html files you wish to work with in the public folder. I replaced the file app.js with the following code:
var express = require('/usr/lib/node_modules/express');
var app = express();
app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Something broke!');
});
app.use(express.bodyParser());
app.use(express.static('public'));
app.listen(5555, function() { console.log("Server is up and running"); });
Note, the require line may be different. You have to find where your system actually put express. You can do that with the following command: sudo find / -name express
Now, start the express web server with the following command: node app.js
At this time, the webserver is up and running. Go ahead and open a browswer and navigate to your ip address (or if you're on the same machine as your server, 127.0.0.1). Use the ip address:portnumber\filename.html where port number is the 5555 in the app.js file we created.
Now in that browser, you shouldn't (and didn't when we tested it) have any of these same problems anymore.
file:// protocol and http:// protocol make things to behave very differently in regards to iframes. I had the same issues you describe with an app on PhoneGap which uses file protocol to access all local files within the local assets/www folder.
If seems that modern browsers prevent the display of "local" files using the file protocol in iframes for security reasons.
We ended up dumping iframes and just using divs as "viewports". Fortunately the overall size of our app was not that big so we managed to load everything in a single page.
I'm currently working with the SoundCloud API and would like to have a track embed when a button is clicked.
I get two errors:
XMLHttpRequest cannot load http://soundcloud.com/oembed.json?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F48419073. Origin null is not allowed by Access-Control-Allow-Origin.
AND
Uncaught TypeError: Cannot read property 'html' of null
Here is my code:
<button onclick="getPopular()">+1</button>
<div id="track"></div>
<script src="http://connect.soundcloud.com/sdk.js" type="text/JavaScript"></script>
<script type="text/JavaScript">
SC.initialize({
client_id: "**************",
});
var getPopular = function() {
SC.get("/tracks", {limit: 1}, function(tracks) {
var track = tracks[0];
alert("Latest track: " + track.title);
SC.oEmbed(track.uri, document.getElementById("track"));
});
};
</script>
I use an alert in my code to let me know that it is actually taking information from the SoundCloud API. I'm just not sure what else is preventing it from embedding.
Thanks, ahead of time, or looking at my question.
jiggabits
Read a little about Same Origin Policy to understand your main problem better. Ajax, localhost and Chrome/Opera don't go well together. This related question is even better.
Your second problem is due to the Ajax call (somewhere in your API) which doesn't return an html response due to the first error.
Instead of explaining the issue (which is very well explained in the links above), I'll provide a solution. Since you're running on Chrome, there's an workaround for that. Start chrome with this option:
--allow-file-access-from-files
(workaround which I shamelessly borrowed from Pointy)
You could also try running it on Firefox, or hosting it temporarily. :)
P.S. If you plan on doing serious development from your local machine, you may consider installing Apache to serve and test content through http://localhost, thus lifting the file:/// restrictions.
Here are some excellent tools that come with Apache and PHP pre-configured for development:
For Windows: EasyPHP, WAMP.
Cross-platform: XAMPP, BitNami.
If you're getting a track back, the I would try, alert(document.getElementById("track")); to make sure that you're getting your dom element.