How can I import jQuery as the dependency for bootstrap in ES6?
I tried with:
import {$,jQuery} from 'jquery';
import bootstrap from 'bootstrap';
But I always get this error:
transition.js:59 Uncaught ReferenceError: jQuery is not defined
Which points to this file:
/* ========================================================================
* Bootstrap: transition.js v3.3.7
* http://getbootstrap.com/javascript/#transitions
* ========================================================================
* Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================
function transitionEnd() {
var el = document.createElement('bootstrap')
var transEndEventNames = {
WebkitTransition : 'webkitTransitionEnd',
MozTransition : 'transitionend',
OTransition : 'oTransitionEnd otransitionend',
transition : 'transitionend'
}
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] }
}
}
return false // explicit for ie8 ( ._.)
}
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false
var $el = this
$(this).one('bsTransitionEnd', function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
return this
}
$(function () {
$.support.transition = transitionEnd()
if (!$.support.transition) return
$.event.special.bsTransitionEnd = {
bindType: $.support.transition.end,
delegateType: $.support.transition.end,
handle: function (e) {
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
}
}
})
}(jQuery);
Any ideas?
EDIT:
my gulp file:
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var gutil = require('gulp-util');
gulp.task('es6', function() {
browserify({
entries: 'js/app.js',
debug: true
})
.transform(babelify, { presets: ['es2015'] })
.on('error',gutil.log)
.bundle()
.on('error',gutil.log)
.pipe(source('compile.js'))
.pipe(gulp.dest('js'));
});
gulp.task('default', ['es6']);
EDIT 2:
package.json:
{
"name": "es6",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-preset-es2015": "^6.16.0",
"babelify": "^7.3.0",
"browserify": "^13.1.0",
"gulp": "^3.9.1",
"gulp-uglify": "^2.0.0",
"gulp-util": "^3.0.7",
"pump": "^1.0.1",
"vinyl-source-stream": "^1.1.0"
},
"browser": {
"jquery": "./node_modules/jquery/dist/jquery.js",
},
"browserify-shim": {
"jquery": "$", // or change it to jQuery
},
"browserify": {
"transform": [
"browserify-shim"
]
}
}
error:
Starting 'build'... events.js:160
throw er; // Unhandled 'error' event
^
Error: SyntaxError: Unexpected token } in JSON at position 526 while
parsing json file
I've tried this answer and it worked.
// webpack.config.js
module.exports = {
...
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
};
In general the destructuring you are doing in the import is not right, as the $ or jQuery object is the main one:
import $ from 'jquery';
// or
import jQuery from 'jquery'
In your case you are dealing with a module (boostrap-transition) which does want jQuery in the global scope to be used.
I had a similar issue some time ago with the materialize module too on this thing.
If you are using webpack you can follow #galkowskit answer steps.
In case you are using browserify instead, what you need is a browserify transform as the follow:
"browser": {
"jquery": "./node_modules/jquery/dist/jquery.js",
},
"browserify-shim": {
"jquery": "$", // or change it to jQuery
},
"browserify": {
"transform": [
"browserify-shim"
]
}
You can put this inside your package.json file: when Gulp is going to call browserify it will read your package.json for configuration tips and execute this shim for jQuery.
In Webpack I usually use (webpack.config.js):
externals: {
jquery: "jQuery"
}
And then:
import jQuery from 'jQuery';
You could also try:
import * as jQuery from 'jQuery';
If you are using curley bracket in es6 you are saying you want only that segment from several segment this module returns.
Jquery expose only one thing so you could do:
import $ from 'jquery';
Or
import jQuery from 'jquery';
It will always expose to one default variable
import jQuery from 'jquery';
or
import $ from 'jquery';
Related
I am building a library that uses ES6 modules and contains classes. If instead of bundling, I just point the package.json "main" to the source code, all works well! I can import the library into an application and it works wonderfully.
Once I bundle the application using WebPack and point the "main" to the packaged bundle, nothing works and I am left scratching what little hair I have left on my head.
Here is the error I am getting:
notablet__WEBPACK_IMPORTED_MODULE_3__.Notablet is not a constructor
Here is my package.json
{
"name": "notablet",
"version": "4.7.0",
"main": "lib/index.js",
"type": "module",
"scripts": {
"test": "npx mocha ./test/**/*.test.js",
"coverage": "c8 --reporter=text --all npm run test",
"build": "webpack --config webpack.config.js"
},
"license": "MIT",
"devDependencies": {
"c8": "^7.12.0",
"chai": "^4.3.6",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.7.1",
"jsdom": "^20.0.0",
"mocha": "^10.0.0",
"sinon": "^14.0.0",
"style-loader": "^3.3.1",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0"
}
}
And here is my webpack.config.js:
import path from 'path';
import {fileURLToPath} from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const config = {
mode: 'development',
devtool: false,
entry: './src/Notablet.js',
output: {
path: path.resolve(__dirname, 'lib'),
filename: "index.js",
library: "notablet"
},
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
}
};
export default config;
Note... I did change the "mode" above from "development" to "production", but got the same error after bundling and using.
Here is relevant parts of my Notablet.js file:
import { Queue } from './Queue.js';
// Themes
import style from './style.css'; // assert { type: "css" };
import light from './theme/light.css';
import dark from './theme/dark.css';
import elegant from './theme/elegant.css';
import fantasy from './theme/fantasy.css';
import robot from './theme/robot.css';
export class Notablet {
constructor(conf = {}, queue = new Queue()) {
this.queue = queue;
var config = {
backgroundColor: 'black',
color: '#ffffff',
theme : 'light'
};
this.config = {...config, ...conf};
this.loadTheme();
}
/**
* Loads the theme identified in the configuration object along with the base stylesheet
*/
loadTheme() {
var theme = this.getTheme(this.config.theme)
var sheet = new CSSStyleSheet();
sheet.replace(theme);
var baseSheet = new CSSStyleSheet();
baseSheet.replace(style);
document.adoptedStyleSheets = [baseSheet, sheet];
}
getTheme(theme = 'light') {
var ret = light;
switch(theme) {
case "dark":
ret = dark;
break;
case "elegant":
ret = elegant;
break;
case "fantasy":
ret = fantasy;
break;
case "robot":
ret = robot;
break;
}
return ret;
}
}
The error appears to be thrown in my application when I call let nt = new Notablet()
Notablet appears to be a valid class in ES6 and it has a constructor. My assumption is Webpack needs to be configured to handle the ES6 module somehow, but I understood I just needed to change my package.json "type" to "module".
Any help is greatly appreciated!
Why do I keep getting error message "SyntaxError: Cannot use import statement outside a module" when I use Babel and Jest?
I have a super simple app that contains two modules:
// moduleTwo.mjs:
let testFuncOneModTwo = () => {
return ('String generated by fn in moduleTwo.mjs')
}
export {testFuncOneModTwo }
/////////////
// moduleOne.mjs:
import {testFuncOneModTwo} from './moduleTwo.mjs'
let testFuncOneModOne = () => {
return (testFuncOneModTwo())
}
export { testFuncOneModOne }
//////////////
Here's my Jest test file:
// myTest.test.js:
import * as myImports from './moduleOne.mjs';
test('tests fn in module that calls fn in another module.', () => {
expect(myImports.testFuncOneModOne()).toEqual( 'String generated by fn in
moduleTwo.mjs' );
});
/////////////
// babel.config.json:
{
"presets": ["#babel/preset-env"]
}
// package.json:
{
"name": "JestIsVeryTesting",
"version": "1.0.0",
"description": "",
"main": "moduleOne.mjs",
"scripts": {
"test": "jest --coverage "
},
"jest": {
"transform": {
"^.+\\.js?$": "babel-jest"
}
},
"dependencies": {
"#babel/runtime": "^7.18.6"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/plugin-transform-runtime": "^7.18.6",
"#babel/preset-env": "^7.18.6",
"babel": "^6.23.0",
"babel-jest": "^28.1.2",
"jest": "^28.1.2"
}
}
// The error message (edited by me):
Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. ...
...
...
Details:
/xxx/xxx/xxx/xxx/moduleOne.mjs:91
import { testFuncOneModTwo } from './moduleTwo.mjs';
^^^^^^
SyntaxError: Cannot use import statement outside a module
1 |
> 2 | import * as myImports from './moduleOne.mjs';
| ^
3 |
4 | test('tests fn in module that calls fn in another module.', () => {
5 | expect(myImports.testFuncOneModOne()).toEqual( 'This string returned by a function in moduleTwo.mjs' );
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1796:14)
at Object.<anonymous> (myTest.test.js:2:1)
Help would be much appreciated as this is driving me mad.
In case anyone is interested I solved the problem myself in the end:
To the top level of the package.json file I added:
"type": "module"
This tells node that all files in the project that end with '.js' are ES6 files
I changed the extensions of my modules to '.js'
(so that
'moduleOne.mjs' became 'moduleOne.js'
and
'moduleTwo.mjs' became 'moduleTwo.js'
)
This is in keeping with the value of the package.json file's "jest" field, which has value:
"transform": {
"^.+\\.js?$": "babel-jest"
}
I want to test a ng-redux reducer wich have angular (1.6) as dependency.
When I run the tests (npm test) with mocha, I get :
/data/work/mocha-angularjs/node_modules/angular/angular.js:33343
})(window);
^
ReferenceError: window is not defined
I tried to add jsdom to provide a fake window. But it still fails during the import of angular with this error :
module.exports = angular;
^
ReferenceError: angular is not defined
Is there a way to make angular work properly in mocha/babel world ?
I made a small github project available here which reproduce the problem.
Here is the content of the project :
Package.json
{
"name": "mocha-angularjs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"angular": "^1.6.3"
},
"devDependencies": {
"babel-core": "^6.24.0",
"babel-preset-es2015": "^6.24.0",
"babel-preset-latest": "^6.24.0",
"chai": "^3.5.0",
"jsdom": "9.12.0",
"jsdom-global": "2.1.1",
"mocha": "^3.2.0"
},
"scripts": {
"test": "NODE_ENV=test mocha src/index.test.js --compilers js:babel-register --require jsdom-global/register"
},
"repository": {
"type": "git",
"url": "git+https://github.com/jtassin/mocha-angularjs.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/jtassin/mocha-angularjs/issues"
},
"homepage": "https://github.com/jtassin/mocha-angularjs#readme"
}
.babelrc
{
"plugins": [],
"presets": [
"latest",
]
}
The code to test
import angular from 'angular';
export default function getFive() {
return 5;
}
The test
import expect from 'chai';
import getFive from './index';
describe('desc', () => {
it('my test', () => {
expect(getFive()).to.equal(5);
});
});
In case of someone needs it one day :
I used angularcontext to solve the problem.
package.json
"devDependencies": {
"angularcontext": "0.0.23",
[...]
},
In my test file
/* eslint-env mocha */
/* eslint-disable import/no-extraneous-dependencies */
import angularcontext from 'angularcontext';
before((done) => {
const context = angularcontext.Context();
context.runFile('./node_modules/angular/angular.js', (result, error) => {
if (error) {
/* eslint-disable no-console */
console.error(error);
done(error);
} else {
global.angular = context.getAngular();
done();
}
});
});
/* eslint-disable import/prefer-default-export */
export const angular = global.angular;
The github project has been updated with it.
My package.json:
...
"scripts": {
"build": "gulp && webpack",
"webpack": "webpack"
},
...
"dependencies": {
"scrollto": "git://github.com/flesler/jquery.scrollTo.git" // ???
}
...
my backbone view:
const Backbone = require('backbone');
const _ = require('underscore');
const $ = require('jquery');
require('scrollto'); // ???
...
_handleError(error) {
if (error) {
$('#header').focus();
$(window).scrollTo('#header'); // ????
} else {
...
}
},
...
Command:
gulp && webpack
Error:
Module not found: Error: Cannot resolve module 'scrollto' in /home/me/src/myproject/src/dashboard/static/js/views/query
Anything missing or wrong?
Thanks
UPDATE
Fixed:
"jquery.scrollto": "^2.0.0"
require('jquery.scrollto');
I've written my React app with ES6. Now I would like to write my tests also with ES6. So the challenge here is to configure karma.
Together with google I came this far with karma.config.js (I've omitted parts of the config file which are the same!):
...
files: [
'../node_modules/karma-babel-preprocessor/node_modules/babel-core/browser-polyfill.js',
'../app/**/*.jsx',
'../test/**/*.jsx'],
preprocessors: {
'app/**/*.jsx': ['react-jsx', 'babel'],
'test/**/*.jsx': ['react-jsx', 'babel']
},
'babelPreprocessor': {
options: {
sourceMap: 'inline'
},
filename: function(file) {
return file.originalPath.replace(/\.jsx$/, '.es5.js');
},
sourceFileName: function(file) {
return file.originalPath;
}
},
....
What I think this setup should do: 1) compile the JSX to JS and next babel should transform ES6 to ES5. This together with the polyfill I expected it should run in phantomjs for example. But no, here is the output from karma when I run it:
PhantomJS 1.9.8 (Mac OS X) ERROR
SyntaxError: Parse error
at Projects/ES6/app/js/app.jsx:35
PhantomJS 1.9.8 (Mac OS X): Executed 0 of 0 ERROR (0.027 secs / 0 secs)
[20:36:59] Karma has exited with 1
Line 35 of app.jsx contains the actual JSX part. So, for some reason the preprocessors seems to do not so much. Any help with the preprocessors would be appreciated ?
UPDATE: I have this almost working nog. Turns out that the preprocessors I had should be swapped like this
'../app/**/*.jsx': ['babel', 'react'],
'../test/**/*.jsx': ['babel', 'react']
Now, when I run this, I get:
Uncaught ReferenceError: require is not defined
I thought I had a polyfill for that :(
I use ES6 with Browserify and JSX. For compilation I use Babel. The following configuration works for me.
karma.conf.js
...
frameworks: ['browserify', 'jasmine'],
files: [
'Component.js', // replace with your component
'__tests__/Component-test.js'
],
preprocessors: {
'Component.js': 'browserify',
'./__tests__/Component-test.js': 'browserify'
},
browserify : {
transform : ['babelify']
},
...
__tests__/Component-test.js
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var Component = require('../Component.js');
describe('Component', () => {
it('should work', () => {
var component = <Component />;
TestUtils.renderIntoDocument(component);
expect(component).toBeTruthy();
});
});
If you have any questions let me know.
#zemirico answer did not work for me and is slightly outdated.
Here is my own setup that you can use for karma.conf.js:
...
frameworks: ['jasmine', 'browserify'],
files: [
'src/*',
'tests/*'
],
preprocessors: {
'src/*': ['browserify'],
'tests/*': ['browserify']
},
browserify: {
debug: true,
transform: ['babelify']
}
...
It uses babelify instead of reactify, and has other dependencies. Thus, .babelrc in the project root is also needed:
{
presets: ['es2015', 'react']
}
The setup also requires the dependencies below to be included in package.json file:
"devDependencies": {
"babel-preset-react": "^6.5.0",
"babelify": "^7.2.0",
"browserify": "^13.0.0",
"jasmine-core": "^2.4.1",
"karma": "^0.13.22",
"karma-browserify": "^5.0.3",
"karma-chrome-launcher": "^0.2.3",
"karma-jasmine": "^0.3.8",
"watchify": "^3.7.0",
"babel-preset-es2015": "^6.6.0",
"react": "^15.0.1",
"react-addons-test-utils": "^15.0.1",
"react-dom": "^15.0.1"
}
Usage
Create a new React component in src/my-element.jsx:
import React from 'react';
export default class MyElement extends React.Component {
constructor(props) {
super(props);
this.state = {isActive: false};
this.onClick = this.onClick.bind(this);
}
onClick() {
this.setState({isActive: !this.state.isActive});
}
render() {
return (
<div onClick={this.onClick}>{this.state.isActive ? "I am active!" : "I am not active :("}</div>
);
}
}
Then, test it as such by creating spec in tests/my-element-spec.js:
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import MyElement from '../src/my-element.jsx';
describe('MyElement', () => {
// Render a checkbox with label in the document
const element = TestUtils.renderIntoDocument(<MyElement />);
const elementNode = ReactDOM.findDOMNode(element);
it('verity correct default text', () => {
expect(elementNode.textContent).toEqual('I am not active :(');
});
it ('verify text has been changed successfuly after click', () => {
// Simulate a click and verify that it is now On
TestUtils.Simulate.click(elementNode);
// Verify text has been changed successfully
expect(elementNode.textContent).toEqual('I am active!');
});
});
Demo
Working example on GitHub.