Source: ui/base/abstract-video.js

/*global require, exports*/

/**
 * @module montage/ui/base/abstract-video.reel
 */
var Component = require("../component").Component,
    MediaController = require("../../core/media-controller").MediaController;

/**
 * @class AbstractVideo
 * @extends Component
 */
var AbstractVideo = exports.AbstractVideo = Component.specialize(/** @lends AbstractVideo# */ {

    /**
     * @private
     */
    constructor: {
        value: function AbstractVideo() {
            if (this.constructor === AbstractVideo) {
                throw new Error("AbstractVideo cannot be instantiated.");
            }
        }
    },

    _mediaElement: {
        value: null
    },

    mediaElement: {
        get: function () {
            return this._mediaElement;
        },
        set: function (element) {
            this._mediaElement = element;

            if (this.videoController) {
                this.videoController.mediaElement = this.mediaElement;
            }
        }
    },

    _videoController: {
        value: null
    },

    /**
     * The MediaController instance used by the video component.
     * @type {module:montage/core/media-controller.MediaController}
     * @default null
     */
    videoController: {
        get: function () {
            return this._videoController;
        },
        set: function (controller) {
            if (controller) {
                this._videoController = controller;

                if (this.mediaElement) {
                    this.videoController.mediaElement = this.mediaElement;
                }
            }
        }
    },

    _src: {
        value: null
    },

    /**
     * @type {string}
     * @default null
     */
    src: {
        get: function () {
            return this._src;
        },
        set: function (src) {
            this._src = src;
        }
    },

    /**
     * @private
     */
    _sources: {
        value: []
    },
    /**
     * @type {Array}
     * @default null
     */
    sources: {
        get: function () {
            return this._sources;
        },
        set: function (sources) {
            if (sources && sources.length) {
                var mediaElement = this.element.ownerDocument.createElement("video");
                for (var i = 0; i < sources.length; i++) {
                    var mediaSrc = sources[i].src,
                        mediaType = sources[i].type;
                    if (mediaType && mediaElement.canPlayType(mediaType)) {
                        this.src = mediaSrc;
                        break;
                    }
                }
                this._sources = sources;
            }
        }
    },

    /**
     * @function
     */
    loadMedia: {
        value: function () {
            this.mediaElement.src = this.src;
            this.mediaElement.load();
        }
    },

    _repeat: {
        value: false
    },

    /**
     * @type {Function}
     * @default {boolean} false
     */
    repeat: {
        get: function () {
            return this._repeat;
        },

        set: function (repeat) {
            if (repeat !== this._repeat) {
                this._repeat = repeat;
                if (repeat) {
                    this.mediaElement.setAttribute("loop", "true");
                } else {
                    this.mediaElement.removeAttribute("loop");
                }
                this.needsDraw = true;
            }
        }
    },

    /**
     * @function
     */
    toggleRepeat: {
        value: function () {
            this.repeat = !this.repeat;
        }
    },

    _posterSrc: {
        value: null
    },

    /**
     * @type {string}
     * @default null
     */
    posterSrc: {
        get: function () {
            return this._posterSrc;
        },
        set: function (posterSrc) {
            this._posterSrc = posterSrc;
        }
    },

    /**
     * @function
     */
    showPoster: {
        value: function () {
            if (this.posterSrc && this.mediaElement) {
                this.mediaElement.poster = this.posterSrc;
            }
        }
    },

    /**
     * Specifies whether the full screen video is supported.
     * @type {boolean}
     * @default true
     */
    supportsFullScreen: {
        value: true
    },

    _isFullScreen: {
        value: false
    },

    /**
     * @type {boolean}
     */
    isFullScreen: {
        get: function () {
            return this._isFullScreen;
        }
    },

    /**
     * Toggles full-screen playback mode.
     * @function
     */
    toggleFullScreen: {
        value: function () {
            if (this.supportsFullScreen) {
                this._isFullScreen = !this._isFullScreen;
                if (!this._isFullScreen) {
                    if (this.element.webkitExitFullscreen) {
                        this.element.webkitExitFullscreen();
                    } else if (this.element.webkitCancelFullScreen) {
                        this.element.webkitCancelFullScreen();
                    } else if (this.element.ownerDocument.webkitCancelFullScreen && this.element.ownerDocument.webkitCurrentFullScreenElement === this.element) {
                        this.element.ownerDocument.webkitCancelFullScreen();
                    }
                } else {
                    if (this.element.webkitEnterFullScreen) {
                        this.element.webkitEnterFullScreen();
                    } else if (this.element.webkitRequestFullScreen) {
                        this.element.webkitRequestFullScreen();
                    }
                }
                this.needsDraw = true;
            }
        }
    },

    handleControllerStatusChange: {
        value: function () {
            this.needsDraw = true;
        }
    },

    handleControllerVolumeChange: {
        value: function () {
            this.needsDraw = true;
        }
    },

    enterDocument: {
        value: function (firstTime) {
            if (firstTime) {
                // look for src attribute on original element
                if (this.originalElement.hasAttribute("src") && this.originalElement.getAttribute("src")) {
                    this.src = this.originalElement.getAttribute("src");
                } else {
                    // try to grab <source> child elements from original element
                    var sources = this.originalElement.getElementsByTagName("source"),
                        mediaSrc, mediaType;
                    for (var sourceIdx = 0; sourceIdx < sources.length; sourceIdx++) {
                        mediaSrc = sources[sourceIdx].getAttribute("src");
                        mediaType = sources[sourceIdx].getAttribute("type");
                        if (mediaType && !this.mediaElement.canPlayType(mediaType)) {
                            continue;
                        }
                        this.src = mediaSrc;
                        break;
                    }
                }

                // try to grab <track> child elements from original element
                var tracks = this.originalElement.getElementsByTagName("track");
                for (var trackIdx = 0; trackIdx < tracks.length; trackIdx++) {
                    var trackKind = tracks[trackIdx].getAttribute("kind");
                    if (trackKind === "captions" || trackKind === "subtitles") {
                        var track = document.createElement("track");
                        track.kind = trackKind;
                        track.label = tracks[trackIdx].getAttribute("label");
                        track.src = tracks[trackIdx].getAttribute("src");
                        track.srclang = tracks[trackIdx].getAttribute("srclang");
                        track.default = tracks[trackIdx].hasAttribute("default");
                        this.mediaElement.appendChild(track);
                        this.mediaElement.textTracks[this.mediaElement.textTracks.length - 1].mode = "showing";
                    }
                }

                this.addPathChangeListener("videoController.status", this, "handleControllerStatusChange");
                this.addPathChangeListener("videoController.volume", this, "handleControllerVolumeChange");

                if (!this.videoController) {
                    this.videoController = new MediaController();
                }

                this.videoController.mediaElement = this.mediaElement;
            }
        }
    }

});