Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VJS 5: Get the DOM out of the core #2006

Open
eXon opened this issue Apr 2, 2015 · 13 comments
Open

VJS 5: Get the DOM out of the core #2006

eXon opened this issue Apr 2, 2015 · 13 comments
Labels
enhancement pinned Things that stalebot shouldn't close automatically

Comments

@eXon
Copy link
Contributor

eXon commented Apr 2, 2015

This might breaks all the plugins that ever existed before. I know. But first let me explaining where that idea is coming from and then it will make a lot of sense.

In the past 2-3 years, their is a major adoption of frameworks like Angular, Ember, React, Meteor and a bunch of other templating frameworks. Most of the time, those frameworks are handling the DOM modifications and if you touch it, it might crash or discard the changes latter. We are no longer in the jQuery era where we keep touching the DOM of others and no one cares. Do not touch my DOM. It's gross.

The reason I'm talking about this is because I had an issue lately that involved ReactJS. The way ReactJS works is with a virtual DOM. It detects the changes and then it makes only the changes needed inside the real DOM. If you want to use VJS, you are screwed. Their is no way you can make a React component for VJS (here is a SO of someone foolishly trying). Their is also a lot of glitches very hard to handle if you try with other frameworks.

Here is a crazy idea. Why not getting the DOM completely out of the core logic. By doing so, we could create different renderers that would be implemented with different frameworks written by contributors.

In plain javascript, it would use the DOM. In React, it would use React.Component. In Angular, it would use directives. You get the idea.

Here is the crazy-over-the-top idea: we could even bring the awesome VJS player, skins and plugins inside native with things like react-native (released last week at the F8 w00t =]) and Cordova (used by frameworks like Meteor).

This could be a game changer for VJS. I feel this is the next logical step for any video player to be usable in the future and if we do this before anyone else, it could grow the adoption by a 10x factor.

I'm sure some people will strongly feel this will breaks too much things. I personally don't care. I want 5.0 to be awesome.

How do you guys feel about that DOM problem?

@heff
Copy link
Member

heff commented Apr 3, 2015

I was having a lot of the same questions, and then I saw the x-gif talk. That's not for 5.0, but I think it's the right long term direction. We're trying to get 5.0 out as early as the end of April, so that puts some of these major changes in context, but that's not to discourage discussing big changes like this. We've also talked about releasing major versions more frequently.

In the mean time, I'd love to have a better understanding of why Video.js breaks with React. Do you know any of the specifics? If we made it possible to add the player div in the HTML and video.js decorates that instead of modifying the dom, could that help?

Either way it would be cool if people could build controls for Video.js with the UI frameworks they're familiar with. At minimum we could make sure we have a good story around removing the video.js built-in controls and adding your own controls. You can do that today, and I've seen it done, but it sounds like we need some compatibility work around just embedding video.js inside some of the major UI frameworks.

However, if people are building different controls with different frameworks, that means different HTML, and different HTML means a few things:

  • Skins won't work across control sets
  • Plugins that add buttons to the control bar (e.g. rendition switchers) or other fancy control features won't work across control sets
  • Any advancements we make in the accessibility of the controls won't translate to other control sets

If people want to build their own controls they should be able to, but providing consistency for plugin and skin authors is also important. A lot of the value of Video.js comes/will come from how many quality plugin and skin options there are.

Though also (sorry, I'm really ping-ponging here), if a React-based set of controls built on top of the Video.js API and techs would attract a ton of extra development we wouldn't see otherwise, we don't want to miss out on that. Would you want to attempt some React controls and let us know the major blockers you run into, so we at least know if it's a realistic idea?

@eXon
Copy link
Contributor Author

eXon commented Apr 3, 2015

The main challenge that you have with ReactJS is dealing with the virtual DOM. If you make changes directly to the DOM, it will not know about it and might override it. One of the solution is to put VJS in a blackbox and then wrap the events handling. Haven't seen anybody do that.

I don't know much yet about Web Component. Because they were not giving a lot of functionalities, I always though it is better to use a framework and go all the way with it. But when building something for any framework, it seems like Web Component is the logical choice. It provides the blackbox that we need to not touch the DOM outside of the shadow DOM and we can write wrappers to handle events.

I had no clue about it but ReactJS actually play very nicely with Web Component. I had no clue you can use Web Component within the virtual DOM in JSX! =).

Angular 2 (not yet released) also amazingly play well with Web Components. It would not even need an angular-specific wrapper because it can handle the custom events that come from it.

