how to fix css of video.js package in reacttjs - css

im using video.js in react for building video player but when im installing it using npm pacakage its does not provide its inbuilt css how i can add inbuilt css of video.js, instead of control bar im getting something like shown in picture below
import React, { Component } from 'react';
import videojs from 'video.js';
import { sendData } from '../../analytics/sendData';
class Video360Player extends Component {
componentDidMount() {
// instantiate Video.js
const videoJsOptions = {
autoplay: true,
controls: true,
sources: [{
src: this.props.videoUrl,
type: 'video/mp4'
}]
}
this.player = videojs(this.videoNode, videoJsOptions,this.props, function onPlayerReady() {
console.log('onPlayerReady', this)
});
}
// destroy player on unmount
componentWillUnmount() {
if (this.player) {
this.player.dispose()
}
}
// wrap the player in a div with a `data-vjs-player` attribute
// so videojs won't create additional wrapper in the DOM
// see https://github.com/videojs/video.js/pull/3856
render() {
return (
<div>
<div data-vjs-player>
<video ref={ node => this.videoNode = node } className="video-js"></video>
</div>
</div>
)
}}
export default Video360Player

Add the following line on top of component file:
import 'video.js/dist/video-js.css';
As pointed here: https://docs.videojs.com/tutorial-react.html

The reason your video is not playing is because the player is not ready. I ran into the same problem and the solution is explained in the documentation.
Basically, You must have a function to change the video source only when the player is ready.
const changePlayerOptions = () => {
// you can update the player through the Video.js player instance
if (!playerRef.current) {
return;
}
// [update player through instance's api]
playerRef.current.src([{ src: 'https://vjs.zencdn.net/v/oceans.mp4', type: 'video/mp4' }]);
};
It is explained in details here https://docs.videojs.com/tutorial-react.html

Related

How to use SSR with Stencil in a Nuxt 3 Vite project?

In Nuxt 2 I could use server-side rendered Stencil components by leveraging the renderToString() method provided in the Stencil package in combination with a Nuxt hook, like this:
import { renderToString } from '[my-components]/dist-hydrate'
export default function () {
this.nuxt.hook('generate:page', async (page) => {
const render = await renderToString(page.html, {
prettyHtml: false
})
page.html = render.html
})
}
Since the recent release of Stencil 2.16.0 I'm able to use native web components in Nuxt 3 that is powered by Vite. However I haven't found a way to hook into the template hydration process. Unfortunately there is no documentation for the composable useHydration() yet.
Does anybody know how I could get this to work in Nuxt 3?
I had the same problem. I solved it via a module.
Make a new custom nuxt module. documentation for creating a module
In the setup method hook into the generate:page hook:
nuxt.hook('generate:page', async (page) => {
const render = await renderToString(page.html, {
prettyHtml: true,
});
page.html = render.html;
});
documentation for nuxt hooks
documentation for stencil hydration (renderToString)
Register the css classes you need via nuxt.options.css.push(PATH_TO_CSS)
Register the module in the nuxt config.
Note: Make sure in the nuxt.config.ts the defineNuxtConfig gets exported as default.
Tap the vue compiler options in the nuxt config:
vue: {
compilerOptions: {
isCustomElement: (tag) => TEST_TAG_HERE,
},
},
This depends on how you wan't to use the custom elements. In my case I defined the elements over the stencil loader in my app.vue file:
import { defineCustomElements } from '<package>/<path_to_loader>';
defineCustomElements();
You could also import the elements you need in your component and then define them right there, for example in a example.vue component:
import { CustomElement } from '<package>/custom-elements';
customElements.define('custom-element', CustomElement);
Here is an example from my module and config:
./modules/sdx.ts
import { defineNuxtModule } from '#nuxt/kit';
import { renderToString } from '#swisscom/sdx/hydrate';
export default defineNuxtModule({
meta: {
name: '#nuxt/sdx',
configKey: 'sdx',
},
setup(options, nuxt) {
nuxt.hook('generate:page', async (page) => {
const render = await renderToString(page.html, {
prettyHtml: true,
});
page.html = render.html;
});
nuxt.options.css.push('#swisscom/sdx/dist/css/webcomponents.css');
nuxt.options.css.push('#swisscom/sdx/dist/css/sdx.css');
},
});
Important: This only works if the stenciljs package supports hydration or in other words has a hydrate output. Read more here
./nuxt.config.ts
import { defineNuxtConfig } from 'nuxt';
//v3.nuxtjs.org/api/configuration/nuxt.config export default
export default defineNuxtConfig({
typescript: { shim: false },
vue: {
compilerOptions: {
isCustomElement: (tag) => /sdx-.+/.test(tag),
},
},
modules: ['./modules/sdx'],
});
./app.vue
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
<script setup lang="ts">
import { defineCustomElements } from '#swisscom/sdx/dist/js/webcomponents/loader';
defineCustomElements();
// https://v3.nuxtjs.org/guide/features/head-management/
useHead({
title: 'demo',
viewport: 'width=device-width, initial-scale=1, maximum-scale=1',
charset: 'utf-8',
meta: [{ name: 'description', content: 'demo for using a stencil package in a nuxt ssr app' }],
bodyAttrs: {
class: 'sdx',
},
});
</script>
Update
I tested my setup with multiple components and it looks like you cannot define your components in the module. I updated the answer to my working solution.
I've found defining a plugin using the 'render:response' hook to work for me:
server/plugins/ssr-components.plugin.ts
import { renderToString } from '#my-lib/components/hydrate';
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('render:response', async (response) => {
response.body = (await renderToString(response.body)).html;
});
});
Perhaps it will work for you :)
Try this in defineNuxtPlugin
nuxtApp.hook('app:rendered', () => {
const response = nuxtApp.ssrContext?.res
if (!response)
return
const end = response.end
response.end = function(chunk) {
chunk = 'hijacked'
end(chunk)
}
})

