I'm making a website to learn PHP and Javascript/JQuery, i don't have much experience yet and i'm trying to understand what's the best structure to implement
PHP creates an array of strings
i can access the array from index.php via json_encode
then i want to send the array to a function in a class which is in a .mjs file
the problem is that in the index.php file, by the script tags i can't import the module, and if i use script type="module" i can use the import
but i get this error:
Failed to load module script: The server responded with a non-JavaScript MIME type of "" in main.mjs::1
the MDN reference the mjs extension is used to prevent that.
that's why i'm stuck.
server directory looks like this:
index.php
js/main.mjs
js/index.mjs
Code snippets:
index.php
<head>
<meta charset="utf-8">
<title>Website</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="js/jquery-3.4.1.slim.min.js"></script>
<script src="js/main.mjs" type="module"></script>
<script type="module">
import {start_index} from "./js/main.mjs";
initialize();
function initialize()
{
var arr = <?php echo json_encode($images_arr); ?>;
start_index(arr);
}
</script>
</head>
main.mjs
function start_index(arr)
{
import {gallery_manager} from './index.mjs';
var gallery_mngr = new gallery_manager();
gallery_mngr.initialize(arr);
}
export {start_index};
index.mjs
class gallery_manager
{
constructor(){}
var images = "";
var placeholder = "../images/common/placeholder.png";
public function initialize(arr)
{
images = arr;
alert(images[0]);
}
function switchByTimer()
{
}
function switchImage(new_image, direction)
{
}
}
export {gallery_manager};
MAIN PROBLEM:
Your web server doesn't appear to "understand" what an "mjs" file is, so it isn't sending the appropriate MIME type in the response's HTTP header.
SUGGESTION: change ".mjs" to "js" and see if that helps. "mjs" is oriented toward NodeJS.
IMPORTANT QUESTIONS:
Q: You're using a web server, correct?
Q: What kind of web servier? Apache2/Linux? IIS Express local Windows PC? Something else?
STRONG SUGGESTION: familiarize yourself with Chrome Developer Tools.
I've managed to fix my code, paulsm4 has lit a spark in my brain
.mjs extension strangely does not work, i have no idea why it's advised to use that extension for javascript modules as it is stated in the MDN reference
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
also, some of my JS code was broken, especially class variables and functions
because i'm still learning the syntax..
now it's working as supposed
index.php
<link rel="stylesheet" type="text/css" href="style.css">
<script src="js/jquery-3.4.1.slim.min.js"></script>
<script src="js/main.js" type="module"></script>
<script type="module">
import start_index from "./js/main.js";
initialize();
function initialize()
{
var arr = <?php echo json_encode($images_arr); ?>;
start_index(arr);
}
</script>
main.js
import gallery_manager from './index.js';
function start_index(arr)
{
var gallery_mngr = new gallery_manager(arr);
gallery_mngr.initialize();
}
export default start_index;
index.js
class gallery_manager
{
constructor(images, placeholder)
{
this.images = images;
this.placeholder = "../images/common/placeholder.png";
}
initialize()
{
alert(this.images[0]);
}
switchByTimer()
{
}
switchImage(new_image, direction)
{
}
}
export default gallery_manager;
Related
I'm learning Javascript and I have a problem using import/export to modularize my code. I tried to learn this by reading this and this in MDN Web Docs (Mozilla), but failed. I know this has already been asked here, but I couldn't fix the problem.
The error I get in the web browser terminal is: Uncaught SyntaxError: Cannot use import statement outside a module
I'll insert a small example of how I tried to use import/export:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
</head>
<body>
<h1 class="title">Example</h1>
<button class="title-button">Change title</button>
<!--
I tried adding this line but nothing has changed:
<script type="module" src="module.js"></script>
--->
<script src='main.js'></script>
</body>
</html>
module.js:
const changeTitle = newTitle => {
const title = document.querySelector(".title");
title.innerHTML = newTitle;
}
export { changeTitle };
main.js:
import { changeTitle } from "./module";
const titleButton = document.querySelector(".title-button");
titleButton.addEventListener("click", () => {
let newTitle = prompt("Enter new title:");
changeTitle(newTitle);
});
Note: all three files are in the same folder.
Thank you for your time. Sorry if I made a mistake in this post.
The type="module" attribute must be added in the script that uses the import statement (in this case, main.js). My mistake was trying to add type="module" in module.js instead of main.js
I'm trying to figure out why my script tags don't work in my html file, and I came across an article that says you can import modules into browsers via a script tag with a module type. Directly from this site: https://www.sitepoint.com/understanding-es6-modules/
<script type="module" src="./main.js"></script>
// or
<script type="module">
import { something } from './somewhere.js';
// ...
</script>
So then I tried it and the imported module is recognized but getting this error Can't find variable World is it because my example.js file doesn't have it in its scope? I don't understand the order in which they are "processed?" don't know the terminology sorry.
My attempt below
//HTML
<body>
<script type="module">
import { World, Ball, Paddle, Brick, Hud} from "./brickbreakclasses.js"
</script>
<script src="example.js"></script>
</body>
example.js file
// commented this part out because it was imported in html file
// import { World, Ball, Paddle, Brick, Hud } from "./brickbreakclasses";
var canvas = new World(document.getElementById("canvas") );
var ball = new Ball(canvas)
var brick = new Brick(canvas)
var hud = new Hud(canvas)
var paddle = new Paddle(canvas)
I hope this makes sense but I really want to understand why I can't just require or import something in JS file and add it to html via script. I've been using webpack to bundle everything and putting that into my html.However I'm now making a npm package and I hear people don't like pre-bundled packages so I'm trying to find a way for a user to use my modules in html without having to install webpack or something like it.
Variables declared inside a <script type="module"> are local to that module. Make example.js a module, import the classes from there, and you can use them:
HTML
<body>
<script type="module" src="example.js"></script>
</body>
example.js
import { World, Ball, Paddle, Brick, Hud } from "./brickbreakclasses.js";
var canvas = new World(document.getElementById("canvas") );
var ball = new Ball(canvas);
var brick = new Brick(canvas);
var hud = new Hud(canvas);
var paddle = new Paddle(canvas);
I can't figure this out. I have a small app setup with an index.html that includes a javascript file. On the same directory as that file is another file named myJsModule.js with the following code:
export default class{
doStuff()
{
console.log("calling goStuff() from external Module");
}
}
The main javascript file that is loaded from the html then does the import in this way:
import myJsModule from "myJsModule";
// TESTING MODULES
let myNewModule = new myJsModule();
myNewModule.doStuff();
I have a local web server running using Node, so I'm accesing this index.hmtl through my localhost: http://127.0.0.1:8080.
Im getting the following error: Uncaught SyntaxError: Unexpected identifier (referring to myJsModule on my main js file). I also tried using babel to transpile this into previous javascript. I had the same problem using the "require".
Shouldn't my local server figure this out? Or am I using this wrong?
As of Chrome 61, modules are natively supported. I was able to get your example working with the following HTML and JavaScript.
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Native Module</title>
</head>
<body>
<p>Hello, world!</p>
<script type="module">
import MyJsModule from './MyJsModule.js';
let myJsModule = new MyJsModule();
myJsModule.doStuff();
</script>
</body>
</html>
MyJsModule.js:
export default class MyJsModule {
doStuff() {
console.log("calling doStuff() from external Module");
}
}
I have built an app using GitHub's Electron. I am using the recommended way of loading modules, the ES6 syntax of:
import os from 'os'
After downloading the boilerplate the app is working fine. I have been able to import scripts in the background.js file without issue. Below is how I am loading my custom module:
import { loadDb } from './assets/scripts/database.js';
However, when I open a new browser window (clipboard.html) within Electron I am then loading a JavaScript file (clipboard.js) which in turn tries to import modules. At this point I am getting an Unexpected token import error.
My clipboard.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Electron Boilerplate</title>
<link href="./stylesheets/main.css" rel="stylesheet" type="text/css">
<script>
window.$ = window.jQuery = require('./assets/scripts/jquery-1.12.1.min.js');
</script>
<script src="./assets/scripts/clipboard.js"></script>
</head>
<body class="clipboard">[...]</body></html>
My clipboard.js file:
import { remote } from 'electron'; // native electron module
import { loadDb } from './assets/scripts/database.js';
const electron = require('electron');
document.addEventListener('DOMContentLoaded', function () {
var db = loadDb();
db.find({ type: 'text/plain' }, function (err, docs) {
var docsjson = JSON.stringify(docs);
console.log(docsjson);
});
});
Just to re-iterate, the same code is used within app.html, which is my app's main window, and this does not error.
It feels like the main window is initialising something that my clipboard.html window isn't (perhaps 'Rollup'?), but there's nothing explicit within my app's code to suggest this.
You need to run clipboard.js through rollup first. Rollup parses the import statements. You have to modify tasks/build/build.js to do that.
var bundleApplication = function () {
return Q.all([
bundle(srcDir.path('background.js'), destDir.path('background.js')),
bundle(srcDir.path('clipboard.js'), destDir.path('clipboard.js')), // Add this line
bundle(srcDir.path('app.js'), destDir.path('app.js')),
]);
};
#user104317 got it right, clipboard.js just didn't get "compiled" by rollup.
Just wanted to add that in your case, it should have been:
var bundleApplication = function () {
return Q.all([
bundle(srcDir.path('background.js'), destDir.path('background.js')),
bundle(srcDir.path('app.js'), destDir.path('app.js')),
bundle(srcDir.path('assets/scripts/clipboard.js'), destDir.path('assets/scripts/clipboard.js')),
]);
};
Then you could have left it at ./assets/scripts/clipboard.js.
If you end up having a lot of independent js files (you shouldn't if you're building a SPA), consider listing them automatically, like done in ./tasks/build/generate_spec_imports.js
I want to use ES6 for my next project and I'm using Traceur as transpiler for the purpose. I got it working the way described in the Getting Started guide. However I would like to compile all my source files into single minified file in a way they describe it on the Compiling Offline page. But I cannot get it to work with multiple source files organized in a nested directory structure.
Here's a sample project to explain the problem. It has index.html in root folder and two .js files under src.
<project-root>
/index.html
/src/one.js
/src/two.js
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="traceur.js" type="text/javascript"></script>
<script src="bootstrap.js" type="text/javascript"></script>
<script type="module" src="src/two.js"></script>
<script type="module">
import Two from 'src/two.js';
let t = new Two();
console.log(t);
</script>
<title>Title</title>
</head>
<body>
</body>
</html>
src/one.js
export default class One {
constructor() {
console.log("One constructor");
}
}
src/two.js
import One from 'src/one.js';
export default class Two extends One {
constructor () {
console.log("Two constructor");
super();
}
}
As I said, if I open index.html in browser, it will correctly work, printing the instance of Two to console.
But when I try to compile this offline, I get following error
PS D:\code\flattraceur> traceur.cmd src/two.js --out out\two.js
[Error: Error: ENOENT: no such file or directory, open 'D:\code\flattraceur\out\src\one.js'
Specified as src/one.js.
Imported by ../src/two.js.
Normalizes to src/one.js
locate resolved against base 'D:/code/flattraceur/out/'
]
As you can see, while compiling src/two.js, traceur looks for src/one.js under the output directory. I couldn't find any options on traceur that would let me customize the root of its search for referenced modules. I tried the --dir option too, but it fails too.
PS D:\code\flattraceur> traceur.cmd --dir src out
Error: At least one input file is needed
Any suggestions?