/**
 * DevExtreme (cjs/__internal/ui/collection/m_collection_widget.base.js)
 * Version: 24.1.7-build-24272-1937
 * Build date: Sat Sep 28 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.default = void 0;
var _action = _interopRequireDefault(require("../../../core/action"));
var _dom_adapter = _interopRequireDefault(require("../../../core/dom_adapter"));
var _element = require("../../../core/element");
var _guid = _interopRequireDefault(require("../../../core/guid"));
var _renderer = _interopRequireDefault(require("../../../core/renderer"));
var _bindable_template = require("../../../core/templates/bindable_template");
var _common = require("../../../core/utils/common");
var _data = require("../../../core/utils/data");
var _deferred = require("../../../core/utils/deferred");
var _extend = require("../../../core/utils/extend");
var _iterator = require("../../../core/utils/iterator");
var _size = require("../../../core/utils/size");
var _template_manager = require("../../../core/utils/template_manager");
var _type = require("../../../core/utils/type");
var _data_helper = _interopRequireDefault(require("../../../data_helper"));
var _click = require("../../../events/click");
var _contextmenu = require("../../../events/contextmenu");
var _events_engine = _interopRequireDefault(require("../../../events/core/events_engine"));
var _hold = _interopRequireDefault(require("../../../events/hold"));
var _pointer = _interopRequireDefault(require("../../../events/pointer"));
var _index = require("../../../events/utils/index");
var _message = _interopRequireDefault(require("../../../localization/message"));
var _selectors = require("../../../ui/widget/selectors");
var _ui = _interopRequireDefault(require("../../../ui/widget/ui.widget"));
var _m_item = _interopRequireDefault(require("./m_item"));

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    }
}

function _extends() {
    _extends = Object.assign ? Object.assign.bind() : function(target) {
        for (var i = 1; i < arguments.length; i++) {
            var source = arguments[i];
            for (var key in source) {
                if (Object.prototype.hasOwnProperty.call(source, key)) {
                    target[key] = source[key]
                }
            }
        }
        return target
    };
    return _extends.apply(this, arguments)
}
const COLLECTION_CLASS = "dx-collection";
const ITEM_CLASS = "dx-item";
const CONTENT_CLASS_POSTFIX = "-content";
const ITEM_CONTENT_PLACEHOLDER_CLASS = "dx-item-content-placeholder";
const ITEM_DATA_KEY = "dxItemData";
const ITEM_INDEX_KEY = "dxItemIndex";
const ITEM_TEMPLATE_ID_PREFIX = "tmpl-";
const ITEMS_OPTIONS_NAME = "dxItem";
const SELECTED_ITEM_CLASS = "dx-item-selected";
const ITEM_RESPONSE_WAIT_CLASS = "dx-item-response-wait";
const EMPTY_COLLECTION = "dx-empty-collection";
const TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper";
const ITEM_PATH_REGEX = /^([^.]+\[\d+\]\.)+([\w.]+)$/;
const ANONYMOUS_TEMPLATE_NAME = "item";
const FOCUS_UP = "up";
const FOCUS_DOWN = "down";
const FOCUS_LEFT = "left";
const FOCUS_RIGHT = "right";
const FOCUS_PAGE_UP = "pageup";
const FOCUS_PAGE_DOWN = "pagedown";
const FOCUS_LAST = "last";
const FOCUS_FIRST = "first";
const CollectionWidget = _ui.default.inherit({
    _activeStateUnit: `.${ITEM_CLASS}`,
    _supportedKeys() {
        const move = function(location, e) {
            if (!(0, _index.isCommandKeyPressed)(e)) {
                e.preventDefault();
                e.stopPropagation();
                this._moveFocus(location, e)
            }
        };
        return (0, _extend.extend)(this.callBase(), {
            space: function(e) {
                e.preventDefault();
                this._enterKeyHandler(e)
            },
            enter: this._enterKeyHandler,
            leftArrow: move.bind(this, "left"),
            rightArrow: move.bind(this, "right"),
            upArrow: move.bind(this, "up"),
            downArrow: move.bind(this, "down"),
            pageUp: move.bind(this, "up"),
            pageDown: move.bind(this, "down"),
            home: move.bind(this, "first"),
            end: move.bind(this, "last")
        })
    },
    _enterKeyHandler(e) {
        const $itemElement = (0, _renderer.default)(this.option("focusedElement"));
        if (!$itemElement.length) {
            return
        }
        const itemData = this._getItemData($itemElement);
        if (null !== itemData && void 0 !== itemData && itemData.onClick) {
            this._itemEventHandlerByHandler($itemElement, itemData.onClick, {
                event: e
            })
        }
        this._itemClickHandler((0, _extend.extend)({}, e, {
            target: $itemElement.get(0),
            currentTarget: $itemElement.get(0)
        }))
    },
    _getDefaultOptions() {
        return (0, _extend.extend)(this.callBase(), {
            selectOnFocus: false,
            loopItemFocus: true,
            items: [],
            itemTemplate: "item",
            onItemRendered: null,
            onItemClick: null,
            onItemHold: null,
            itemHoldTimeout: 750,
            onItemContextMenu: null,
            onFocusedItemChanged: null,
            noDataText: _message.default.format("dxCollectionWidget-noDataText"),
            encodeNoDataText: false,
            dataSource: null,
            _dataController: null,
            _itemAttributes: {},
            itemTemplateProperty: "template",
            focusOnSelectedItem: true,
            focusedElement: null,
            displayExpr: void 0,
            disabledExpr: data => data ? data.disabled : void 0,
            visibleExpr: data => data ? data.visible : void 0
        })
    },
    _init() {
        this._compileDisplayGetter();
        this._initDataController();
        this.callBase();
        this._cleanRenderedItems();
        this._refreshDataSource()
    },
    _compileDisplayGetter() {
        const displayExpr = this.option("displayExpr");
        this._displayGetter = displayExpr ? (0, _data.compileGetter)(this.option("displayExpr")) : void 0
    },
    _initTemplates() {
        this._initItemsFromMarkup();
        this._initDefaultItemTemplate();
        this.callBase()
    },
    _getAnonymousTemplateName: () => "item",
    _initDefaultItemTemplate() {
        const fieldsMap = this._getFieldsMap();
        this._templateManager.addDefaultTemplates({
            item: new _bindable_template.BindableTemplate((($container, data) => {
                if ((0, _type.isPlainObject)(data)) {
                    this._prepareDefaultItemTemplate(data, $container)
                } else {
                    if (fieldsMap && (0, _type.isFunction)(fieldsMap.text)) {
                        data = fieldsMap.text(data)
                    }
                    $container.text(String((0, _common.ensureDefined)(data, "")))
                }
            }), this._getBindableFields(), this.option("integrationOptions.watchMethod"), fieldsMap)
        })
    },
    _getBindableFields: () => ["text", "html"],
    _getFieldsMap() {
        if (this._displayGetter) {
            return {
                text: this._displayGetter
            }
        }
    },
    _prepareDefaultItemTemplate(data, $container) {
        if ((0, _type.isDefined)(data.text)) {
            $container.text(data.text)
        }
        if ((0, _type.isDefined)(data.html)) {
            $container.html(data.html)
        }
    },
    _initItemsFromMarkup() {
        const rawItems = (0, _template_manager.findTemplates)(this.$element(), "dxItem");
        if (!rawItems.length || this.option("items").length) {
            return
        }
        const items = rawItems.map((_ref => {
            let {
                element: element,
                options: options
            } = _ref;
            const isTemplateRequired = /\S/.test(element.innerHTML) && !options.template;
            if (isTemplateRequired) {
                options.template = this._prepareItemTemplate(element)
            } else {
                (0, _renderer.default)(element).remove()
            }
            return options
        }));
        this.option("items", items)
    },
    _prepareItemTemplate(item) {
        const templateId = "tmpl-" + new _guid.default;
        const $template = (0, _renderer.default)(item).detach().clone().removeAttr("data-options").addClass("dx-template-wrapper");
        this._saveTemplate(templateId, $template);
        return templateId
    },
    _dataSourceOptions: () => ({
        paginate: false
    }),
    _cleanRenderedItems() {
        this._renderedItemsCount = 0
    },
    _focusTarget() {
        return this.$element()
    },
    _focusInHandler(e) {
        this.callBase.apply(this, arguments);
        if (!this._isFocusTarget(e.target)) {
            return
        }
        const $focusedElement = (0, _renderer.default)(this.option("focusedElement"));
        if ($focusedElement.length) {
            this._setFocusedItem($focusedElement)
        } else {
            const $activeItem = this._getActiveItem();
            if ($activeItem.length) {
                this.option("focusedElement", (0, _element.getPublicElement)($activeItem))
            }
        }
    },
    _focusOutHandler() {
        this.callBase.apply(this, arguments);
        const $target = (0, _renderer.default)(this.option("focusedElement"));
        this._updateFocusedItemState($target, false)
    },
    _findActiveTarget($element) {
        return $element.find(this._activeStateUnit)
    },
    _getActiveItem(last) {
        const $focusedElement = (0, _renderer.default)(this.option("focusedElement"));
        if ($focusedElement.length) {
            return $focusedElement
        }
        let index = this.option("focusOnSelectedItem") ? this.option("selectedIndex") : 0;
        const activeElements = this._getActiveElement();
        const lastIndex = activeElements.length - 1;
        if (index < 0) {
            index = last ? lastIndex : 0
        }
        return activeElements.eq(index)
    },
    _moveFocus(location) {
        const $items = this._getAvailableItems();
        let $newTarget;
        switch (location) {
            case "pageup":
            case "up":
                $newTarget = this._prevItem($items);
                break;
            case "pagedown":
            case "down":
                $newTarget = this._nextItem($items);
                break;
            case "right":
                $newTarget = this.option("rtlEnabled") ? this._prevItem($items) : this._nextItem($items);
                break;
            case "left":
                $newTarget = this.option("rtlEnabled") ? this._nextItem($items) : this._prevItem($items);
                break;
            case "first":
                $newTarget = $items.first();
                break;
            case "last":
                $newTarget = $items.last();
                break;
            default:
                return false
        }
        if (0 !== $newTarget.length) {
            this.option("focusedElement", (0, _element.getPublicElement)($newTarget))
        }
    },
    _getVisibleItems($itemElements) {
        $itemElements = $itemElements || this._itemElements();
        return $itemElements.filter(":visible")
    },
    _getAvailableItems($itemElements) {
        return this._getVisibleItems($itemElements)
    },
    _prevItem($items) {
        const $target = this._getActiveItem();
        const targetIndex = $items.index($target);
        const $last = $items.last();
        let $item = (0, _renderer.default)($items[targetIndex - 1]);
        const loop = this.option("loopItemFocus");
        if (0 === $item.length && loop) {
            $item = $last
        }
        return $item
    },
    _nextItem($items) {
        const $target = this._getActiveItem(true);
        const targetIndex = $items.index($target);
        const $first = $items.first();
        let $item = (0, _renderer.default)($items[targetIndex + 1]);
        const loop = this.option("loopItemFocus");
        if (0 === $item.length && loop) {
            $item = $first
        }
        return $item
    },
    _selectFocusedItem($target) {
        this.selectItem($target)
    },
    _updateFocusedItemState(target, isFocused, needCleanItemId) {
        const $target = (0, _renderer.default)(target);
        if ($target.length) {
            this._refreshActiveDescendant();
            this._refreshItemId($target, needCleanItemId);
            this._toggleFocusClass(isFocused, $target)
        }
        this._updateParentActiveDescendant()
    },
    _refreshActiveDescendant($target) {
        this.setAria("activedescendant", (0, _type.isDefined)(this.option("focusedElement")) ? this.getFocusedItemId() : null, $target)
    },
    _refreshItemId($target, needCleanItemId) {
        if (!needCleanItemId && this.option("focusedElement")) {
            this.setAria("id", this.getFocusedItemId(), $target)
        } else {
            this.setAria("id", null, $target)
        }
    },
    _isDisabled: $element => $element && "true" === (0, _renderer.default)($element).attr("aria-disabled"),
    _setFocusedItem($target) {
        if (!$target || !$target.length) {
            return
        }
        this._updateFocusedItemState($target, true);
        this.onFocusedItemChanged(this.getFocusedItemId());
        const {
            selectOnFocus: selectOnFocus
        } = this.option();
        const isTargetDisabled = this._isDisabled($target);
        if (selectOnFocus && !isTargetDisabled) {
            this._selectFocusedItem($target)
        }
    },
    _findItemElementByItem(item) {
        let result = (0, _renderer.default)();
        const that = this;
        this.itemElements().each((function() {
            const $item = (0, _renderer.default)(this);
            if ($item.data(that._itemDataKey()) === item) {
                result = $item;
                return false
            }
        }));
        return result
    },
    _getIndexByItem(item) {
        return this.option("items").indexOf(item)
    },
    _itemOptionChanged(item, property, value, oldValue) {
        const $item = this._findItemElementByItem(item);
        if (!$item.length) {
            return
        }
        if (!this.constructor.ItemClass.getInstance($item).setDataField(property, value)) {
            this._refreshItem($item, item)
        }
        const isDisabling = "disabled" === property && value;
        if (isDisabling) {
            this._resetItemFocus($item)
        }
    },
    _resetItemFocus($item) {
        if ($item.is(this.option("focusedElement"))) {
            this.option("focusedElement", null)
        }
    },
    _refreshItem($item) {
        const itemData = this._getItemData($item);
        const index = $item.data(this._itemIndexKey());
        this._renderItem(this._renderedItemsCount + index, itemData, null, $item)
    },
    _updateParentActiveDescendant: _common.noop,
    _optionChanged(args) {
        if ("items" === args.name) {
            const matches = args.fullName.match(ITEM_PATH_REGEX);
            if (matches && matches.length) {
                const property = matches[matches.length - 1];
                const itemPath = args.fullName.replace(`.${property}`, "");
                const item = this.option(itemPath);
                this._itemOptionChanged(item, property, args.value, args.previousValue);
                return
            }
        }
        switch (args.name) {
            case "items":
            case "_itemAttributes":
            case "itemTemplateProperty":
            case "useItemTextAsTitle":
                this._cleanRenderedItems();
                this._invalidate();
                break;
            case "dataSource":
                this._refreshDataSource();
                this._renderEmptyMessage();
                break;
            case "noDataText":
            case "encodeNoDataText":
                this._renderEmptyMessage();
                break;
            case "itemTemplate":
            case "visibleExpr":
            case "disabledExpr":
                this._invalidate();
                break;
            case "onItemRendered":
                this._createItemRenderAction();
                break;
            case "onItemClick":
            case "selectOnFocus":
            case "loopItemFocus":
            case "focusOnSelectedItem":
                break;
            case "onItemHold":
            case "itemHoldTimeout":
                this._attachHoldEvent();
                break;
            case "onItemContextMenu":
                this._attachContextMenuEvent();
                break;
            case "onFocusedItemChanged":
                this.onFocusedItemChanged = this._createActionByOption("onFocusedItemChanged");
                break;
            case "focusedElement":
                this._updateFocusedItemState(args.previousValue, false, true);
                this._setFocusedItem((0, _renderer.default)(args.value));
                break;
            case "displayExpr":
                this._compileDisplayGetter();
                this._initDefaultItemTemplate();
                this._invalidate();
                break;
            default:
                this.callBase(args)
        }
    },
    _invalidate() {
        this.option("focusedElement", null);
        return this.callBase.apply(this, arguments)
    },
    _loadNextPage() {
        this._expectNextPageLoading();
        return this._dataController.loadNextPage()
    },
    _expectNextPageLoading() {
        this._startIndexForAppendedItems = 0
    },
    _expectLastItemLoading() {
        this._startIndexForAppendedItems = -1
    },
    _forgetNextPageLoading() {
        this._startIndexForAppendedItems = null
    },
    _dataSourceChangedHandler(newItems) {
        const items = this.option("items");
        if (this._initialized && items && this._shouldAppendItems()) {
            this._renderedItemsCount = items.length;
            if (!this._isLastPage() || -1 !== this._startIndexForAppendedItems) {
                this.option().items = items.concat(newItems.slice(this._startIndexForAppendedItems))
            }
            this._forgetNextPageLoading();
            this._refreshContent()
        } else {
            this.option("items", newItems.slice())
        }
    },
    _refreshContent() {
        this._prepareContent();
        this._renderContent()
    },
    _dataSourceLoadErrorHandler() {
        this._forgetNextPageLoading();
        this.option("items", this.option("items"))
    },
    _shouldAppendItems() {
        return null != this._startIndexForAppendedItems && this._allowDynamicItemsAppend()
    },
    _allowDynamicItemsAppend: () => false,
    _clean() {
        this._cleanFocusState();
        this._cleanItemContainer();
        this._inkRipple && delete this._inkRipple;
        this._resetActiveState()
    },
    _cleanItemContainer() {
        (0, _renderer.default)(this._itemContainer()).empty()
    },
    _dispose() {
        this.callBase();
        clearTimeout(this._itemFocusTimeout)
    },
    _refresh() {
        this._cleanRenderedItems();
        this.callBase.apply(this, arguments)
    },
    _itemContainer() {
        return this.$element()
    },
    _itemClass: () => ITEM_CLASS,
    _itemContentClass() {
        return this._itemClass() + "-content"
    },
    _selectedItemClass: () => "dx-item-selected",
    _itemResponseWaitClass: () => "dx-item-response-wait",
    _itemSelector() {
        return `.${this._itemClass()}`
    },
    _itemDataKey: () => "dxItemData",
    _itemIndexKey: () => "dxItemIndex",
    _itemElements() {
        return this._itemContainer().find(this._itemSelector())
    },
    _initMarkup() {
        this.callBase();
        this.onFocusedItemChanged = this._createActionByOption("onFocusedItemChanged");
        this.$element().addClass("dx-collection");
        this._prepareContent()
    },
    _prepareContent: (0, _common.deferRenderer)((function() {
        this._renderContentImpl()
    })),
    _renderContent() {
        this._fireContentReadyAction()
    },
    _render() {
        this.callBase();
        this._attachClickEvent();
        this._attachHoldEvent();
        this._attachContextMenuEvent()
    },
    _getPointerEvent: () => _pointer.default.down,
    _attachClickEvent() {
        const itemSelector = this._itemSelector();
        const pointerEvent = this._getPointerEvent();
        const clickEventNamespace = (0, _index.addNamespace)(_click.name, this.NAME);
        const pointerEventNamespace = (0, _index.addNamespace)(pointerEvent, this.NAME);
        const pointerAction = new _action.default((args => {
            const {
                event: event
            } = args;
            this._itemPointerDownHandler(event)
        }));
        _events_engine.default.off(this._itemContainer(), clickEventNamespace, itemSelector);
        _events_engine.default.off(this._itemContainer(), pointerEventNamespace, itemSelector);
        _events_engine.default.on(this._itemContainer(), clickEventNamespace, itemSelector, (e => this._itemClickHandler(e)));
        _events_engine.default.on(this._itemContainer(), pointerEventNamespace, itemSelector, (e => {
            pointerAction.execute({
                element: (0, _renderer.default)(e.target),
                event: e
            })
        }))
    },
    _itemClickHandler(e, args, config) {
        this._itemDXEventHandler(e, "onItemClick", args, config)
    },
    _itemPointerDownHandler(e) {
        if (!this.option("focusStateEnabled")) {
            return
        }
        this._itemFocusHandler = function() {
            clearTimeout(this._itemFocusTimeout);
            this._itemFocusHandler = null;
            if (e.isDefaultPrevented()) {
                return
            }
            const $target = (0, _renderer.default)(e.target);
            const $closestItem = $target.closest(this._itemElements());
            const $closestFocusable = this._closestFocusable($target);
            if ($closestItem.length && this._isFocusTarget(null === $closestFocusable || void 0 === $closestFocusable ? void 0 : $closestFocusable.get(0))) {
                this.option("focusedElement", (0, _element.getPublicElement)($closestItem))
            }
        }.bind(this);
        this._itemFocusTimeout = setTimeout(this._forcePointerDownFocus.bind(this))
    },
    _closestFocusable($target) {
        if ($target.is(_selectors.focusable)) {
            return $target
        }
        $target = $target.parent();
        while ($target.length && !_dom_adapter.default.isDocument($target.get(0)) && !_dom_adapter.default.isDocumentFragment($target.get(0))) {
            if ($target.is(_selectors.focusable)) {
                return $target
            }
            $target = $target.parent()
        }
    },
    _forcePointerDownFocus() {
        this._itemFocusHandler && this._itemFocusHandler()
    },
    _updateFocusState() {
        this.callBase.apply(this, arguments);
        this._forcePointerDownFocus()
    },
    _attachHoldEvent() {
        const $itemContainer = this._itemContainer();
        const itemSelector = this._itemSelector();
        const eventName = (0, _index.addNamespace)(_hold.default.name, this.NAME);
        _events_engine.default.off($itemContainer, eventName, itemSelector);
        _events_engine.default.on($itemContainer, eventName, itemSelector, {
            timeout: this._getHoldTimeout()
        }, this._itemHoldHandler.bind(this))
    },
    _getHoldTimeout() {
        return this.option("itemHoldTimeout")
    },
    _shouldFireHoldEvent() {
        return this.hasActionSubscription("onItemHold")
    },
    _itemHoldHandler(e) {
        if (this._shouldFireHoldEvent()) {
            this._itemDXEventHandler(e, "onItemHold")
        } else {
            e.cancel = true
        }
    },
    _attachContextMenuEvent() {
        const $itemContainer = this._itemContainer();
        const itemSelector = this._itemSelector();
        const eventName = (0, _index.addNamespace)(_contextmenu.name, this.NAME);
        _events_engine.default.off($itemContainer, eventName, itemSelector);
        _events_engine.default.on($itemContainer, eventName, itemSelector, this._itemContextMenuHandler.bind(this))
    },
    _shouldFireContextMenuEvent() {
        return this.hasActionSubscription("onItemContextMenu")
    },
    _itemContextMenuHandler(e) {
        if (this._shouldFireContextMenuEvent()) {
            this._itemDXEventHandler(e, "onItemContextMenu")
        } else {
            e.cancel = true
        }
    },
    _renderContentImpl() {
        const items = this.option("items") || [];
        if (this._renderedItemsCount) {
            this._renderItems(items.slice(this._renderedItemsCount))
        } else {
            this._renderItems(items)
        }
    },
    _renderItems(items) {
        if (items.length) {
            (0, _iterator.each)(items, ((index, itemData) => {
                this._renderItem(this._renderedItemsCount + index, itemData)
            }))
        }
        this._renderEmptyMessage()
    },
    _getItemsContainer() {
        return this._itemContainer()
    },
    _setAttributes($element) {
        const attributes = _extends({}, this.option("_itemAttributes"));
        const {
            class: customClassValue
        } = attributes;
        if (customClassValue) {
            const currentClassValue = $element.get(0).className;
            attributes.class = [currentClassValue, customClassValue].join(" ")
        }
        $element.attr(attributes)
    },
    _renderItem(index, itemData, $container, $itemToReplace) {
        const itemIndex = (null === index || void 0 === index ? void 0 : index.item) ?? index;
        $container = $container || this._getItemsContainer();
        const $itemFrame = this._renderItemFrame(itemIndex, itemData, $container, $itemToReplace);
        this._setElementData($itemFrame, itemData, itemIndex);
        this._setAttributes($itemFrame);
        this._attachItemClickEvent(itemData, $itemFrame);
        const $itemContent = this._getItemContent($itemFrame);
        const renderContentPromise = this._renderItemContent({
            index: itemIndex,
            itemData: itemData,
            container: (0, _element.getPublicElement)($itemContent),
            contentClass: this._itemContentClass(),
            defaultTemplateName: this.option("itemTemplate")
        });
        const that = this;
        (0, _deferred.when)(renderContentPromise).done(($itemContent => {
            that._postprocessRenderItem({
                itemElement: $itemFrame,
                itemContent: $itemContent,
                itemData: itemData,
                itemIndex: itemIndex
            });
            that._executeItemRenderAction(index, itemData, (0, _element.getPublicElement)($itemFrame))
        }));
        return $itemFrame
    },
    _getItemContent($itemFrame) {
        const $itemContent = $itemFrame.find(".dx-item-content-placeholder");
        $itemContent.removeClass("dx-item-content-placeholder");
        return $itemContent
    },
    _attachItemClickEvent(itemData, $itemElement) {
        if (!itemData || !itemData.onClick) {
            return
        }
        _events_engine.default.on($itemElement, _click.name, (e => {
            this._itemEventHandlerByHandler($itemElement, itemData.onClick, {
                event: e
            })
        }))
    },
    _renderItemContent(args) {
        const itemTemplateName = this._getItemTemplateName(args);
        const itemTemplate = this._getTemplate(itemTemplateName);
        this._addItemContentClasses(args);
        const $templateResult = (0, _renderer.default)(this._createItemByTemplate(itemTemplate, args));
        if (!$templateResult.hasClass("dx-template-wrapper")) {
            return args.container
        }
        return this._renderItemContentByNode(args, $templateResult)
    },
    _renderItemContentByNode(args, $node) {
        (0, _renderer.default)(args.container).replaceWith($node);
        args.container = (0, _element.getPublicElement)($node);
        this._addItemContentClasses(args);
        return $node
    },
    _addItemContentClasses(args) {
        const classes = [ITEM_CLASS + "-content", args.contentClass];
        (0, _renderer.default)(args.container).addClass(classes.join(" "))
    },
    _appendItemToContainer($container, $itemFrame, index) {
        $itemFrame.appendTo($container)
    },
    _renderItemFrame(index, itemData, $container, $itemToReplace) {
        const $itemFrame = (0, _renderer.default)("<div>");
        new this.constructor.ItemClass($itemFrame, this._itemOptions(), itemData || {});
        if ($itemToReplace && $itemToReplace.length) {
            $itemToReplace.replaceWith($itemFrame)
        } else {
            this._appendItemToContainer.call(this, $container, $itemFrame, index)
        }
        if (this.option("useItemTextAsTitle")) {
            const displayValue = this._displayGetter ? this._displayGetter(itemData) : itemData;
            $itemFrame.attr("title", displayValue)
        }
        return $itemFrame
    },
    _itemOptions() {
        const that = this;
        return {
            watchMethod: () => that.option("integrationOptions.watchMethod"),
            owner: that,
            fieldGetter(field) {
                const expr = that.option(`${field}Expr`);
                const getter = (0, _data.compileGetter)(expr);
                return getter
            }
        }
    },
    _postprocessRenderItem: _common.noop,
    _executeItemRenderAction(index, itemData, itemElement) {
        this._getItemRenderAction()({
            itemElement: itemElement,
            itemIndex: index,
            itemData: itemData
        })
    },
    _setElementData(element, data, index) {
        element.addClass([ITEM_CLASS, this._itemClass()].join(" ")).data(this._itemDataKey(), data).data(this._itemIndexKey(), index)
    },
    _createItemRenderAction() {
        return this._itemRenderAction = this._createActionByOption("onItemRendered", {
            element: this.element(),
            excludeValidators: ["disabled", "readOnly"],
            category: "rendering"
        })
    },
    _getItemRenderAction() {
        return this._itemRenderAction || this._createItemRenderAction()
    },
    _getItemTemplateName(args) {
        const data = args.itemData;
        const templateProperty = args.templateProperty || this.option("itemTemplateProperty");
        const template = data && data[templateProperty];
        return template || args.defaultTemplateName
    },
    _createItemByTemplate(itemTemplate, renderArgs) {
        return itemTemplate.render({
            model: renderArgs.itemData,
            container: renderArgs.container,
            index: renderArgs.index,
            onRendered: this._onItemTemplateRendered(itemTemplate, renderArgs)
        })
    },
    _onItemTemplateRendered: () => _common.noop,
    _emptyMessageContainer() {
        return this._itemContainer()
    },
    _renderEmptyMessage(items) {
        items = items || this.option("items");
        const noDataText = this.option("noDataText");
        const hideNoData = !noDataText || items && items.length || this._dataController.isLoading();
        if (hideNoData && this._$noData) {
            this._$noData.remove();
            this._$noData = null;
            this.setAria("label", void 0)
        }
        if (!hideNoData) {
            this._$noData = this._$noData || (0, _renderer.default)("<div>").addClass("dx-empty-message");
            this._$noData.appendTo(this._emptyMessageContainer());
            if (this.option("encodeNoDataText")) {
                this._$noData.text(noDataText)
            } else {
                this._$noData.html(noDataText)
            }
        }
        this.$element().toggleClass(EMPTY_COLLECTION, !hideNoData)
    },
    _itemDXEventHandler(dxEvent, handlerOptionName, actionArgs, actionConfig) {
        this._itemEventHandler(dxEvent.target, handlerOptionName, (0, _extend.extend)(actionArgs, {
            event: dxEvent
        }), actionConfig)
    },
    _itemEventHandler(initiator, handlerOptionName, actionArgs, actionConfig) {
        const action = this._createActionByOption(handlerOptionName, (0, _extend.extend)({
            validatingTargetName: "itemElement"
        }, actionConfig));
        return this._itemEventHandlerImpl(initiator, action, actionArgs)
    },
    _itemEventHandlerByHandler(initiator, handler, actionArgs, actionConfig) {
        const action = this._createAction(handler, (0, _extend.extend)({
            validatingTargetName: "itemElement"
        }, actionConfig));
        return this._itemEventHandlerImpl(initiator, action, actionArgs)
    },
    _itemEventHandlerImpl(initiator, action, actionArgs) {
        const $itemElement = this._closestItemElement((0, _renderer.default)(initiator));
        const args = (0, _extend.extend)({}, actionArgs);
        return action((0, _extend.extend)(actionArgs, this._extendActionArgs($itemElement), args))
    },
    _extendActionArgs($itemElement) {
        return {
            itemElement: (0, _element.getPublicElement)($itemElement),
            itemIndex: this._itemElements().index($itemElement),
            itemData: this._getItemData($itemElement)
        }
    },
    _closestItemElement($element) {
        return (0, _renderer.default)($element).closest(this._itemSelector())
    },
    _getItemData(itemElement) {
        return (0, _renderer.default)(itemElement).data(this._itemDataKey())
    },
    _getSummaryItemsSize(dimension, items, includeMargin) {
        let result = 0;
        if (items) {
            (0, _iterator.each)(items, ((_, item) => {
                if ("width" === dimension) {
                    result += (0, _size.getOuterWidth)(item, includeMargin || false)
                } else if ("height" === dimension) {
                    result += (0, _size.getOuterHeight)(item, includeMargin || false)
                }
            }))
        }
        return result
    },
    getFocusedItemId() {
        if (!this._focusedItemId) {
            this._focusedItemId = `dx-${new _guid.default}`
        }
        return this._focusedItemId
    },
    itemElements() {
        return this._itemElements()
    },
    itemsContainer() {
        return this._itemContainer()
    }
}).include(_data_helper.default);
CollectionWidget.ItemClass = _m_item.default;
var _default = exports.default = CollectionWidget;
