UNPKG

@syncfusion/ej2-splitbuttons

Version:

A package of feature-rich Essential JS 2 components such as DropDownButton, SplitButton, ProgressButton and ButtonGroup.

449 lines (448 loc) 17.9 kB
var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; // eslint-disable-next-line @typescript-eslint/triple-slash-reference /// <reference path='../drop-down-button/drop-down-button-model.d.ts'/> import { Event, remove, addClass, removeClass, detach, getValue, setValue } from '@syncfusion/ej2-base'; import { EventHandler, Collection, NotifyPropertyChanges, Property } from '@syncfusion/ej2-base'; import { attributes, getUniqueID, getInstance, KeyboardEvents } from '@syncfusion/ej2-base'; import { Button } from '@syncfusion/ej2-buttons'; import { getModel, Item } from './../common/common'; import { DropDownButton } from '../drop-down-button/drop-down-button'; var RTL = 'e-rtl'; var TAGNAME = 'EJS-SPLITBUTTON'; /** * SplitButton component has primary and secondary button. Primary button is used to select * default action and secondary button is used to toggle contextual overlays for displaying list of * action items. It can contain both text and images. * ```html * <button id="element"></button> * ``` * ```typescript * <script> * var splitBtnObj = new SplitButton({content: 'SplitButton'}); * splitBtnObj.appendTo("#element"); * </script> * ``` */ var SplitButton = /** @class */ (function (_super) { __extends(SplitButton, _super); /** * Constructor for creating the widget * * @param {SplitButtonModel} options - Specifies the splitbutton model * @param {string|HTMLButtonElement} element - Specifies the element * @hidden */ function SplitButton(options, element) { return _super.call(this, options, element) || this; } /** * Initialize Angular support. * * @private * @returns {void} */ SplitButton.prototype.preRender = function () { var ele = this.element; if (ele.tagName === TAGNAME) { var ejInstance = getValue('ej2_instances', ele); var btn = this.createElement('button', { attrs: { 'type': 'button' } }); var wrapper = this.createElement(TAGNAME, { className: 'e-' + this.getModuleName() + '-wrapper' }); for (var idx = 0, len = ele.attributes.length; idx < len; idx++) { btn.setAttribute(ele.attributes[idx].nodeName, ele.attributes[idx].nodeValue); } ele.parentNode.insertBefore(wrapper, ele); detach(ele); ele = btn; wrapper.appendChild(ele); setValue('ej2_instances', ejInstance, ele); this.wrapper = wrapper; this.element = ele; } if (!this.element.id) { this.element.id = getUniqueID('e-' + this.getModuleName()); } }; /** * Initialize the Component rendering. * * @returns {void} * @private */ SplitButton.prototype.render = function () { this.initWrapper(); this.createPrimaryButton(); this.renderControl(); }; SplitButton.prototype.renderControl = function () { this.createSecondaryButton(); this.setActiveElem([this.element, this.secondaryBtnObj.element]); this.setAria(); this.wireEvents(); this.renderComplete(); }; /** * Adds a new item to the menu. By default, new item appends to the list as the last item, * but you can insert based on the text parameter. * * @param { ItemModel[] } items - Specifies an array of JSON data. * @param { string } text - Specifies the text to insert the newly added item in the menu. * @returns {void}. */ SplitButton.prototype.addItems = function (items, text) { _super.prototype.addItems.call(this, items, text); this.secondaryBtnObj.items = this.items; }; /** * Removes the items from the menu. * * @param { string[] } items - Specifies an array of string to remove the items. * @param { string } isUniqueId - Set `true` if specified items is a collection of unique id. * @returns {void}. */ SplitButton.prototype.removeItems = function (items, isUniqueId) { _super.prototype.removeItems.call(this, items, isUniqueId); this.secondaryBtnObj.items = this.items; }; SplitButton.prototype.initWrapper = function () { if (!this.wrapper) { this.wrapper = this.createElement('div', { className: 'e-' + this.getModuleName() + '-wrapper' }); this.element.parentNode.insertBefore(this.wrapper, this.element); } this.element.classList.remove('e-' + this.getModuleName()); if (this.enableRtl) { this.wrapper.classList.add(RTL); } if (this.cssClass) { addClass([this.wrapper], this.cssClass.replace(/\s+/g, ' ').trim().split(' ')); } }; SplitButton.prototype.createPrimaryButton = function () { var btnModel = { cssClass: this.cssClass, enableRtl: this.enableRtl, iconCss: this.iconCss, iconPosition: this.iconPosition, content: this.content, disabled: this.disabled }; this.primaryBtnObj = new Button(btnModel); this.primaryBtnObj.createElement = this.createElement; this.primaryBtnObj.appendTo(this.element); this.element.classList.add('e-' + this.getModuleName()); this.element.type = 'button'; this.wrapper.appendChild(this.element); }; SplitButton.prototype.createSecondaryButton = function () { var _this = this; var btnElem = this.createElement('button', { className: 'e-icon-btn', attrs: { 'tabindex': '-1' }, id: this.element.id + '_dropdownbtn' }); this.wrapper.appendChild(btnElem); var dropDownBtnModel = { cssClass: this.cssClass, disabled: this.disabled, enableRtl: this.enableRtl, items: this.items, target: this.target, createPopupOnClick: this.createPopupOnClick }; dropDownBtnModel.beforeItemRender = function (args) { if (_this.createPopupOnClick) { _this.secondaryBtnObj.dropDown.relateTo = _this.wrapper; _this.dropDown = _this.secondaryBtnObj.dropDown; } _this.trigger('beforeItemRender', args); }; dropDownBtnModel.open = function (args) { _this.trigger('open', args); }; dropDownBtnModel.close = function (args) { _this.trigger('close', args); }; dropDownBtnModel.select = function (args) { _this.trigger('select', args); }; dropDownBtnModel.beforeOpen = function (args) { if (_this.createPopupOnClick && _this.items.length === 0) { _this.secondaryBtnObj.dropDown.relateTo = _this.wrapper; _this.dropDown = _this.secondaryBtnObj.dropDown; } var callBackPromise = new Deferred(); _this.trigger('beforeOpen', args, function (observedArgs) { callBackPromise.resolve(observedArgs); }); return callBackPromise; }; dropDownBtnModel.beforeClose = function (args) { var callBackPromise = new Deferred(); _this.trigger('beforeClose', args, function (observedArgs) { callBackPromise.resolve(observedArgs); }); return callBackPromise; }; this.secondaryBtnObj = new DropDownButton(dropDownBtnModel); this.secondaryBtnObj.createElement = this.createElement; this.secondaryBtnObj.appendTo(btnElem); if (!this.createPopupOnClick) { this.secondaryBtnObj.dropDown.relateTo = this.wrapper; this.dropDown = this.secondaryBtnObj.dropDown; } // eslint-disable-next-line @typescript-eslint/no-explicit-any this.isPopupCreated = this.secondaryBtnObj.isPopupCreated; this.secondaryBtnObj.activeElem = [this.element, this.secondaryBtnObj.element]; this.secondaryBtnObj.element.querySelector('.e-btn-icon').classList.remove('e-icon-right'); if (this.disabled) { this.wrapper.classList.add('e-splitbtn-disabled'); } }; SplitButton.prototype.setAria = function () { attributes(this.element, { 'aria-expanded': 'false', 'aria-haspopup': 'true', 'aria-label': this.element.textContent ? this.element.textContent + ' splitbutton' : 'splitbutton', 'aria-owns': this.element.id + '_dropdownbtn-popup' }); }; /** * Get component name. * * @returns {string} - Module Name * @private */ SplitButton.prototype.getModuleName = function () { return 'split-btn'; }; /** * To open/close SplitButton popup based on current state of the SplitButton. * * @returns {void} */ SplitButton.prototype.toggle = function () { this.secondaryBtnObj.toggle(); }; SplitButton.prototype.destroy = function () { var _this = this; var classList = [RTL]; if (this.cssClass) { classList = classList.concat(this.cssClass.split(' ')); } if (this.element) { var element = document.getElementById(this.element.id); if (element && element.parentElement === this.wrapper) { if (this.wrapper.tagName === TAGNAME) { this.wrapper.innerHTML = ''; removeClass([this.wrapper], ['e-rtl', 'e-' + this.getModuleName() + '-wrapper']); removeClass([this.wrapper], this.cssClass.split(' ')); } else { removeClass([this.element], classList); ['aria-label', 'aria-haspopup', 'aria-expanded', 'aria-owns', 'type'].forEach(function (key) { _this.element.removeAttribute(key); }); this.wrapper.parentNode.insertBefore(this.element, this.wrapper); remove(this.wrapper); } this.unWireEvents(); } } this.primaryBtnObj.destroy(); this.secondaryBtnObj.destroy(); _super.prototype.destroy.call(this); if (this.element && !this.element.getAttribute('class')) { this.element.removeAttribute('class'); } // eslint-disable-next-line @typescript-eslint/no-explicit-any if (this.refreshing && this.isAngular) { this.element = this.wrapper; ['e-control', 'e-split-btn', 'e-lib'].forEach(function (key) { _this.element.classList.add(key); }); setValue('ej2_instances', [this], this.element); } this.wrapper = null; }; SplitButton.prototype.wireEvents = function () { EventHandler.add(this.element, 'click', this.primaryBtnClickHandler, this); new KeyboardEvents(this.element, { keyAction: this.btnKeyBoardHandler.bind(this), keyConfigs: { altdownarrow: 'alt+downarrow', enter: 'enter' } }); }; SplitButton.prototype.unWireEvents = function () { EventHandler.remove(this.element, 'click', this.primaryBtnClickHandler); getInstance(this.element, KeyboardEvents).destroy(); }; SplitButton.prototype.primaryBtnClickHandler = function () { this.trigger('click', { element: this.element }); }; SplitButton.prototype.btnKeyBoardHandler = function (e) { switch (e.action) { case 'altdownarrow': this.clickHandler(e); break; case 'enter': this.clickHandler(e); if (this.getPopUpElement() && !this.getPopUpElement().classList.contains('e-popup-close')) { this.element.classList.remove('e-active'); this.secondaryBtnObj.element.classList.add('e-active'); } else { this.secondaryBtnObj.element.classList.remove('e-active'); } break; } }; /** * Called internally if any of the property value changed. * * @param {SplitButtonModel} newProp - Specifies new properties * @param {SplitButtonModel} oldProp - Specifies old properties * @returns {void} */ SplitButton.prototype.onPropertyChanged = function (newProp, oldProp) { var model = ['content', 'iconCss', 'iconPosition', 'cssClass', 'disabled', 'enableRtl']; this.primaryBtnObj.setProperties(getModel(newProp, model)); model = ['beforeOpen', 'beforeItemRender', 'select', 'open', 'close', 'cssClass', 'disabled', 'enableRtl', 'createPopupOnClick']; if (Object.keys(newProp).indexOf('items') > -1) { this.secondaryBtnObj.items = newProp.items; this.secondaryBtnObj.dataBind(); } this.secondaryBtnObj.setProperties(getModel(newProp, model)); for (var _i = 0, _a = Object.keys(newProp); _i < _a.length; _i++) { var prop = _a[_i]; switch (prop) { case 'cssClass': if (oldProp.cssClass) { removeClass([this.wrapper], oldProp.cssClass.split(' ')); } addClass([this.wrapper], newProp.cssClass.replace(/\s+/g, ' ').trim().split(' ')); break; case 'enableRtl': if (newProp.enableRtl) { addClass([this.wrapper], RTL); } else { removeClass([this.wrapper], RTL); } break; case 'disabled': if (newProp.disabled) { addClass([this.wrapper], 'e-splitbtn-disabled'); } else { removeClass([this.wrapper], 'e-splitbtn-disabled'); } } } }; /** * Sets the focus to SplitButton * its native method * * @public * @returns {void} */ SplitButton.prototype.focusIn = function () { this.element.focus(); }; __decorate([ Property('') ], SplitButton.prototype, "content", void 0); __decorate([ Property('') ], SplitButton.prototype, "cssClass", void 0); __decorate([ Property(false) ], SplitButton.prototype, "disabled", void 0); __decorate([ Property('') ], SplitButton.prototype, "iconCss", void 0); __decorate([ Property('Left') ], SplitButton.prototype, "iconPosition", void 0); __decorate([ Property(false) ], SplitButton.prototype, "createPopupOnClick", void 0); __decorate([ Collection([], Item) ], SplitButton.prototype, "items", void 0); __decorate([ Property('') ], SplitButton.prototype, "target", void 0); __decorate([ Event() ], SplitButton.prototype, "beforeItemRender", void 0); __decorate([ Event() ], SplitButton.prototype, "beforeOpen", void 0); __decorate([ Event() ], SplitButton.prototype, "beforeClose", void 0); __decorate([ Event() ], SplitButton.prototype, "click", void 0); __decorate([ Event() ], SplitButton.prototype, "close", void 0); __decorate([ Event() ], SplitButton.prototype, "open", void 0); __decorate([ Event() ], SplitButton.prototype, "select", void 0); __decorate([ Event() ], SplitButton.prototype, "created", void 0); SplitButton = __decorate([ NotifyPropertyChanges ], SplitButton); return SplitButton; }(DropDownButton)); export { SplitButton }; /** * Deferred is used to handle asynchronous operation. */ var Deferred = /** @class */ (function () { function Deferred() { var _this = this; /** * Promise is an object that represents a value that may not be available yet, but will be resolved at some point in the future. */ this.promise = new Promise(function (resolve, reject) { _this.resolve = resolve; _this.reject = reject; }); /** * Defines the callback function triggers when the Deferred object is rejected. */ this.catch = this.promise.catch.bind(this.promise); /** * Defines the callback function triggers when the Deferred object is resolved. */ this.then = this.promise.then.bind(this.promise); } return Deferred; }()); export { Deferred };