CodeMirror on Vue3 has a problem when setValue is kicked

I'm trying to use CodeMirror on Vue3 and the problem occurs when I call doc.setValue().
The Problem is following:
Cursor position is broken when doc.setValue() is called
CodeMirror throws an exception when continuing editing
The exception is here.
Uncaught TypeError: Cannot read property 'height' of undefined
at lineLength (codemirror.js:1653)
at codemirror.js:5459
at LeafChunk.iterN (codemirror.js:5623)
at Doc.iterN (codemirror.js:5725)
at Doc.iter (codemirror.js:6111)
at makeChangeSingleDocInEditor (codemirror.js:5458)
at makeChangeSingleDoc (codemirror.js:5428)
at makeChangeInner (codemirror.js:5297)
at makeChange (codemirror.js:5288)
at replaceRange (codemirror.js:5502)
How should I solve this?
~~~
Versions are CodeMirror: 5.61.1, Vue.js: 3.0.11
My code is following:
index.html
<div id="app"></div>
<script src="./index.js"></script>
index.js
import { createApp } from 'vue';
import App from './App';
const app = createApp(App);
app.mount('#app');
App.vue
<template>
<div>
<button #click="click">Push Me</button>
<textarea id="codemirror"></textarea>
</div>
</template>
<script>
import CodeMirror from 'codemirror/lib/codemirror.js';
import 'codemirror/lib/codemirror.css';
// import codemirror resources
import 'codemirror/addon/mode/overlay.js';
import 'codemirror/mode/markdown/markdown.js';
import 'codemirror/mode/gfm/gfm.js';
export default {
data () {
return {
cm: null
}
},
mounted () {
this.cm = CodeMirror.fromTextArea(document.getElementById('codemirror'), {
mode: 'gfm',
lineNumbers: true,
});
},
methods: {
click (event) {
this.cm.getDoc().setValue('foo\nbar');
}
}
}
</script>
Thanks.
UPDATES
First, this problem also occurs when I used replaceRange() with multiline.
Unfortunately, I couldn't find any solution. So I tried to find another way.
My solution is recreating Codemirror instance with a textarea that has new content.
It works well.
// Remove old editor
this.cm.toTextArea();
// Get textarea
const textarea = document.getElementById('codemirror');
// Set new content
textarea.value = 'foo\nbar';
// Create new editor
this.cm = CodeMirror.fromTextArea(textarea, { /** options */ });
I found a method, you can use toRaw to get the original Object from Proxy,and this method can be also used in monaco-editor
import { toRaw } from 'vue'
import CodeMirror from 'codemirror/lib/codemirror.js';
import 'codemirror/lib/codemirror.css';
// import codemirror resources
import 'codemirror/addon/mode/overlay.js';
import 'codemirror/mode/markdown/markdown.js';
import 'codemirror/mode/gfm/gfm.js';
export default {
data () {
return {
cm: null
}
},
mounted () {
this.cm = CodeMirror.fromTextArea(document.getElementById('codemirror'), {
mode: 'gfm',
lineNumbers: true,
});
},
methods: {
click (event) {
toRaw(this.cm).setValue('foo\nbar');
}
}
}
Another way,you don't have to define cm in data, just use this.cm
data () {
return {
//cm: null
}
},

