I'm still a beginner in Nextjs, trying to implement a simple javascript like:
document.addEventListener("scroll", function () {console.log("scroll!")})
how to add the function in a local file and then load it with <script/> in nextjs ?
P.S: i made a .js file with the function inside inside the project folder and tried to load it with next Script component but it gives me this error:
Failed to load resource: the server responded with a status of 404 (Not Found)
Next.js works with Modulation system.
If you want to add this function in some file, you need to export this function.
The code of the external file, let's call it "externalFile.js"
export function addScrollEventListener() {
document.addEventListener("scroll", function () {console.log("scroll!")})
}
Then when you want to use it in your component, you need to import it.
import { addScrollEventListener } from './externalFile';
In the useEffect hook ( which executes after mounting ), you can use it.
useEffect(() => { addScrollEventListener() }, [] )
Related
I'm trying to implement a audio player with subtitle synchronization in my vue app.
I found a pen by #Musixmatch which does the work.
However, its all vanilla.
In my vue app, I created a lyric.js file which contains the js code enclosed by:
export const initAudioSub = () => {
return new Promise(resolve => {
....the vanillajs code here...
})
}
Now in my component.vue, I imported it like this import { initAudioSub } from './lyric.js'
and called the initAUdioSub in the mounted hook like this mounted() { initAudioSub(); }
but I get an error saying :
Uncaught (in promise) ReferenceError: $ is not defined
at eval (lyric.js?6080:4)
Am I even close? can someone enlighten me on how to do it?
I am trying to parse some markdown before a page loads, so I have the following code:
<script context="module">
var markdown = require( "markdown" ).markdown;
export async function preload(page, session) {
var someMakrdown = '# Title'
var html = markdown.toHTML(someMakrdown)
return {post : html}
}
</script>
This fails with a 500 and the message: require is not defined
I have also tried using import in the following way:
<script context="module">
import {markdown} from 'markdown';
export async function preload(page, session) {
var someMakrdown = '# Title'
var html = markdown.toHTML(someMakrdown)
return {post : html}
}
</script>
This also fails with a 500 and the message Error resolving module specifier: util
I have got this to work by moving the code into a [slug].json.js file and calling that from within the preload, but is there a better way to do this?
One of the things that I've enjoyed so far about Svelte is keeping the HTML, CSS and JS together for each component. It just doesn't feel right that I need to call a seperate JS file to create JSON that can then be used.
It appears that the markdown module imports util, making it unsuitable for client-side use. Since preload functions run both server-side and client-side, that's no good. My suggestion would be to use a different library instead (I can recommend marked) and/or raise an issue on the markdown bug tracker.
Just in case someone needs a complete answer, here's how it looks like using marked, as proposed by Rich.
<script context="module">
import marked from 'marked';
let elem = '';
export function preload({ params, query }) {
elem = marked('# Marked in the server or/and browser');
}
</script>
<div>{#html elem}</div>
It'll run in the server and then, for subsequent navigation, in the browser.
I try to use an external script (https://libs.crefopay.de/3.0/secure-fields.js) which is not vue based
I added the script via -tags into index.html
But when I try to intsanciate an object, like in the excample of the script publisher.
let secureFieldsClientInstance =
new SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
Vue says "'SecureFieldsClient' is not defined"
If I use this.
let secureFieldsClientInstance =
new this.SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
secureFieldsClientInstance.registerPayment()
Vue says: Error in v-on handler: "TypeError: this.SecureFieldsClient is not a constructor"
My Code:
methods: {
startPayment () {
this.state = null
if (!this.selected) {
this.state = false
this.msg = 'Bitte Zahlungsweise auswählen.'
} else {
localStorage.payment = this.selected
let configuration = {
url: 'https://sandbox.crefopay.de/secureFields/',
placeholders: {
}
}
let secureFieldsClientInstance =
new SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
secureFieldsClientInstance.registerPayment()
// this.$router.replace({ name: 'payment' })
}
}
}
Where is my mistake?
EDIT:
Updated the hole question
Here is a minimal Vue app for the context your provided, which works:
https://codepen.io/krukid/pen/voxqPj
Without additional details it's hard to say what your specific problem is, but most probably the library gets loaded after your method executes, so window.SecureFieldsClient is expectedly not yet defined. Or, there is some runtime error that crashes your script and prevents your method from executing. There could be some other more exotic issues, but lacking a broader context I can only speculate.
To ensure your library loads before running any code from it, you should attach an onload listener to your external script:
mounted () {
let crefPayApi = document.createElement('script')
crefPayApi.onload = () => this.startPayment()
crefPayApi.setAttribute('src', 'https://libs.crefopay.de/3.0/secure-fields.js')
document.head.appendChild(crefPayApi)
},
I found the solution.
the import was never the problem.
I had just to ignore VUEs/eslints complaining about the missing "this" via // eslint-disable-next-line and it works.
So external fuctions/opbjects should be called without "this" it seems.
let secureFieldsClientInstance =
new SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
You could download the script and then use the import directive to load the script via webpack. You probably have something like import Vue from 'vue'; in your project. This just imports vue from your node modules.
It's the exact same thing for other external scripts, just use a relative path. When using Vue-CLI, you can do import i18n from './i18n';, where the src folder would contain a i18n.js
If you really want to use a CDN, you can add it like you normally would and then add it to the externals: https://webpack.js.org/configuration/externals/#externals to make it accessible from within webpack
how I can run Javascript file in the flutter_webview_plugin. I try it with this.
flutterWebViewPlugin.evalJavascript("require('./index.js');");
But nothing happens.
when I try to run flutter code it's shows nothing
my index.Js file contains a simple alert statement
alert('hello world');
First, You used "require" function. this function is not implemented in javascript itself. it's a part of NodeJs. so that function will not work.
In order to load a js file into flutter, you should consider it as a text file and load it properly. So, you need to add the file to assets folder, add into pubspec file, then load it. read the full answer here
Second, you used evalJavascript. this function can be used in many different situations. but it will work only if you have a view panel.
Check below example:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
main() async {
String jsCode = await rootBundle.loadString('assets/javascript.js');
runApp(new MaterialApp(
home: LunchWebView(jsCode),
));
}
class LunchWebView extends StatelessWidget {
final String text;
LunchWebView(this.text);
#override
Widget build(BuildContext context) {
final FlutterWebviewPlugin flutterWebviewPlugin = FlutterWebviewPlugin();
flutterWebviewPlugin.launch('https://www.google.com');
flutterWebviewPlugin.evalJavascript(text);
return Container();
}
}
NOTE: : I didn't handle reloading and other exceptions. you should check if there is any webview object open and then call Lunch method.
I have this function:
// menuAnimate() adds/removes the classes for the mobile menu animation
export default function menuAnimate() {...}
which I am importing into my mocha test file like so:
import { menuAnimate } from '../src/scripts/nav';
However, when I run a test involving menuAnimate, I get an error this error:
/Users/johnsoct/Dropbox/Development/andybeverlyschool/src/scripts/nav.js:67
navToggle.addEventListener('click', menuAnimate);
TypeError: Cannot read property 'addEventListener' of null
This error is being thrown from code further down within nav.js.
navToggle.addEventListener('click', menuAnimate);
How can I export only the function block?
import { menuAnimate } from '../src/scripts/nav';
says "import this file, and let me access one function from it". There's no importing of only part of a file. If you don't want other stuff in that file to run, then you should split the code into two separate files, or rearchitect your code such that it doesn't run when the file loads.
navToggle.addEventListener('click', menuAnimate);
specifically seems like something I'd never expect to execute when the file loads. If you need to bind a listener, you should export a function from your module to do it, then call that function when you actually want the listener to be bound. e.g.
export function initNav() {
var navToggle = ...
navToggle.addEventListener('click', menuAnimate);
}
The top-level scope of a module should have pretty minimal logic of its own. Loading a module on its own isn't something that should have sideeffects like adding an event listener. Pretty much the only time you'd want that is in the initial application JS file.
Also, as mentioned in a comment, since you do
export default ...
you'd want to do
import menuAnimate from
or keep the import you have and do
export function menuAnimate() {...}
without the default.