Source: widgets/player/progress.js

define('application/widgets/player/progress', [
    'rofl/widgets/container',
    'rofl/widgets/label',
    'rofl/lib/l10n',
    'application/widgets/pointerdrag',
    'application/events/mouseseekevent',
    'application/managers/player'
], function (
    Container,
    Label,
    L10N,
    PointerDrag,
    MouseSeekEvent,
    PlayerManager
) {
    'use strict';

    var l10n = L10N.getInstance(),
        player = PlayerManager.getPlayer(),
        _maxMousePosition,
        ProgressBar;

    ProgressBar = Container.extend({

        /**
         * Initialises the progress widget.
         */
        init: function init () {
            init.base.call(this, 'progress');
            this._pointerSupport = true;

            this._build();
            this._setupPointer();
        },

        /**
         * Builds the progress widget.
         *
         * @private
         */
        _build: function () {
            var startTime = this._startTime = new Label({ text: '', classNames: ['duration', 'starttime'] }),
                endTime = this._endTime = new Label({ text: '', classNames: ['duration', 'endtime'] }),
                progressBar = this._progressBar = this._buildProgressBar();

            this.appendChildWidget(startTime);
            this.appendChildWidget(progressBar);
            this.appendChildWidget(endTime);
        },

        /**
         * Sets up pointer decorator.
         *
         * @private
         */
        _setupPointer: function () {

            this.decorate([PointerDrag]);
        },

        /**
         * Builds the actual progress bar.
         *
         * @returns {Object} The progress bar.
         * @private
         */
        _buildProgressBar: function () {
            var bar = new Container(),
                progress = this._progress = new Container(),
                pauseTime = this._pauseTime = new Container(),
                indicator = this._indicator = new Container(),
                pauseLabel = this._pauseLabel = new Label({ classNames: ['pauselabel'] });

            bar.addClass('progressbar');
            progress.addClass('progress');
            pauseTime.addClass('pausetime');
            indicator.addClass('indicator');

            bar.appendChildWidget(pauseTime);
            bar.appendChildWidget(progress);
            bar.appendChildWidget(indicator);
            bar.appendChildWidget(pauseLabel);

            return bar;
        },

        /**
         * Sets the progress percentage.
         *
         * @param {number} percentage - The percentage.
         */
        setProgress: function (percentage) {
            if (!this._isMouseActive()) {
                this._currentPercentage = percentage;

                // Never go beyond the full length of the bar.
                if (percentage > 100) {
                    percentage = 100;
                }

                this._progress.setStyleTo('width', percentage + '%');
                this._indicator.setStyleTo('left', percentage + '%');

                if (percentage > 90) {
                    percentage = 90;
                }
                this._pauseLabel.setStyleTo('left', percentage + '%');
            }
        },

        /**
         * Sets the progress state to live if true.
         *
         * @param {boolean} isLive - True if the progress widget reports live progress.
         */
        setIsLive: function (isLive) {

            this._isLive = isLive;

            if (isLive) {
                this.addClass('live');
                this.setIsVodMovie(!isLive);
            } else {
                this.removeClass('live');
            }
        },

        /**
         * Sets the progress state to VOD_MOVIE if true.
         *
         * @param {boolean} isVodMovie - True if the progress widget reports live progress.
         */
        setIsVodMovie: function (isVodMovie) {

            this._isVodMovie = isVodMovie;

            if (isVodMovie) {
                this.addClass('vodMovie');
                this.setIsLive(!isVodMovie);
            } else {
                this.removeClass('vodMovie');
            }
        },

        /**
         * Sets the start time.
         *
         * @param {string} time - The start time (in hh:mm).
         */
        setStartTime: function (time) {
            this._startTime.setText(time);
        },

        /**
         * Sets the end time.
         *
         * @param {string} time - The end time (in hh:mm).
         */
        setEndTime: function (time) {
            this._endTime.setText(time);
        },

        /**
         * Sets the pause time label.
         *
         * @param {Object} args - The arguments.
         * @param {string} args.behind - The number of minutes behind live (mm:ss).
         * @param {number} args.position - The position behind the live time (percentage).
         */
        setPauseTime: function (args) {
            var position = args.position;

            if (position > 100) {
                position = 100;
            }

            this._currentPercentage = position;
            this._pauseTime.setStyleTo('width', position + '%');
            this._pauseLabel.setText(l10n.get('player.progress.pausetime', { time: args.behind }));
        },

        /**
         * Resets the pause position.
         */
        resetPause: function () {
            this._pauseTime.setStyleTo('width', '0');
            this._pauseLabel.setText('');
        },

        /**
         * Renders the widget.
         *
         * @param {Object} device - The device.
         * @returns {Object} - The output element.
         */
        render: function render (device) {
            var outputElement = render.base.call(this, device);

            if (!this._rendered) {
                this._rendered = true;
                this.setPointerListeners(this._progressBar);
            }

            return outputElement;
        },

        /**
         * Gets executed when the mouse movement finishes.
         *
         * @param {Object} e - The mouse event.
         * @private
         */
        _onMouseFinished: function (e) {
            var percentage = this._setMouseEventPosition(e);

            this.bubbleEvent(new MouseSeekEvent(percentage, true));
        },

        /**
         * Gets executed when the mouse movement position changes.
         *
         * @param {Object} e - The mouse event.
         * @private
         */
        _onMousePosition: function (e) {
            var percentage = this._setMouseEventPosition(e);

            this.bubbleEvent(new MouseSeekEvent(percentage, false));
        },

        /**
         * Sets the mouse event position.
         *
         * @param {Object} e - The mouse event.
         * @returns {number} - The percentage.
         * @private
         */
        _setMouseEventPosition: function (e) {
            var percentage;

            e.mouseClientX = e.mouseClientX - e.elementLeft;
            e.elementRight = e.elementRight - e.elementLeft;

            percentage = (100 * e.mouseClientX) / e.elementRight;

            if (this._isLive && percentage > this._currentPercentage) {
                percentage = this._currentPercentage;
            }

            if (percentage > 100) {
                percentage = 100;
            } else if (percentage < 0) {
                percentage = 0;
            }

            if (percentage > _maxMousePosition) {
                percentage = _maxMousePosition;
            }

            this._progress.setStyleTo('width', percentage + '%');
            this._indicator.setStyleTo('left', percentage + '%');


            this._pauseLabel.setStyleTo('left', percentage > 90 ? 90 : percentage + '%');

            return percentage;
        },

        /**
         * Sets the maximum pointer position.
         *
         * @param {Object} [trickplaySettings] - Any custom trickplay settings.
         * @private
         */
        setMaxPointerPosition: function (trickplaySettings) {
            var type,
                maxPosition,
                currentVideoType;

            trickplaySettings = trickplaySettings || PlayerManager.getTrickplaySettings();
            type = trickplaySettings.type;

            if (trickplaySettings.canSeek) {
                maxPosition = 100;
            } else {
                currentVideoType = PlayerManager.getVideoType();

                if ((type === 'VOD' || type === 'VOD_MOVIE') && currentVideoType !== 'live') {
                    maxPosition = this._setMaxVODPosition(trickplaySettings);
                } else {
                    maxPosition = this._setMaxLivePosition(trickplaySettings);
                }
            }

            _maxMousePosition = maxPosition;
        },

        /**
         * Sets the maximum pointer position.
         *
         * @param {Object} settings - The trickplay settings.
         * @returns {number} - The max position.
         * @private
         */
        _setMaxLivePosition: function (settings) {
            var startTime = settings.startTime * 1000,
                endTime = (settings.endTime * 1000) - startTime,
                maxSeekValue = settings.maxSeekValue * 1000,
                currentTime = settings.currentLivePosition - startTime,
                maxSeekTime = maxSeekValue,
                currentPosition = (currentTime / endTime) * 100,
                maxSeekPosition = (maxSeekTime / endTime) * 100;

            if (currentPosition > maxSeekPosition) {
                return currentPosition;
            }

            return maxSeekPosition;
        },

        /**
         * Sets the maximum pointer position.
         *
         * @param {Object} settings - The trickplay settings.
         * @returns {number} - The max position.
         * @private
         */
        _setMaxVODPosition: function (settings) {
            var duration = player.getDuration(),
                currentTime = player.getCurrentTime(),
                maxSeekValue = settings.maxSeekValue,
                maxSeekPosition = (maxSeekValue / duration) * 100,
                currentPosition = (currentTime / duration) * 100;

            if (currentPosition > maxSeekPosition) {
                return currentPosition;
            }

            return maxSeekPosition;
        },

        /**
         * Enable/disable pointer support for this button.
         *
         * @param {boolean} support - Supported or not.
         */
        setPointerSupport: function setPointerSupport (support) {
            this._pointerSupport = support;
        },

        /**
         * Returns true if mouse down is enabled.
         *
         * @returns {boolean} - True if mouse down is enabled.
         * @private
         */
        _isMouseDownEnabled: function () {
            return PlayerManager.isTrickplayEnabled() && this._pointerSupport;
        }
    });

    return ProgressBar;
});