@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
332 lines (331 loc) • 11.1 kB
JavaScript
//#region ../src/kendo.segmentedcontrol.js
const __meta__ = {
id: "segmentedcontrol",
name: "SegmentedControl",
category: "web",
description: "The SegmentedControl widget provides a segmented control UI with selectable buttons.",
depends: [
"core",
"icons",
"html.icon"
]
};
(function($, undefined) {
const kendo = window.kendo, encode = kendo.htmlEncode, Widget = kendo.ui.Widget, ns = ".kendoSegmentedControl", CLICK = "click", CHANGE = "change", HOVER_CLASS = "k-hover", FOCUS_CLASS = "k-focus", DISABLED_CLASS = "k-disabled", SELECTED_CLASS = "k-selected", BUTTON_SELECTOR = ".k-segmented-control-button", ICON_WRAPPER_CLASS = "k-segmented-control-button-icon", COMPACT = "compact", STRETCH = "stretch", ROLE = "role", ARIA_HIDDEN = "aria-hidden", ARIA_LABEL = "aria-label", ARIA_PRESSED = "aria-pressed", ARIA_DISABLED = "aria-disabled";
const SegmentedControl = Widget.extend({
init: function(element, options) {
const that = this;
Widget.fn.init.call(that, element, options);
that._items = that.options.items || [];
that._selectedValue = that.options.selectedValue;
that._enabled = that.options.enabled !== false;
that._isRtl = kendo.support.isRtl(that.element) || that.element.css("direction") === "rtl";
that._createIconClassMap();
that._render();
that._bindEvents();
that._initResizeObserver();
if (!that._enabled) {
that._toggleEnabled(false);
}
kendo.notify(that);
},
options: {
name: "SegmentedControl",
items: [],
selectedValue: null,
size: undefined,
layoutMode: COMPACT,
enabled: true
},
events: [CHANGE],
_createIconClassMap: function() {
const that = this;
const items = that._items;
const map = that._iconClassMap = new Map();
items.forEach((item) => {
if (item.iconClassOnSelection) {
map.set(item.value, item.iconClassOnSelection);
}
});
},
_render: function() {
const that = this;
const element = that.element;
const items = that._items;
const size = that.options.size;
const sizeEntry = kendo.cssProperties.sizeValues.find(([name]) => name === size);
const sizeClass = sizeEntry;
const isStretched = that.options.layoutMode === STRETCH;
element.addClass(`k-segmented-control k-segmented-control${sizeClass ? `-` + sizeClass[1] : ""}${isStretched ? " k-segmented-control-stretched" : ""}`);
element.attr(ROLE, "group");
const thumb = $("<div>").addClass("k-segmented-control-thumb").attr(ARIA_HIDDEN, "true");
element.append(thumb);
items.forEach((item, index) => {
const button = that._renderButton(item, index);
element.append(button);
});
that._calculateThumbPosition();
},
_renderButton: function(item, index) {
const that = this;
const isSelected = item.value === that._selectedValue;
const isDisabled = item.enabled === false;
const button = $("<button>").attr("type", "button").addClass("k-segmented-control-button").attr("data-value", item.value).attr("data-button-index", index).attr("title", item.text || "").attr(ARIA_PRESSED, (isSelected && !isDisabled).toString()).toggleClass(DISABLED_CLASS, isDisabled).toggleClass(SELECTED_CLASS, isSelected && !isDisabled).prop("disabled", isDisabled);
if (isDisabled) {
button.attr(ARIA_DISABLED, "true");
}
if (item.icon) {
const iconClass = ICON_WRAPPER_CLASS + (item.iconClass ? " " + item.iconClass : "");
const icon = $(kendo.html.renderIcon({
icon: item.icon,
iconClass
}));
icon.attr(ARIA_HIDDEN, true);
if (isSelected && !isDisabled) {
const specialClass = that._iconClassMap.get(item.value);
if (specialClass) {
icon.addClass(specialClass);
}
}
button.append(icon);
} else if (item.iconClass) {
button.append(`<span class='${ICON_WRAPPER_CLASS} ${item.iconClass}' ${ARIA_HIDDEN}='true'></span>`);
}
if (item.text) {
const text = $("<span>").addClass("k-segmented-control-button-text").text(encode(item.text));
button.append(text);
} else if (item.icon) {
button.attr(ARIA_LABEL, item.value);
}
return button;
},
_calculateThumbPosition: function() {
const that = this;
const selected = that._selectedValue;
const totalWidth = kendo._outerWidth(that.element);
const totalButtonCount = that._items?.length || 0;
if (!totalWidth) {
return;
}
if (!selected) {
return;
}
const buttons = that.element.find("button[data-value]");
const button = buttons.filter(`[data-value="${selected}"]`);
const index = button.data("buttonIndex");
const thumb = that.element.find(".k-segmented-control-thumb");
const buttonWidth = kendo._outerWidth(button);
let left = 0;
let right = 0;
let spacing = 0;
if (that.options.layoutMode === STRETCH) {
const buttonsRightFromTarget = totalButtonCount - 1 - index;
left = index * buttonWidth;
right = buttonsRightFromTarget * buttonWidth;
spacing = (totalWidth - totalButtonCount * buttonWidth) / 2;
} else {
let totalButtonWidth = 0;
buttons.each((btnIndex, btnElement) => {
const elementRef = $(btnElement);
totalButtonWidth += kendo._outerWidth(elementRef);
if (btnIndex < index) {
left += kendo._outerWidth(elementRef);
}
if (btnIndex > index) {
right += kendo._outerWidth(elementRef);
}
});
spacing = (totalWidth - totalButtonWidth) / 2;
}
if (that._isRtl) {
thumb.css({
right: left + spacing,
left: right + spacing
});
} else {
thumb.css({
left: left + spacing,
right: right + spacing
});
}
},
_bindEvents: function() {
const that = this;
that.element.on(CLICK + ns, BUTTON_SELECTOR, function(e) {
const button = $(e.currentTarget);
if (!that._enabled || button.hasClass(DISABLED_CLASS)) {
return;
}
const value = button.data("value");
if (value !== that._selectedValue) {
that.select(value);
}
}).on("mouseenter" + ns, BUTTON_SELECTOR, function(e) {
const button = $(e.currentTarget);
if (that._enabled && !button.hasClass(DISABLED_CLASS)) {
button.addClass(HOVER_CLASS);
}
}).on("mouseleave" + ns, BUTTON_SELECTOR, function(e) {
$(e.currentTarget).removeClass(HOVER_CLASS);
}).on("focus" + ns, BUTTON_SELECTOR, function(e) {
const button = $(e.currentTarget);
if (that._enabled && !button.hasClass(DISABLED_CLASS)) {
button.addClass(FOCUS_CLASS);
}
}).on("blur" + ns, BUTTON_SELECTOR, function(e) {
$(e.currentTarget).removeClass(FOCUS_CLASS);
});
},
select: function(value) {
const that = this;
if (value === undefined) {
return that._selectedValue;
}
const item = that._items.find((i) => i.value === value);
if (!item || item.enabled === false) {
return;
}
const eventArgs = {
value,
item
};
if (that.trigger(CHANGE, eventArgs)) {
return;
}
that._selectedValue = value;
that._updateSelectedState();
},
_updateSelectedState: function() {
const that = this;
const buttons = that.element.find(BUTTON_SELECTOR);
const selectedValue = that._selectedValue;
buttons.each((_, btnElement) => {
const btn = $(btnElement);
that._removeSelectionClasses(btn);
});
const selectedButton = buttons.filter(`[data-value="${selectedValue}"]`);
that._addSelectionClasses(selectedButton, selectedValue);
that._calculateThumbPosition();
},
_addSelectionClasses: function(button, selectedValue) {
const that = this;
const specialSelectedIconClass = that._iconClassMap.get(selectedValue);
button.addClass(SELECTED_CLASS);
button.attr(ARIA_PRESSED, "true");
const icon = button.find(".k-icon,.k-svg-icon");
if (icon.length && specialSelectedIconClass) {
icon.addClass(specialSelectedIconClass);
}
},
_removeSelectionClasses: function(button) {
const that = this;
const value = button.data("value");
const specialSelectedIconClass = that._iconClassMap.get(value);
button.removeClass(SELECTED_CLASS);
button.attr(ARIA_PRESSED, "false");
const icon = button.find(".k-icon,.k-svg-icon");
if (icon.length && specialSelectedIconClass) {
icon.removeClass(specialSelectedIconClass);
}
},
value: function(value) {
const that = this;
if (value === undefined) {
return that._selectedValue;
}
that._selectedValue = value;
that._updateSelectedState();
},
item: function(index) {
return this.element.find(BUTTON_SELECTOR).eq(index);
},
items: function() {
return this.element.find(BUTTON_SELECTOR);
},
enable: function(enable) {
const that = this;
const isEnabled = enable !== false;
that._enabled = isEnabled;
that._toggleEnabled(isEnabled);
},
_toggleEnabled: function(isEnabled) {
const that = this;
const buttons = that.element.find(BUTTON_SELECTOR);
that.element.toggleClass(DISABLED_CLASS, !isEnabled);
if (!isEnabled) {
buttons.each((_, btnElement) => {
const btn = $(btnElement);
btn.prop("disabled", true);
btn.attr(ARIA_DISABLED, "true");
btn.removeClass(HOVER_CLASS + " " + FOCUS_CLASS);
});
} else {
buttons.each((idx, btnElement) => {
const btn = $(btnElement);
const item = that._items[idx];
const isItemDisabled = item && item.enabled === false;
btn.prop("disabled", isItemDisabled);
if (isItemDisabled) {
btn.attr(ARIA_DISABLED, "true");
} else {
btn.removeAttr(ARIA_DISABLED);
}
});
}
},
focus: function(item) {
const that = this;
if (item !== undefined) {
const button = item instanceof $ ? item : that.item(item);
if (button && button.length) {
button[0].focus();
}
return;
}
const buttons = that.element.find(BUTTON_SELECTOR).not(":disabled");
if (buttons.length) {
buttons.first()[0].focus();
}
},
setOptions: function(options) {
const that = this;
that.element.empty();
that.element.removeClass(function(index, className) {
return (className.match(/(^|\s)k-segmented-control\S*/g) || []).join(" ");
});
Widget.fn.setOptions.call(that, options);
that._items = that.options.items || [];
that._selectedValue = that.options.selectedValue;
that._enabled = that.options.enabled !== false;
that._isRtl = kendo.support.isRtl(that.element) || that.element.css("direction") === "rtl";
that._createIconClassMap();
that._render();
if (!that._enabled) {
that._toggleEnabled(false);
}
},
_initResizeObserver: function() {
const that = this;
if (typeof ResizeObserver === "undefined") {
return;
}
that._resizeObserver = new ResizeObserver(function() {
that._calculateThumbPosition();
});
that._resizeObserver.observe(that.element[0]);
},
destroy: function() {
const that = this;
if (that._resizeObserver) {
that._resizeObserver.disconnect();
that._resizeObserver = null;
}
that.element.off(ns);
Widget.fn.destroy.call(that);
}
});
kendo.ui.plugin(SegmentedControl);
})(window.kendo.jQuery);
var kendo_segmentedcontrol_default = kendo;
//#endregion
export { kendo_segmentedcontrol_default as n, __meta__ as t };