devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
362 lines (286 loc) • 12 kB
JavaScript
"use strict";
var $ = require("../../core/renderer"),
commonUtils = require("../../core/utils/common"),
isPlainObject = require("../../core/utils/type").isPlainObject,
registerComponent = require("../../core/component_registrator"),
inArray = require("../../core/utils/array").inArray,
extend = require("../../core/utils/extend").extend,
each = require("../../core/utils/iterator").each,
CollectionWidget = require("../collection/ui.collection_widget.edit"),
BindableTemplate = require("../widget/bindable_template");
var TOOLBAR_CLASS = "dx-toolbar",
TOOLBAR_BEFORE_CLASS = "dx-toolbar-before",
TOOLBAR_CENTER_CLASS = "dx-toolbar-center",
TOOLBAR_AFTER_CLASS = "dx-toolbar-after",
TOOLBAR_BOTTOM_CLASS = "dx-toolbar-bottom",
TOOLBAR_MINI_CLASS = "dx-toolbar-mini",
TOOLBAR_ITEM_CLASS = "dx-toolbar-item",
TOOLBAR_LABEL_CLASS = "dx-toolbar-label",
TOOLBAR_BUTTON_CLASS = "dx-toolbar-button",
TOOLBAR_ITEMS_CONTAINER_CLASS = "dx-toolbar-items-container",
TOOLBAR_GROUP_CLASS = "dx-toolbar-group",
TOOLBAR_LABEL_SELECTOR = "." + TOOLBAR_LABEL_CLASS,
TOOLBAR_ITEM_DATA_KEY = "dxToolbarItemDataKey";
var ToolbarBase = CollectionWidget.inherit({
/**
* @name dxToolbarItemTemplate
* @publicName dxToolbarItemTemplate
* @inherits CollectionWidgetItemTemplate
* @type object
*/
/**
* @name dxToolbarItemTemplate.widget
* @publicName widget
* @type Enums.ToolbarItemWidget
*/
/**
* @name dxToolbarItemTemplate.options
* @publicName options
* @type object
*/
_initTemplates: function _initTemplates() {
this.callBase();
var template = new BindableTemplate(function ($container, data, rawModel) {
if (isPlainObject(data)) {
if (data.text) {
$container.text(data.text).wrapInner("<div>");
}
if (data.html) {
$container.html(data.html);
}
} else {
$container.text(String(data));
}
this._getTemplate("dx-polymorph-widget").render({
container: $container,
model: rawModel
});
}.bind(this), ["text", "html", "widget", "options"], this.option("integrationOptions.watchMethod"));
this._defaultTemplates["item"] = template;
this._defaultTemplates["menuItem"] = template;
},
_getDefaultOptions: function _getDefaultOptions() {
return extend(this.callBase(), {
renderAs: "topToolbar"
});
},
_itemContainer: function _itemContainer() {
return this._$toolbarItemsContainer.find(["." + TOOLBAR_BEFORE_CLASS, "." + TOOLBAR_CENTER_CLASS, "." + TOOLBAR_AFTER_CLASS].join(","));
},
_itemClass: function _itemClass() {
return TOOLBAR_ITEM_CLASS;
},
_itemDataKey: function _itemDataKey() {
return TOOLBAR_ITEM_DATA_KEY;
},
_buttonClass: function _buttonClass() {
return TOOLBAR_BUTTON_CLASS;
},
_dimensionChanged: function _dimensionChanged() {
this._arrangeItems();
},
_initMarkup: function _initMarkup() {
this._renderToolbar();
this._renderSections();
this.callBase();
this.setAria("role", "toolbar");
},
_render: function _render() {
this.callBase();
this._arrangeItems();
},
_renderToolbar: function _renderToolbar() {
this.$element().addClass(TOOLBAR_CLASS).toggleClass(TOOLBAR_BOTTOM_CLASS, this.option("renderAs") === "bottomToolbar");
this._$toolbarItemsContainer = $("<div>").addClass(TOOLBAR_ITEMS_CONTAINER_CLASS).appendTo(this.$element());
},
_renderSections: function _renderSections() {
var $container = this._$toolbarItemsContainer,
that = this;
each(["before", "center", "after"], function () {
var sectionClass = "dx-toolbar-" + this,
$section = $container.find("." + sectionClass);
if (!$section.length) {
that["_$" + this + "Section"] = $section = $("<div>").addClass(sectionClass).appendTo($container);
}
});
},
_arrangeItems: function _arrangeItems(elementWidth) {
elementWidth = elementWidth || this.$element().width();
this._$centerSection.css({
margin: "0 auto",
float: "none"
});
var beforeRect = this._$beforeSection.get(0).getBoundingClientRect(),
afterRect = this._$afterSection.get(0).getBoundingClientRect();
this._alignCenterSection(beforeRect, afterRect, elementWidth);
var $label = this._$toolbarItemsContainer.find(TOOLBAR_LABEL_SELECTOR).eq(0),
$section = $label.parent();
if (!$label.length) {
return;
}
var labelOffset = beforeRect.width ? beforeRect.width : $label.position().left,
widthBeforeSection = $section.hasClass(TOOLBAR_BEFORE_CLASS) ? 0 : labelOffset,
widthAfterSection = $section.hasClass(TOOLBAR_AFTER_CLASS) ? 0 : afterRect.width,
elemsAtSectionWidth = 0;
$section.children().not(TOOLBAR_LABEL_SELECTOR).each(function () {
elemsAtSectionWidth += $(this).outerWidth();
});
var freeSpace = elementWidth - elemsAtSectionWidth,
sectionMaxWidth = Math.max(freeSpace - widthBeforeSection - widthAfterSection, 0);
if ($section.hasClass(TOOLBAR_BEFORE_CLASS)) {
this._alignSection(this._$beforeSection, sectionMaxWidth);
} else {
var labelPaddings = $label.outerWidth() - $label.width();
$label.css("maxWidth", sectionMaxWidth - labelPaddings);
}
},
_alignCenterSection: function _alignCenterSection(beforeRect, afterRect, elementWidth) {
this._alignSection(this._$centerSection, elementWidth - beforeRect.width - afterRect.width);
var isRTL = this.option("rtlEnabled"),
leftRect = isRTL ? afterRect : beforeRect,
rightRect = isRTL ? beforeRect : afterRect,
centerRect = this._$centerSection.get(0).getBoundingClientRect();
if (leftRect.right > centerRect.left || centerRect.right > rightRect.left) {
this._$centerSection.css({
marginLeft: leftRect.width,
marginRight: rightRect.width,
float: leftRect.width > rightRect.width ? "none" : "right"
});
}
},
_alignSection: function _alignSection($section, maxWidth) {
var $labels = $section.find(TOOLBAR_LABEL_SELECTOR),
labels = $labels.toArray();
maxWidth = maxWidth - this._getCurrentLabelsPaddings(labels);
var currentWidth = this._getCurrentLabelsWidth(labels),
difference = Math.abs(currentWidth - maxWidth);
if (maxWidth < currentWidth) {
labels = labels.reverse();
this._alignSectionLabels(labels, difference, false);
} else {
this._alignSectionLabels(labels, difference, true);
}
},
_alignSectionLabels: function _alignSectionLabels(labels, difference, expanding) {
var getRealLabelWidth = function getRealLabelWidth(label) {
return label.getBoundingClientRect().width;
};
for (var i = 0; i < labels.length; i++) {
var $label = $(labels[i]),
currentLabelWidth = Math.ceil(getRealLabelWidth(labels[i])),
labelMaxWidth;
if (expanding) {
$label.css("maxWidth", "inherit");
}
var possibleLabelWidth = Math.ceil(expanding ? getRealLabelWidth(labels[i]) : currentLabelWidth);
if (possibleLabelWidth < difference) {
labelMaxWidth = expanding ? possibleLabelWidth : 0;
difference = difference - possibleLabelWidth;
} else {
labelMaxWidth = expanding ? currentLabelWidth + difference : currentLabelWidth - difference;
$label.css("maxWidth", labelMaxWidth);
break;
}
$label.css("maxWidth", labelMaxWidth);
}
},
_getCurrentLabelsWidth: function _getCurrentLabelsWidth(labels) {
var width = 0;
labels.forEach(function (label, index) {
width += $(label).outerWidth();
});
return width;
},
_getCurrentLabelsPaddings: function _getCurrentLabelsPaddings(labels) {
var padding = 0;
labels.forEach(function (label, index) {
padding += $(label).outerWidth() - $(label).width();
});
return padding;
},
_renderItem: function _renderItem(index, item, itemContainer, $after) {
var location = item.location || "center",
container = itemContainer || this._$toolbarItemsContainer.find(".dx-toolbar-" + location),
itemHasText = Boolean(item.text) || Boolean(item.html),
itemElement = this.callBase(index, item, container, $after);
itemElement.toggleClass(this._buttonClass(), !itemHasText).toggleClass(TOOLBAR_LABEL_CLASS, itemHasText);
return itemElement;
},
_renderGroupedItems: function _renderGroupedItems() {
var that = this;
each(this.option("items"), function (groupIndex, group) {
var groupItems = group.items,
$container = $("<div>").addClass(TOOLBAR_GROUP_CLASS),
location = group.location || "center";
if (!groupItems.length) return;
each(groupItems, function (itemIndex, item) {
that._renderItem(itemIndex, item, $container, null);
});
that._$toolbarItemsContainer.find(".dx-toolbar-" + location).append($container);
});
},
_renderItems: function _renderItems(items) {
var grouped = items.length && items[0].items;
grouped ? this._renderGroupedItems() : this.callBase(items);
},
_getToolbarItems: function _getToolbarItems() {
return this.option("items") || [];
},
_renderContentImpl: function _renderContentImpl() {
var items = this._getToolbarItems();
this.$element().toggleClass(TOOLBAR_MINI_CLASS, items.length === 0);
if (this._renderedItemsCount) {
this._renderItems(items.slice(this._renderedItemsCount));
} else {
this._renderItems(items);
}
},
_renderEmptyMessage: commonUtils.noop,
_clean: function _clean() {
this._$toolbarItemsContainer.children().empty();
this.$element().empty();
},
_visibilityChanged: function _visibilityChanged(visible) {
if (visible) {
this._arrangeItems();
}
},
_isVisible: function _isVisible() {
return this.$element().width() > 0 && this.$element().height() > 0;
},
_getIndexByItem: function _getIndexByItem(item) {
return inArray(item, this._getToolbarItems());
},
_itemOptionChanged: function _itemOptionChanged(item, property, value) {
this.callBase.apply(this, [item, property, value]);
this._arrangeItems();
},
_optionChanged: function _optionChanged(args) {
var name = args.name;
switch (name) {
case "width":
this.callBase.apply(this, arguments);
this._dimensionChanged();
break;
case "renderAs":
this._invalidate();
break;
default:
this.callBase.apply(this, arguments);
}
}
/**
* @name dxToolbarMethods.registerKeyHandler
* @publicName registerKeyHandler(key, handler)
* @hidden
* @inheritdoc
*/
/**
* @name dxToolbarMethods.focus
* @publicName focus()
* @hidden
* @inheritdoc
*/
});
registerComponent("dxToolbarBase", ToolbarBase);
module.exports = ToolbarBase;