devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
1,137 lines (947 loc) • 37.3 kB
JavaScript
"use strict";
var $ = require("../../core/renderer"),
eventsEngine = require("../../events/core/events_engine"),
commonUtils = require("../../core/utils/common"),
getPublicElement = require("../../core/utils/dom").getPublicElement,
domAdapter = require("../../core/dom_adapter"),
isPlainObject = require("../../core/utils/type").isPlainObject,
when = require("../../core/utils/deferred").when,
extend = require("../../core/utils/extend").extend,
inArray = require("../../core/utils/array").inArray,
iteratorUtils = require("../../core/utils/iterator"),
Action = require("../../core/action"),
Guid = require("../../core/guid"),
domUtils = require("../../core/utils/dom"),
dataUtils = require("../../core/utils/data"),
Widget = require("../widget/ui.widget"),
eventUtils = require("../../events/utils"),
pointerEvents = require("../../events/pointer"),
DataHelperMixin = require("../../data_helper"),
CollectionWidgetItem = require("./item"),
selectors = require("../widget/selectors"),
messageLocalization = require("../../localization/message"),
holdEvent = require("../../events/hold"),
clickEvent = require("../../events/click"),
contextMenuEvent = require("../../events/contextmenu"),
BindableTemplate = require("../widget/bindable_template");
var COLLECTION_CLASS = "dx-collection",
ITEM_CLASS = "dx-item",
CONTENT_CLASS_POSTFIX = "-content",
ITEM_CONTENT_PLACEHOLDER_CLASS = "dx-item-content-placeholder",
ITEM_DATA_KEY = "dxItemData",
ITEM_INDEX_KEY = "dxItemIndex",
ITEM_TEMPLATE_ID_PREFIX = "tmpl-",
ITEMS_SELECTOR = "[data-options*='dxItem']",
SELECTED_ITEM_CLASS = "dx-item-selected",
ITEM_RESPONSE_WAIT_CLASS = "dx-item-response-wait",
EMPTY_COLLECTION = "dx-empty-collection",
TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper",
ITEM_PATH_REGEX = /^([^.]+\[\d+\]\.)+([\w\.]+)$/;
var FOCUS_UP = "up",
FOCUS_DOWN = "down",
FOCUS_LEFT = "left",
FOCUS_RIGHT = "right",
FOCUS_PAGE_UP = "pageup",
FOCUS_PAGE_DOWN = "pagedown",
FOCUS_LAST = "last",
FOCUS_FIRST = "first";
/**
* @name CollectionWidget
* @publicName CollectionWidget
* @type object
* @inherits Widget, DataHelperMixin
* @module ui/collection/ui.collection_widget.base
* @export default
* @hidden
*/
var CollectionWidget = Widget.inherit({
_activeStateUnit: "." + ITEM_CLASS,
_supportedKeys: function _supportedKeys() {
var enter = function enter(e) {
var $itemElement = $(this.option("focusedElement"));
if (!$itemElement.length) {
return;
}
e.target = $itemElement;
e.currentTarget = $itemElement;
this._itemClickHandler(e);
},
space = function space(e) {
e.preventDefault();
enter.call(this, e);
},
move = function move(location, e) {
e.preventDefault();
e.stopPropagation();
this._moveFocus(location, e);
};
return extend(this.callBase(), {
space: space,
enter: enter,
leftArrow: move.bind(this, FOCUS_LEFT),
rightArrow: move.bind(this, FOCUS_RIGHT),
upArrow: move.bind(this, FOCUS_UP),
downArrow: move.bind(this, FOCUS_DOWN),
pageUp: move.bind(this, FOCUS_UP),
pageDown: move.bind(this, FOCUS_DOWN),
home: move.bind(this, FOCUS_FIRST),
end: move.bind(this, FOCUS_LAST)
});
},
_getDefaultOptions: function _getDefaultOptions() {
return extend(this.callBase(), {
/**
* @name CollectionWidgetOptions.selectOnFocus
* @publicName selectOnFocus
* @type boolean
* @hidden
*/
selectOnFocus: false,
/**
* @name CollectionWidgetOptions.loopItemFocus
* @publicName loopItemFocus
* @type boolean
* @hidden
*/
loopItemFocus: true,
/**
* @name CollectionWidgetOptions.items
* @publicName items
* @type Array<string, object>
* @fires CollectionWidgetOptions.onOptionChanged
*/
items: [],
/**
* @name CollectionWidgetOptions.itemTemplate
* @publicName itemTemplate
* @type template|function
* @default "item"
* @type_function_param1 itemData:object
* @type_function_param2 itemIndex:number
* @type_function_param3 itemElement:dxElement
* @type_function_return string|Node|jQuery
*/
itemTemplate: "item",
/**
* @name CollectionWidgetOptions.onItemRendered
* @publicName onItemRendered
* @extends Action
* @type function(e)
* @type_function_param1 e:object
* @type_function_param1_field4 itemData:object
* @type_function_param1_field5 itemElement:dxElement
* @type_function_param1_field6 itemIndex:number
* @action
*/
onItemRendered: null,
/**
* @name CollectionWidgetOptions.onItemClick
* @publicName onItemClick
* @type function(e)|string
* @extends Action
* @type_function_param1 e:object
* @type_function_param1_field4 itemData:object
* @type_function_param1_field5 itemElement:dxElement
* @type_function_param1_field6 itemIndex:number
* @type_function_param1_field7 jQueryEvent:jQuery.Event:deprecated(event)
* @type_function_param1_field8 event:event
* @action
*/
onItemClick: null,
/**
* @name CollectionWidgetOptions.onItemHold
* @publicName onItemHold
* @extends Action
* @type function(e)
* @type_function_param1 e:object
* @type_function_param1_field4 itemData:object
* @type_function_param1_field5 itemElement:dxElement
* @type_function_param1_field6 itemIndex:number
* @action
*/
onItemHold: null,
/**
* @name CollectionWidgetOptions.itemHoldTimeout
* @publicName itemHoldTimeout
* @type number
* @default 750
*/
itemHoldTimeout: 750,
/**
* @name CollectionWidgetOptions.onItemContextMenu
* @publicName onItemContextMenu
* @extends Action
* @type function(e)
* @type_function_param1 e:object
* @type_function_param1_field4 itemData:object
* @type_function_param1_field5 itemElement:dxElement
* @type_function_param1_field6 itemIndex:number
* @type_function_param1_field7 jQueryEvent:jQuery.Event:deprecated(event)
* @type_function_param1_field8 event:event
* @action
*/
onItemContextMenu: null,
onFocusedItemChanged: null,
/**
* @name CollectionWidgetOptions.noDataText
* @publicName noDataText
* @type string
* @default "No data to display"
*/
noDataText: messageLocalization.format("dxCollectionWidget-noDataText"),
/**
* @name CollectionWidgetOptions.datasource
* @publicName dataSource
* @type string|Array<string,CollectionWidgetItemTemplate>|DataSource|DataSourceOptions
* @default null
*/
dataSource: null,
/**
* @name CollectionWidgetItemTemplate
* @publicName CollectionWidgetItemTemplate
* @type object
*/
/**
* @name CollectionWidgetItemTemplate.template
* @publicName template
* @type template|function
* @type_function_return string|Node|jQuery
*/
_itemAttributes: {},
itemTemplateProperty: "template",
focusOnSelectedItem: true,
/**
* @name CollectionWidgetOptions.focusedElement
* @publicName focusedElement
* @type dxElement
* @default null
* @hidden
* @inheritdoc
*/
focusedElement: null,
disabledExpr: function disabledExpr(data) {
return data ? data.disabled : undefined;
},
visibleExpr: function visibleExpr(data) {
return data ? data.visible : undefined;
}
/**
* @name CollectionWidgetItemTemplate.html
* @publicName html
* @type String
*/
/**
* @name CollectionWidgetItemTemplate.text
* @publicName text
* @type String
*/
/**
* @name CollectionWidgetItemTemplate.disabled
* @publicName disabled
* @type boolean
* @default false
*/
/**
* @name CollectionWidgetItemTemplate.visible
* @publicName visible
* @type boolean
* @default true
*/
});
},
_getAnonymousTemplateName: function _getAnonymousTemplateName() {
return "item";
},
_init: function _init() {
this.callBase();
this._cleanRenderedItems();
this._refreshDataSource();
},
_initTemplates: function _initTemplates() {
this._initItemsFromMarkup();
this.callBase();
this._defaultTemplates["item"] = new BindableTemplate(function ($container, data) {
if (isPlainObject(data)) {
this._prepareDefaultItemTemplate(data, $container);
} else {
$container.text(String(data));
}
}.bind(this), ["text", "html"], this.option("integrationOptions.watchMethod"));
},
_prepareDefaultItemTemplate: function _prepareDefaultItemTemplate(data, $container) {
if (data.text) {
$container.text(data.text);
}
if (data.html) {
$container.html(data.html);
}
},
_initItemsFromMarkup: function _initItemsFromMarkup() {
var $items = this.$element().contents().filter(ITEMS_SELECTOR);
if (!$items.length || this.option("items").length) {
return;
}
var items = iteratorUtils.map($items, function (item) {
var $item = $(item);
var result = domUtils.getElementOptions(item).dxItem;
var isTemplateRequired = $item.html().trim() && !result.template;
if (isTemplateRequired) {
result.template = this._prepareItemTemplate($item);
} else {
$item.remove();
}
return result;
}.bind(this));
this.option("items", items);
},
_prepareItemTemplate: function _prepareItemTemplate($item) {
var templateId = ITEM_TEMPLATE_ID_PREFIX + new Guid();
var templateOptions = "dxTemplate: { name: \"" + templateId + "\" }";
$item.detach().clone().attr("data-options", templateOptions).data("options", templateOptions).appendTo(this.$element());
return templateId;
},
_dataSourceOptions: function _dataSourceOptions() {
return { paginate: false };
},
_cleanRenderedItems: function _cleanRenderedItems() {
this._renderedItemsCount = 0;
},
_focusTarget: function _focusTarget() {
return this.$element();
},
_focusInHandler: function _focusInHandler(e) {
this.callBase.apply(this, arguments);
if (inArray(e.target, this._focusTarget()) === -1) {
return;
}
var $focusedElement = $(this.option("focusedElement"));
if ($focusedElement.length) {
this._setFocusedItem($focusedElement);
} else {
var $activeItem = this._getActiveItem();
if ($activeItem.length) {
this.option("focusedElement", getPublicElement($activeItem));
}
}
},
_focusOutHandler: function _focusOutHandler() {
this.callBase.apply(this, arguments);
var $target = $(this.option("focusedElement"));
if ($target.length) {
this._toggleFocusClass(false, $target);
}
},
_getActiveItem: function _getActiveItem(last) {
var $focusedElement = $(this.option("focusedElement"));
if ($focusedElement.length) {
return $focusedElement;
}
var index = this.option("focusOnSelectedItem") ? this.option("selectedIndex") : 0,
activeElements = this._getActiveElement(),
lastIndex = activeElements.length - 1;
if (index < 0) {
index = last ? lastIndex : 0;
}
return activeElements.eq(index);
},
_renderFocusTarget: function _renderFocusTarget() {
this.callBase.apply(this, arguments);
this._refreshActiveDescendant();
},
_moveFocus: function _moveFocus(location) {
var $items = this._getAvailableItems(),
$newTarget;
switch (location) {
case FOCUS_PAGE_UP:
case FOCUS_UP:
$newTarget = this._prevItem($items);
break;
case FOCUS_PAGE_DOWN:
case FOCUS_DOWN:
$newTarget = this._nextItem($items);
break;
case FOCUS_RIGHT:
$newTarget = this.option("rtlEnabled") ? this._prevItem($items) : this._nextItem($items);
break;
case FOCUS_LEFT:
$newTarget = this.option("rtlEnabled") ? this._nextItem($items) : this._prevItem($items);
break;
case FOCUS_FIRST:
$newTarget = $items.first();
break;
case FOCUS_LAST:
$newTarget = $items.last();
break;
default:
return false;
}
if ($newTarget.length !== 0) {
this.option("focusedElement", getPublicElement($newTarget));
}
},
_getAvailableItems: function _getAvailableItems($itemElements) {
$itemElements = $itemElements || this._itemElements();
return $itemElements.filter(":visible").not(".dx-state-disabled");
},
_prevItem: function _prevItem($items) {
var $target = this._getActiveItem(),
targetIndex = $items.index($target),
$last = $items.last(),
$item = $($items[targetIndex - 1]),
loop = this.option("loopItemFocus");
if ($item.length === 0 && loop) {
$item = $last;
}
return $item;
},
_nextItem: function _nextItem($items) {
var $target = this._getActiveItem(true),
targetIndex = $items.index($target),
$first = $items.first(),
$item = $($items[targetIndex + 1]),
loop = this.option("loopItemFocus");
if ($item.length === 0 && loop) {
$item = $first;
}
return $item;
},
_selectFocusedItem: function _selectFocusedItem($target) {
this.selectItem($target);
},
_removeFocusedItem: function _removeFocusedItem(target) {
var $target = $(target);
if ($target.length) {
this._toggleFocusClass(false, $target);
$target.removeAttr("id");
}
},
_refreshActiveDescendant: function _refreshActiveDescendant() {
this.setAria("activedescendant", "");
this.setAria("activedescendant", this.getFocusedItemId());
},
_setFocusedItem: function _setFocusedItem($target) {
if (!$target || !$target.length) {
return;
}
$target.attr("id", this.getFocusedItemId());
this._toggleFocusClass(true, $target);
this.onFocusedItemChanged(this.getFocusedItemId());
this._refreshActiveDescendant();
if (this.option("selectOnFocus")) {
this._selectFocusedItem($target);
}
},
_findItemElementByItem: function _findItemElementByItem(item) {
var result = $(),
that = this;
this.itemElements().each(function () {
var $item = $(this);
if ($item.data(that._itemDataKey()) === item) {
result = $item;
return false;
}
});
return result;
},
_getIndexByItem: function _getIndexByItem(item) {
return this.option("items").indexOf(item);
},
_itemOptionChanged: function _itemOptionChanged(item, property, value, oldValue) {
var $item = this._findItemElementByItem(item);
if (!$item.length) {
return;
}
if (!this.constructor.ItemClass.getInstance($item).setDataField(property, value)) {
this._refreshItem($item, item);
}
},
_refreshItem: function _refreshItem($item) {
var itemData = this._getItemData($item),
index = $item.data(this._itemIndexKey());
this._renderItem(index, itemData, null, $item);
},
_optionChanged: function _optionChanged(args) {
if (args.name === "items") {
var matches = args.fullName.match(ITEM_PATH_REGEX);
if (matches && matches.length) {
var property = matches[matches.length - 1],
itemPath = args.fullName.replace("." + property, ""),
item = this.option(itemPath);
this._itemOptionChanged(item, property, args.value, args.previousValue);
return;
}
}
switch (args.name) {
case "items":
case "_itemAttributes":
case "itemTemplateProperty":
this._cleanRenderedItems();
this._invalidate();
break;
case "dataSource":
this.option("items", []);
this._refreshDataSource();
this._renderEmptyMessage();
break;
case "noDataText":
this._renderEmptyMessage();
break;
case "itemTemplate":
this._invalidate();
break;
case "onItemRendered":
this._createItemRenderAction();
break;
case "onItemClick":
break;
case "onItemHold":
case "itemHoldTimeout":
this._attachHoldEvent();
break;
case "onItemContextMenu":
this._attachContextMenuEvent();
break;
case "onFocusedItemChanged":
this.onFocusedItemChanged = this._createActionByOption("onFocusedItemChanged");
break;
case "selectOnFocus":
case "loopItemFocus":
case "focusOnSelectedItem":
break;
case "focusedElement":
this._removeFocusedItem(args.previousValue);
this._setFocusedItem($(args.value));
break;
case "visibleExpr":
case "disabledExpr":
this._invalidate();
break;
default:
this.callBase(args);
}
},
_loadNextPage: function _loadNextPage() {
var dataSource = this._dataSource;
this._expectNextPageLoading();
dataSource.pageIndex(1 + dataSource.pageIndex());
return dataSource.load();
},
_expectNextPageLoading: function _expectNextPageLoading() {
this._startIndexForAppendedItems = 0;
},
_expectLastItemLoading: function _expectLastItemLoading() {
this._startIndexForAppendedItems = -1;
},
_forgetNextPageLoading: function _forgetNextPageLoading() {
this._startIndexForAppendedItems = null;
},
_dataSourceChangedHandler: function _dataSourceChangedHandler(newItems) {
var items = this.option("items");
if (this._initialized && items && this._shouldAppendItems()) {
this._renderedItemsCount = items.length;
if (!this._isLastPage() || this._startIndexForAppendedItems !== -1) {
this.option().items = items.concat(newItems.slice(this._startIndexForAppendedItems));
}
this._forgetNextPageLoading();
this._refreshContent();
this._renderFocusTarget();
} else {
this.option("items", newItems);
}
},
_refreshContent: function _refreshContent() {
this._prepareContent();
this._renderContent();
},
_dataSourceLoadErrorHandler: function _dataSourceLoadErrorHandler() {
this._forgetNextPageLoading();
this.option("items", this.option("items"));
},
_shouldAppendItems: function _shouldAppendItems() {
return this._startIndexForAppendedItems != null && this._allowDynamicItemsAppend();
},
_allowDynamicItemsAppend: function _allowDynamicItemsAppend() {
return false;
},
_clean: function _clean() {
this._cleanFocusState();
this._cleanItemContainer();
},
_cleanItemContainer: function _cleanItemContainer() {
$(this._itemContainer()).empty();
},
_dispose: function _dispose() {
this.callBase();
clearTimeout(this._itemFocusTimeout);
},
_refresh: function _refresh() {
this._cleanRenderedItems();
this.callBase.apply(this, arguments);
},
_itemContainer: function _itemContainer() {
return this.$element();
},
_itemClass: function _itemClass() {
return ITEM_CLASS;
},
_itemContentClass: function _itemContentClass() {
return this._itemClass() + CONTENT_CLASS_POSTFIX;
},
_selectedItemClass: function _selectedItemClass() {
return SELECTED_ITEM_CLASS;
},
_itemResponseWaitClass: function _itemResponseWaitClass() {
return ITEM_RESPONSE_WAIT_CLASS;
},
_itemSelector: function _itemSelector() {
return "." + this._itemClass();
},
_itemDataKey: function _itemDataKey() {
return ITEM_DATA_KEY;
},
_itemIndexKey: function _itemIndexKey() {
return ITEM_INDEX_KEY;
},
_itemElements: function _itemElements() {
return this._itemContainer().find(this._itemSelector());
},
_initMarkup: function _initMarkup() {
this.callBase();
this.onFocusedItemChanged = this._createActionByOption("onFocusedItemChanged");
this.$element().addClass(COLLECTION_CLASS);
this._prepareContent();
},
_prepareContent: function _prepareContent() {
var that = this;
commonUtils.deferRender(function () {
that._renderContentImpl();
});
},
_renderContent: function _renderContent() {
this._fireContentReadyAction();
},
_render: function _render() {
this.callBase();
this._attachClickEvent();
this._attachHoldEvent();
this._attachContextMenuEvent();
},
_attachClickEvent: function _attachClickEvent() {
var itemSelector = this._itemSelector(),
clickEventNamespace = eventUtils.addNamespace(clickEvent.name, this.NAME),
pointerDownEventNamespace = eventUtils.addNamespace(pointerEvents.down, this.NAME),
that = this;
var pointerDownAction = new Action(function (args) {
var event = args.event;
that._itemPointerDownHandler(event);
});
eventsEngine.off(this._itemContainer(), clickEventNamespace, itemSelector);
eventsEngine.off(this._itemContainer(), pointerDownEventNamespace, itemSelector);
eventsEngine.on(this._itemContainer(), clickEventNamespace, itemSelector, function (e) {
this._itemClickHandler(e);
}.bind(this));
eventsEngine.on(this._itemContainer(), pointerDownEventNamespace, itemSelector, function (e) {
pointerDownAction.execute({
element: $(e.target),
event: e
});
});
},
_itemClickHandler: function _itemClickHandler(e, args, config) {
this._itemDXEventHandler(e, "onItemClick", args, config);
},
_itemPointerDownHandler: function _itemPointerDownHandler(e) {
if (!this.option("focusStateEnabled")) {
return;
}
this._itemFocusHandler = function () {
clearTimeout(this._itemFocusTimeout);
this._itemFocusHandler = null;
if (e.isDefaultPrevented()) {
return;
}
var $target = $(e.target),
$closestItem = $target.closest(this._itemElements()),
$closestFocusable = this._closestFocusable($target);
if ($closestItem.length && $closestFocusable && inArray($closestFocusable.get(0), this._focusTarget()) !== -1) {
this.option("focusedElement", getPublicElement($closestItem));
}
}.bind(this);
this._itemFocusTimeout = setTimeout(this._forcePointerDownFocus.bind(this));
},
_closestFocusable: function _closestFocusable($target) {
if ($target.is(selectors.focusable)) {
return $target;
} else {
$target = $target.parent();
while ($target.length && !domAdapter.isDocument($target.get(0))) {
if ($target.is(selectors.focusable)) {
return $target;
}
$target = $target.parent();
}
}
},
_forcePointerDownFocus: function _forcePointerDownFocus() {
this._itemFocusHandler && this._itemFocusHandler();
},
_updateFocusState: function _updateFocusState() {
this.callBase.apply(this, arguments);
this._forcePointerDownFocus();
},
_attachHoldEvent: function _attachHoldEvent() {
var $itemContainer = this._itemContainer(),
itemSelector = this._itemSelector(),
eventName = eventUtils.addNamespace(holdEvent.name, this.NAME);
eventsEngine.off($itemContainer, eventName, itemSelector);
eventsEngine.on($itemContainer, eventName, itemSelector, { timeout: this._getHoldTimeout() }, this._itemHoldHandler.bind(this));
},
_getHoldTimeout: function _getHoldTimeout() {
return this.option("itemHoldTimeout");
},
_shouldFireHoldEvent: function _shouldFireHoldEvent() {
return this.hasActionSubscription("onItemHold");
},
_itemHoldHandler: function _itemHoldHandler(e) {
if (this._shouldFireHoldEvent()) {
this._itemDXEventHandler(e, "onItemHold");
} else {
e.cancel = true;
}
},
_attachContextMenuEvent: function _attachContextMenuEvent() {
var $itemContainer = this._itemContainer(),
itemSelector = this._itemSelector(),
eventName = eventUtils.addNamespace(contextMenuEvent.name, this.NAME);
eventsEngine.off($itemContainer, eventName, itemSelector);
eventsEngine.on($itemContainer, eventName, itemSelector, this._itemContextMenuHandler.bind(this));
},
_shouldFireContextMenuEvent: function _shouldFireContextMenuEvent() {
return this.hasActionSubscription("onItemContextMenu");
},
_itemContextMenuHandler: function _itemContextMenuHandler(e) {
if (this._shouldFireContextMenuEvent()) {
this._itemDXEventHandler(e, "onItemContextMenu");
} else {
e.cancel = true;
}
},
_renderContentImpl: function _renderContentImpl() {
var items = this.option("items") || [];
if (this._renderedItemsCount) {
this._renderItems(items.slice(this._renderedItemsCount));
} else {
this._renderItems(items);
}
},
_renderItems: function _renderItems(items) {
if (items.length) {
iteratorUtils.each(items, this._renderItem.bind(this));
}
this._renderEmptyMessage();
},
_renderItem: function _renderItem(index, itemData, $container, $itemToReplace) {
$container = $container || this._itemContainer();
var $itemFrame = this._renderItemFrame(index, itemData, $container, $itemToReplace);
this._setElementData($itemFrame, itemData, index);
$itemFrame.attr(this.option("_itemAttributes"));
this._attachItemClickEvent(itemData, $itemFrame);
var $itemContent = this._getItemContent($itemFrame);
var renderContentPromise = this._renderItemContent({
index: index,
itemData: itemData,
container: getPublicElement($itemContent),
contentClass: this._itemContentClass(),
defaultTemplateName: this.option("itemTemplate")
});
var that = this;
when(renderContentPromise).done(function ($itemContent) {
that._postprocessRenderItem({
itemElement: $itemFrame,
itemContent: $itemContent,
itemData: itemData,
itemIndex: index
});
that._executeItemRenderAction(index, itemData, getPublicElement($itemFrame));
});
return $itemFrame;
},
_getItemContent: function _getItemContent($itemFrame) {
var $itemContent = $itemFrame.find("." + ITEM_CONTENT_PLACEHOLDER_CLASS);
$itemContent.removeClass(ITEM_CONTENT_PLACEHOLDER_CLASS);
return $itemContent;
},
_attachItemClickEvent: function _attachItemClickEvent(itemData, $itemElement) {
if (!itemData || !itemData.onClick) {
return;
}
eventsEngine.on($itemElement, clickEvent.name, function (e) {
this._itemEventHandlerByHandler($itemElement, itemData.onClick, {
event: e
});
}.bind(this));
},
_renderItemContent: function _renderItemContent(args) {
var itemTemplateName = this._getItemTemplateName(args);
var itemTemplate = this._getTemplate(itemTemplateName);
this._addItemContentClasses(args);
var $templateResult = $(this._createItemByTemplate(itemTemplate, args));
if (!$templateResult.hasClass(TEMPLATE_WRAPPER_CLASS)) {
return args.container;
}
return this._renderItemContentByNode(args, $templateResult);
},
_renderItemContentByNode: function _renderItemContentByNode(args, $node) {
$(args.container).replaceWith($node);
args.container = getPublicElement($node);
this._addItemContentClasses(args);
return $node;
},
_addItemContentClasses: function _addItemContentClasses(args) {
var classes = [ITEM_CLASS + CONTENT_CLASS_POSTFIX, args.contentClass];
$(args.container).addClass(classes.join(" "));
},
_renderItemFrame: function _renderItemFrame(index, itemData, $container, $itemToReplace) {
var $itemFrame = $("<div>");
new this.constructor.ItemClass($itemFrame, this._itemOptions(), itemData || {});
if ($itemToReplace && $itemToReplace.length) {
$itemToReplace.replaceWith($itemFrame);
} else {
$itemFrame.appendTo($container);
}
return $itemFrame;
},
_itemOptions: function _itemOptions() {
var that = this;
return {
watchMethod: function watchMethod() {
return that.option("integrationOptions.watchMethod");
},
fieldGetter: function fieldGetter(field) {
var expr = that.option(field + "Expr"),
getter = dataUtils.compileGetter(expr);
return getter;
}
};
},
_postprocessRenderItem: commonUtils.noop,
_executeItemRenderAction: function _executeItemRenderAction(index, itemData, itemElement) {
this._getItemRenderAction()({
itemElement: itemElement,
itemIndex: index,
itemData: itemData
});
},
_setElementData: function _setElementData(element, data, index) {
element.addClass([ITEM_CLASS, this._itemClass()].join(" ")).data(this._itemDataKey(), data).data(this._itemIndexKey(), index);
},
_createItemRenderAction: function _createItemRenderAction() {
return this._itemRenderAction = this._createActionByOption("onItemRendered", {
element: this.element(),
excludeValidators: ["designMode", "disabled", "readOnly"],
category: "rendering"
});
},
_getItemRenderAction: function _getItemRenderAction() {
return this._itemRenderAction || this._createItemRenderAction();
},
_getItemTemplateName: function _getItemTemplateName(args) {
var data = args.itemData,
templateProperty = args.templateProperty || this.option("itemTemplateProperty"),
template = data && data[templateProperty];
return template || args.defaultTemplateName;
},
_createItemByTemplate: function _createItemByTemplate(itemTemplate, renderArgs) {
return itemTemplate.render({
model: renderArgs.itemData,
container: renderArgs.container,
index: renderArgs.index
});
},
_emptyMessageContainer: function _emptyMessageContainer() {
return this._itemContainer();
},
_renderEmptyMessage: function _renderEmptyMessage(items) {
items = items || this.option("items");
var noDataText = this.option("noDataText"),
hideNoData = !noDataText || items && items.length || this._isDataSourceLoading();
if (hideNoData && this._$noData) {
this._$noData.remove();
this._$noData = null;
this.setAria("label", undefined);
}
if (!hideNoData) {
this._$noData = this._$noData || $("<div>").addClass("dx-empty-message");
this._$noData.appendTo(this._emptyMessageContainer()).html(noDataText);
this.setAria("label", noDataText);
}
this.$element().toggleClass(EMPTY_COLLECTION, !hideNoData);
},
_itemDXEventHandler: function _itemDXEventHandler(dxEvent, handlerOptionName, actionArgs, actionConfig) {
this._itemEventHandler(dxEvent.target, handlerOptionName, extend(actionArgs, {
event: dxEvent
}), actionConfig);
},
_itemEventHandler: function _itemEventHandler(initiator, handlerOptionName, actionArgs, actionConfig) {
var action = this._createActionByOption(handlerOptionName, extend({
validatingTargetName: "itemElement"
}, actionConfig));
return this._itemEventHandlerImpl(initiator, action, actionArgs);
},
_itemEventHandlerByHandler: function _itemEventHandlerByHandler(initiator, handler, actionArgs, actionConfig) {
var action = this._createAction(handler, extend({
validatingTargetName: "itemElement"
}, actionConfig));
return this._itemEventHandlerImpl(initiator, action, actionArgs);
},
_itemEventHandlerImpl: function _itemEventHandlerImpl(initiator, action, actionArgs) {
var $itemElement = this._closestItemElement($(initiator)),
args = extend({}, actionArgs);
return action(extend(actionArgs, this._extendActionArgs($itemElement), args));
},
_extendActionArgs: function _extendActionArgs($itemElement) {
return {
itemElement: getPublicElement($itemElement),
itemIndex: this._itemElements().index($itemElement),
itemData: this._getItemData($itemElement)
};
},
_closestItemElement: function _closestItemElement($element) {
return $($element).closest(this._itemSelector());
},
_getItemData: function _getItemData(itemElement) {
return $(itemElement).data(this._itemDataKey());
},
/**
* @name CollectionWidgetmethods.getFocusedItemId
* @publicName getFocusedItemId()
* @return string
* @hidden
*/
getFocusedItemId: function getFocusedItemId() {
if (!this._focusedItemId) {
this._focusedItemId = "dx-" + new Guid();
}
return this._focusedItemId;
},
/**
* @name CollectionWidgetmethods.itemElements
* @publicName itemElements()
* @return Array<Node>
* @hidden
*/
itemElements: function itemElements() {
return this._itemElements();
},
/**
* @name CollectionWidgetmethods.itemsContainer
* @publicName itemsContainer()
* @return Node
* @hidden
*/
itemsContainer: function itemsContainer() {
return this._itemContainer();
}
}).include(DataHelperMixin);
CollectionWidget.ItemClass = CollectionWidgetItem;
module.exports = CollectionWidget;