Q: how to import a const to a string? - javascript

At the moment im building a application which requires a react-native webview because I wanted to build a offline charting application. There are at the moment of writing no librarys used for react-native to create a chart.
In order to create the chart I started to make a WebView because there are already librarys made based on D3.js this webview got a template HTML inside.
So my train of thoughts: Create a webview add all the library's needed for the Graph's and voila a nice graph in React-native.
The idea behind it works, but the Graph is a big blob on a component and trying to get it in another file. So I can include it with 1 line.
//import librarys for the html 'string'.
import d3 from './librarys/d3'
import c3 from './librarys/c3'
import styleSheet from './librarys/c3css'
These library's are concatenated to the Webview.
like this way:
const HTML = `<html>
<head>
<title>Hello Static World</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=320, user-scalable=no">
<style type="text/css">
body {
margin: 0;
padding: 0;
font: 62.5% arial, sans-serif;
background: #ccc;
}
h1 {
padding: 45px;
margin: 0;
text-align: center;
color: #33f;
}
`+ { styleSheet }+ `
</style>`;
`
Result: all html but this part: + { styleSheet }+ `` still remains a [Object object] instead of the resulting string.
Is there anyway to include it properly? Instead of receiving Object object. Parsemethod?

#Dan_abramov: "You can't "concatenate" imports. You need a bundler (like Browserify) that would bundle your JS. Then include it in HTML."
Source: https://twitter.com/dan_abramov/status/737283387128459264

Related

How can I add a stylesheet dynamically with NextJS?

In my nextJS application, I need to load a stylesheet dynamically based on the user preference received from the database.
So, in my page, I'm adding it in the Head (next/head), as follows:
<Head>
<link rel="stylesheet" href={`/fonts/${type}/stylesheet.css`}></link>
</Head>
However, this is giving me a warning in the console in development mode:
Do not add stylesheets using next/head (see <link rel="stylesheet"> tag with href="/fonts/cal/stylesheet.css"). Use Document instead.
See more info here: https://nextjs.org/docs/messages/no-stylesheets-in-head-component
The stylesheet itself contains the font-face:
#font-face {
font-family: "Cal Sans";
src: url("CalSans-SemiBold.woff2") format("woff2"),
url("CalSans-SemiBold.woff") format("woff");
font-weight: 600;
font-style: normal;
font-display: swap;
}
Since the user's preference is stored in the database, and I receive this value via a query, I don't know how I can add it to the Document.js file.
I'll really appreciate any help on this.
While it might be possible to dynamically import a CSS file in your main app component (and you can check out an example in this guide), I would suggest a different solution.
Include all stylesheets in your application, but make its styles only apply when the html (or body) element has a certain class. Then all you need to do is modify that class based on user preference.
// styles.css
body.themeFoo #container {
// some styles...
}
This is how many implementations of dark mode work, e.g. in tailwind CSS. I believe this is a better pattern to solve your problem.
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html>
<Head>
<link rel="stylesheet" href="..." />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
This problem is resolved in the new Nextjs version where they provide support for Font Optimization, as documented here - https://nextjs.org/docs/basic-features/font-optimization
It also supports font self-hosting which was the key to my requirements.

How to work with CDN script only in Vue... unable to import component?

I am a newbie to Vue.js. I don't like working with cli, so I am using CDN for everything but stuck in some unknown problem. I googled many thing but couldn't understand what going on. Any help would be really appreciated.
Here is my index.php
<!DOCTYPE html>
<html>
<head>
<meta charset="8-utf" />
<meta name="author" content="Yash Gaikwad">
<meta name="description" content="">
<meta name="keyword" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="style.css"> <!--Stylesheet-->
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400&display=swap" rel="stylesheet"> <!--Google Fonts-->
<script src="https://www.w3schools.com/lib/w3.js"></script> <!--W3.Css-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/6.1.19/browser.js" type="text/babel"></script><!--Bable Hosting-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!--Vue Hosting-->
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <!--Vue Router-->
</head>
<body>
<div id="app">
</div>
<script src="script.js"></script> <!--Javascript-->
</body>
</html>
Here is my script.js
import app from "./main.vue"
new Vue({
el: "#app",
data: {
},
methods: {
},
render: h => h(app)
});
This is my main.vue (root component)
<template>
<app-header></app-header>
<app-footer></app-footer>
</template>
<script>
import Header from "./components/header.vue";
import Footer from "./components/footer.vue";
export default {
components: {
"app-header": Header,
"app-footer": Footer
}
}
</script>
<style scoped>
</style>
Seems to me that importing main.vue is causing error. And something is going wrong there.
This are the errors I being getting from both ff and chrome
Uncaught SyntaxError: Cannot use import statement outside a module
SyntaxError: import declarations may only appear at top level of a module
Thankyou every much guys.
.vue is not a file type that a browser understands. If you want to build VueJS applications without using any CLI tools you'll have to learn about ES6 Modules and understand that your application won't be supported by all browsers.
CLI tools like Webpack transforms your JavaScript and Vue code into JavaScript code that is compatible with more browsers, minifies your code (makes the size of the files that are downloaded smaller), etc. It also makes it much easier for you to use third-party packages in your code, as well as to keep them updated.
Using a CLI tool like Webpack or VueCLI for Vue apps will make your life much easier in the long run and is the standard way of doing things across the industry.
Always import statement should be at the top of the file,
you are using template and then the import
in main.vue put script block to the top and then the template
The browser cannot understand .vue extension while using vue CDN so replace that with .js or load vue via CLI instead.
Next inside the JS (vue) files, remove the template, style and script tag and make it look like this:
//header.js
export default {
data: () => ({
}),
template:`<h1>Header</h1>`
}
//footer.js
export default {
data: () => ({
}),
template:`<h1>Footer</h1>`
}
Next, add a type module to your script tag like:
<script type="module">
import Header from "./components/header.js";
import Footer from "./components/footer.js";
export default {
components: {
"app-header": Header,
"app-footer": Footer
}
}
</script>
You can also replace ES6 import statement with ES5 require if you don't want to use type="module"

Using html code with a javascript code as a widget in flutter web

I am currently using flutter web and I already have an html button that I want to add inside my flutter app. This html contains a java script as its body. How to add the html with javascript as a widget inside my app? This is the html snippet:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Paytabs Express Checkout V4</title>
</head>
<body>
<script
src="https://paytabs.com/express/v4/paytabs-express-checkout.js"
id="paytabs-express-checkout"
data-secret-key="key"
data-ui-type="button"
data-merchant-id="mid"
data-url-redirect="https://my09713z28.codesandbox.io/"
data-amount="3.3"
data-currency="SAR"
data-title="John Doe"
data-product-names="click"
data-order-id="25"
data-ui-show-header="true"
data-customer-phone-number="5486253"
data-customer-email-address="john.deo#paytabs.com"
data-customer-country-code="973"
data-ui-show-billing-address="false"
data-billing-full-address="test test test"
data-billing-city="test"
data-billing-state="test"
data-billing-country="BHR"
data-billing-postal-code="123"
></script>
<script>
</script>
</body>
</html>
Hope you provide me with some help.
You can go something like this. You should put your html releated code in index.html file and in src you need to put a path for your index.html e.g. 'assets/index.html'
import 'dart:html' as html;
import 'dart:js' as js;
import 'dart:ui' as ui;
String viewID = "your-view-id";
#override
Widget build(BuildContext context) {
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
viewID,
(int id) => html.IFrameElement()
..width = MediaQuery.of(context).size.width.toString()
..height = MediaQuery.of(context).size.height.toString()
..src = 'path/to/your/index.html'
..style.border = 'none');
return SizedBox(
height: 500,
child: HtmlElementView(
viewType: viewID,
),
);
}
You can use HtmlElementView for adding html elements inside a flutter web app
https://api.flutter.dev/flutter/widgets/HtmlElementView-class.html
Beware that would only work in flutter web and
Embedding HTML is an expensive operation and should be avoided when a
Flutter equivalent is possible
You should add this html content inside the file web/main.html.
I suggest you to build the button with Flutter and call javascript code with dart like this example calling javascript from Dart
If I understand correctly, your intention is to be able to render your html/javascript as a native widget in flutter.
Unfortunately, I don't think this is technically possible due to the fact that flutter is rendering everything in its own light-weight rendering engine, rather than creating native code that your native runtime executes. The artifact(s) created (even in flutter web) after compilation is a combination of flutter runtime + your compiled code that executes on flutter runtime. Therefore this is not possible to add html/javascript to your flutter code as a widget and run it everywhere.
The solution is to implement your widget in pure Dart code.

Learning how to use ES6 import and modules getting Reference Error

I am just beginning to learn ES6 imports, with the hopes to transition an application to modular ES6. My current project has the following directory structure:
index.html
-scripts\
--function1.js
--function2.js
--globals.js
--main.js
My index.html file code is as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Modular JS Example</title>
</head>
<body>
<button onclick="changevar1()">Change Var 1</button>
<button onclick="changevar2()">Change Var 2</button>
<script src="scripts/main.js" type="module"></script>
</body>
</html>
As you can see, I have two buttons which have onclick triggers assigned to them. These functions namely, changevar1() and changevar2() are found in files function1.js and function2.js respectively. And my entry point is main.js.
My main.js is as follows:
import {globalvar1 as globalvar1,
globalvar2 as globalvar2} from "./globals.js";
import {changevar1 as changevar1} from "./function1.js";
import {changevar2 as changevar2} from "./function2.js";
console.log(globalvar1, globalvar2,changevar1,changevar2);
My globals.js is where I declare some global variables which will be used by functions in either functions1.js or functions2.js and is as follows:
export let globalvar1 = "I am globalvar1";
export let globalvar2 = "I am globalvar2";
My function1.js has the function for the first button and is as follows:
import { globalvar1 } from "./globals.js" //do I need to import here?
export function changevar1() {
globalvar1 = "Now changed globalvar1"
console.log(globalvar1);
}
In the case above, I am importing the globalvar1 from globals.js and I am not sure if that is required, or if it will all come together in main.js?
My function2.js has the function for the second button and is as follows:
export function changevar2() {
globalvar2 = "Now changed globalvar2"
console.log(globalvar2);
}
In this case, I was not importing the globalvar2, just to see if it was not required.
Now the question is simply when you press the button how can you trigger either changevar1() or changevar2() to change the globalvar1 or globalvar2? I keep getting "Reference errors".
I have read several online documents and watched a few video tutorials online too to try to understand modular js.
Please excuse my lack of knowledge about modules and any help even if very basic knowledge is helpful.

Error when importing web components in the "wrong" order

I have built a small library of several HTML web components for internal company use. Some components are mutually dependent on each other, so I also import them mutually. Until recently, I had no serious issues with this approach, but I am now encountering an error message when loading a HTML page that uses such mutually dependent components.
I have isolated the issue in a small example. Please review the following three files.
test-container.js
import { TestItem } from "./test-item";
export class TestContainer extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" }).innerHTML = `
<style>
* {
position: relative;
box-sizing: border-box;
}
:host {
contain: content;
display: block;
}
</style>
<div>
<slot></slot>
</div>
`;
}
connectedCallback() {
if (!this.isConnected) {
return;
}
for (const node of this.childNodes) {
if (node instanceof TestItem) {
//...
}
}
}
}
customElements.define("test-container", TestContainer);
test-item.js
import { TestContainer } from "./test-container";
export class TestItem extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" }).innerHTML = `
<style>
* {
position: relative;
box-sizing: border-box;
}
:host {
contain: content;
display: block;
}
</style>
<div>
<slot></slot>
</div>
`;
}
}
customElements.define("test-item", TestItem);
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
<script type="module" src="/test-container"></script>
<script type="module" src="/test-item"></script>
<style>
test-container {
width: 600px;
height: 400px;
background: lightblue;
border: 1px solid;
}
test-item {
width: 200px;
height: 200px;
background: lightgreen;
border: 1px solid;
}
</style>
</head>
<body>
<test-container>
<test-item></test-item>
</test-container>
</body>
</html>
This code seems to work fine.
However, if I switch the two <script> tags in the index.html file, the developer tools console shows the following error:
Uncaught ReferenceError: Cannot access 'TestItem' before initialization
at HTMLElement.connectedCallback (test-container:30)
at test-container:37
Since I import several modules in many of my components, I want to sort them alphabetically (for clarity). In my test example it's fine, but in my actual code it isn't...
So basically I want my modules to be completely independent of the order in which they will be imported by other modules. Is there any way to achieve that?
All suggestions are very welcome. However, I am not allowed to install and use any external/3rd party packages. Even the use of jQuery is not allowed. So a solution should consist of only plain vanilla JS, plain CSS, and plain HTML5, and it should at least work correctly in the latest Google Chrome and Mozilla Firefox web browsers.
When you can't control the order in which Elements are loaded,
you have to handle the dependency in your Element
Use: https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/whenDefined
whenDefined returns a Promise!
So your <test-container> code needs something like:
customElements.whenDefined('test-item')
.then( () => {
//execute when already exist or became available
});
https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/whenDefined
has a more detailed example waiting for all undefined elements in a page
Dependencies
An Event driven approach might be better to get rid of dependencies.
Make <test-item> dispatch Event X in the connectedCallback
<test-container> listens for Event X and does something with the item
You can then add <another-item> to the mix without having to change <test-container>
Maybe the default slotchange Event can be of help:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement/slotchange_event
.
Success met welke aanpak je ook kiest
it may help
<!-- This script will execute after… -->
<script type="module" src="1.mjs"></script>
<!-- …this script… -->
<script src="2.js"></script>
<!-- …but before this script. -->
<script defer src="3.js"></script>
The order should be 2.js, 1.mjs, 3.js.
The way scripts block the HTML parser during fetching is baaaad.
With regular scripts you can use defer to prevent blocking, which also delays script execution until the document has finished parsing, and maintains execution order with other deferred scripts.
Module scripts behave like defer by default – there's no way to make a module script block the HTML parser while it fetches.
Module scripts use the same execution queue as regular scripts using defer.
Source

Categories