Beispiel #1
0
    constructor(model, api) {
        this.el = utils.createElement(displayContainerTemplate(model.get('localization')));

        const container = this.el.querySelector('.jw-display-controls');
        const buttons = {};

        addButton('rewind', cloneIcons('rewind'), RewindDisplayIcon, container, buttons, model, api);
        addButton('display', cloneIcons('play,pause,buffer,replay'), PlayDisplayIcon, container, buttons, model, api);
        addButton('next', cloneIcons('next'), NextDisplayIcon, container, buttons, model, api);

        this.container = container;
        this.buttons = buttons;
    }
Beispiel #2
0
function createCastButton(castToggle, localization) {

    if (Browser.safari) {
        const airplayButton = button(
            'jw-icon-airplay jw-off',
            castToggle,
            localization.airplay,
            cloneIcons('airplay-off,airplay-on'));

        SimpleTooltip(airplayButton.element(), 'airplay', localization.airplay);

        return airplayButton;
    }

    if (!Browser.chrome || OS.iOS) {
        return;
    }


    const castButton = document.createElement('button', 'google-cast-button');
    castButton.setAttribute('type', 'button');
    castButton.setAttribute('tabindex', '-1');

    const element = document.createElement('div');
    element.className = 'jw-reset jw-icon jw-icon-inline jw-icon-cast jw-button-color';
    element.style.display = 'none';
    element.style.cursor = 'pointer';
    element.appendChild(castButton);
    ariaLabel(element, localization.cast);

    SimpleTooltip(element, 'chromecast', localization.cast);

    return {
        element: function() {
            return element;
        },
        toggle: function(m) {
            if (m) {
                this.show();
            } else {
                this.hide();
            }
        },
        show: function() {
            element.style.display = '';
        },
        hide: function() {
            element.style.display = 'none';
        },
        button: castButton
    };
}
Beispiel #3
0
    constructor(_api, _model) {
        Object.assign(this, Events);
        this._api = _api;
        this._model = _model;
        this._isMobile = OS.mobile;
        const localization = _model.get('localization');
        const timeSlider = new TimeSlider(_model, _api);
        let volumeTooltip;
        let muteButton;

        const vol = localization.volume;

        // Do not show the volume toggle in the mobile SDKs or <iOS10
        if (!_model.get('sdkplatform') && !(OS.iOS && OS.version.major < 10)) {
            // Clone icons so that can be used in VolumeTooltip
            const svgIcons = cloneIcons('volume-0,volume-100');
            muteButton = button('jw-icon-volume', () => {
                _api.setMute();
            }, vol, svgIcons);
        }

        // Do not initialize volume slider or tooltip on mobile
        if (!this._isMobile) {
            volumeTooltip = new VolumeTooltip(_model, 'jw-icon-volume', vol,
                cloneIcons('volume-0,volume-50,volume-100'));
        }

        const nextButton = button('jw-icon-next', () => {
            _api.next();
        }, localization.next, cloneIcons('next'));

        const settingsButton = button('jw-icon-settings jw-settings-submenu-button', (event) => {
            this.trigger('settingsInteraction', 'quality', true, event);
        }, localization.settings, cloneIcons('settings'));
        settingsButton.element().setAttribute('aria-haspopup', 'true');

        const captionsButton = button('jw-icon-cc jw-settings-submenu-button', (event) => {
            this.trigger('settingsInteraction', 'captions', false, event);
        }, localization.cc, cloneIcons('cc-off,cc-on'));
        captionsButton.element().setAttribute('aria-haspopup', 'true');

        const liveButton = button('jw-text-live', () => {
            this.goToLiveEdge();
        }, localization.liveBroadcast);
        liveButton.element().textContent = localization.liveBroadcast;

        const elements = this.elements = {
            alt: text('jw-text-alt', 'status'),
            play: button('jw-icon-playback', () => {
                _api.playToggle(reasonInteraction());
            }, localization.play, cloneIcons('play,pause,stop')),
            rewind: button('jw-icon-rewind', () => {
                this.rewind();
            }, localization.rewind, cloneIcons('rewind')),
            live: liveButton,
            next: nextButton,
            elapsed: textIcon('jw-text-elapsed', 'timer'),
            countdown: textIcon('jw-text-countdown', 'timer'),
            time: timeSlider,
            duration: textIcon('jw-text-duration', 'timer'),
            mute: muteButton,
            volumetooltip: volumeTooltip,
            cast: createCastButton(() => {
                _api.castToggle();
            }, localization),
            fullscreen: button('jw-icon-fullscreen', () => {
                _api.setFullscreen();
            }, localization.fullscreen, cloneIcons('fullscreen-off,fullscreen-on')),
            spacer: div('jw-spacer'),
            buttonContainer: div('jw-button-container'),
            settingsButton,
            captionsButton
        };

        // Add text tooltips
        const captionsTip = SimpleTooltip(captionsButton.element(), 'captions', localization.cc);
        const onCaptionsChanged = (model) => {
            const currentCaptions = model.get('captionsList')[model.get('captionsIndex')];
            let newText = localization.cc;
            if (currentCaptions && currentCaptions.label !== 'Off') {
                newText = currentCaptions.label;
            }
            captionsTip.setText(newText);
        };

        const nextUpTip = SimpleTooltip(elements.next.element(), 'next', localization.nextUp, () => {
            const nextUp = _model.get('nextUp');

            this.trigger('nextShown', {
                mode: nextUp.mode,
                ui: 'nextup',
                itemsShown: [nextUp],
                feedData: nextUp.feedData,
                reason: 'hover'
            });
        });
        SimpleTooltip(elements.rewind.element(), 'rewind', localization.rewind);
        SimpleTooltip(elements.settingsButton.element(), 'settings', localization.settings);
        SimpleTooltip(elements.fullscreen.element(), 'fullscreen', localization.fullscreen);

        // Filter out undefined elements
        const buttonLayout = [
            elements.play,
            elements.rewind,
            elements.next,
            elements.volumetooltip,
            elements.mute,
            elements.alt,
            elements.live,
            elements.elapsed,
            elements.countdown,
            elements.duration,
            elements.spacer,
            elements.cast,
            elements.captionsButton,
            elements.settingsButton,
            elements.fullscreen
        ].filter(e => e);

        const layout = [
            elements.time,
            elements.buttonContainer
        ].filter(e => e);

        const menus = this.menus = [
            elements.volumetooltip
        ].filter(e => e);

        this.el = document.createElement('div');
        this.el.className = 'jw-controlbar jw-reset';

        appendChildren(elements.buttonContainer, buttonLayout);
        appendChildren(this.el, layout);

        const logo = _model.get('logo');
        if (logo && logo.position === 'control-bar') {
            this.addLogo(logo);
        }

        // Initial State
        elements.play.show();
        elements.fullscreen.show();
        if (elements.mute) {
            elements.mute.show();
        }

        // Listen for model changes
        _model.change('volume', this.onVolume, this);
        _model.change('mute', this.onMute, this);
        _model.change('state', this.onState, this);
        _model.change('duration', this.onDuration, this);
        _model.change('position', this.onElapsed, this);
        _model.change('fullscreen', this.onFullscreen, this);
        _model.change('streamType', this.onStreamTypeChange, this);
        _model.change('dvrLive', (model, dvrLive) => {
            utils.toggleClass(this.elements.live.element(), 'jw-dvr-live', dvrLive === false);
        }, this);
        _model.change('altText', this.setAltText, this);
        _model.change('customButtons', this.updateButtons, this);
        _model.on('change:captionsIndex', onCaptionsChanged, this);
        _model.on('change:captionsList', onCaptionsChanged, this);
        _model.change('nextUp', (model, nextUp) => {
            let tipText = localization.nextUp;
            if (nextUp && nextUp.title) {
                tipText += (`: ${nextUp.title}`);
            }
            nextUpTip.setText(tipText);
            elements.next.toggle(!!nextUp);
        });
        _model.change('audioMode', this.onAudioMode, this);
        if (elements.cast) {
            _model.change('castAvailable', this.onCastAvailable, this);
            _model.change('castActive', this.onCastActive, this);
        }

        // Event listeners
        // Volume sliders do not exist on mobile so don't assign listeners to them.
        if (elements.volumetooltip) {
            elements.volumetooltip.on('update', function (pct) {
                const val = pct.percentage;
                this._api.setVolume(val);
            }, this);
            elements.volumetooltip.on('toggleValue', function () {
                this._api.setMute();
            }, this);
        }

        if (elements.cast && elements.cast.button) {
            new UI(elements.cast.element()).on('click tap enter', function(evt) {
                // controlbar cast button needs to manually trigger a click
                // on the native cast button for taps and enter key
                if (evt.type !== 'click') {
                    elements.cast.button.click();
                }
                this._model.set('castClicked', true);
            }, this);
        }

        new UI(elements.duration).on('click tap enter', function () {
            if (this._model.get('streamType') === 'DVR') {
                // Seek to "Live" position within live buffer, but not before current position
                const currentPosition = this._model.get('position');
                const dvrSeekLimit = this._model.get('dvrSeekLimit');
                this._api.seek(Math.max(-dvrSeekLimit, currentPosition), reasonInteraction());
            }
        }, this);

        // When the control bar is interacted with, trigger a user action event
        new UI(this.el).on('click tap drag', function () {
            this.trigger(USER_ACTION);
        }, this);
        _.each(menus, function (ele) {
            ele.on('open-tooltip', this.closeMenus, this);
        }, this);
    }