Source: widgets/uibuilder/heroslider.js

define('application/widgets/uibuilder/heroslider', [
    'rofl/widgets/carousel',
    'rofl/widgets/container',
    'rofl/widgets/label',
    'application/formatters/vodasset',
    'application/formatters/epgasset',
    'antie/widgets/carousel/strips/cullingstrip',
    'rofl/lib/utils',
    'antie/runtimecontext',
    'antie/widgets/carousel/keyhandlers/activatefirsthandler',
    'rofl/widgets/carousel/aligners/basic',
    'application/widgets/uibuilder/watchall',
    'application/widgets/pointerfocusablebutton',
    'application/widgets/uibuilder/herocarousel'
], function (
    Carousel,
    Container,
    Label,
    VodFormatter,
    EpgFormatter,
    CullingStrip,
    Utils,
    RuntimeContext,
    KeyHandler,
    Aligner,
    WatchAll,
    SelectableButton,
    HeroAbstract
) {
    'use strict';

    var layout = RuntimeContext.getCurrentApplication().getLayout(),
        SLIDER_INTERVAL_TIME = 7000;

    return HeroAbstract.extend({

        /**
         * Initialises the widget.
         *
         * @param {Object} data - The Carousel model.
         * @param {Object} [heroParams] - Specific params to use for the carousel.
         * @param {Object} [heroParams.layout] - Asset layout.
         * @param {Object} [heroParams.formatter] - Asset formatter.
         * @param {Object} [heroParams.numberOfVisibleItemsOnScreen] - Max number of visible items.
         */
        init: function init (data, heroParams) {
            init.base.call(this, data, heroParams);

            this._setListeners();
            this.addClass('ui-hero-slider');
        },

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

            this._carousel.alignToIndex(this._lastAlignedIndex);
            return outputElement;
        },

        /**
         * BeforeHide event.
         */
        onBeforeHide: function () {
            this._removeListeners();
        },

        /**
         * Set the listeners for the carousel.
         **/
        _setListeners: function () {
            this._onSelectedItemChangeBound = Utils.bind(this._onSelectedItemChange, this);
            this._onBlurBound = Utils.bind(this._onBlur, this);
            this._onFocusBound = Utils.bind(this._onFocus, this);
            this._onSelectBound = Utils.bind(this._onSelect, this);
            this.addEventListener('selecteditemchange', this._onSelectedItemChangeBound);
            this.addEventListener('blur', this._onBlurBound);
            this.addEventListener('focus', this._onFocusBound);
            this.addEventListener('select', this._onSelectBound);
        },

        /**
         * Set the listeners for the carousel.
         **/
        _removeListeners: function () {
            this.removeEventListener('selecteditemchange', this._onSelectedItemChangeBound);
            this.removeEventListener('blur', this._onBlurBound);
            this.removeEventListener('focus', this._onFocusBound);
            this.removeEventListener('select', this._onSelectBound);
        },

        /**
         * On selected item change event.
         *
         * @param {Object} e - Selected item change event.
         */
        _onSelectedItemChange: function (e) {
            this._lastAlignedIndex = e.index;

            this._indicators.setActiveChildIndex(this._lastAlignedIndex);
        },

        /**
         * Focus event.
         *
         * @param {Object} e - The event data.
         * @private
         */
        _onFocus: function (e) {
            this._selected = false;

            if (e.target === this && this._sliderIntervalId) {
                this._clearSliderInterval();
            }
        },

        /**
         * Select event.
         *
         * @private
         */
        _onSelect: function () {
            this._selected = true;

            if (this._sliderIntervalId) {
                this._clearSliderInterval();
            }
        },

        /**
         * Blur event.
         *
         * @param {Object} e - The event data.
         * @private
         */
        _onBlur: function (e) {
            var sliderItemsCount = this._carousel.getChildWidgetCount(),
                activeSliderItemIndex;

            // Start slider interval if there are more than 1 items.
            if (!this._selected && (e.target === this && sliderItemsCount > 1)) {
                if (this._sliderIntervalId) {
                    this._clearSliderInterval();
                }

                this._sliderIntervalId = setInterval(Utils.bind(function () {
                    sliderItemsCount = this._carousel && this._carousel.getChildWidgetCount();
                    activeSliderItemIndex = this._carousel.getActiveChildIndex();

                    if (activeSliderItemIndex === (sliderItemsCount - 1)) {
                        this._carousel.alignToIndex(0,
                            {
                                skipAnim: false
                            }
                        );
                    } else {
                        this._carousel.alignNext(
                            {
                                skipAnim: false
                            }
                        );
                    }
                }, this), SLIDER_INTERVAL_TIME);

                e.preventDefault();
                e.stopPropagation();
            }
        },

        /**
         * Clears the slider interval.
         *
         * @private
         */
        _clearSliderInterval: function () {
            if (this._sliderIntervalId) {
                clearInterval(this._sliderIntervalId);
                this._sliderIntervalId = null;
            }
        },

        /**
         * Creates the carousel.
         *
         * @param {Object} data - The hero model.
         * @param {Object} [heroParams] - Specific params to use for the hero carousel.
         * @private
         */
        _buildHero: function (data, heroParams) {
            this._buildCarousel(data, heroParams);
            this._createSliderIndicator();
        },

        /**
         * Builds the carousel styled hero.
         *
         * @param {Object} data - The hero model.
         * @param {Object} heroParameters - Specific params to use for the hero carousel.
         * @private
         */
        _buildCarousel: function (data, heroParameters) {
            var carousel = this._carousel = new Carousel('', Carousel.orientations.HORIZONTAL),
                heroParams = this._heroParams = heroParameters || {},
                keyHandler = new KeyHandler(),
                aligner,
                formatter = heroParams.formatter || VodFormatter,
                assetLayout = heroParams.layout || layout.home.slider,
                assetWidth = assetLayout.width,
                formatterParams = {
                    layout: assetLayout
                };

            carousel.setWidgetStrip(CullingStrip);
            carousel.setMaskLength(layout.requiredScreenSize.width);

            aligner = new Aligner(carousel.getMask());

            keyHandler.setAnimationOptions({
                duration: 300,
                easing: 'easeInOut',
                fps: 60,
                skipAnim: false
            });

            keyHandler.attach(carousel);

            formatter = new formatter();

            Utils.each(data, function (item) {
                carousel.append(formatter.format(item, formatterParams), (assetWidth));
            });

            carousel.setAligner(aligner);
            carousel.setContinuousListener(true);
            carousel.setAlignPoint(assetLayout.alignPoint);
            carousel.setNormalisedAlignPoint(0);
            carousel.setNormalisedWidgetAlignPoint(0);

            this._lastAlignedIndex = 0;

            this.appendChildWidget(carousel);
        },

        /**
         * Creates the slider's item index indicator.
         *
         * @private
         */
        _createSliderIndicator: function () {
            var itemsCount = this._carousel.getChildWidgetCount(),
                i = 0,
                indicators,
                indicator;

            if (itemsCount) {
                indicators = this._indicators = new Container();

                for (; i < itemsCount; i++) {
                    indicator = new SelectableButton();
                    indicator.setDisabled(false);
                    indicator.addClass('indicator');

                    indicators.appendChildWidget(indicator);
                }

                indicators.addClass('indicators');
                this.appendChildWidget(indicators);
            }
        },

        /**
         * Builds the background image. N/A for carousel hero.
         *
         * @override
         * @private
         */
        _buildImage: function () {},

        /**
         * Builds the gradients. N/A for carousel hero.
         *
         * @override
         * @private
         */
        _buildGradients: function () {},

        /**
         * Builds the titles. N/A for carousel hero.
         *
         * @override
         * @private
         */
        _buildTitles: function () {},

        /**
         * Builds the action list. N/A for carousel hero.
         *
         * @override
         * @private
         */
        _buildActionList: function () {},

        /**
         * Returns the carousel.
         *
         * @returns {Object} - The carousel.
         */
        getCarousel: function () {
            return this._carousel;
        },

        /**
         * Sets carousel focus.
         */
        setButtonActiveChildIndex: function () {
            this._carousel.focus();
        }
    });
});