Source: widgets/uibuilder/carousel.js

define('application/widgets/uibuilder/carousel', [
    'rofl/widgets/carousel',
    'rofl/widgets/container',
    'rofl/widgets/label',
    'application/formatters/vodasset',
    'antie/widgets/carousel/strips/cullingstrip',
    'rofl/lib/utils',
    'antie/runtimecontext',
    'antie/widgets/carousel/keyhandlers/activatefirsthandler',
    'application/widgets/carousel/horizontalcarouselaligner',
    'application/widgets/uibuilder/watchall',
    'application/widgets/pointerfocusableasset'
], function (
    Carousel,
    Container,
    Label,
    VodFormatter,
    Cullingstrip,
    Utils,
    RuntimeContext,
    KeyHandler,
    Aligner,
    WatchAll,
    SelectableButton
) {
    'use strict';

    var layout = RuntimeContext.getCurrentApplication().getLayout(),
        WATCH_ALL_ASSET_LENGTH = 15,
        device = RuntimeContext.getDevice();

    return Container.extend({

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

            this.addClass('ui-carousel');

            this._carouselParams = carouselParams || {};
            this._carouselLayout = data.getLayout();
            this._createTitle(data);
            this._createCarousel(data);
            this.setDataItem(data);
            this._createPointerContainers();
        },

        /**
         * Creates the title.
         *
         * @param {Object} data - The Carousel model.
         * @private
         */
        _createTitle: function (data) {
            var title = this._title = new Label(data.getTitle());

            title.addClass('title');

            this.appendChildWidget(title);
        },

        /**
         * Creates the carousel.
         *
         * @param {Object} data - The Carousel model.
         * @param {boolean} renderItems - True if the carousel needs to update the carousel items.
         * @private
         */
        _createCarousel: function (data, renderItems) {
            var carousel = this._carousel,
                carouselParams = this._carouselParams,
                items = data.getItems(),
                formatter = carouselParams.formatter || VodFormatter,
                assetLayout = carouselParams.layout || layout.movie,
                assetWidth = assetLayout.width,
                watchallParams = carouselParams.watchAll,
                carouselItem,
                aligner,
                keyHandler;

            if (!carousel) {
                keyHandler = new KeyHandler();
                carousel = this._carousel = new Carousel('', Carousel.orientations.HORIZONTAL);

                aligner = new Aligner(carousel.getMask());
                carousel.setWidgetStrip(Cullingstrip);
                carousel.setMaskLength(layout.requiredScreenSize.width);
                carousel.setContinuousListener(true);
                carousel.setAlignPoint(assetLayout.alignPoint);
                carousel.setNormalisedWidgetAlignPoint(0);

                aligner.setNumberOfItemsVisibleOnScreen(carouselParams.numberOfVisibleItemsOnScreen);
                carousel.setAligner(aligner);

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

                keyHandler.attach(carousel);
            }

            formatter = new formatter();
            Utils.each(items, function (item) {
                carouselItem = formatter.format(item);

                carousel.append(carouselItem, (assetWidth));

                if (renderItems) {
                    carouselItem.render(device);
                }
            });

            if (data.getTotal() >= WATCH_ALL_ASSET_LENGTH) {
                carousel.append(new WatchAll(data, watchallParams), (assetWidth || layout.movie.width));
            }

            if (!renderItems) {
                this.appendChildWidget(carousel);
            }
        },

        /**
         * Aligns the carousel to a specific index, or 0 if not supplied.
         *
         * @param {number} [index] - The index. Optional.
         */
        alignToIndex: function (index) {
            index = index || 0;
            this._carousel.alignToIndex(index);
        },

        /**
         * Aligns to the last index.
         */
        alignToLastIndex: function () {
            var index = this._carousel.getActiveIndex();

            this._carousel.alignToIndex(this._carousel.getActiveIndex());
            this._carousel.setActiveChildIndex(index);
        },

        /**
         * Creates container containing pointer buttons.
         *
         * @private
         */
        _createPointerContainers: function () {
            var leftPointer = this._leftPointer = new SelectableButton(),
                leftPointerImage = new Container(),
                rightPointer = this._rightPointer = new SelectableButton(),
                rightPointerImage = new Container();

            leftPointerImage.addClass('arrow');
            rightPointerImage.addClass('arrow');

            leftPointer.addClass(['pointer-button-big', 'left-pointer']);
            rightPointer.addClass(['pointer-button-big', 'right-pointer']);

            leftPointer.appendChildWidget(leftPointerImage);
            rightPointer.appendChildWidget(rightPointerImage);

            this.appendChildWidget(leftPointer);
            this.appendChildWidget(rightPointer);
        },

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

        /**
         * Returns the type of layout of the carousel. Reference layout on uibuilder's page model.
         *
         * @returns {string} - The carousel layout.
         */
        getCarouselLayout: function () {
            return this._carouselLayout;
        },

        /**
         * Requests and updates carousel items.
         */
        updateCarousel: function () {
            var dataItem = this.getDataItem(),
                lastActiveIndex,
                isCarouselFocused;

            if (dataItem) {
                dataItem.prepare().then(Utils.bind(function (data) {
                    if (data.getItems().length) {
                        lastActiveIndex = this._carousel.getActiveChildIndex();
                        isCarouselFocused = this._carousel.isFocussed();

                        // Remove previous data and set new data received.
                        this._carousel.removeChildWidgets();
                        this._updateTitle(data);
                        this._createCarousel(data, true);
                        this.setDataItem(data);

                        // Check to avoid aligning to a index that is not available in the new received assets.
                        if (!(lastActiveIndex <= this._carousel.getChildWidgetCount() - 1)) {
                            lastActiveIndex = 0;
                        }

                        // Align and focus carousel to the previous state.
                        this.alignToIndex(lastActiveIndex);

                        if (isCarouselFocused) {
                            this._carousel.focus();
                        }
                    }
                }, this));
            }
        },

        /**
         * Updates the title.
         *
         * @param {Object} data - The Carousel model.
         * @private
         */
        _updateTitle: function (data) {
            this._title.setText(data.getTitle());
        }
    });
});