Search code examples
javascripthtmlobjectweb-componentcustom-element

Making a HTML source object


I want to create a little HTML extension which provides a tag (uai) which will be formatted like <uai src="some_what_file.mp3" controller="nav" autoplay="true">

And so on this tag will get a javascript object assigned.

function uai(){
    this.src = { ... }
    this.controller = { ... }
    this.autoplay = { ... }
}

But I wonder how I will apply this function as an object to the html tag and make the HTML tag to apply the source to this.src

This object will be similar to the input tag *


I know the audio tag exists, and I fully know how to use it. But I want to replace the audio tag and functions with this one. It will make it easier for me to make canvas supported audio marks, so that's why I need it.


Solution

  • If you want to use Custom Elements you need to insert an hyphen - in the name of your tag to be sure it won't be used in the future standard, for example: <ultimate-audio>.

    Also you should use now the version 1 of the Custom Elements specification, which uses customElements.define() instead of document.registerElement() to register a new element.

    Last, you cannot use the extends:'audio' option if you want to create a new tag.

    You can use the class definition in all modern browsers:

    Content of ulimate-audio.html:

    <template>
        <h3>UAI</h3>
        <nav>
            <button id=PlayBtn>Play</button>
            <button id=StopBtn>Stop</button>
            <input id=AutoplayCB type=checkbox disabled>Auto-Play
            <div>Source : <output id=SourceOut></output></div>
        </nav>
    </template>
    
    <script>
    ( function ( owner )
    {
        class UAI extends HTMLElement 
        {
            constructor ()
            {
                super()
                this.model = {}
                this.view = {}
            }
    
            connectedCallback ()
            {
              //View
                this.innerHTML = owner.querySelector( 'template' ).innerHTML
                this.view.autoplay = this.querySelector( '#AutoplayCB' )
                this.view.source = this.querySelector( '#SourceOut' )
    
              //Model
                //autoplay
                var attr =  this.getAttribute( 'autoplay' ) 
                this.model.autoplay =  typeof attr == 'string' && ( attr == '' || attr == 'true' ) 
    
                //source
                this.model.source = this.getAttribute( 'src' )
    
    
              //Model -> View
                this.view.source.textContent = this.model.source
                this.view.autoplay.checked = this.model.autoplay
    
              //[play] event
                var self = this
                this.querySelector( '#PlayBtn' ).addEventListener( 'click', function () 
                {
                    self.play() 
                } )
                this.querySelector( '#StopBtn' ).addEventListener( 'click', function () 
                {
                    self.stop() 
                } )
    
              //init
                if ( this.model.autoplay )
                    this.play()
            }
    
            play ()
            {   
                this.model.audio = new Audio( this.model.source )
                this.model.audio.play()
            }
    
            stop ()
            {
                this.model.audio.pause()
            }
    
            set src ( file ) 
            {
                console.log( '%s.src=%s', this, file )
                this.model.source = file
                this.model.audio.src = file 
                this.view.source.textContent = file
                if ( this.model.autoplay )
                    this.model.audio.play()
            }
    
            set autoplay ( value )
            {
                console.warn( 'autoplay=', value )
                this.model.autoplay = ( value === "true" || value === true )
                this.view.autoplay.checked = this.model.autoplay
            }
    
        }
    
        customElements.define( 'ultimate-audio', UAI )
    } )( document.currentScript.ownerDocument ) 
    </script>
    

    The UI of you control is defined in the <template>, where you can add a <style> element. Then you can use your tag like this:

    In the header, include the custom element:

    <link rel="import" href="ultimate-audio.html">
    

    In the body, use the new tag:

    <ultimate-audio id=UA src="path/file.mp3" autoplay></ultimate-audio>
    

    The methods play(), stop(), and the properties src and autoplay can be invoked form javascript:

    UA.src = "path/file2.mp3"
    UA.play()