Search code examples
javascriptjqueryhtml5-videojsrenderjsviews

How create custom attribute handler for jsviews?


I want to use JsViews to play html5 video content, like this:

html:

<div id="result"></div>
<script id="myTmpl" type="text/x-jsrender">
    <video autobuffer controls data-link="muted{:muted}">
        <source id="mp4" data-link="src{:src}" type="video/mp4">
    </video>
    <button id="muted">change muted</button>
</script>

js:

var data = {
    src: "http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4",
    muted: true
};

var myTmpl = $.templates("#myTmpl");

myTmpl.link("#result", data);

$("#result").on("click", "#muted", function () {
    $.observable(data).setProperty("muted", !data.muted);
});

example on jsfidle

As can be seen attribute muted processed by default and looks like muted=true or muted=false, but in HTML specifications - attribute "muted" may or may not be. That is, to should behave as an attribute of a disable here: Data-linking the disabled and title attributes.

Maybe there is some way to customize(substitute) the standard html attribute handler in jsviews?


Solution

  • You can make the muted attribute get removed when muted is false, by writing:

    <video autobuffer controls data-link="muted{:muted||null}">

    However that will not make things work as you want since the dynamically removing or adding the muted attribute will not actually mute/unmute the video control. To do that you need to set the muted property on the muted element to true/false.

    Also when the user clicks on the built-in mute control on the video element UI, you want that to observably modify your muted data property. All that can be made to work with the following code:

    var video = $("video");
    
    $.observe(data, "muted", function(ev, eventArgs) {
        video[0].muted = eventArgs.value;
    })
    
    video.on("volumechange", function() {
        $.observable(data).setProperty("muted", video[0].muted);
    });
    

    Here is an updated version of your jsfiddle, with the changes: http://jsfiddle.net/ck9sr49L/3/.

    I intend to add a new feature in the next JsViews to be able to choose to data-link to a property on an HTML element, rather than to the corresponding attribute. The syntax will be data-link="prop-muted{:...}" (similar to data-linking to a CSS property data-link="css-muted{:...}"). With that update you will be able to simplify things and write the following:

    Template:

    <video autobuffer controls data-link="prop-muted{:muted}">
        <source id="mp4" data-link="src{:src}" type="video/mp4"/>
    </video>
    <label>Muted: <input type="checkbox" data-link="muted"/></label>
    

    Code:

    var data = {
        src: "http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4",
        muted: true
    };
    
    var myTmpl = $.templates("#theTmpl");
    
    myTmpl.link("#result", data);
    
    $("video").on("volumechange", function(ev) {
        $.observable(data).setProperty("muted", ev.target.muted);
    });