# vjs.RemainingTimeDisplay

__EXTENDS__: [vjs.Component](vjs.Component.md)
__DEFINED IN__: [src/js/control-bar/time-display.js#L108](https://github.com/videojs/video.js/blob/master/src/js/control-bar/time-display.js#L108)

Displays the time left in the video

---

## INDEX

- [METHODS](#methods)
  - [init](#init-player-options-)
  - [addChild](#addchild-child-options-) _`inherited`_
  - [addClass](#addclass-classtoadd-) _`inherited`_
  - [buildCSSClass](#buildcssclass) _`inherited`_
  - [children](#children) _`inherited`_
  - [contentEl](#contentel) _`inherited`_
  - [createEl](#createel-tagname-attributes-) _`inherited`_
  - [dimensions](#dimensions-width-height-) _`inherited`_
  - [dispose](#dispose) _`inherited`_
  - [el](#el) _`inherited`_
  - [enableTouchActivity](#enabletouchactivity) _`inherited`_
  - [getChild](#getchild-name-) _`inherited`_
  - [getChildById](#getchildbyid-id-) _`inherited`_
  - [height](#height-num-skiplisteners-) _`inherited`_
  - [hide](#hide) _`inherited`_
  - [id](#id) _`inherited`_
  - [initChildren](#initchildren) _`inherited`_
  - [name](#name) _`inherited`_
  - [off](#off-type-fn-) _`inherited`_
  - [on](#on-type-fn-) _`inherited`_
  - [one](#one-type-fn-) _`inherited`_
  - [options](#options-obj-) _`inherited`_
  - [player](#player) _`inherited`_
  - [ready](#ready-fn-) _`inherited`_
  - [removeChild](#removechild-component-) _`inherited`_
  - [removeClass](#removeclass-classtoremove-) _`inherited`_
  - [show](#show) _`inherited`_
  - [trigger](#trigger-type-event-) _`inherited`_
  - [triggerReady](#triggerready) _`inherited`_
  - [width](#width-num-skiplisteners-) _`inherited`_

- [EVENTS](#events)
  - [resize](#resize-event) _`inherited`_

---

## METHODS

### addChild( child, [options] )
> Adds a child component inside this component
>
>     myComponent.el();
>     // ->

>     myComonent.children();
>     // [empty array]
>
>     var myButton = myComponent.addChild('MyButton');
>     // ->

myButton

>     // -> myButton === myComonent.children()[0];
>
> Pass in options for child constructors and options for children of the child
>
>     var myButton = myComponent.addChild('MyButton', {
>       text: 'Press Me',
>       children: {
>         buttonChildExample: {
>           buttonChildOption: true
>         }
>       }
>     });

##### PARAMETERS:
* __child__ `String|vjs.Component` The class name or instance of a child to add
* __options__ `Object` _(OPTIONAL)_ Options, including options to be passed to children of the child.

##### RETURNS:
* `vjs.Component` The child component (created by this process if a string was used)

_inherited from_: [src/js/component.js#L347](https://github.com/videojs/video.js/blob/master/src/js/component.js#L347)

---

### addClass( classToAdd )
> Add a CSS class name to the component's element

##### PARAMETERS:
* __classToAdd__ `String` Classname to add

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L663](https://github.com/videojs/video.js/blob/master/src/js/component.js#L663)

---

### buildCSSClass()
> Allows sub components to stack CSS class names

##### RETURNS:
* `String` The constructed class name

_inherited from_: [src/js/component.js#L506](https://github.com/videojs/video.js/blob/master/src/js/component.js#L506)

---

### children()
> Get an array of all child components
>
>     var kids = myComponent.children();

##### RETURNS:
* `Array` The children

_inherited from_: [src/js/component.js#L281](https://github.com/videojs/video.js/blob/master/src/js/component.js#L281)

---

### contentEl()
> Return the component's DOM element for embedding content.
> Will either be el_ or a new element defined in createEl.

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L224](https://github.com/videojs/video.js/blob/master/src/js/component.js#L224)

---

### createEl( [tagName], [attributes] )
> Create the component's DOM element

##### PARAMETERS:
* __tagName__ `String` _(OPTIONAL)_ Element's node type. e.g. 'div'
* __attributes__ `Object` _(OPTIONAL)_ An object of element attributes that should be set on the element

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L194](https://github.com/videojs/video.js/blob/master/src/js/component.js#L194)

---

### dimensions( width, height )
> Set both width and height at the same time

##### PARAMETERS:
* __width__ `Number|String`
* __height__ `Number|String`

##### RETURNS:
* `vjs.Component` The component

_inherited from_: [src/js/component.js#L775](https://github.com/videojs/video.js/blob/master/src/js/component.js#L775)

---

### dispose()
> Dispose of the component and all child components

_inherited from_: [src/js/component.js#L78](https://github.com/videojs/video.js/blob/master/src/js/component.js#L78)

---

### el()
> Get the component's DOM element
>
>     var domEl = myComponent.el();

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L205](https://github.com/videojs/video.js/blob/master/src/js/component.js#L205)

---

### enableTouchActivity()
> Report user touch activity when touch events occur
>
> User activity is used to determine when controls should show/hide. It's
> relatively simple when it comes to mouse events, because any mouse event
> should show the controls. So we capture mouse events that bubble up to the
> player and report activity when that happens.
>
> With touch events it isn't as easy. We can't rely on touch events at the
> player level, because a tap (touchstart + touchend) on the video itself on
> mobile devices is meant to turn controls off (and on). User activity is
> checked asynchronously, so what could happen is a tap event on the video
> turns the controls off, then the touchend event bubbles up to the player,
> which if it reported user activity, would turn the controls right back on.
> (We also don't want to completely block touch events from bubbling up)
>
> Also a touchmove, touch+hold, and anything other than a tap is not supposed
> to turn the controls back on on a mobile device.
>
> Here we're setting the default component behavior to report user activity
> whenever touch events happen, and this can be turned off by components that
> want touch events to act differently.

_inherited from_: [src/js/component.js#L954](https://github.com/videojs/video.js/blob/master/src/js/component.js#L954)

---

### getChild( name )
> Returns a child component with the provided name

##### PARAMETERS:
* __name__

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L315](https://github.com/videojs/video.js/blob/master/src/js/component.js#L315)

---

### getChildById( id )
> Returns a child component with the provided ID

##### PARAMETERS:
* __id__

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L298](https://github.com/videojs/video.js/blob/master/src/js/component.js#L298)

---

### height( [num], [skipListeners] )
> Get or set the height of the component (CSS values)
>
> Setting the video tag dimension values only works with values in pixels.
> Percent values will not work.
> Some percents can be used, but width()/height() will return the number + %,
> not the actual computed width/height.

##### PARAMETERS:
* __num__ `Number|String` _(OPTIONAL)_ New component height
* __skipListeners__ `Boolean` _(OPTIONAL)_ Skip the resize event trigger

##### RETURNS:
* `vjs.Component` This component, when setting the height
* `Number|String` The height, when getting

_inherited from_: [src/js/component.js#L764](https://github.com/videojs/video.js/blob/master/src/js/component.js#L764)

---

### hide()
> Hide the component element if currently showing

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L694](https://github.com/videojs/video.js/blob/master/src/js/component.js#L694)

---

### id()
> Get the component's ID
>
>     var id = myComponent.id();

##### RETURNS:
* `String`

_inherited from_: [src/js/component.js#L243](https://github.com/videojs/video.js/blob/master/src/js/component.js#L243)

---

### init( player, options )

##### PARAMETERS:
* __player__
* __options__

_defined in_: [src/js/control-bar/time-display.js#L110](https://github.com/videojs/video.js/blob/master/src/js/control-bar/time-display.js#L110)

---

### initChildren()
> Add and initialize default child components from options
>
>     // when an instance of MyComponent is created, all children in options
>     // will be added to the instance by their name strings and options
>     MyComponent.prototype.options_.children = {
>       myChildComponent: {
>         myChildOption: true
>       }
>     }
>
>     // Or when creating the component
>     var myComp = new MyComponent(player, {
>       children: {
>         myChildComponent: {
>           myChildOption: true
>         }
>       }
>     });
>
> The children option can also be an Array of child names or
> child options objects (that also include a 'name' key).
>
>     var myComp = new MyComponent(player, {
>       children: [
>         'button',
>         {
>           name: 'button',
>           someOtherOption: true
>         }
>       ]
>     });

_inherited from_: [src/js/component.js#L466](https://github.com/videojs/video.js/blob/master/src/js/component.js#L466)

---

### name()
> Get the component's name. The name is often used to reference the component.
>
>     var name = myComponent.name();

##### RETURNS:
* `String`

_inherited from_: [src/js/component.js#L262](https://github.com/videojs/video.js/blob/master/src/js/component.js#L262)

---

### off( [type], [fn] )
> Remove an event listener from the component's element
>
>     myComponent.off("eventName", myFunc);

##### PARAMETERS:
* __type__ `String` _(OPTIONAL)_ Event type. Without type it will remove all listeners.
* __fn__ `Function` _(OPTIONAL)_ Event listener. Without fn it will remove all listeners for a type.

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L545](https://github.com/videojs/video.js/blob/master/src/js/component.js#L545)

---

### on( type, fn )
> Add an event listener to this component's element
>
>     var myFunc = function(){
>       var myPlayer = this;
>       // Do something when the event is fired
>     };
>
>     myPlayer.on("eventName", myFunc);
>
> The context will be the component.

##### PARAMETERS:
* __type__ `String` The event type e.g. 'click'
* __fn__ `Function` The event listener

##### RETURNS:
* `vjs.Component` self

_inherited from_: [src/js/component.js#L531](https://github.com/videojs/video.js/blob/master/src/js/component.js#L531)

---

### one( type, fn )
> Add an event listener to be triggered only once and then removed

##### PARAMETERS:
* __type__ `String` Event type
* __fn__ `Function` Event listener

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L557](https://github.com/videojs/video.js/blob/master/src/js/component.js#L557)

---

### options( obj )
> Deep merge of options objects
>
> Whenever a property is an object on both options objects
> the two properties will be merged using vjs.obj.deepMerge.
>
> This is used for merging options for child components. We
> want it to be easy to override individual options on a child
> component without having to rewrite all the other default options.
>
>     Parent.prototype.options_ = {
>       children: {
>         'childOne': { 'foo': 'bar', 'asdf': 'fdsa' },
>         'childTwo': {},
>         'childThree': {}
>       }
>     }
>     newOptions = {
>       children: {
>         'childOne': { 'foo': 'baz', 'abc': '123' }
>         'childTwo': null,
>         'childFour': {}
>       }
>     }
>
>     this.options(newOptions);
>
> RESULT
>
>     {
>       children: {
>         'childOne': { 'foo': 'baz', 'asdf': 'fdsa', 'abc': '123' },
>         'childTwo': null, // Disabled. Won't be initialized.
>         'childThree': {},
>         'childFour': {}
>       }
>     }

##### PARAMETERS:
* __obj__ `Object` Object of new option values

##### RETURNS:
* `Object` A NEW object of this.options_ and obj merged

_inherited from_: [src/js/component.js#L173](https://github.com/videojs/video.js/blob/master/src/js/component.js#L173)

---

### player()
> Return the component's player

##### RETURNS:
* `vjs.Player`

_inherited from_: [src/js/component.js#L120](https://github.com/videojs/video.js/blob/master/src/js/component.js#L120)

---

### ready( fn )
> Bind a listener to the component's ready state
>
> Different from event listeners in that if the ready event has already happend
> it will trigger the function immediately.

##### PARAMETERS:
* __fn__ `Function` Ready listener

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L616](https://github.com/videojs/video.js/blob/master/src/js/component.js#L616)

---

### removeChild( component )
> Remove a child component from this component's list of children, and the
> child component's element from this component's element

##### PARAMETERS:
* __component__ `vjs.Component` Component to remove

_inherited from_: [src/js/component.js#L405](https://github.com/videojs/video.js/blob/master/src/js/component.js#L405)

---

### removeClass( classToRemove )
> Remove a CSS class name from the component's element

##### PARAMETERS:
* __classToRemove__ `String` Classname to remove

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L674](https://github.com/videojs/video.js/blob/master/src/js/component.js#L674)

---

### show()
> Show the component element if hidden

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L684](https://github.com/videojs/video.js/blob/master/src/js/component.js#L684)

---

### trigger( type, event )
> Trigger an event on an element
>
>     myComponent.trigger('eventName');

##### PARAMETERS:
* __type__ `String` The event type to trigger, e.g. 'click'
* __event__ `Event|Object` The event object to be passed to the listener

##### RETURNS:
* `vjs.Component` self

_inherited from_: [src/js/component.js#L571](https://github.com/videojs/video.js/blob/master/src/js/component.js#L571)

---

### triggerReady()
> Trigger the ready listeners

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L635](https://github.com/videojs/video.js/blob/master/src/js/component.js#L635)

---

### width( [num], skipListeners )
> Set or get the width of the component (CSS values)
>
> Setting the video tag dimension values only works with values in pixels.
> Percent values will not work.
> Some percents can be used, but width()/height() will return the number + %,
> not the actual computed width/height.

##### PARAMETERS:
* __num__ `Number|String` _(OPTIONAL)_ Optional width number
* __skipListeners__ `Boolean` Skip the 'resize' event trigger

##### RETURNS:
* `vjs.Component` This component, when setting the width
* `Number|String` The width, when getting

_inherited from_: [src/js/component.js#L747](https://github.com/videojs/video.js/blob/master/src/js/component.js#L747)

---

## EVENTS

### resize `EVENT`
> Fired when the width and/or height of the component changes

_inherited from_: [src/js/component.js#L854](https://github.com/videojs/video.js/blob/master/src/js/component.js#L854)

---


keep keep keep keep add keep keep keep keep keep

/**
 * @fileoverview VideoJS-SWF - Custom Flash Player with HTML5-ish API
 * https://github.com/zencoder/video-js-swf
 * Not using setupTriggers. Using global onEvent func to distribute events
 */

/**
 * Flash Media Controller - Wrapper for fallback SWF API
 *
 * @param {vjs.Player} player
 * @param {Object=} options
 * @param {Function=} ready
 * @constructor
 */
vjs.Flash = vjs.MediaTechController.extend({
  /** @constructor */
  init: function(player, options, ready){
    vjs.MediaTechController.call(this, player, options, ready);

    var source = options['source'],

        // Which element to embed in
        parentEl = options['parentEl'],

        // Create a temporary element to be replaced by swf object
        placeHolder = this.el_ = vjs.createEl('div', { id: player.id() + '_temp_flash' }),

        // Generate ID for swf object
        objId = player.id()+'_flash_api',

        // Store player options in local var for optimization
        // TODO: switch to using player methods instead of options
        // e.g. player.autoplay();
        playerOptions = player.options_,

        // Merge default flashvars with ones passed in to init
        flashVars = vjs.obj.merge({

          // SWF Callback Functions
          'readyFunction': 'videojs.Flash.onReady',
          'eventProxyFunction': 'videojs.Flash.onEvent',
          'errorEventProxyFunction': 'videojs.Flash.onError',

          // Player Settings
          'autoplay': playerOptions.autoplay,
          'preload': playerOptions.preload,
          'loop': playerOptions.loop,
          'muted': playerOptions.muted

        }, options['flashVars']),

        // Merge default parames with ones passed in
        params = vjs.obj.merge({
          'wmode': 'opaque', // Opaque is needed to overlay controls, but can affect playback performance
          'bgcolor': '#000000' // Using bgcolor prevents a white flash when the object is loading
        }, options['params']),

        // Merge default attributes with ones passed in
        attributes = vjs.obj.merge({
          'id': objId,
          'name': objId, // Both ID and Name needed or swf to identifty itself
          'class': 'vjs-tech'
        }, options['attributes']),

        lastSeekTarget
    ;

    // If source was supplied pass as a flash var.
    if (source) {
      if (source.type && vjs.Flash.isStreamingType(source.type)) {
        var parts = vjs.Flash.streamToParts(source.src);
        flashVars['rtmpConnection'] = encodeURIComponent(parts.connection);
        flashVars['rtmpStream'] = encodeURIComponent(parts.stream);
      }
      else {
        flashVars['src'] = encodeURIComponent(vjs.getAbsoluteURL(source.src));
      }
    }

    this['setCurrentTime'] = function(time){
      lastSeekTarget = time;
      this.el_.vjs_setProperty('currentTime', time);
    };
    this['currentTime'] = function(time){
      // when seeking make the reported time keep up with the requested time
      // by reading the time we're seeking to
      if (this.seeking()) {
        return lastSeekTarget;
      }
      return this.el_.vjs_getProperty('currentTime');
    };

    // Add placeholder to player div
    vjs.insertFirst(placeHolder, parentEl);

    // Having issues with Flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers
    // This allows resetting the playhead when we catch the reload
    if (options['startTime']) {
      this.ready(function(){
        this.load();
        this.play();
        this.currentTime(options['startTime']);
      });
    }

    // firefox doesn't bubble mousemove events to parent. videojs/video-js-swf#37
    // bugzilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=836786
    if (vjs.IS_FIREFOX) {
      this.ready(function(){
        vjs.on(this.el(), 'mousemove', vjs.bind(this, function(){
          // since it's a custom event, don't bubble higher than the player
          this.player().trigger({ 'type':'mousemove', 'bubbles': false });
        }));
      });
    }

    // native click events on the SWF aren't triggered on IE11, Win8.1RT
    // use stageclick events triggered from inside the SWF instead
    player.on('stageclick', player.reportUserActivity);

    // Flash iFrame Mode
    // In web browsers there are multiple instances where changing the parent element or visibility of a plugin causes the plugin to reload.
    // - Firefox just about always. https://bugzilla.mozilla.org/show_bug.cgi?id=90268 (might be fixed by version 13)
    // - Webkit when hiding the plugin
    // - Webkit and Firefox when using requestFullScreen on a parent element
    // Loading the flash plugin into a dynamically generated iFrame gets around most of these issues.
    // Issues that remain include hiding the element and requestFullScreen in Firefox specifically

    // There's on particularly annoying issue with this method which is that Firefox throws a security error on an offsite Flash object loaded into a dynamically created iFrame.
    // Even though the iframe was inserted into a page on the web, Firefox + Flash considers it a local app trying to access an internet file.
    // I tried mulitple ways of setting the iframe src attribute but couldn't find a src that worked well. Tried a real/fake source, in/out of domain.
    // Also tried a method from stackoverflow that caused a security error in all browsers. http://stackoverflow.com/questions/2486901/how-to-set-document-domain-for-a-dynamically-generated-iframe
    // In the end the solution I found to work was setting the iframe window.location.href right before doing a document.write of the Flash object.
    // The only downside of this it seems to trigger another http request to the original page (no matter what's put in the href). Not sure why that is.

    // NOTE (2012-01-29): Cannot get Firefox to load the remote hosted SWF into a dynamically created iFrame
    // Firefox 9 throws a security error, unleess you call location.href right before doc.write.
    //    Not sure why that even works, but it causes the browser to look like it's continuously trying to load the page.
    // Firefox 3.6 keeps calling the iframe onload function anytime I write to it, causing an endless loop.

    if (options['iFrameMode'] === true && !vjs.IS_FIREFOX) {

      // Create iFrame with vjs-tech class so it's 100% width/height
      var iFrm = vjs.createEl('iframe', {
        'id': objId + '_iframe',
        'name': objId + '_iframe',
        'className': 'vjs-tech',
        'scrolling': 'no',
        'marginWidth': 0,
        'marginHeight': 0,
        'frameBorder': 0
      });

      // Update ready function names in flash vars for iframe window
      flashVars['readyFunction'] = 'ready';
      flashVars['eventProxyFunction'] = 'events';
      flashVars['errorEventProxyFunction'] = 'errors';

      // Tried multiple methods to get this to work in all browsers

      // Tried embedding the flash object in the page first, and then adding a place holder to the iframe, then replacing the placeholder with the page object.
      // The goal here was to try to load the swf URL in the parent page first and hope that got around the firefox security error
      // var newObj = vjs.Flash.embed(options['swf'], placeHolder, flashVars, params, attributes);
      // (in onload)
      //  var temp = vjs.createEl('a', { id:'asdf', innerHTML: 'asdf' } );
      //  iDoc.body.appendChild(temp);

      // Tried embedding the flash object through javascript in the iframe source.
      // This works in webkit but still triggers the firefox security error
      // iFrm.src = 'javascript: document.write('"+vjs.Flash.getEmbedCode(options['swf'], flashVars, params, attributes)+"');";

      // Tried an actual local iframe just to make sure that works, but it kills the easiness of the CDN version if you require the user to host an iframe
      // We should add an option to host the iframe locally though, because it could help a lot of issues.
      // iFrm.src = "iframe.html";

      // Wait until iFrame has loaded to write into it.
      vjs.on(iFrm, 'load', vjs.bind(this, function(){

        var iDoc,
            iWin = iFrm.contentWindow;

        // The one working method I found was to use the iframe's document.write() to create the swf object
        // This got around the security issue in all browsers except firefox.
        // I did find a hack where if I call the iframe's window.location.href='', it would get around the security error
        // However, the main page would look like it was loading indefinitely (URL bar loading spinner would never stop)
        // Plus Firefox 3.6 didn't work no matter what I tried.
        // if (vjs.USER_AGENT.match('Firefox')) {
        //   iWin.location.href = '';
        // }

        // Get the iFrame's document depending on what the browser supports
        iDoc = iFrm.contentDocument ? iFrm.contentDocument : iFrm.contentWindow.document;

        // Tried ensuring both document domains were the same, but they already were, so that wasn't the issue.
        // Even tried adding /. that was mentioned in a browser security writeup
        // document.domain = document.domain+'/.';
        // iDoc.domain = document.domain+'/.';

        // Tried adding the object to the iframe doc's innerHTML. Security error in all browsers.
        // iDoc.body.innerHTML = swfObjectHTML;

        // Tried appending the object to the iframe doc's body. Security error in all browsers.
        // iDoc.body.appendChild(swfObject);

        // Using document.write actually got around the security error that browsers were throwing.
        // Again, it's a dynamically generated (same domain) iframe, loading an external Flash swf.
        // Not sure why that's a security issue, but apparently it is.
        iDoc.write(vjs.Flash.getEmbedCode(options['swf'], flashVars, params, attributes));

        // Setting variables on the window needs to come after the doc write because otherwise they can get reset in some browsers
        // So far no issues with swf ready event being called before it's set on the window.
        iWin['player'] = this.player_;

        // Create swf ready function for iFrame window
        iWin['ready'] = vjs.bind(this.player_, function(currSwf){
          var el = iDoc.getElementById(currSwf),
              player = this,
              tech = player.tech;

          // Update reference to playback technology element
          tech.el_ = el;

          // Make sure swf is actually ready. Sometimes the API isn't actually yet.
          vjs.Flash.checkReady(tech);
        });

        // Create event listener for all swf events
        iWin['events'] = vjs.bind(this.player_, function(swfID, eventName){
          var player = this;
          if (player && player.techName === 'flash') {
            player.trigger(eventName);
          }
        });

        // Create error listener for all swf errors
        iWin['errors'] = vjs.bind(this.player_, function(swfID, eventName){
          vjs.log('Flash Error', eventName);
        });

      }));

      // Replace placeholder with iFrame (it will load now)
      placeHolder.parentNode.replaceChild(iFrm, placeHolder);

    // If not using iFrame mode, embed as normal object
    } else {
      vjs.Flash.embed(options['swf'], placeHolder, flashVars, params, attributes);
    }
  }
});

vjs.Flash.prototype.dispose = function(){
  vjs.MediaTechController.prototype.dispose.call(this);
};

vjs.Flash.prototype.play = function(){
  this.el_.vjs_play();
};

vjs.Flash.prototype.pause = function(){
  this.el_.vjs_pause();
};

vjs.Flash.prototype.src = function(src){
  if (src === undefined) {
    return this.currentSrc();
  }

  if (vjs.Flash.isStreamingSrc(src)) {
    src = vjs.Flash.streamToParts(src);
    this.setRtmpConnection(src.connection);
    this.setRtmpStream(src.stream);
  } else {
    // Make sure source URL is abosolute.
    src = vjs.getAbsoluteURL(src);
    this.el_.vjs_src(src);
  }

  // Currently the SWF doesn't autoplay if you load a source later.
  // e.g. Load player w/ no source, wait 2s, set src.
  if (this.player_.autoplay()) {
    var tech = this;
    setTimeout(function(){ tech.play(); }, 0);
  }
};

vjs.Flash.prototype.currentSrc = function(){
  var src = this.el_.vjs_getProperty('currentSrc');
  // no src, check and see if RTMP
  if (src == null) {
    var connection = this['rtmpConnection'](),
        stream = this['rtmpStream']();

    if (connection && stream) {
      src = vjs.Flash.streamFromParts(connection, stream);
    }
  }
  return src;
};

vjs.Flash.prototype.load = function(){
  this.el_.vjs_load();
};

vjs.Flash.prototype.poster = function(){
  this.el_.vjs_getProperty('poster');
};
vjs.Flash.prototype.setPoster = function(){
  // poster images are not handled by the Flash tech so make this a no-op
};

vjs.Flash.prototype.buffered = function(){
  return vjs.createTimeRange(0, this.el_.vjs_getProperty('buffered'));
};

vjs.Flash.prototype.supportsFullScreen = function(){
  return false; // Flash does not allow fullscreen through javascript
};

vjs.Flash.prototype.enterFullScreen = function(){
  return false;
};

// Create setters and getters for attributes
var api = vjs.Flash.prototype,
    readWrite = 'rtmpConnection,rtmpStream,preload,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted'.split(','),
    readOnly = 'error,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks'.split(',');
    // Overridden: buffered, currentTime, currentSrc

/**
 * @this {*}
 * @private
 */
var createSetter = function(attr){
  var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
  api['set'+attrUpper] = function(val){ return this.el_.vjs_setProperty(attr, val); };
};

/**
 * @this {*}
 * @private
 */
var createGetter = function(attr){
  api[attr] = function(){ return this.el_.vjs_getProperty(attr); };
};

(function(){
  var i;
  // Create getter and setters for all read/write attributes
  for (i = 0; i < readWrite.length; i++) {
    createGetter(readWrite[i]);
    createSetter(readWrite[i]);
  }

  // Create getters for read-only attributes
  for (i = 0; i < readOnly.length; i++) {
    createGetter(readOnly[i]);
  }
})();

/* Flash Support Testing -------------------------------------------------------- */

vjs.Flash.isSupported = function(){
  return vjs.Flash.version()[0] >= 10;
  // return swfobject.hasFlashPlayerVersion('10');
};

vjs.Flash.canPlaySource = function(srcObj){
  var type;

  if (!srcObj.type) {
    return '';
  }

  type = srcObj.type.replace(/;.*/,'').toLowerCase();
  if (type in vjs.Flash.formats || type in vjs.Flash.streamingFormats) {
    return 'maybe';
  }
};

vjs.Flash.formats = {
  'video/flv': 'FLV',
  'video/x-flv': 'FLV',
  'video/mp4': 'MP4',
  'video/m4v': 'MP4'
};

vjs.Flash.streamingFormats = {
  'rtmp/mp4': 'MP4',
  'rtmp/flv': 'FLV'
};

vjs.Flash['onReady'] = function(currSwf){
  var el = vjs.el(currSwf);

  // Get player from box
  // On firefox reloads, el might already have a player
  var player = el['player'] || el.parentNode['player'],
      tech = player.tech;

  // Reference player on tech element
  el['player'] = player;

  // Update reference to playback technology element
  tech.el_ = el;

  vjs.Flash.checkReady(tech);
};

// The SWF isn't alwasy ready when it says it is. Sometimes the API functions still need to be added to the object.
// If it's not ready, we set a timeout to check again shortly.
vjs.Flash.checkReady = function(tech){

  // Check if API property exists
  if (tech.el().vjs_getProperty) {

    // If so, tell tech it's ready
    tech.triggerReady();

  // Otherwise wait longer.
  } else {

    setTimeout(function(){
      vjs.Flash.checkReady(tech);
    }, 50);

  }
};

// Trigger events from the swf on the player
vjs.Flash['onEvent'] = function(swfID, eventName){
  var player = vjs.el(swfID)['player'];
  player.trigger(eventName);
};

// Log errors from the swf
vjs.Flash['onError'] = function(swfID, err){
  var player = vjs.el(swfID)['player'];
  var msg = 'FLASH: '+err;

  if (err == 'srcnotfound') {
    player.error({ code: 4, message: msg });

  // errors we haven't categorized into the media errors
  } else {
    player.error(msg);
  }
};

// Flash Version Check
vjs.Flash.version = function(){
  var version = '0,0,0';

  // IE
  try {
    version = new window.ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];

  // other browsers
  } catch(e) {
    try {
      if (navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin){
        version = (navigator.plugins['Shockwave Flash 2.0'] || navigator.plugins['Shockwave Flash']).description.replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
      }
    } catch(err) {}
  }
  return version.split(',');
};

// Flash embedding method. Only used in non-iframe mode
vjs.Flash.embed = function(swf, placeHolder, flashVars, params, attributes){
  var code = vjs.Flash.getEmbedCode(swf, flashVars, params, attributes),

      // Get element by embedding code and retrieving created element
      obj = vjs.createEl('div', { innerHTML: code }).childNodes[0],

      par = placeHolder.parentNode
  ;

  placeHolder.parentNode.replaceChild(obj, placeHolder);

  // IE6 seems to have an issue where it won't initialize the swf object after injecting it.
  // This is a dumb fix
  var newObj = par.childNodes[0];
  setTimeout(function(){
    newObj.style.display = 'block';
  }, 1000);

  return obj;

};

vjs.Flash.getEmbedCode = function(swf, flashVars, params, attributes){

  var objTag = '<object type="application/x-shockwave-flash"',
      flashVarsString = '',
      paramsString = '',
      attrsString = '';

  // Convert flash vars to string
  if (flashVars) {
    vjs.obj.each(flashVars, function(key, val){
      flashVarsString += (key + '=' + val + '&');
    });
  }

  // Add swf, flashVars, and other default params
  params = vjs.obj.merge({
    'movie': swf,
    'flashvars': flashVarsString,
    'allowScriptAccess': 'always', // Required to talk to swf
    'allowNetworking': 'all' // All should be default, but having security issues.
  }, params);

  // Create param tags string
  vjs.obj.each(params, function(key, val){
    paramsString += '<param name="'+key+'" value="'+val+'" />';
  });

  attributes = vjs.obj.merge({
    // Add swf to attributes (need both for IE and Others to work)
    'data': swf,

    // Default to 100% width/height
    'width': '100%',
    'height': '100%'

  }, attributes);

  // Create Attributes string
  vjs.obj.each(attributes, function(key, val){
    attrsString += (key + '="' + val + '" ');
  });

  return objTag + attrsString + '>' + paramsString + '</object>';
};

vjs.Flash.streamFromParts = function(connection, stream) {
  return connection + '&' + stream;
};

vjs.Flash.streamToParts = function(src) {
  var parts = {
    connection: '',
    stream: ''
  };

  if (! src) {
    return parts;
  }

  // Look for the normal URL separator we expect, '&'.
  // If found, we split the URL into two pieces around the
  // first '&'.
  var connEnd = src.indexOf('&');
  var streamBegin;
  if (connEnd !== -1) {
    streamBegin = connEnd + 1;
  }
  else {
    // If there's not a '&', we use the last '/' as the delimiter.
    connEnd = streamBegin = src.lastIndexOf('/') + 1;
    if (connEnd === 0) {
      // really, there's not a '/'?
      connEnd = streamBegin = src.length;
    }
  }
  parts.connection = src.substring(0, connEnd);
  parts.stream = src.substring(streamBegin, src.length);

  return parts;
};

vjs.Flash.isStreamingType = function(srcType) {
  return srcType in vjs.Flash.streamingFormats;
};

// RTMP has four variations, any string starting
// with one of these protocols should be valid
vjs.Flash.RTMP_RE = /^rtmp[set]?:\/\//i;

vjs.Flash.isStreamingSrc = function(src) {
  return vjs.Flash.RTMP_RE.test(src);
};


# vjs.VolumeControl

__EXTENDS__: [vjs.Component](vjs.Component.md)
__DEFINED IN__: [src/js/control-bar/volume-control.js#L8](https://github.com/videojs/video.js/blob/master/src/js/control-bar/volume-control.js#L8)

The component for controlling the volume level

---

## INDEX

- [METHODS](#methods)
  - [init](#init-player-options-)
  - [addChild](#addchild-child-options-) _`inherited`_
  - [addClass](#addclass-classtoadd-) _`inherited`_
  - [buildCSSClass](#buildcssclass) _`inherited`_
  - [children](#children) _`inherited`_
  - [contentEl](#contentel) _`inherited`_
  - [createEl](#createel-tagname-attributes-) _`inherited`_
  - [dimensions](#dimensions-width-height-) _`inherited`_
  - [dispose](#dispose) _`inherited`_
  - [el](#el) _`inherited`_
  - [enableTouchActivity](#enabletouchactivity) _`inherited`_
  - [getChild](#getchild-name-) _`inherited`_
  - [getChildById](#getchildbyid-id-) _`inherited`_
  - [height](#height-num-skiplisteners-) _`inherited`_
  - [hide](#hide) _`inherited`_
  - [id](#id) _`inherited`_
  - [initChildren](#initchildren) _`inherited`_
  - [name](#name) _`inherited`_
  - [off](#off-type-fn-) _`inherited`_
  - [on](#on-type-fn-) _`inherited`_
  - [one](#one-type-fn-) _`inherited`_
  - [options](#options-obj-) _`inherited`_
  - [player](#player) _`inherited`_
  - [ready](#ready-fn-) _`inherited`_
  - [removeChild](#removechild-component-) _`inherited`_
  - [removeClass](#removeclass-classtoremove-) _`inherited`_
  - [show](#show) _`inherited`_
  - [trigger](#trigger-type-event-) _`inherited`_
  - [triggerReady](#triggerready) _`inherited`_
  - [width](#width-num-skiplisteners-) _`inherited`_

- [EVENTS](#events)
  - [resize](#resize-event) _`inherited`_

---

## METHODS

### addChild( child, [options] )
> Adds a child component inside this component
>
>     myComponent.el();
>     // ->

>     myComonent.children();
>     // [empty array]
>
>     var myButton = myComponent.addChild('MyButton');
>     // ->

myButton

>     // -> myButton === myComonent.children()[0];
>
> Pass in options for child constructors and options for children of the child
>
>     var myButton = myComponent.addChild('MyButton', {
>       text: 'Press Me',
>       children: {
>         buttonChildExample: {
>           buttonChildOption: true
>         }
>       }
>     });

##### PARAMETERS:
* __child__ `String|vjs.Component` The class name or instance of a child to add
* __options__ `Object` _(OPTIONAL)_ Options, including options to be passed to children of the child.

##### RETURNS:
* `vjs.Component` The child component (created by this process if a string was used)

_inherited from_: [src/js/component.js#L347](https://github.com/videojs/video.js/blob/master/src/js/component.js#L347)

---

### addClass( classToAdd )
> Add a CSS class name to the component's element

##### PARAMETERS:
* __classToAdd__ `String` Classname to add

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L663](https://github.com/videojs/video.js/blob/master/src/js/component.js#L663)

---

### buildCSSClass()
> Allows sub components to stack CSS class names

##### RETURNS:
* `String` The constructed class name

_inherited from_: [src/js/component.js#L506](https://github.com/videojs/video.js/blob/master/src/js/component.js#L506)

---

### children()
> Get an array of all child components
>
>     var kids = myComponent.children();

##### RETURNS:
* `Array` The children

_inherited from_: [src/js/component.js#L281](https://github.com/videojs/video.js/blob/master/src/js/component.js#L281)

---

### contentEl()
> Return the component's DOM element for embedding content.
> Will either be el_ or a new element defined in createEl.

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L224](https://github.com/videojs/video.js/blob/master/src/js/component.js#L224)

---

### createEl( [tagName], [attributes] )
> Create the component's DOM element

##### PARAMETERS:
* __tagName__ `String` _(OPTIONAL)_ Element's node type. e.g. 'div'
* __attributes__ `Object` _(OPTIONAL)_ An object of element attributes that should be set on the element

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L194](https://github.com/videojs/video.js/blob/master/src/js/component.js#L194)

---

### dimensions( width, height )
> Set both width and height at the same time

##### PARAMETERS:
* __width__ `Number|String`
* __height__ `Number|String`

##### RETURNS:
* `vjs.Component` The component

_inherited from_: [src/js/component.js#L775](https://github.com/videojs/video.js/blob/master/src/js/component.js#L775)

---

### dispose()
> Dispose of the component and all child components

_inherited from_: [src/js/component.js#L78](https://github.com/videojs/video.js/blob/master/src/js/component.js#L78)

---

### el()
> Get the component's DOM element
>
>     var domEl = myComponent.el();

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L205](https://github.com/videojs/video.js/blob/master/src/js/component.js#L205)

---

### enableTouchActivity()
> Report user touch activity when touch events occur
>
> User activity is used to determine when controls should show/hide. It's
> relatively simple when it comes to mouse events, because any mouse event
> should show the controls. So we capture mouse events that bubble up to the
> player and report activity when that happens.
>
> With touch events it isn't as easy. We can't rely on touch events at the
> player level, because a tap (touchstart + touchend) on the video itself on
> mobile devices is meant to turn controls off (and on). User activity is
> checked asynchronously, so what could happen is a tap event on the video
> turns the controls off, then the touchend event bubbles up to the player,
> which if it reported user activity, would turn the controls right back on.
> (We also don't want to completely block touch events from bubbling up)
>
> Also a touchmove, touch+hold, and anything other than a tap is not supposed
> to turn the controls back on on a mobile device.
>
> Here we're setting the default component behavior to report user activity
> whenever touch events happen, and this can be turned off by components that
> want touch events to act differently.

_inherited from_: [src/js/component.js#L954](https://github.com/videojs/video.js/blob/master/src/js/component.js#L954)

---

### getChild( name )
> Returns a child component with the provided name

##### PARAMETERS:
* __name__

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L315](https://github.com/videojs/video.js/blob/master/src/js/component.js#L315)

---

### getChildById( id )
> Returns a child component with the provided ID

##### PARAMETERS:
* __id__

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L298](https://github.com/videojs/video.js/blob/master/src/js/component.js#L298)

---

### height( [num], [skipListeners] )
> Get or set the height of the component (CSS values)
>
> Setting the video tag dimension values only works with values in pixels.
> Percent values will not work.
> Some percents can be used, but width()/height() will return the number + %,
> not the actual computed width/height.

##### PARAMETERS:
* __num__ `Number|String` _(OPTIONAL)_ New component height
* __skipListeners__ `Boolean` _(OPTIONAL)_ Skip the resize event trigger

##### RETURNS:
* `vjs.Component` This component, when setting the height
* `Number|String` The height, when getting

_inherited from_: [src/js/component.js#L764](https://github.com/videojs/video.js/blob/master/src/js/component.js#L764)

---

### hide()
> Hide the component element if currently showing

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L694](https://github.com/videojs/video.js/blob/master/src/js/component.js#L694)

---

### id()
> Get the component's ID
>
>     var id = myComponent.id();

##### RETURNS:
* `String`

_inherited from_: [src/js/component.js#L243](https://github.com/videojs/video.js/blob/master/src/js/component.js#L243)

---

### init( player, options )

##### PARAMETERS:
* __player__
* __options__

_defined in_: [src/js/control-bar/volume-control.js#L10](https://github.com/videojs/video.js/blob/master/src/js/control-bar/volume-control.js#L10)

---

### initChildren()
> Add and initialize default child components from options
>
>     // when an instance of MyComponent is created, all children in options
>     // will be added to the instance by their name strings and options
>     MyComponent.prototype.options_.children = {
>       myChildComponent: {
>         myChildOption: true
>       }
>     }
>
>     // Or when creating the component
>     var myComp = new MyComponent(player, {
>       children: {
>         myChildComponent: {
>           myChildOption: true
>         }
>       }
>     });
>
> The children option can also be an Array of child names or
> child options objects (that also include a 'name' key).
>
>     var myComp = new MyComponent(player, {
>       children: [
>         'button',
>         {
>           name: 'button',
>           someOtherOption: true
>         }
>       ]
>     });

_inherited from_: [src/js/component.js#L466](https://github.com/videojs/video.js/blob/master/src/js/component.js#L466)

---

### name()
> Get the component's name. The name is often used to reference the component.
>
>     var name = myComponent.name();

##### RETURNS:
* `String`

_inherited from_: [src/js/component.js#L262](https://github.com/videojs/video.js/blob/master/src/js/component.js#L262)

---

### off( [type], [fn] )
> Remove an event listener from the component's element
>
>     myComponent.off("eventName", myFunc);

##### PARAMETERS:
* __type__ `String` _(OPTIONAL)_ Event type. Without type it will remove all listeners.
* __fn__ `Function` _(OPTIONAL)_ Event listener. Without fn it will remove all listeners for a type.

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L545](https://github.com/videojs/video.js/blob/master/src/js/component.js#L545)

---

### on( type, fn )
> Add an event listener to this component's element
>
>     var myFunc = function(){
>       var myPlayer = this;
>       // Do something when the event is fired
>     };
>
>     myPlayer.on("eventName", myFunc);
>
> The context will be the component.

##### PARAMETERS:
* __type__ `String` The event type e.g. 'click'
* __fn__ `Function` The event listener

##### RETURNS:
* `vjs.Component` self

_inherited from_: [src/js/component.js#L531](https://github.com/videojs/video.js/blob/master/src/js/component.js#L531)

---

### one( type, fn )
> Add an event listener to be triggered only once and then removed

##### PARAMETERS:
* __type__ `String` Event type
* __fn__ `Function` Event listener

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L557](https://github.com/videojs/video.js/blob/master/src/js/component.js#L557)

---

### options( obj )
> Deep merge of options objects
>
> Whenever a property is an object on both options objects
> the two properties will be merged using vjs.obj.deepMerge.
>
> This is used for merging options for child components. We
> want it to be easy to override individual options on a child
> component without having to rewrite all the other default options.
>
>     Parent.prototype.options_ = {
>       children: {
>         'childOne': { 'foo': 'bar', 'asdf': 'fdsa' },
>         'childTwo': {},
>         'childThree': {}
>       }
>     }
>     newOptions = {
>       children: {
>         'childOne': { 'foo': 'baz', 'abc': '123' }
>         'childTwo': null,
>         'childFour': {}
>       }
>     }
>
>     this.options(newOptions);
>
> RESULT
>
>     {
>       children: {
>         'childOne': { 'foo': 'baz', 'asdf': 'fdsa', 'abc': '123' },
>         'childTwo': null, // Disabled. Won't be initialized.
>         'childThree': {},
>         'childFour': {}
>       }
>     }

##### PARAMETERS:
* __obj__ `Object` Object of new option values

##### RETURNS:
* `Object` A NEW object of this.options_ and obj merged

_inherited from_: [src/js/component.js#L173](https://github.com/videojs/video.js/blob/master/src/js/component.js#L173)

---

### player()
> Return the component's player

##### RETURNS:
* `vjs.Player`

_inherited from_: [src/js/component.js#L120](https://github.com/videojs/video.js/blob/master/src/js/component.js#L120)

---

### ready( fn )
> Bind a listener to the component's ready state
>
> Different from event listeners in that if the ready event has already happend
> it will trigger the function immediately.

##### PARAMETERS:
* __fn__ `Function` Ready listener

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L616](https://github.com/videojs/video.js/blob/master/src/js/component.js#L616)

---

### removeChild( component )
> Remove a child component from this component's list of children, and the
> child component's element from this component's element

##### PARAMETERS:
* __component__ `vjs.Component` Component to remove

_inherited from_: [src/js/component.js#L405](https://github.com/videojs/video.js/blob/master/src/js/component.js#L405)

---

### removeClass( classToRemove )
> Remove a CSS class name from the component's element

##### PARAMETERS:
* __classToRemove__ `String` Classname to remove

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L674](https://github.com/videojs/video.js/blob/master/src/js/component.js#L674)

---

### show()
> Show the component element if hidden

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L684](https://github.com/videojs/video.js/blob/master/src/js/component.js#L684)

---

### trigger( type, event )
> Trigger an event on an element
>
>     myComponent.trigger('eventName');

##### PARAMETERS:
* __type__ `String` The event type to trigger, e.g. 'click'
* __event__ `Event|Object` The event object to be passed to the listener

##### RETURNS:
* `vjs.Component` self

_inherited from_: [src/js/component.js#L571](https://github.com/videojs/video.js/blob/master/src/js/component.js#L571)

---

### triggerReady()
> Trigger the ready listeners

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L635](https://github.com/videojs/video.js/blob/master/src/js/component.js#L635)

---

### width( [num], skipListeners )
> Set or get the width of the component (CSS values)
>
> Setting the video tag dimension values only works with values in pixels.
> Percent values will not work.
> Some percents can be used, but width()/height() will return the number + %,
> not the actual computed width/height.

##### PARAMETERS:
* __num__ `Number|String` _(OPTIONAL)_ Optional width number
* __skipListeners__ `Boolean` Skip the 'resize' event trigger

##### RETURNS:
* `vjs.Component` This component, when setting the width
* `Number|String` The width, when getting

_inherited from_: [src/js/component.js#L747](https://github.com/videojs/video.js/blob/master/src/js/component.js#L747)

---

## EVENTS

### resize `EVENT`
> Fired when the width and/or height of the component changes

_inherited from_: [src/js/component.js#L854](https://github.com/videojs/video.js/blob/master/src/js/component.js#L854)

---


# vjs.TimeDivider

__EXTENDS__: [vjs.Component](vjs.Component.md)
__DEFINED IN__: [src/js/control-bar/time-display.js#L88](https://github.com/videojs/video.js/blob/master/src/js/control-bar/time-display.js#L88)

The separator between the current time and duration

Can be hidden if it's not needed in the design.

---

## INDEX

- [METHODS](#methods)
  - [init](#init-player-options-)
  - [addChild](#addchild-child-options-) _`inherited`_
  - [addClass](#addclass-classtoadd-) _`inherited`_
  - [buildCSSClass](#buildcssclass) _`inherited`_
  - [children](#children) _`inherited`_
  - [contentEl](#contentel) _`inherited`_
  - [createEl](#createel-tagname-attributes-) _`inherited`_
  - [dimensions](#dimensions-width-height-) _`inherited`_
  - [dispose](#dispose) _`inherited`_
  - [el](#el) _`inherited`_
  - [enableTouchActivity](#enabletouchactivity) _`inherited`_
  - [getChild](#getchild-name-) _`inherited`_
  - [getChildById](#getchildbyid-id-) _`inherited`_
  - [height](#height-num-skiplisteners-) _`inherited`_
  - [hide](#hide) _`inherited`_
  - [id](#id) _`inherited`_
  - [initChildren](#initchildren) _`inherited`_
  - [name](#name) _`inherited`_
  - [off](#off-type-fn-) _`inherited`_
  - [on](#on-type-fn-) _`inherited`_
  - [one](#one-type-fn-) _`inherited`_
  - [options](#options-obj-) _`inherited`_
  - [player](#player) _`inherited`_
  - [ready](#ready-fn-) _`inherited`_
  - [removeChild](#removechild-component-) _`inherited`_
  - [removeClass](#removeclass-classtoremove-) _`inherited`_
  - [show](#show) _`inherited`_
  - [trigger](#trigger-type-event-) _`inherited`_
  - [triggerReady](#triggerready) _`inherited`_
  - [width](#width-num-skiplisteners-) _`inherited`_

- [EVENTS](#events)
  - [resize](#resize-event) _`inherited`_

---

## METHODS

### addChild( child, [options] )
> Adds a child component inside this component
>
>     myComponent.el();
>     // ->

>     myComonent.children();
>     // [empty array]
>
>     var myButton = myComponent.addChild('MyButton');
>     // ->

myButton

>     // -> myButton === myComonent.children()[0];
>
> Pass in options for child constructors and options for children of the child
>
>     var myButton = myComponent.addChild('MyButton', {
>       text: 'Press Me',
>       children: {
>         buttonChildExample: {
>           buttonChildOption: true
>         }
>       }
>     });

##### PARAMETERS:
* __child__ `String|vjs.Component` The class name or instance of a child to add
* __options__ `Object` _(OPTIONAL)_ Options, including options to be passed to children of the child.

##### RETURNS:
* `vjs.Component` The child component (created by this process if a string was used)

_inherited from_: [src/js/component.js#L347](https://github.com/videojs/video.js/blob/master/src/js/component.js#L347)

---

### addClass( classToAdd )
> Add a CSS class name to the component's element

##### PARAMETERS:
* __classToAdd__ `String` Classname to add

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L663](https://github.com/videojs/video.js/blob/master/src/js/component.js#L663)

---

### buildCSSClass()
> Allows sub components to stack CSS class names

##### RETURNS:
* `String` The constructed class name

_inherited from_: [src/js/component.js#L506](https://github.com/videojs/video.js/blob/master/src/js/component.js#L506)

---

### children()
> Get an array of all child components
>
>     var kids = myComponent.children();

##### RETURNS:
* `Array` The children

_inherited from_: [src/js/component.js#L281](https://github.com/videojs/video.js/blob/master/src/js/component.js#L281)

---

### contentEl()
> Return the component's DOM element for embedding content.
> Will either be el_ or a new element defined in createEl.

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L224](https://github.com/videojs/video.js/blob/master/src/js/component.js#L224)

---

### createEl( [tagName], [attributes] )
> Create the component's DOM element

##### PARAMETERS:
* __tagName__ `String` _(OPTIONAL)_ Element's node type. e.g. 'div'
* __attributes__ `Object` _(OPTIONAL)_ An object of element attributes that should be set on the element

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L194](https://github.com/videojs/video.js/blob/master/src/js/component.js#L194)

---

### dimensions( width, height )
> Set both width and height at the same time

##### PARAMETERS:
* __width__ `Number|String`
* __height__ `Number|String`

##### RETURNS:
* `vjs.Component` The component

_inherited from_: [src/js/component.js#L775](https://github.com/videojs/video.js/blob/master/src/js/component.js#L775)

---

### dispose()
> Dispose of the component and all child components

_inherited from_: [src/js/component.js#L78](https://github.com/videojs/video.js/blob/master/src/js/component.js#L78)

---

### el()
> Get the component's DOM element
>
>     var domEl = myComponent.el();

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L205](https://github.com/videojs/video.js/blob/master/src/js/component.js#L205)

---

### enableTouchActivity()
> Report user touch activity when touch events occur
>
> User activity is used to determine when controls should show/hide. It's
> relatively simple when it comes to mouse events, because any mouse event
> should show the controls. So we capture mouse events that bubble up to the
> player and report activity when that happens.
>
> With touch events it isn't as easy. We can't rely on touch events at the
> player level, because a tap (touchstart + touchend) on the video itself on
> mobile devices is meant to turn controls off (and on). User activity is
> checked asynchronously, so what could happen is a tap event on the video
> turns the controls off, then the touchend event bubbles up to the player,
> which if it reported user activity, would turn the controls right back on.
> (We also don't want to completely block touch events from bubbling up)
>
> Also a touchmove, touch+hold, and anything other than a tap is not supposed
> to turn the controls back on on a mobile device.
>
> Here we're setting the default component behavior to report user activity
> whenever touch events happen, and this can be turned off by components that
> want touch events to act differently.

_inherited from_: [src/js/component.js#L954](https://github.com/videojs/video.js/blob/master/src/js/component.js#L954)

---

### getChild( name )
> Returns a child component with the provided name

##### PARAMETERS:
* __name__

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L315](https://github.com/videojs/video.js/blob/master/src/js/component.js#L315)

---

### getChildById( id )
> Returns a child component with the provided ID

##### PARAMETERS:
* __id__

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L298](https://github.com/videojs/video.js/blob/master/src/js/component.js#L298)

---

### height( [num], [skipListeners] )
> Get or set the height of the component (CSS values)
>
> Setting the video tag dimension values only works with values in pixels.
> Percent values will not work.
> Some percents can be used, but width()/height() will return the number + %,
> not the actual computed width/height.

##### PARAMETERS:
* __num__ `Number|String` _(OPTIONAL)_ New component height
* __skipListeners__ `Boolean` _(OPTIONAL)_ Skip the resize event trigger

##### RETURNS:
* `vjs.Component` This component, when setting the height
* `Number|String` The height, when getting

_inherited from_: [src/js/component.js#L764](https://github.com/videojs/video.js/blob/master/src/js/component.js#L764)

---

### hide()
> Hide the component element if currently showing

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L694](https://github.com/videojs/video.js/blob/master/src/js/component.js#L694)

---

### id()
> Get the component's ID
>
>     var id = myComponent.id();

##### RETURNS:
* `String`

_inherited from_: [src/js/component.js#L243](https://github.com/videojs/video.js/blob/master/src/js/component.js#L243)

---

### init( player, options )

##### PARAMETERS:
* __player__
* __options__

_defined in_: [src/js/control-bar/time-display.js#L90](https://github.com/videojs/video.js/blob/master/src/js/control-bar/time-display.js#L90)

---

### initChildren()
> Add and initialize default child components from options
>
>     // when an instance of MyComponent is created, all children in options
>     // will be added to the instance by their name strings and options
>     MyComponent.prototype.options_.children = {
>       myChildComponent: {
>         myChildOption: true
>       }
>     }
>
>     // Or when creating the component
>     var myComp = new MyComponent(player, {
>       children: {
>         myChildComponent: {
>           myChildOption: true
>         }
>       }
>     });
>
> The children option can also be an Array of child names or
> child options objects (that also include a 'name' key).
>
>     var myComp = new MyComponent(player, {
>       children: [
>         'button',
>         {
>           name: 'button',
>           someOtherOption: true
>         }
>       ]
>     });

_inherited from_: [src/js/component.js#L466](https://github.com/videojs/video.js/blob/master/src/js/component.js#L466)

---

### name()
> Get the component's name. The name is often used to reference the component.
>
>     var name = myComponent.name();

##### RETURNS:
* `String`

_inherited from_: [src/js/component.js#L262](https://github.com/videojs/video.js/blob/master/src/js/component.js#L262)

---

### off( [type], [fn] )
> Remove an event listener from the component's element
>
>     myComponent.off("eventName", myFunc);

##### PARAMETERS:
* __type__ `String` _(OPTIONAL)_ Event type. Without type it will remove all listeners.
* __fn__ `Function` _(OPTIONAL)_ Event listener. Without fn it will remove all listeners for a type.

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L545](https://github.com/videojs/video.js/blob/master/src/js/component.js#L545)

---

### on( type, fn )
> Add an event listener to this component's element
>
>     var myFunc = function(){
>       var myPlayer = this;
>       // Do something when the event is fired
>     };
>
>     myPlayer.on("eventName", myFunc);
>
> The context will be the component.

##### PARAMETERS:
* __type__ `String` The event type e.g. 'click'
* __fn__ `Function` The event listener

##### RETURNS:
* `vjs.Component` self

_inherited from_: [src/js/component.js#L531](https://github.com/videojs/video.js/blob/master/src/js/component.js#L531)

---

### one( type, fn )
> Add an event listener to be triggered only once and then removed

##### PARAMETERS:
* __type__ `String` Event type
* __fn__ `Function` Event listener

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L557](https://github.com/videojs/video.js/blob/master/src/js/component.js#L557)

---

### options( obj )
> Deep merge of options objects
>
> Whenever a property is an object on both options objects
> the two properties will be merged using vjs.obj.deepMerge.
>
> This is used for merging options for child components. We
> want it to be easy to override individual options on a child
> component without having to rewrite all the other default options.
>
>     Parent.prototype.options_ = {
>       children: {
>         'childOne': { 'foo': 'bar', 'asdf': 'fdsa' },
>         'childTwo': {},
>         'childThree': {}
>       }
>     }
>     newOptions = {
>       children: {
>         'childOne': { 'foo': 'baz', 'abc': '123' }
>         'childTwo': null,
>         'childFour': {}
>       }
>     }
>
>     this.options(newOptions);
>
> RESULT
>
>     {
>       children: {
>         'childOne': { 'foo': 'baz', 'asdf': 'fdsa', 'abc': '123' },
>         'childTwo': null, // Disabled. Won't be initialized.
>         'childThree': {},
>         'childFour': {}
>       }
>     }

##### PARAMETERS:
* __obj__ `Object` Object of new option values

##### RETURNS:
* `Object` A NEW object of this.options_ and obj merged

_inherited from_: [src/js/component.js#L173](https://github.com/videojs/video.js/blob/master/src/js/component.js#L173)

---

### player()
> Return the component's player

##### RETURNS:
* `vjs.Player`

_inherited from_: [src/js/component.js#L120](https://github.com/videojs/video.js/blob/master/src/js/component.js#L120)

---

### ready( fn )
> Bind a listener to the component's ready state
>
> Different from event listeners in that if the ready event has already happend
> it will trigger the function immediately.

##### PARAMETERS:
* __fn__ `Function` Ready listener

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L616](https://github.com/videojs/video.js/blob/master/src/js/component.js#L616)

---

### removeChild( component )
> Remove a child component from this component's list of children, and the
> child component's element from this component's element

##### PARAMETERS:
* __component__ `vjs.Component` Component to remove

_inherited from_: [src/js/component.js#L405](https://github.com/videojs/video.js/blob/master/src/js/component.js#L405)

---

### removeClass( classToRemove )
> Remove a CSS class name from the component's element

##### PARAMETERS:
* __classToRemove__ `String` Classname to remove

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L674](https://github.com/videojs/video.js/blob/master/src/js/component.js#L674)

---

### show()
> Show the component element if hidden

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L684](https://github.com/videojs/video.js/blob/master/src/js/component.js#L684)

---

### trigger( type, event )
> Trigger an event on an element
>
>     myComponent.trigger('eventName');

##### PARAMETERS:
* __type__ `String` The event type to trigger, e.g. 'click'
* __event__ `Event|Object` The event object to be passed to the listener

##### RETURNS:
* `vjs.Component` self

_inherited from_: [src/js/component.js#L571](https://github.com/videojs/video.js/blob/master/src/js/component.js#L571)

---

### triggerReady()
> Trigger the ready listeners

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L635](https://github.com/videojs/video.js/blob/master/src/js/component.js#L635)

---

### width( [num], skipListeners )
> Set or get the width of the component (CSS values)
>
> Setting the video tag dimension values only works with values in pixels.
> Percent values will not work.
> Some percents can be used, but width()/height() will return the number + %,
> not the actual computed width/height.

##### PARAMETERS:
* __num__ `Number|String` _(OPTIONAL)_ Optional width number
* __skipListeners__ `Boolean` Skip the 'resize' event trigger

##### RETURNS:
* `vjs.Component` This component, when setting the width
* `Number|String` The width, when getting

_inherited from_: [src/js/component.js#L747](https://github.com/videojs/video.js/blob/master/src/js/component.js#L747)

---

## EVENTS

### resize `EVENT`
> Fired when the width and/or height of the component changes

_inherited from_: [src/js/component.js#L854](https://github.com/videojs/video.js/blob/master/src/js/component.js#L854)

---


/**
 * @fileoverview Media Technology Controller - Base class for media playback
 * technology controllers like Flash and HTML5
 */

/**
 * Base class for media (HTML5 Video, Flash) controllers
 * @param {vjs.Player|Object} player  Central player instance
 * @param {Object=} options Options object
 * @constructor
 */
vjs.MediaTechController = vjs.Component.extend({
  /** @constructor */
  init: function(player, options, ready){
    options = options || {};
    // we don't want the tech to report user activity automatically.
    // This is done manually in addControlsListeners
    options.reportTouchActivity = false;
    vjs.Component.call(this, player, options, ready);

    this.initControlsListeners();
  }
});

/**
 * Set up click and touch listeners for the playback element
 * On desktops, a click on the video itself will toggle playback,
 * on a mobile device a click on the video toggles controls.
 * (toggling controls is done by toggling the user state between active and
 * inactive)
 *
 * A tap can signal that a user has become active, or has become inactive
 * e.g. a quick tap on an iPhone movie should reveal the controls. Another
 * quick tap should hide them again (signaling the user is in an inactive
 * viewing state)
 *
 * In addition to this, we still want the user to be considered inactive after
 * a few seconds of inactivity.
 *
 * Note: the only part of iOS interaction we can't mimic with this setup
 * is a touch and hold on the video element counting as activity in order to
 * keep the controls showing, but that shouldn't be an issue. A touch and hold on
 * any controls will still keep the user active
 */
vjs.MediaTechController.prototype.initControlsListeners = function(){
  var player, tech, activateControls, deactivateControls;

  tech = this;
  player = this.player();

  var activateControls = function(){
    if (player.controls() && !player.usingNativeControls()) {
      tech.addControlsListeners();
    }
  };

  deactivateControls = vjs.bind(tech, tech.removeControlsListeners);

  // Set up event listeners once the tech is ready and has an element to apply
  // listeners to
  this.ready(activateControls);
  player.on('controlsenabled', activateControls);
  player.on('controlsdisabled', deactivateControls);

  // if we're loading the playback object after it has started loading or playing the
  // video (often with autoplay on) then the loadstart event has already fired and we
  // need to fire it manually because many things rely on it.
  // Long term we might consider how we would do this for other events like 'canplay'
  // that may also have fired.
  this.ready(function(){
    if (this.networkState && this.networkState() > 0) {
      this.player().trigger('loadstart');
    }
  });
};

vjs.MediaTechController.prototype.addControlsListeners = function(){
  var userWasActive;

  // Some browsers (Chrome & IE) don't trigger a click on a flash swf, but do
  // trigger mousedown/up.
  // http://stackoverflow.com/questions/1444562/javascript-onclick-event-over-flash-object
  // Any touch events are set to block the mousedown event from happening
  this.on('mousedown', this.onClick);

  // If the controls were hidden we don't want that to change without a tap event
  // so we'll check if the controls were already showing before reporting user
  // activity
  this.on('touchstart', function(event) {
    // Stop the mouse events from also happening
    event.preventDefault();
    userWasActive = this.player_.userActive();
  });

  this.on('touchmove', function(event) {
    if (userWasActive){
      this.player().reportUserActivity();
    }
  });

  // Turn on component tap events
  this.emitTapEvents();

  // The tap listener needs to come after the touchend listener because the tap
  // listener cancels out any reportedUserActivity when setting userActive(false)
  this.on('tap', this.onTap);
};

/**
 * Remove the listeners used for click and tap controls. This is needed for
 * toggling to controls disabled, where a tap/touch should do nothing.
 */
vjs.MediaTechController.prototype.removeControlsListeners = function(){
  // We don't want to just use `this.off()` because there might be other needed
  // listeners added by techs that extend this.
  this.off('tap');
  this.off('touchstart');
  this.off('touchmove');
  this.off('touchleave');
  this.off('touchcancel');
  this.off('touchend');
  this.off('click');
  this.off('mousedown');
};

/**
 * Handle a click on the media element. By default will play/pause the media.
 */
vjs.MediaTechController.prototype.onClick = function(event){
  // We're using mousedown to detect clicks thanks to Flash, but mousedown
  // will also be triggered with right-clicks, so we need to prevent that
  if (event.button !== 0) return;

  // When controls are disabled a click should not toggle playback because
  // the click is considered a control
  if (this.player().controls()) {
    if (this.player().paused()) {
      this.player().play();
    } else {
      this.player().pause();
    }
  }
};

/**
 * Handle a tap on the media element. By default it will toggle the user
 * activity state, which hides and shows the controls.
 */
vjs.MediaTechController.prototype.onTap = function(){
  this.player().userActive(!this.player().userActive());
};

/**
 * Provide a default setPoster method for techs
 *
 * Poster support for techs should be optional, so we don't want techs to
 * break if they don't have a way to set a poster.
 */
vjs.MediaTechController.prototype.setPoster = function(){};

vjs.MediaTechController.prototype.features = {
  'volumeControl': true,

  // Resizing plugins using request fullscreen reloads the plugin
  'fullscreenResize': false,
  'playbackRate': false,

  // Optional events that we can manually mimic with timers
  // currently not triggered by video-js-swf
  'progressEvents': false,
  'timeupdateEvents': false
};

vjs.media = {};


keep keep keep keep keep replace keep keep keep

module('Flash');

var streamToPartsAndBack = function(url) {
  var parts = vjs.Flash.streamToParts(url);
  return vjs.Flash.streamFromParts(parts.connection, parts.stream);
};

test('test using both streamToParts and streamFromParts', function() {
  ok('rtmp://myurl.com/&isthis' === streamToPartsAndBack('rtmp://myurl.com/isthis'));
  ok('rtmp://myurl.com/&isthis' === streamToPartsAndBack('rtmp://myurl.com/&isthis'));
  ok('rtmp://myurl.com/isthis/&andthis' === streamToPartsAndBack('rtmp://myurl.com/isthis/andthis'));
});

test('test streamToParts', function() {
  var parts = vjs.Flash.streamToParts('http://myurl.com/streaming&/is/fun');
  ok(parts.connection === 'http://myurl.com/streaming');
  ok(parts.stream === '/is/fun');

  parts = vjs.Flash.streamToParts('http://myurl.com/&streaming&/is/fun');
  ok(parts.connection === 'http://myurl.com/');
  ok(parts.stream === 'streaming&/is/fun');

  parts = vjs.Flash.streamToParts('http://myurl.com/streaming/is/fun');
  ok(parts.connection === 'http://myurl.com/streaming/is/');
  ok(parts.stream === 'fun');

  parts = vjs.Flash.streamToParts('whatisgoingonhere');
  ok(parts.connection === 'whatisgoingonhere');
  ok(parts.stream === '');

  parts = vjs.Flash.streamToParts();
  ok(parts.connection === '');
  ok(parts.stream === '');
});

test('test isStreamingSrc', function() {
  var isStreamingSrc = vjs.Flash.isStreamingSrc;
  ok(isStreamingSrc('rtmp://streaming.is/fun'));
  ok(isStreamingSrc('rtmps://streaming.is/fun'));
  ok(isStreamingSrc('rtmpe://streaming.is/fun'));
  ok(isStreamingSrc('rtmpt://streaming.is/fun'));
  // test invalid protocols
  ok(!isStreamingSrc('rtmp:streaming.is/fun'));
  ok(!isStreamingSrc('rtmpz://streaming.is/fun'));
  ok(!isStreamingSrc('http://streaming.is/fun'));
  ok(!isStreamingSrc('https://streaming.is/fun'));
  ok(!isStreamingSrc('file://streaming.is/fun'));
});

test('test canPlaySource', function() {
  var canPlaySource = vjs.Flash.canPlaySource;

  // supported
  ok(canPlaySource({ type: 'video/mp4; codecs=avc1.42E01E,mp4a.40.2' }), 'codecs supported');
  ok(canPlaySource({ type: 'video/mp4' }), 'video/mp4 supported');
  ok(canPlaySource({ type: 'video/x-flv' }), 'video/x-flv supported');
  ok(canPlaySource({ type: 'video/flv' }), 'video/flv supported');
  ok(canPlaySource({ type: 'video/m4v' }), 'video/m4v supported');
  ok(canPlaySource({ type: 'VIDEO/FLV' }), 'capitalized mime type');

  // not supported
  ok(!canPlaySource({ type: 'video/webm; codecs="vp8, vorbis"' }));
  ok(!canPlaySource({ type: 'video/webm' }));
});

test('currentTime is the seek target during seeking', function() {
  var noop = function() {},
      seeking = false,
      parentEl = document.createElement('div'),
      tech = new vjs.Flash({
        id: noop,
        on: noop,
        options_: {}
      }, {
        'parentEl': parentEl
      }),
      currentTime;

  tech.el().vjs_setProperty = function(property, value) {
    if (property === 'currentTime') {
      currentTime = value;
    }
  };
  tech.el().vjs_getProperty = function(name) {
    if (name === 'currentTime') {
      return currentTime;
    } else if (name === 'seeking') {
      return seeking;
    }
  };

  currentTime = 3;
  strictEqual(3, tech.currentTime(), 'currentTime is retreived from the SWF');

  tech['setCurrentTime'](7);
  seeking = true;
  strictEqual(7, tech.currentTime(), 'during seeks the target time is returned');
});


// This file is used to load the video.js source files into a page
// in the correct order based on dependencies.
// When you create a new source file you will need to add
// it to the list below to use it in sandbox/index.html and
// test/index.html

// You can use the projectRoot variable to adjust relative urls
// that this script loads. By default it's "../", which is what /sandbox
// and /test need. If you had sandbox/newDir/index.html, in index.html you
// would set projectRoot = "../../"

// We could use somehting like requireJS to load files, and at one point
// we used goog.require/provide to load dependencies, but that seems like
// overkill with the small number of files we actually have.

// ADD NEW SOURCE FILES HERE
var sourceFiles = [
  "src/js/core.js",
  "src/js/core-object.js",
  "src/js/events.js",
  "src/js/lib.js",
  "src/js/util.js",
  "src/js/component.js",
  "src/js/button.js",
  "src/js/slider.js",
  "src/js/menu.js",
  "src/js/media-error.js",
  "src/js/fullscreen-api.js",
  "src/js/player.js",
  "src/js/control-bar/control-bar.js",
  "src/js/control-bar/live-display.js",
  "src/js/control-bar/play-toggle.js",
  "src/js/control-bar/time-display.js",
  "src/js/control-bar/fullscreen-toggle.js",
  "src/js/control-bar/progress-control.js",
  "src/js/control-bar/volume-control.js",
  "src/js/control-bar/mute-toggle.js",
  "src/js/control-bar/volume-menu-button.js",
  "src/js/control-bar/playback-rate-menu-button.js",
  "src/js/poster.js",
  "src/js/loading-spinner.js",
  "src/js/big-play-button.js",
  "src/js/error-display.js",
  "src/js/media/media.js",
  "src/js/media/html5.js",
  "src/js/media/flash.js",
  "src/js/media/loader.js",
  "src/js/tracks.js",
  "src/js/json.js",
  "src/js/setup.js",
  "src/js/plugins.js"
];

// Allow overriding the default project root
var projectRoot = projectRoot || '../';

function loadScripts(scriptsArr){
  for (var i = 0; i < scriptsArr.length; i++) {
    // Using document.write because that's the easiest way to avoid triggering
    // asynchrnous script loading
    document.write( "<script src='" + projectRoot + scriptsArr[i] + "'><\/script>" );
  }
}

// We use this file in the grunt build script to load the same source file list
// and don't want to load the scripts there.
if (typeof blockSourceLoading === 'undefined') {
  loadScripts(sourceFiles);

  // Allow for making Flash first
  if (window.location.href.indexOf("?flash") !== -1) {
    // Using doc.write to load this script to, otherwise when it runs videojs
    // is undefined
    document.write('<script>videojs.options.techOrder = ["flash"];videojs.options.flash.swf = "../src/swf/video-js.swf";</script>')
  }
}


<!DOCTYPE html>

  <title>Video.js | HTML5 Video Player</title>

  <link href="video-js.css" rel="stylesheet" type="text/css">

  <video id="example_video_1" class="video-js vjs-default-skin" controls preload="none" width="640" height="264"
      poster="http://video-js.zencoder.com/oceans-clip.png"
      data-setup="{}">
    <source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
    <source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm' />
    <source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg' />
    <track kind="captions" src="demo.captions.vtt" srclang="en" label="English"></track>
    <track kind="subtitles" src="demo.captions.vtt" srclang="en" label="English"></track>

To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video

  </video>


# vjs.PosterImage

__EXTENDS__: [vjs.Button](vjs.Button.md)
__DEFINED IN__: [src/js/poster.js#L10](https://github.com/videojs/video.js/blob/master/src/js/poster.js#L10)

The component that handles showing the poster image.

---

## INDEX

- [METHODS](#methods)
  - [init](#init-player-options-)
  - [addChild](#addchild-child-options-) _`inherited`_
  - [addClass](#addclass-classtoadd-) _`inherited`_
  - [buildCSSClass](#buildcssclass) _`inherited`_
  - [children](#children) _`inherited`_
  - [contentEl](#contentel) _`inherited`_
  - [createEl](#createel-tagname-attributes-) _`inherited`_
  - [dimensions](#dimensions-width-height-) _`inherited`_
  - [dispose](#dispose) _`inherited`_
  - [el](#el) _`inherited`_
  - [enableTouchActivity](#enabletouchactivity) _`inherited`_
  - [getChild](#getchild-name-) _`inherited`_
  - [getChildById](#getchildbyid-id-) _`inherited`_
  - [height](#height-num-skiplisteners-) _`inherited`_
  - [hide](#hide) _`inherited`_
  - [id](#id) _`inherited`_
  - [initChildren](#initchildren) _`inherited`_
  - [name](#name) _`inherited`_
  - [off](#off-type-fn-) _`inherited`_
  - [on](#on-type-fn-) _`inherited`_
  - [one](#one-type-fn-) _`inherited`_
  - [options](#options-obj-) _`inherited`_
  - [player](#player) _`inherited`_
  - [ready](#ready-fn-) _`inherited`_
  - [removeChild](#removechild-component-) _`inherited`_
  - [removeClass](#removeclass-classtoremove-) _`inherited`_
  - [show](#show) _`inherited`_
  - [trigger](#trigger-type-event-) _`inherited`_
  - [triggerReady](#triggerready) _`inherited`_
  - [width](#width-num-skiplisteners-) _`inherited`_

- [EVENTS](#events)
  - [resize](#resize-event) _`inherited`_

---

## METHODS

### addChild( child, [options] )
> Adds a child component inside this component
>
>     myComponent.el();
>     // ->

>     myComonent.children();
>     // [empty array]
>
>     var myButton = myComponent.addChild('MyButton');
>     // ->

myButton

>     // -> myButton === myComonent.children()[0];
>
> Pass in options for child constructors and options for children of the child
>
>     var myButton = myComponent.addChild('MyButton', {
>       text: 'Press Me',
>       children: {
>         buttonChildExample: {
>           buttonChildOption: true
>         }
>       }
>     });

##### PARAMETERS:
* __child__ `String|vjs.Component` The class name or instance of a child to add
* __options__ `Object` _(OPTIONAL)_ Options, including options to be passed to children of the child.

##### RETURNS:
* `vjs.Component` The child component (created by this process if a string was used)

_inherited from_: [src/js/component.js#L347](https://github.com/videojs/video.js/blob/master/src/js/component.js#L347)

---

### addClass( classToAdd )
> Add a CSS class name to the component's element

##### PARAMETERS:
* __classToAdd__ `String` Classname to add

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L663](https://github.com/videojs/video.js/blob/master/src/js/component.js#L663)

---

### buildCSSClass()
> Allows sub components to stack CSS class names

##### RETURNS:
* `String` The constructed class name

_inherited from_: [src/js/component.js#L506](https://github.com/videojs/video.js/blob/master/src/js/component.js#L506)

---

### children()
> Get an array of all child components
>
>     var kids = myComponent.children();

##### RETURNS:
* `Array` The children

_inherited from_: [src/js/component.js#L281](https://github.com/videojs/video.js/blob/master/src/js/component.js#L281)

---

### contentEl()
> Return the component's DOM element for embedding content.
> Will either be el_ or a new element defined in createEl.

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L224](https://github.com/videojs/video.js/blob/master/src/js/component.js#L224)

---

### createEl( [tagName], [attributes] )
> Create the component's DOM element

##### PARAMETERS:
* __tagName__ `String` _(OPTIONAL)_ Element's node type. e.g. 'div'
* __attributes__ `Object` _(OPTIONAL)_ An object of element attributes that should be set on the element

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L194](https://github.com/videojs/video.js/blob/master/src/js/component.js#L194)

---

### dimensions( width, height )
> Set both width and height at the same time

##### PARAMETERS:
* __width__ `Number|String`
* __height__ `Number|String`

##### RETURNS:
* `vjs.Component` The component

_inherited from_: [src/js/component.js#L775](https://github.com/videojs/video.js/blob/master/src/js/component.js#L775)

---

### dispose()
> Dispose of the component and all child components

_inherited from_: [src/js/component.js#L78](https://github.com/videojs/video.js/blob/master/src/js/component.js#L78)

---

### el()
> Get the component's DOM element
>
>     var domEl = myComponent.el();

##### RETURNS:
* `Element`

_inherited from_: [src/js/component.js#L205](https://github.com/videojs/video.js/blob/master/src/js/component.js#L205)

---

### enableTouchActivity()
> Report user touch activity when touch events occur
>
> User activity is used to determine when controls should show/hide. It's
> relatively simple when it comes to mouse events, because any mouse event
> should show the controls. So we capture mouse events that bubble up to the
> player and report activity when that happens.
>
> With touch events it isn't as easy. We can't rely on touch events at the
> player level, because a tap (touchstart + touchend) on the video itself on
> mobile devices is meant to turn controls off (and on). User activity is
> checked asynchronously, so what could happen is a tap event on the video
> turns the controls off, then the touchend event bubbles up to the player,
> which if it reported user activity, would turn the controls right back on.
> (We also don't want to completely block touch events from bubbling up)
>
> Also a touchmove, touch+hold, and anything other than a tap is not supposed
> to turn the controls back on on a mobile device.
>
> Here we're setting the default component behavior to report user activity
> whenever touch events happen, and this can be turned off by components that
> want touch events to act differently.

_inherited from_: [src/js/component.js#L954](https://github.com/videojs/video.js/blob/master/src/js/component.js#L954)

---

### getChild( name )
> Returns a child component with the provided name

##### PARAMETERS:
* __name__

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L315](https://github.com/videojs/video.js/blob/master/src/js/component.js#L315)

---

### getChildById( id )
> Returns a child component with the provided ID

##### PARAMETERS:
* __id__

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L298](https://github.com/videojs/video.js/blob/master/src/js/component.js#L298)

---

### height( [num], [skipListeners] )
> Get or set the height of the component (CSS values)
>
> Setting the video tag dimension values only works with values in pixels.
> Percent values will not work.
> Some percents can be used, but width()/height() will return the number + %,
> not the actual computed width/height.

##### PARAMETERS:
* __num__ `Number|String` _(OPTIONAL)_ New component height
* __skipListeners__ `Boolean` _(OPTIONAL)_ Skip the resize event trigger

##### RETURNS:
* `vjs.Component` This component, when setting the height
* `Number|String` The height, when getting

_inherited from_: [src/js/component.js#L764](https://github.com/videojs/video.js/blob/master/src/js/component.js#L764)

---

### hide()
> Hide the component element if currently showing

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L694](https://github.com/videojs/video.js/blob/master/src/js/component.js#L694)

---

### id()
> Get the component's ID
>
>     var id = myComponent.id();

##### RETURNS:
* `String`

_inherited from_: [src/js/component.js#L243](https://github.com/videojs/video.js/blob/master/src/js/component.js#L243)

---

### init( player, options )

##### PARAMETERS:
* __player__
* __options__

_defined in_: [src/js/poster.js#L12](https://github.com/videojs/video.js/blob/master/src/js/poster.js#L12)

---

### initChildren()
> Add and initialize default child components from options
>
>     // when an instance of MyComponent is created, all children in options
>     // will be added to the instance by their name strings and options
>     MyComponent.prototype.options_.children = {
>       myChildComponent: {
>         myChildOption: true
>       }
>     }
>
>     // Or when creating the component
>     var myComp = new MyComponent(player, {
>       children: {
>         myChildComponent: {
>           myChildOption: true
>         }
>       }
>     });
>
> The children option can also be an Array of child names or
> child options objects (that also include a 'name' key).
>
>     var myComp = new MyComponent(player, {
>       children: [
>         'button',
>         {
>           name: 'button',
>           someOtherOption: true
>         }
>       ]
>     });

_inherited from_: [src/js/component.js#L466](https://github.com/videojs/video.js/blob/master/src/js/component.js#L466)

---

### name()
> Get the component's name. The name is often used to reference the component.
>
>     var name = myComponent.name();

##### RETURNS:
* `String`

_inherited from_: [src/js/component.js#L262](https://github.com/videojs/video.js/blob/master/src/js/component.js#L262)

---

### off( [type], [fn] )
> Remove an event listener from the component's element
>
>     myComponent.off("eventName", myFunc);

##### PARAMETERS:
* __type__ `String` _(OPTIONAL)_ Event type. Without type it will remove all listeners.
* __fn__ `Function` _(OPTIONAL)_ Event listener. Without fn it will remove all listeners for a type.

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L545](https://github.com/videojs/video.js/blob/master/src/js/component.js#L545)

---

### on( type, fn )
> Add an event listener to this component's element
>
>     var myFunc = function(){
>       var myPlayer = this;
>       // Do something when the event is fired
>     };
>
>     myPlayer.on("eventName", myFunc);
>
> The context will be the component.

##### PARAMETERS:
* __type__ `String` The event type e.g. 'click'
* __fn__ `Function` The event listener

##### RETURNS:
* `vjs.Component` self

_inherited from_: [src/js/component.js#L531](https://github.com/videojs/video.js/blob/master/src/js/component.js#L531)

---

### one( type, fn )
> Add an event listener to be triggered only once and then removed

##### PARAMETERS:
* __type__ `String` Event type
* __fn__ `Function` Event listener

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L557](https://github.com/videojs/video.js/blob/master/src/js/component.js#L557)

---

### options( obj )
> Deep merge of options objects
>
> Whenever a property is an object on both options objects
> the two properties will be merged using vjs.obj.deepMerge.
>
> This is used for merging options for child components. We
> want it to be easy to override individual options on a child
> component without having to rewrite all the other default options.
>
>     Parent.prototype.options_ = {
>       children: {
>         'childOne': { 'foo': 'bar', 'asdf': 'fdsa' },
>         'childTwo': {},
>         'childThree': {}
>       }
>     }
>     newOptions = {
>       children: {
>         'childOne': { 'foo': 'baz', 'abc': '123' }
>         'childTwo': null,
>         'childFour': {}
>       }
>     }
>
>     this.options(newOptions);
>
> RESULT
>
>     {
>       children: {
>         'childOne': { 'foo': 'baz', 'asdf': 'fdsa', 'abc': '123' },
>         'childTwo': null, // Disabled. Won't be initialized.
>         'childThree': {},
>         'childFour': {}
>       }
>     }

##### PARAMETERS:
* __obj__ `Object` Object of new option values

##### RETURNS:
* `Object` A NEW object of this.options_ and obj merged

_inherited from_: [src/js/component.js#L173](https://github.com/videojs/video.js/blob/master/src/js/component.js#L173)

---

### player()
> Return the component's player

##### RETURNS:
* `vjs.Player`

_inherited from_: [src/js/component.js#L120](https://github.com/videojs/video.js/blob/master/src/js/component.js#L120)

---

### ready( fn )
> Bind a listener to the component's ready state
>
> Different from event listeners in that if the ready event has already happend
> it will trigger the function immediately.

##### PARAMETERS:
* __fn__ `Function` Ready listener

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L616](https://github.com/videojs/video.js/blob/master/src/js/component.js#L616)

---

### removeChild( component )
> Remove a child component from this component's list of children, and the
> child component's element from this component's element

##### PARAMETERS:
* __component__ `vjs.Component` Component to remove

_inherited from_: [src/js/component.js#L405](https://github.com/videojs/video.js/blob/master/src/js/component.js#L405)

---

### removeClass( classToRemove )
> Remove a CSS class name from the component's element

##### PARAMETERS:
* __classToRemove__ `String` Classname to remove

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L674](https://github.com/videojs/video.js/blob/master/src/js/component.js#L674)

---

### show()
> Show the component element if hidden

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L684](https://github.com/videojs/video.js/blob/master/src/js/component.js#L684)

---

### trigger( type, event )
> Trigger an event on an element
>
>     myComponent.trigger('eventName');

##### PARAMETERS:
* __type__ `String` The event type to trigger, e.g. 'click'
* __event__ `Event|Object` The event object to be passed to the listener

##### RETURNS:
* `vjs.Component` self

_inherited from_: [src/js/component.js#L571](https://github.com/videojs/video.js/blob/master/src/js/component.js#L571)

---

### triggerReady()
> Trigger the ready listeners

##### RETURNS:
* `vjs.Component`

_inherited from_: [src/js/component.js#L635](https://github.com/videojs/video.js/blob/master/src/js/component.js#L635)

---

### width( [num], skipListeners )
> Set or get the width of the component (CSS values)
>
> Setting the video tag dimension values only works with values in pixels.
> Percent values will not work.
> Some percents can be used, but width()/height() will return the number + %,
> not the actual computed width/height.

##### PARAMETERS:
* __num__ `Number|String` _(OPTIONAL)_ Optional width number
* __skipListeners__ `Boolean` Skip the 'resize' event trigger

##### RETURNS:
* `vjs.Component` This component, when setting the width
* `Number|String` The width, when getting

_inherited from_: [src/js/component.js#L747](https://github.com/videojs/video.js/blob/master/src/js/component.js#L747)

---

## EVENTS

### resize `EVENT`
> Fired when the width and/or height of the component changes

_inherited from_: [src/js/component.js#L854](https://github.com/videojs/video.js/blob/master/src/js/component.js#L854)

---


keep keep keep replace replace keep keep keep keep keep

const onerror = err => ctx.onerror(err);

'use strict';

/**
 * Module dependencies.
 */

const isGeneratorFunction = require('is-generator-function');
const debug = require('debug')('koa:application');
const onFinished = require('on-finished');
const response = require('./response');
const compose = require('koa-compose');
const isJSON = require('koa-is-json');
const context = require('./context');
const request = require('./request');
const statuses = require('statuses');
const Cookies = require('cookies');
const accepts = require('accepts');
const Emitter = require('events');
const assert = require('assert');
const Stream = require('stream');
const http = require('http');
const only = require('only');
const convert = require('koa-convert');
const deprecate = require('depd')('koa');

/**
 * Expose `Application` class.
 * Inherits from `Emitter.prototype`.
 */

module.exports = class Application extends Emitter {

  /**
   * Initialize a new `Application`.
   *
   * @api public
   */

  constructor() {
    super();

    this.proxy = false;
    this.middleware = [];
    this.subdomainOffset = 2;
    this.env = process.env.NODE_ENV || 'development';
    this.context = Object.create(context);
    this.request = Object.create(request);
    this.response = Object.create(response);
  }

  /**
   * Shorthand for:
   *
   *    http.createServer(app.callback()).listen(...)
   *
   * @param {Mixed} ...
   * @return {Server}
   * @api public
   */

  listen() {
    debug('listen');
    const server = http.createServer(this.callback());
    return server.listen.apply(server, arguments);
  }

  /**
   * Return JSON representation.
   * We only bother showing settings.
   *
   * @return {Object}
   * @api public
   */

  toJSON() {
    return only(this, [
      'subdomainOffset',
      'proxy',
      'env'
    ]);
  }

  /**
   * Inspect implementation.
   *
   * @return {Object}
   * @api public
   */

  inspect() {
    return this.toJSON();
  }

  /**
   * Use the given middleware `fn`.
   *
   * Old-style middleware will be converted.
   *
   * @param {Function} fn
   * @return {Application} self
   * @api public
   */

  use(fn) {
    if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
    if (isGeneratorFunction(fn)) {
      deprecate('Support for generators will been removed in v3. ' +
                'See the documentation for examples of how to convert old middleware ' +
                'https://github.com/koajs/koa/tree/v2.x#old-signature-middleware-v1x---deprecated');
      fn = convert(fn);
    }
    debug('use %s', fn._name || fn.name || '-');
    this.middleware.push(fn);
    return this;
  }

  /**
   * Return a request handler callback
   * for node's native http server.
   *
   * @return {Function}
   * @api public
   */

  callback() {
    const fn = compose(this.middleware);

    if (!this.listeners('error').length) this.on('error', this.onerror);

    return (req, res) => {
      res.statusCode = 404;
      const ctx = this.createContext(req, res);
      onFinished(res, ctx.onerror);
      fn(ctx).then(() => respond(ctx)).catch(ctx.onerror);
    };
  }

  /**
   * Initialize a new context.
   *
   * @api private
   */

  createContext(req, res) {
    const context = Object.create(this.context);
    const request = context.request = Object.create(this.request);
    const response = context.response = Object.create(this.response);
    context.app = request.app = response.app = this;
    context.req = request.req = response.req = req;
    context.res = request.res = response.res = res;
    request.ctx = response.ctx = context;
    request.response = response;
    response.request = request;
    context.onerror = context.onerror.bind(context);
    context.originalUrl = request.originalUrl = req.url;
    context.cookies = new Cookies(req, res, {
      keys: this.keys,
      secure: request.secure
    });
    request.ip = request.ips[0] || req.socket.remoteAddress || '';
    context.accept = request.accept = accepts(req);
    context.state = {};
    return context;
  }

  /**
   * Default error handler.
   *
   * @param {Error} err
   * @api private
   */

  onerror(err) {
    assert(err instanceof Error, `non-error thrown: ${err}`);

    if (404 == err.status || err.expose) return;
    if (this.silent) return;

    const msg = err.stack || err.toString();
    console.error();
    console.error(msg.replace(/^/gm, '  '));
    console.error();
  }

};

/**
 * Response helper.
 */

function respond(ctx) {
  // allow bypassing koa
  if (false === ctx.respond) return;

  const res = ctx.res;
  if (!ctx.writable) return;

  let body = ctx.body;
  const code = ctx.status;

  // ignore body
  if (statuses.empty[code]) {
    // strip headers
    ctx.body = null;
    return res.end();
  }

  if ('HEAD' == ctx.method) {
    if (!res.headersSent && isJSON(body)) {
      ctx.length = Buffer.byteLength(JSON.stringify(body));
    }
    return res.end();
  }

  // status body
  if (null == body) {
    body = ctx.message || String(code);
    if (!res.headersSent) {
      ctx.type = 'text';
      ctx.length = Buffer.byteLength(body);
    }
    return res.end(body);
  }

  // responses
  if (Buffer.isBuffer(body)) return res.end(body);
  if ('string' == typeof body) return res.end(body);
  if (body instanceof Stream) return body.pipe(res);

  // body: json
  body = JSON.stringify(body);
  if (!res.headersSent) {
    ctx.length = Buffer.byteLength(body);
  }
  res.end(body);
}


'use strict';

const response = require('../helpers/context').response;

describe('res.header', () => {
  it('should return the response header object', () => {
    const res = response();
    res.set('X-Foo', 'bar');
    res.header.should.eql({ 'x-foo': 'bar' });
  });

  describe('when res._headers not present', () => {
    it('should return empty object', () => {
      const res = response();
      res.res._headers = null;
      res.header.should.eql({});
    });
  });
});