API Docs for: 1.0.0
Show:

File: Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerlevelview.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-universaldiscoveryfinderexplorerlevelview', function (Y) {
    "use strict";
    /**
     * Provides the universal discovery finder explorer level view
     *
     * @module ez-universaldiscoveryfinderexplorerlevelview
     */
    Y.namespace('eZ');

    var events = {
            '.ez-explorer-level-item': {
                'tap': '_fireExplorerNavigate',
            }
        },
        viewName = 'universalDiscoveryFinderExplorerLevelView',
        HAS_SELECTED_ITEM = 'has-selected-item',
        IS_LOADING = 'is-loading',
        IS_DISABLED = 'is-disabled';

    /**
     * The universal discovery finder explorer level. It shows content of a given depth
     *
     * @namespace eZ
     * @class UniversalDiscoveryFinderExplorerLevelView
     * @constructor
     * @extends eZ.TemplateBasedView
     */
    Y.eZ.UniversalDiscoveryFinderExplorerLevelView = Y.Base.create(viewName, Y.eZ.TemplateBasedView, [Y.eZ.AsynchronousView], {
        initializer: function () {
            var container = this.get('container');

            /**
             * FLag to indicate if we are currently watching the scroll and trying to load items.
             *
             * @property _watchingScroll
             * @type Boolean
             * @protected
             */
            this._watchingScroll = true;
            this._fireMethod = this._fireLocationSearch;
            this._watchAttribute = 'items';
            container.addClass(IS_LOADING);

            this.after('activeChange', function () {
                if (!this.get('active')) {
                    this.get('container').addClass(IS_LOADING);
                }
            });
            this.on('itemsChange', function () {
                this._watchingScroll = true;
                container.removeClass(IS_LOADING);
            });
            this.after('offsetChange', function () {
                this._watchingScroll = false;
                this.get('container').addClass(IS_LOADING);
                this._fireLocationSearch();
            });
            container.plug(Y.Plugin.ScrollInfo);
            container.scrollInfo.on('scrollDown', this._handleScroll, this);

            this.after('ownSelectedItemChange', this._uiOwnSelectedItem);
            this._uiDisableLevelView();
            this._uiOwnSelectedItem();
            this._addDOMEventHandlers(events);
        },

        /**
         * Adds the is disabled item class on the container
         * depending on the `disabled` attribute value.
         *
         * @method _uiDisableLevelView
         * @protected
         */
        _uiDisableLevelView: function () {
            var container = this.get('container');

            if (this.get('disabled')) {
                container.addClass(IS_DISABLED);
            }
        },

        /**
         * Adds or removes the has selected item class on the container
         * depending on the `ownSelectedItem` attribute value.
         *
         * @method _uiOwnSelectedItem
         * @protected
         */
        _uiOwnSelectedItem: function () {
            var container = this.get('container');

            if (!this.get('ownSelectedItem')) {
                container.removeClass(HAS_SELECTED_ITEM);
            } else {
                container.addClass(HAS_SELECTED_ITEM);
            }
        },

        render: function () {
            var container = this.get('container'),
                itemsJSONified = [];

            Y.Array.each(this.get('items'), function (item) {
                itemsJSONified.push({
                    location: item.location.toJSON(),
                    contentInfo: item.location.get('contentInfo').toJSON(),
                    selectedLocationId: item.location.get('locationId') == this.get('selectLocationId') ? true : false,
                });
            }, this);
            container.setHTML(this.template({
                items: itemsJSONified,
                loadingError: this.get('loadingError'),
            }));
            return this;
        },

        /**
         * Custom reset implementation to explicitly reset the items.
         *
         * @method reset
         */
        reset: function (name) {
            if (name == 'items') {
                this.set('items', null);
            } else {
                this.constructor.superclass.reset.apply(this, arguments);
            }
        },

        /**
         * Scrolls to fully display the levelView.
         *
         * @method displayLevelView
         */
        displayLevelView: function () {
            this.get('container').one('.ez-ud-finder-explorerlevel-anchor').scrollIntoView({behavior: "smooth"});
        },

        /**
         * Handles user scrolling to determine if it needs to load more items.
         *
         * @method _handleScroll
         * @protected
         */
        _handleScroll: function () {
            var offset = this.get('offset'),
                limit = this.get('limit');

            if (this._watchingScroll && this._hasScrolledEnough() && limit + offset < this.get('childCount')) {
                this.set('offset', offset + limit);
            }
        },

        /**
         * Determines if user has scrolled enough to try to load other items.
         *
         * @method _hasScrolledEnough
         * @protected
         */
        _hasScrolledEnough: function () {
            var container = this.get('container');

            return container.get('scrollHeight') - container.get('scrollTop') <= 2 * container.get('offsetHeight');
        },

        /**
         * Fires the `locationSearch` event to fetch the result list of the search.
         *
         * @method _fireLocationSearch
         * @protected
         */
        _fireLocationSearch: function () {
            this.fire('locationSearch', {
                viewName: 'udwexplorerlevel-',
                resultAttribute: 'items',
                resultTotalCountAttribute: 'childCount',
                loadContent: true,
                loadContentType: true,
                search: {
                    filter: {
                        "ParentLocationIdCriterion": this.get('parentLocation').get('locationId'),
                    },
                    sortLocation: this.get('parentLocation'),
                    offset: this.get('offset'),
                    limit: this.get('limit'),
                },
            });
        },

        /**
         * items attribute setter. It sets items attribute with the results.
         *
         * @method _setItems
         * @param {Array} newItems
         * @protected
         */
        _setItems: function (newItems) {
            var items = [];

            Y.Array.each(newItems, function (hit) {
                var location = hit.location,
                    contentType = hit.contentType,
                    content = hit.content,
                    data = {
                        location: location,
                        contentInfo: location.get('contentInfo'),
                        contentType: contentType,
                        content: content,
                    };

                items.push(data);
            }, this);
            if (this.get('items')) {
                return  this.get('items').concat(items);
            } else {
                return items;
            }
        },

        /**
         * Finds location in item by a given locationId and returns the item.
         *
         * @method _findItemByLocationId
         * @param {Number} locationId
         * @protected
         * @return {Object} Returns an item containing a location.
         */
        _findItemByLocationId: function (locationId) {
            var item;

            Y.Array.each(this.get('items'), function (hit) {
                if (hit.location.get('locationId') == locationId) {
                    item = hit;
                }
            }, this);
            return item;
        },

        /**
         * Fires the `explorerNavigate` event to explore the chosen location.
         *
         * @method _fireExplorerNavigate
         * @protected
         */
        _fireExplorerNavigate: function (e) {
            var nodeLocationId = e.target.getData('location-id'),
                item = this._findItemByLocationId(nodeLocationId);

            if (!this.get('disabled') && (this.get('selectLocationId') != nodeLocationId || !this.get('ownSelectedItem')) && item) {
                this.set('selectLocationId', nodeLocationId);

                /**
                 * Navigates to the given item's location in the explorer.
                 *
                 * @event explorerNavigate
                 * @param {Object} data
                 * @param {eZ.Location} location
                 * @param {Number} depth
                 *
                 */
                this.fire('explorerNavigate', {
                    data: item,
                    location: item.location,
                    depth: this.get('depth')
                });
            }
        },
    }, {
        ATTRS: {
            /**
             * The items to display
             *
             * @attribute items
             * @type Array
             */
            items: {
                setter: function (resultList) {
                    if (resultList !== null) {
                        return this._setItems(resultList);
                    }
                }
            },

            /**
             * Defines if the level view own the current selected item
             *
             * @attribute ownSelecteditem
             * @type Boolean
             */
            ownSelectedItem: {
                value: false
            },

            /**
             * The location id of the selected item
             *
             * @attribute selectLocationId
             * @default 0
             * @type Number
             */
            selectLocationId: {
                value: 0
            },

            /**
             * The depth of the level view (the first level view depth is 1)
             *
             * @attribute depth
             * @type Number
             */
            depth: {},

            /**
             * The offset to start the locationSearch to
             *
             * @attribute offset
             * @type Number
             */
            offset: {
                value: 0
            },

            /**
             * The limit of the results
             *
             * @attribute limit
             * @type Number
             */
            limit: {
                value: 50
            },

            /**
             * The number of total child the parent location has.
             *
             * @attribute childCount
             * @type Number
             */
            childCount: {},

            /**
             * Boolean that tell if the view is disabled or not.
             * The items of a disabled level view can not be explored.
             * 
             * @attribute disabled
             * @writeOnce
             * @default false
             * @type Boolean
             */
            disabled: {
                writeOnce: 'initOnly',
                value: false,
            },
        },
    });
});