I've seen someone creating a Web Component with VJS 4.6 very easily so I might give a try at building react-videojs/ng-videojs when I have time (none exists AFAIK). It could bring a new crowd that wouldn't use it before.

@heff
Copy link
Member

heff commented Apr 3, 2015

Yeah, that's a lot of the same conclusions I came to. The Addy video.js web component is a great example. We'd need to do a lot of work to complete the API, but I think eventually that's the direction we'll need to go.

@hspinks
Copy link

hspinks commented Jul 7, 2015

👍

Huge +1 to this concept, as it's affected our decision on video player

@mmcc
Copy link
Member

mmcc commented Jul 7, 2015

@hspinks Does something like @eXon's videojs-webcomponent library apply to you at all? Full disclosure, I haven't really looked at it beyond the README, but I've always known him to do good work :)

@heff
Copy link
Member

heff commented Jul 8, 2015

@hspinks yeah, I'd be interested to hear more details of your situation -- what you were looking for and what was the specific blockers.

@hspinks
Copy link

hspinks commented Jul 10, 2015

The short of it is that we're rebuilding our application with ReactJS, and we moved away from Video.js because it didn't play very nicely with React's virtual DOM. I haven't yet gotten the chance to explore the webcomponent library deeply, but I see that it's using Polymer rather than React.

Please keep me updated on this topic and let us know if there's anything we can do to help

@eXon
Copy link
Contributor Author

eXon commented Jul 11, 2015

@hspinks you can use web components within ReactJS. I'm also looking to do a ReactJS version because this is now the main framework I am working with.

@gkatsev
Copy link
Member

gkatsev commented Jul 11, 2015

Can't you tell react to ignore the element that videojs deals with?

@eXon
Copy link
Contributor Author

eXon commented Jul 11, 2015

Easiest way is to do is to something like:

var video = (
    <video id="videoplayer" className="video-js vjs-default-skin vjs-big-play-centered" controls preload="none"
          width="100%"
          height="300"
          poster="poster.png"
          data-setup="{}">
          <source src="video.mp4" type="video/mp4" />
      </video>
);
var vjsVideo = <div dangerouslySetInnerHTML={{ __html: React.renderToString(video) }} />;

However the communication between React.JS and video.js will be very hard to manage. I'm looking into building a react-video.js for that but haven't managed to find the time for that :)

@chemoish
Copy link
Member

I am currently rewriting an app and implementing video.js.

I am at the very early stages of both…

http://stackoverflow.com/questions/24864947/react-ignore-subnodes
http://stackoverflow.com/questions/26255344/reactjs-cant-change-video-and-poster-videojs

React.createClass({
    componentDidMount: function () {
        document.querySelector('.video-container').innerHTML = '<video id="videoplayer"></video>';

        this.player = videojs('videoplayer');
    },

    componentWillUnmount: function () {
        this.player.dispose();
    },

    togglePlayback: function() {
        if (this.player.paused()) {
            this.player.play();
        } else {
            this.player.pause();
        }
    },

    render: function () {
        return (
            <div>
                <div className="video-container"></div>

                <button onClick={this.togglePlayback}></button>
            </div>
        );
    }
});

Just through it together so it may be a holey solution. #FWIW

@kvervo
Copy link

kvervo commented Sep 13, 2015

Googling around this issue I found a gist for react videojs component: https://gist.github.com/mikechau/5547c67d0dc2957e907d

@HeyWrecker
Copy link

The last post was a while ago and I don't know if anyone came up with a better implementation, however, what I did was the following:

  1. Added the videojs function as a getInitialState prop and added a "videoHTML" prop to the getInitialState as well.
  2. Generated my video tag and sources in the componentDidMount method and assigned that variable string to the videoHTML state prop.
  3. Added a dispose() of the instantiated vjs player and a replaceState with the initial state to the componentWillUnmount() method.
  4. Added a component function __initVideo(elem) that checks to see if the passed in element has children and if it does then "this.vjsPlayer = this.state.initVideoJS(elem.children[0], {})". Then I return this.vjsPlayer.
  5. In the attachment div in the render() method, I set the dangerouslySetInnerHTML prop to the this.state.videoHTML prop and set a ref that calls the the __initVideo function, passing in the div.

Can't post any code, but this is as close to a pure React implementation of videoJS that I've been able to figure out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement pinned Things that stalebot shouldn't close automatically
Projects
None yet
Development

No branches or pull requests

8 participants