I'm having trouble understanding exactly how to use older javascript libraries within newer ES6 projects. I'm looking at a React project that's been compiled with webpack, written with ES6 and transpiled with Babel. Each component follows the import * from "" notation.
There's an external javascript library I want to use within the project: https://github.com/pchen66/panolens.js. The compiled library doesn't follow ES6 export format, and only has one global object PANOLENS.
What should I do if I want to include this into my project?
This is not the best.
Include it in your html :
<script src="js/three.min.js"></script>
<script src="js/panolens.min.js"></script>
<script src="bundle.js"></script>
<script>window.PANOLENS = PANOLENS</script>
Where bundle.js is your own builded javascript code.
Then, you will be able to use PANOLENS object anywhere.
Example component :
import react, {Component} from 'react'
export default class Test extends Component {
componentDidMount(){
var panorama, viewer;
panorama = new window.PANOLENS.ImagePanorama('asset/equirectangular.jpg' );
viewer = new window.PANOLENS.Viewer(
container: document.getelementbyid('viewer-container'), // A DOM Element container
controlBar: true, // Vsibility of bottom control bar
controlButtons: [], // Buttons array in the control bar. Default to ['fullscreen', 'setting', 'video']
autoHideControlBar: false, // Auto hide control bar
autoHideInfospot: true, // Auto hide infospots
horizontalView: false, // Allow only horizontal camera control
cameraFov: 60, // Camera field of view in degree
reverseDragging: false, // Reverse orbit control direction
enableReticle: false, // Enable reticle for mouseless interaction
dwellTime: 1500, // Dwell time for reticle selection in millisecond
autoReticleSelect: true, // Auto select a clickable target after dwellTime
passiveRendering: false, // Render only when control triggered by user input
);
viewer.add( panorama );
}
render(){
return(
<div id='viewer-container'></div>
)
}
}
It doesn't really matter if the module itself follows ES6 syntax. It will either follow commonJS or AMD, both of which webpack can handle, and at worst, you can just require/import the whole file into your bundle: https://www.npmjs.com/package/panolens.js.
EDIT: This npm module/repo does use module.exports if you look at the dist.
EDIT:
Yeah, it looks like someone has forked the library and made an NPM package out of it. Have you taken a look at https://github.com/sbolel/pano. There is an ES6 example.
Install the package:
npm install --save pano
Then import:
import Pano from 'pano'
import { Page } from 'pano'
// Pano.Page === Page
const panoPage = new Page('pano')
panoPage.init()
ORIGINAL:
You could load the script asynchronously using the method below, or if you are using a bundler, it would have a way to import external scripts. For example, Webpack has Externals for this.
After doing this, you can access the the global object PANOLENS, as per the documentation. You'll want to make sure the PANOLENS object is available before using it in your application.
Add the following to your static HTML:
<script src="https://github.com/pchen66/panolens.js" async></script>
If you are planning to only use the script in a certain React component (presuming you use React), you could use a library such as react-async-script-loader. This will allow you to lazy load a script on a particular component. It has a bunch of properties that can be used to determine when the script is ready to be used.
Again, after the script has successfully loaded, you may use the library by accessing it through the global PANOLENS variable.
So you would want some kind of module shimmer. If you are using webpack you should try this:
https://github.com/webpack/docs/wiki/shimming-modules
There are similar shims for browserify too:
https://github.com/thlorenz/browserify-shim
You could also fork the repo and shim it manually something like this, the implementations may vary though.
/**
* Panolens.js
* #author pchen66
* #namespace PANOLENS
*/
var PANOLENS = { REVISION: '3' };
module.exports = PANOLENS;
Related
I am trying to create a simple JS/ESM based Angular example. It has been a while since I have been in the angular space and I see there are really 2 options
Using the UMD lib (I would like to avoid this)
Use the ESM2015 folder and load using ESM (this is what I would like to do)
I try doing this like...
<html>
<head></head>
<body ng-app="jrg-module">
<jrg-element></jrg-element>
<jrg-app></jrg-app>
<script type="module">
import { Component } from "//unpkg.com/#angular/core/esm2015/index.js";
import { platformBrowserDynamic } from "//unpkg.com/#angular/platform-browser-dynamic/esm2015/index.js"
import {ShadowElement, CREATE_ELEMENT} from "//unpkg.com/#jrg/ui/target/jrg-ui.esm.mjs";
class JrgElement extends ShadowElement {
constructor() {
super("<h1>CustomElement</h1>");
this.render();
}
}
CREATE_ELEMENT("jrg-element", JrgElement, {});
const MyComponent = Component({
selector:"jrg-app",
template:"<h1>Angular</h1>"
}).Class({
constructor: function() {}
});
const app = platformBrowserDynamic().bootstrapModule(MyComponent)
</script>
</body>
</html>
But (after taking forever to download 500+ files) I get
Uncaught TypeError: Error resolving module specifier “rxjs”. Relative module specifiers must start with “./”, “../” or “/”.
Can I use the ESM version in the browser or do I have to use UMD? If I can use ESM from the browser is there a link to an example?
I swear Angular used to have a dropdown for their examples where you could switch between TS and JS but I don't see it now.
Have you tried out the website stackblitz it has plenty of angular examples of setting up a new project.
You can also do ng new my-app from the cli to generate a new project locally.
Angular has moved away from javascript in favor of typescript, so you will have to use ESM
I need to import a library in my vue component, in the documentation I explain how to install it using npm (already do this step) but not how to import it into a vue component, this is the way in which it explains how to use the files:
<link href="node_modules/webdatarocks/webdatarocks.min.css" rel="stylesheet"/>
<script src="node_modules/webdatarocks/webdatarocks.toolbar.min.js"></script>
<script src="node_modules/webdatarocks/webdatarocks.js"></script>
and this is the way to instantiate the library:
<script>
var pivot = new WebDataRocks({
container: "#wdr-component",
toolbar: true,
report: {
dataSource: {
filename: "https://cdn.webdatarocks.com/data/data.csv"
}
}
});
</script>
So what is the best way to call this in my component?
This is a bit heavy.
The library is is not develop in module-like system, so the solution is make the js file imported as global.
A good library would be like const WebDataRocks = require("WebDataRocks"); or with imports, but the library is made only for end-client.
First Part - Add the JS file to the global web client
To use WebDataRocks you have to get the global variable, to get the global variable you have to inyect, as common javascript on html but with webpack.
Here are a solution for this
Webpack - How to load non module scripts into global scope | window
You have to do this for webdatarocks.toolbar.min.js and webdatarocks.js
Second Part - Add the CSS
You have some options, the easy way i found to do this is use require in your <script> zone:
require('../node_modules/webdatarocks/webdatarocks.js')
Good luck! 😁
If something fails check the paths and let us know more information about it
Alternative solution (But worse)
If you are going to use this script in a internet system, you could insert the script and CSS in the HTML. For this do:
Open index.html
Add this code on the head section:
<link href="https://cdn.webdatarocks.com/latest/webdatarocks.min.css" rel="stylesheet"/>
<script src="https://cdn.webdatarocks.com/latest/webdatarocks.toolbar.min.js"></script>
<script src="https://cdn.webdatarocks.com/latest/webdatarocks.js"></script>
Rebuild
Extracted from WebDataRocks React Example
Important! this is unsafe ☣ ⚠
Make this only if you are sure about what this mean
If the webdatarocks CDN's fails, your app will also fails.
Hope it helps :)
I did this and it works:
import WebDataRocks from 'webdatarocks'
import '#/../node_modules/webdatarocks/webdatarocks.min.css' // # is resolved to src/ folder
I didn't import the toolbar as I don't need it:
WebDataRocks({
container: '#pivot',
toolbar: false,
...
})
I am using svg.js in my Laravel project running vue.js.
This is how i use svg.js
Step 1: Install svg.js as a plugin in my vue app.
import svgJs from "svg.js/dist/svg"
export default {
install(Vue) {
Vue.prototype.$svg = svgJs
}
}
Step 2: Import and use the plugin.
import svgJs from "./plugins/vueSvgPlugin"
Vue.use(svgJs);
Step 3: Then i can do this.
console.log(this.$svg);
console.log(this.$svg.get("samplesvg"));
However i am not sure how to add the svg.js plugins. I want to use below three plugins, in case someone wants to know.
svg.select.js
svg.resize.js
svg.draggable.js
I have my solution for working with non npm/module library.
First I will use jsdelivr to serve file from directly from Github. For example https://cdn.jsdelivr.net/npm/svg.js#2.7.1/dist/svg.min.js.
Then I use script.js to load them.
script.order([
"https://cdn.jsdelivr.net/npm/svg.js#2.7.1/dist/svg.min.js",
"https://cdn.jsdelivr.net/npm/svg.select.js#3.0.1/dist/svg.select.min.js"
], () => {
// window.SVG is available
});
Live Example
To use version 3.x you would either just do it with esm imports:
import { SVG } from '#svgdotjs/svg.js'
import '#svgdotjs/svg.draggable.js'
// ...
No need to use plugins for vue. Just use SVG() in your code when you need it. If you need other functionality lile the "old" SVG.on() you need to import it, too: import { SVG, on } from '#svgdotjs/svg.js'
Or you include it via script tags. svg.js always ships with prebundled files for that purpose:
<script src="node_modules/#svgdotjs/svg.js/dist/svg.js"></script>
<script src="node_modules/#svgdotjs/svg.draggable.js/dist/svg.draggable.js"></script>
You can just use the global SVG variable in that case and access everything with it like SVG.on(...)
I had to change my approach according to comment by Fuzzyma
So i just did simple import in my app file, and it all worked fine. It is also worth mentioning that i used versions < 3.0 to make it work.
import * as SVG from 'svg.js/dist/svg';
import './plugins/svg.draggable/dist/svg.draggable';
import './plugins/svg.select/dist/svg.select';
import './plugins/svg.resize/dist/svg.resize';
I have put my js files eva.min.js/feather.min.js and so on in vendor dir, then I imported them in ember-cli-build.js app.import('vendor/eva.min.js'). But how to use it?
I tried something like import eva from 'eva'/'eva.min'/'eva.min.js' or import Eva from 'eva'; and so on, but it doesn't work.
app.import('vendor/eva.min.js');
app.import('vendor/bootstrap.min.js');
app.import('vendor/feather.min.js');
app.import('vendor/popper.min.js');
app.import('vendor/jquery-slim.min.js');
app.import('vendor/swipe.js');
import Swipe from 'swipe';
Console usually gives me the could not find the module error.
And I don't have a deep background in programming, so I would highly appreciate if you explained the problem as simple as possible.
UPD: I found all js code as npm package (it happens that the js files weren't third-party)
https://www.npmjs.com/package/feather
https://www.npmjs.com/package/popper.js
https://www.npmjs.com/package/jquery-slim
https://www.npmjs.com/package/swipe
https://www.npmjs.com/package/bootstrap
https://www.npmjs.com/package/eva-icons
But all your responses were helpful. Anyway in the near future I expect to use third-party libraries.
A quick way is to use scriptjs and it allows you to load any javascript into your component in the following way: (I am using Yammer as an example)
import $scriptjs from 'scriptjs';
componentDidUpdate() {
//script loader
setTimeout(function(){
$scriptjs('https://c64.assets-yammer.com/assets/platform_embed.js',
() => {
window.yam.connect.embedFeed(YammerHelper.loadComments());
});
}, 1000);
}
You should get the idea how to consume it. Check their docs with lots of examples.
This is not the best solution. But one way of using the third party js is,
1) say you have a function in your js file vendor/third-party.js
someFunction = function (element) {
...
console.log("works")
};
2) Then import it in your ember-cli-build.js
...
app.import('vendor/third-party.js');
...
3) After importing restart your server.
Use the function directly in your controller/component as
window["someFunction"]
Unless the JavaScript library being used explicitly supports the import X from 'y' syntax then when you import in the build using the app.import syntax you just use it in your app just as the plugin documentation describes.
So for Swipe you would do the following.
Based on this documentation: https://github.com/thebird/Swipe
// ember-cli-build.js
app.import('myswipe.js`);
// component.js
/* global Swipe */ // This silences the linter from throwing errors...
classNames: ['swipe'],
didInsertElement() {
this._swipe = Swipe(this.element, {
option1: option1
});
}
// component.hbs
<div class='swipe-wrap'>
{{yield}}
</div>
This codes creates a component to control your swipe plugin.
This code would create a swipe object and isolate it to the component.
Again when you use the app.import you are just loading the library on boot. The library does whatever it says it will do in the docs. Sometimes they register a global object, sometimes they dont.
I have a Monaco editor which the user inputs custom javascript code. Within this Monaco Editor they can use Lodash functionality. I want to be able to give them the intellisense / code completion for lodash, by including the type definitions.
I've seen a few answers relating to adding custom declarations, but none that are including a whole 3rd party libraries declarations. Has anybody had experience with this.
This is what I have so far. Then below I create the editor, similar to the example in the documentation.
monaco.languages.typescript.typescriptDefaults.addExtraLib("", "./../../types/lodash/index.d.ts");
I'd like to add the package monaco-editor-auto-typings as an option. Disclaimer: I'm the developer of that package.
It continuously scans code entered in the monaco editor, detects imports and automatically loads the declaration files from UnPkg.
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import { AutoTypings, LocalStorageCache } from 'monaco-editor-auto-typings';
const val = `
import React from 'react';
React.useEffect(0); // Type Error!
`;
// Create monaco editor instance
const editor = monaco.editor.create(document.getElementById('root')!, {
model: monaco.editor.createModel(val, 'typescript'),
});
// Initialize auto typing on monaco editor. Imports will now automatically be typed!
const autoTypings = AutoTypings.create(editor, {
sourceCache: new LocalStorageCache(), // Cache loaded sources in localStorage. May be omitted
// Other options...
});
You can explore how it works in the demo.
(Copied from my GH Gist: https://gist.github.com/cdrini/9de507f6ac19da30fd27c5f618783b31 )
Well that was a headache! This is certainly not an elegant solution, but it works. Hopefully someone can use these notes to save themselves a bunch of time.
Known issues:
This does not scale easily to any other library
Requires some internal knowledge of lodash's types library which might break on a lodash update
Add raw-loader and #types/lodash
npm install --save-dev #types/lodash raw-loader
(as of writing, these are at 4.14.162 and 4.0.2, respectively)
Import and register the .d.ts files
Looking at #types/lodash/index.d.ts, copy all the common references and import them. :
import LODASH_index from '!raw-loader!#types/lodash/index.d.ts';
import LODASH_common from '!raw-loader!#types/lodash/common/common.d.ts';
import LODASH_array from '!raw-loader!#types/lodash/common/array.d.ts';
import LODASH_collection from '!raw-loader!#types/lodash/common/collection.d.ts';
import LODASH_date from '!raw-loader!#types/lodash/common/date.d.ts';
import LODASH_function from '!raw-loader!#types/lodash/common/function.d.ts';
import LODASH_lang from '!raw-loader!#types/lodash/common/lang.d.ts';
import LODASH_math from '!raw-loader!#types/lodash/common/math.d.ts';
import LODASH_number from '!raw-loader!#types/lodash/common/number.d.ts';
import LODASH_object from '!raw-loader!#types/lodash/common/object.d.ts';
import LODASH_seq from '!raw-loader!#types/lodash/common/seq.d.ts';
import LODASH_string from '!raw-loader!#types/lodash/common/string.d.ts';
import LODASH_util from '!raw-loader!#types/lodash/common/util.d.ts';
Note: Vetur will complain in VS Code about importing .d.ts files, but won't error.
Then register them into monaco (wherever monaco is in your project):
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_index, '#types/lodash/index.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_common, '#types/lodash/common/common.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_array, '#types/lodash/common/array.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_collection, '#types/lodash/common/collection.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_date, '#types/lodash/common/date.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_function, '#types/lodash/common/function.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_lang, '#types/lodash/common/lang.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_math, '#types/lodash/common/math.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_number, '#types/lodash/common/number.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_object, '#types/lodash/common/object.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_seq, '#types/lodash/common/seq.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_string, '#types/lodash/common/string.d.ts');
window.monaco?.languages.typescript.javascriptDefaults.addExtraLib(LODASH_util, '#types/lodash/common/util.d.ts');
Note:
The file names matter here (somehow); removing the .d.ts extension causes them to break.
References/External Links
The (largely useless) docs: https://microsoft.github.io/monaco-editor/api/interfaces/monaco.languages.typescript.languageservicedefaults.html#addextralib
GH Issues:
#758: monaco-typescript not picking up configured modules from addExtraLib
#754: Cannot require contents of '.d.ts' files as string in browser for addExtraLib method
StackOverflow Questions:
Adding Typescript Type Declarations to Monaco Editor
Monaco demo using addExtraLib: https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-configure-javascript-defaults
#types/lodash at unpkg, if you want to see the .d.ts files directly: https://unpkg.com/browse/#types/lodash#4.14.162/
GH Search for uses of addExtraLib: https://github.com/search?l=JavaScript&q=addExtraLib&type=Code
Open Questions
What does the filename actually do? Also, what are the protocol prefixes for?
See this as an example and the apis. you should pass the content of the .d.ts file as the first argument
monaco.languages.typescript.typescriptDefaults.addExtraLib(content, "")
check this demo of how pass arguments