API Docs for: 1.0.0
Show:

File: Resources/public/js/views/universaldiscovery/ez-universaldiscoveryselectedview.js

/*
 * Copyright (C) eZ Systems AS. All rights reserved.
 * For full copyright and license information view LICENSE file distributed with this source code.
 */
YUI.add('ez-universaldiscoveryselectedview', function (Y) {
    "use strict";
    /**
     * Provides the universal discovery selected view
     *
     * @module ez-universaldiscoveryselectedview
     */
    Y.namespace('eZ');

    var IS_ANIMATED = 'is-animated',
        STATE_CLASS_PREFIX = 'is-state-',
        STATE_IMAGE_NONE = 'no-image',
        STATE_IMAGE_LOADING = 'image-loading',
        STATE_IMAGE_LOADED = 'image-loaded',
        STATE_IMAGE_ERROR = 'image-error';

    /**
     * Universal Discovery Selected View. It's a view meant to display the
     * currently selected content in the different discovery method.
     *
     * @namespace eZ
     * @class UniversalDiscoverySelectedView
     * @constructor
     * @extends eZ.TemplateBasedView
     */
    Y.eZ.UniversalDiscoverySelectedView = Y.Base.create('universalDiscoverySelectedView', Y.eZ.TemplateBasedView, [Y.eZ.AsynchronousView], {
        events: {
            '.ez-ud-selected-confirm': {
                'tap': '_confirmSelected',
            },
            '.ez-ud-selected-visual': {
                'tap': '_openContentPeekView',
            },
        },

        initializer: function () {
            this._fireMethod = Y.bind(this._fireLoadImageVariation, this);
            this._triggerAttribute = 'imageField';

            this.after('imageStateChange', this._uiSetState);
            this.after('loadImageVariation', function () {
                this._set('imageState', STATE_IMAGE_LOADING);
            });

            this.after('imageVariationChange', function (e) {
                if (this.get('imageVariation')) {
                    this._set('imageState', STATE_IMAGE_LOADED);
                    this._renderImageVariation();
                }
            });

            this._errorHandlingMethod = function () {
                this._set('imageState', STATE_IMAGE_ERROR);
            };

            this.after('contentStructChange', function (e) {
                this._setConfirmButtonState(e.newVal);
                if ( this.get('contentStruct') && this.get('contentStruct').content ) {
                    this._setTranslations();
                    this._detectImage();
                }

                this.render();
            });
            this.after('confirmButtonEnabledChange', function (e) {
                this._uiButtonState();
                if ( this.get('confirmButtonEnabled') ) {
                    this._uiResetAnimation();
                }
            });
        },

        /**
         * Opens the ContentPeekView by firing the `contentPeekOpen` event.
         *
         * @method _openContentPeekView
         * @protected
         * @param {EventFacade} e tap event facade
         */
        _openContentPeekView: function (e) {
            var struct = this.get('contentStruct');

            e.preventDefault();
            /**
             * Fired to open the content peek view.
             *
             * @event contentPeekOpen
             * @param {Object} config
             * @param {eZ.Content} config.content
             * @param {eZ.Location} config.location
             * @param {eZ.ContentType} config.contentType
             */
            this.fire('contentPeekOpen', {
                config: {
                    content: struct.content,
                    location: struct.location,
                    contentType: struct.contentType,
                },
            });
        },

        /**
         * Detect if the content has an image and set the view state accordingly
         *
         * @method _detectImage
         * @protected
         */
        _detectImage: function () {
            if ( this._getFilledImageField() ) {
                this.set('imageField', this._getFilledImageField());

            } else {
                this._set('imageState', STATE_IMAGE_NONE);
                this.set('imageVariation', null);
            }
        },

        /**
         * Set translations
         *
         * @method _setTranslations
         * @protected
         */
        _setTranslations: function () {
            this.set('translations', this._getTranslations());
        },

        /**
         * Renders the image variation
         *
         * @method _renderImageVariation
         * @protected
         */
        _renderImageVariation: function () {
            this.get('container').one('.ez-ud-selected-image').setAttribute(
                'src', this.get('imageVariation').uri
            );
        },

        /**
         * Fires the `loadImageVariation` event for the given image field and
         * the image variation stored in `variationIdentifier` attribute.
         *
         * @method _fireLoadImageVariation
         * @protected
         */
        _fireLoadImageVariation: function () {
            this.fire('loadImageVariation', {
                field: this.get('imageField'),
                variation: this.get('variationIdentifier'),
            });
        },

        /**
         * `imageStateChange` handler. It sets a state class on the container
         * and make sure the previous state class was removed.
         *
         * @method _uiSetState
         * @protected
         * @param {EventFacade} e
         */
        _uiSetState: function (e) {
            var prevClass = STATE_CLASS_PREFIX + e.prevVal,
                newClass = STATE_CLASS_PREFIX + e.newVal;

            this.get('container')
                .removeClass(prevClass)
                .addClass(newClass);
        },

        /**
         * Returns the first filled ezimage field of the content or null if
         * there's none.
         *
         * @method _getFilledImageField
         * @protected
         * @return {Object|Null}
         */
        _getFilledImageField: function () {
            var content = this.get('contentStruct').content,
                contentType = this.get('contentStruct').contentType;

            return Y.Array.find(content.getFieldsOfType(contentType, 'ezimage', content.get('mainLanguageCode')), function (field) {
                return !!field.fieldValue;
            });
        },

        /**
         * Sets the confirm selection button state depending on wether content
         * is selectable and is not already selected.
         *
         * @method _setConfirmButtonState
         * @protected
         */
        _setConfirmButtonState: function (contentStruct) {
            var isAlreadySelected = this.get('isAlreadySelected'),
                isSelectable = this.get('isSelectable');

            if (this.get('contentStruct')) {
                this.set(
                    'confirmButtonEnabled',
                    (!isAlreadySelected(contentStruct) && isSelectable(contentStruct))
                );
            }
        },

        /**
         * `confirmButtonEnabledChange` event handler. It sets the confirm
         * button state depending on the value of the `confirmButtonEnabled`
         * attribute
         *
         * @method _uiButtonState
         * @protected
         */
        _uiButtonState: function () {
            var confirmButton = this.get('container').one('.ez-ud-selected-confirm');

            if ( this.get('addConfirmButton') && confirmButton ) {
                confirmButton.set(
                    'disabled', !this.get('confirmButtonEnabled')
                );
            }
        },

        /**
         * tap event handler on the confirm button. If the given content is not already selected
         * it disables the confirm button and  fires the `confirmSelectedContent` event
         * meaning that the user wants the content to be added to his confirmed content list.
         *
         * @method _confirmSelected
         * @protected
         * @param {EventFacade} e
         */
        _confirmSelected: function (e) {
            var isAlreadySelected = this.get('isAlreadySelected'),
                contentStruct = this.get('contentStruct');

            if (!isAlreadySelected(contentStruct)) {
                this.set('confirmButtonEnabled', false);
                /**
                 * Fired when the user has confirmed that he wants the content to be
                 * added in the confirmed list. This event will be fired/used only
                 * when the universal discovery widget is configured to allow
                 * several contents to be selected.
                 *
                 * @event confirmSelectedContent
                 * @param selection {Object} the content structure for the content
                 * which is selected
                 */
                this.fire('confirmSelectedContent', {
                    selection: contentStruct,
                });
            }
        },

        /**
         * Returns and formats the translations list to a string suitable for the template
         *
         * @method _getTranslations
         * @protected
         * @return {String} String of language codes in which the content is
         * translated
         */
        _getTranslations: function () {
            return this.get('contentStruct').content.get('currentVersion').getTranslationsList().join(', ');
        },

        render: function () {
            this.get('container').setHTML(this.template({
                translations: this.get('translations'),
                content: this._modelJson('content'),
                contentInfo: this._modelJson('contentInfo'),
                location: this._modelJson('location'),
                contentType: this._modelJson('contentType'),
                addConfirmButton: this.get('addConfirmButton'),
                confirmButtonEnabled: this.get('confirmButtonEnabled'),
            }));
            return this;
        },

        /**
         * Returns the element that will be animated when the displayed content
         * is selected
         *
         * @method _getAnimatedElement
         * @protected
         * @return {Y.Node|Null}
         */
        _getAnimatedElement: function () {
            return this.get('container').one('.ez-ud-selected-animation');
        },

        /**
         * Starts the animation of the content selection. It also returns the
         * node to animate.
         *
         * @method startAnimation
         * @return {Y.Node|Null}
         */
        startAnimation: function () {
            var node = this._getAnimatedElement();

            if ( node ) {
                node.addClass(IS_ANIMATED);
                return node;
            }
            return null;
        },

        /**
         * Resets the animated element to its original state
         *
         * @method _uiResetAnimation
         * @protected
         */
        _uiResetAnimation: function () {
            var node = this._getAnimatedElement();

            if ( node ) {
                node.removeClass(IS_ANIMATED).removeAttribute('style');
            }
        },

        /**
         * 'jsonifies' the model available under the identifier in the
         * `contentStruct` attribute
         *
         * @method _modelJson
         * @protected
         * @param {String} identifier the identifier of the model in the
         * `contentStruct` attribute
         * @return {Object|false}
         */
        _modelJson: function (identifier) {
            var struct = this.get('contentStruct');

            if ( struct && struct[identifier] ) {
                return struct[identifier].toJSON();
            }
            return false;
        },
    }, {
        ATTRS: {
            /**
             * Holds the current state of the selected view regarding an image
             * to display.
             *
             * @attribute imageState
             * @readOnly
             * @default undefined
             * @type {String}
             */
            imageState: {
                readOnly: true,
            },

            /**
             * The image variation to display. This attribute is filled
             * asynchronously if the content has a filled ezimage field.
             *
             * @attribute imageVariation
             * @type {Object}
             */
            imageVariation: {
                value: null
            },

            /**
             * The image field of the content
             *
             * @attribute imageField
             * @type {null|Object}
             * @default null
             */
            imageField : {
                value: null
            },

            /**
             * The variation identifier to use to display the image
             *
             * @attribute variationIdentifier
             * @type {String}
             * @default 'platformui_rawcontentview'
             */
            variationIdentifier: {
                value: 'platformui_rawcontentview'
            },

            /**
             * The content structure representing the content to display. It
             * should contain the content info, the location and the content
             * type models under the key `contentInfo`, `location` and
             * `contentType`.
             *
             * @attribute contentStruct
             * @type {null|Object}
             * @default null
             */
            contentStruct: {
                value: null,
            },

            /**
             * Flag indicating whether a confirm button has to be added.
             *
             * @attribute addConfirmButton
             * @type {Boolean}
             * @default false
             */
            addConfirmButton: {
                value: false,
            },

            /**
             * Flag indicating whether the confirm button should be enabled or
             * not.
             *
             * @attribute confirmButtonEnabled
             * @type {Boolean}
             * @default true
             */
            confirmButtonEnabled: {
                value: true,
            },

            /**
             * Checks wether the content is already selected.
             *
             * @attribute isAlreadySelected
             * @type {Function}
             */
            isAlreadySelected: {
                validator: Y.Lang.isFunction,
                value: function (contentStruct) {
                    return false;
                }
            },

            /**
             * Checks wether the content is selectable.
             *
             * @attribute isSelectable
             * @type {Function}
             */
            isSelectable: {
                validator: Y.Lang.isFunction,
                value: function (contentStruct) {
                    return true;
                }
            },
        }
    });
});