Importing css from a node module required in a plugin file with nuxt js

To add the fullscreen button to my leaflet map into nuxt i have installed leaflet.fullscreen package and i have edited my plugin leaflet.js like so:
import Vue from "vue";
import { LMap, LTileLayer, LMarker, LPolyline } from "vue2-leaflet";
require("leaflet-routing-machine");
require("lrm-graphhopper");
require("leaflet.fullscreen");
So i can use it in my main template:
<template>
<div>
<section class="search__page">
<div id="map-wrap" class="map__wrapper"></div>
</section>
</div>
</template>
<script>
import Tmap from "#/utils/TripMap.js";
export default {
mounted() {
this.initTmap();
},
data() {
return {
mainMap: null,
},
methods: {
initTmap() {
this.mainMap = new Tmap();
this.mainMap.load();
}
}
}
</script>
My class looks like that :
export default class Tmap {
constructor() {
this.map = null;
}
load) {
this.map = L.map("map-wrap", {
fullscreenControl: true,
fullscreenControlOptions: {
position: "topleft"
}).setView([46.7227062, 2.5046503], 6);
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
maxZoom: 18,
attribution: '© OpenStreetMap, ©TRIP'
}).addTo(this.map);
}
addMarkerOnClick() {
this.map.addEventListener("click", ev => {
L.marker(ev.latlng).addTo(this.map);
});
}
getBounds() {
return this.map.getBounds();
}
}
So in my main component i don't know how to import the css associated to this fullscreen plugin. I tried :
<style>
#import "~/node_modules/leaflet.fullscreen/Control.FullScreen.css";
</style>
That works but it's obviously not the good way to do that. Any idea how to that properly ?
From a quick web research i would say you should be able to access the styles like this:
#import "~leaflet/dist/leaflet.css";
When you register a global style in your nuxt.config.js the app will load it just once. I assume your build is taking more time than normal due to the node_modules path.
// nuxt.config.js
css: ['~/assets/styles/global.css'],
You could also give the nuxt resource loader a try.

How to use video.js with create-next-app nextjs?

I am trying to use Video.js with create-next-app, and I am not able to load the video.js.css. this is what my component looks like.
import videojs from 'video.js'
import videoStyles from '../node_modules/video.js/dist/video-js.min.css'
export default class VideoPlayer extends React.Component {
componentDidMount() {
// instantiate Video.js
this.player = videojs(this.videoNode, this.props, function onPlayerReady() {
console.log('onPlayerReady', this)
});
}
// destroy player on unmount
componentWillUnmount() {
if (this.player) {
this.player.dispose()
}
}
// wrap the player in a div with a `data-vjs-player` attribute
// so videojs won't create additional wrapper in the DOM
// see https://github.com/videojs/video.js/pull/3856
render() {
return (
<div>
<div data-vjs-player>
<video ref={ node => this.videoNode = node } className="video-js"></video>
</div>
<style jsx>{videoStyles}</style>
</div>
)
}
}
I am using styled-jsx/css loader to load the external css file.
Look at the next.js github example. It should be enough to get you started.

Neither setInterval nor setTimeout works react-native ES6

I'm trying to get a basic timer going in react-native, but it's not working. I get no errors in the console. It just simply ignores the setInterval. I read the TimerMixin issue with ES6 (not supported). So what is the alternative if you want to use just a basic setInterval timer?, as it simply does not work in its simplest form shown here...
import React, { Component } from 'react';
import { AppRegistry, Text } from 'react-native';
class HelloWorldApp extends Component {
componentDidMount() {
console.log('COMPONENTDIDMOUNT')
//this.timer= <--//This doesn't work either
var timer = setInterval(() => {
console.log('I do not leak!');
}, 5000);
}
componentWillUnmount() {
console.log('COMPONENTWILLUNMOUNT')
clearInterval(timer);
}
render() {
return (
<Text>Hello world!</Text>
);
}
}
AppRegistry.registerComponent('HelloWorldApp', () => HelloWorldApp);
You need to save the time as an instance variable and clear it on component unmount. Example:
componentDidMount() {
this._interval = setInterval(() => {
// Your code
}, 5000);
}
componentWillUnmount() {
clearInterval(this._interval);
}
You can try this module as Timers in react-native is little pain with ES6.
https://github.com/fractaltech/react-native-timer
As per your screenshot, it clearly mentions there is a time difference between your device and debugger. Please sync both devices to use a time server (automatically set date and time) and issue will be resolved.
Reference: https://github.com/facebook/react-native/issues/9436

Resources