AutorÃa | Ultima modificación | Ver Log |
import $ from 'jquery';import Popover from 'bootstrap/js/src/popover';/*** ------------------------------------------------------------------------* Constants* ------------------------------------------------------------------------*/const NAME = 'confirmation';const VERSION = '$VERSION';const DATA_KEY = `bs.${NAME}`;const EVENT_KEY = `.${DATA_KEY}`;const JQUERY_NO_CONFLICT = $.fn[NAME];const BTN_CLASS_BASE = 'h-100 d-flex align-items-center';const BTN_CLASS_DEFAULT = 'btn btn-sm';const DefaultType = {...Popover.DefaultType,singleton : 'boolean',popout : 'boolean',copyAttributes : '(string|array)',onConfirm : 'function',onCancel : 'function',btnOkClass : 'string',btnOkLabel : 'string',btnOkIconClass : 'string',btnOkIconContent : 'string',btnCancelClass : 'string',btnCancelLabel : 'string',btnCancelIconClass : 'string',btnCancelIconContent: 'string',buttons : 'array',};const Default = {...Popover.Default,_attributes : {},_selector : null,placement : 'top',title : 'Are you sure?',trigger : 'click',confirmationEvent : undefined,content : '',singleton : false,popout : false,copyAttributes : 'href target',onConfirm : $.noop,onCancel : $.noop,btnOkClass : `${BTN_CLASS_DEFAULT} btn-primary`,btnOkLabel : 'Yes',btnOkIconClass : '',btnOkIconContent : '',btnCancelClass : `${BTN_CLASS_DEFAULT} btn-secondary`,btnCancelLabel : 'No',btnCancelIconClass : '',btnCancelIconContent: '',buttons : [],// @formatter:offtemplate : `<div class="popover confirmation"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"><p class="confirmation-content"></p><div class="confirmation-buttons text-center"><div class="btn-group"></div></div></div></div>`,// @formatter:on};if (Default.whiteList) {Default.whiteList['*'].push('data-apply', 'data-dismiss');}const ClassName = {FADE: 'fade',SHOW: 'show',};const Selector = {TITLE : '.popover-header',CONTENT: '.confirmation-content',BUTTONS: '.confirmation-buttons .btn-group',};const Keymap = {13: 'Enter',27: 'Escape',39: 'ArrowRight',40: 'ArrowDown',};const Event = {HIDE : `hide${EVENT_KEY}`,HIDDEN : `hidden${EVENT_KEY}`,SHOW : `show${EVENT_KEY}`,SHOWN : `shown${EVENT_KEY}`,INSERTED : `inserted${EVENT_KEY}`,CLICK : `click${EVENT_KEY}`,FOCUSIN : `focusin${EVENT_KEY}`,FOCUSOUT : `focusout${EVENT_KEY}`,MOUSEENTER: `mouseenter${EVENT_KEY}`,MOUSELEAVE: `mouseleave${EVENT_KEY}`,CONFIRMED : `confirmed${EVENT_KEY}`,CANCELED : `canceled${EVENT_KEY}`,KEYUP : `keyup${EVENT_KEY}`,};/*** ------------------------------------------------------------------------* Class Definition* ------------------------------------------------------------------------*/// keep track of the last openned confirmation for keyboard navigationlet activeConfirmation;class Confirmation extends Popover {// Gettersstatic get VERSION() {return VERSION;}static get Default() {return Default;}static get NAME() {return NAME;}static get DATA_KEY() {return DATA_KEY;}static get Event() {return Event;}static get EVENT_KEY() {return EVENT_KEY;}static get DefaultType() {return DefaultType;}// Constructorconstructor(element, config) {super(element, config);if ((this.config.popout || this.config.singleton) && !this.config.rootSelector) {throw new Error('The rootSelector option is required to use popout and singleton features since jQuery 3.');}// keep trace of selectorsthis._isDelegate = false;if (config.selector) { // container of buttonsconfig._selector = `${config.rootSelector} ${config.selector}`;this.config._selector = config._selector;}else if (config._selector) { // children of containerthis.config._selector = config._selector;this._isDelegate = true;}else { // standalonethis.config._selector = config.rootSelector;}if (this.config.confirmationEvent === undefined) {this.config.confirmationEvent = this.config.trigger;}if (!this.config.selector) {this._copyAttributes();}this._setConfirmationListeners();}// OverridesisWithContent() {return true;}setContent() {const $tip = $(this.getTipElement());let content = this._getContent();if (typeof content === 'function') {content = content.call(this.element);}this.setElementContent($tip.find(Selector.TITLE), this.getTitle());$tip.find(Selector.CONTENT).toggle(!!content);if (content) {this.setElementContent($tip.find(Selector.CONTENT), content);}if (this.config.buttons.length > 0) {this._setButtons($tip, this.config.buttons);}else {this._setStandardButtons($tip);}$tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`);this._setupKeyupEvent();}dispose() {$('body').off(`${Event.CLICK}.${this.uid}`);this.eventBody = false;this._cleanKeyupEvent();super.dispose();}hide(callback) {this._cleanKeyupEvent();super.hide(callback);}// Private/*** Copy the value of `copyAttributes` on the config object* @private*/_copyAttributes() {this.config._attributes = {};if (this.config.copyAttributes) {if (typeof this.config.copyAttributes === 'string') {this.config.copyAttributes = this.config.copyAttributes.split(' ');}}else {this.config.copyAttributes = [];}this.config.copyAttributes.forEach((attr) => {this.config._attributes[attr] = $(this.element).attr(attr);});}/*** Custom event listeners for popouts and singletons* @private*/_setConfirmationListeners() {const self = this;if (!this.config.selector) {// cancel original event$(this.element).on(this.config.trigger, (e, ack) => {if (!ack) {e.preventDefault();e.stopPropagation();e.stopImmediatePropagation();}});// manage singleton$(this.element).on(Event.SHOWN, function () {if (self.config.singleton) {// close all other popover already initialized$(self.config._selector).not($(this)).filter(function () {return $(this).data(DATA_KEY) !== undefined;}).confirmation('hide');}});}else {// cancel original event$(this.element).on(this.config.trigger, this.config.selector, (e, ack) => {if (!ack) {e.preventDefault();e.stopPropagation();e.stopImmediatePropagation();}});}if (!this._isDelegate) {// manage popoutthis.eventBody = false;this.uid = this.element.id || Confirmation.getUID(`${NAME}_group`);$(this.element).on(Event.SHOWN, () => {if (self.config.popout && !self.eventBody) {self.eventBody = $('body').on(`${Event.CLICK}.${self.uid}`, (e) => {if ($(self.config._selector).is(e.target) || $(self.config._selector).has(e.target).length > 0) {return;}// close all popover already initialized$(self.config._selector).filter(function () {return $(this).data(DATA_KEY) !== undefined;}).confirmation('hide');$('body').off(`${Event.CLICK}.${self.uid}`);self.eventBody = false;});}});}}/*** Init the standard ok/cancel buttons* @param $tip* @private*/_setStandardButtons($tip) {const buttons = [{class : this.config.btnOkClass,label : this.config.btnOkLabel,iconClass : this.config.btnOkIconClass,iconContent: this.config.btnOkIconContent,attr : this.config._attributes,},{class : this.config.btnCancelClass,label : this.config.btnCancelLabel,iconClass : this.config.btnCancelIconClass,iconContent: this.config.btnCancelIconContent,cancel : true,},];this._setButtons($tip, buttons);}/*** Init the buttons* @param $tip* @param buttons* @private*/_setButtons($tip, buttons) {const self = this;const $group = $tip.find(Selector.BUTTONS).empty();buttons.forEach((button) => {const btn = $('<a href="#"></a>').addClass(BTN_CLASS_BASE).addClass(button.class || `${BTN_CLASS_DEFAULT} btn-secondary`).html(button.label || '').attr(button.attr || {});if (button.iconClass || button.iconContent) {btn.prepend($('<i></i>').addClass(button.iconClass || '').text(button.iconContent || ''));}btn.one('click', function (e) {if ($(this).attr('href') === '#') {e.preventDefault();}if (button.onClick) {button.onClick.call($(self.element));}if (button.cancel) {self.config.onCancel.call(self.element, button.value);$(self.element).trigger(Event.CANCELED, [button.value]);}else {self.config.onConfirm.call(self.element, button.value);$(self.element).trigger(Event.CONFIRMED, [button.value]);$(self.element).trigger(self.config.confirmationEvent, [true]);}self.hide();});$group.append(btn);});}/*** Install the keyboatd event handler* @private*/_setupKeyupEvent() {activeConfirmation = this;$(window).off(Event.KEYUP).on(Event.KEYUP, this._onKeyup.bind(this));}/*** Remove the keyboard event handler* @private*/_cleanKeyupEvent() {if (activeConfirmation === this) {activeConfirmation = undefined;$(window).off(Event.KEYUP);}}/*** Event handler for keyboard navigation* @param event* @private*/_onKeyup(event) {if (!this.tip) {this._cleanKeyupEvent();return;}const $tip = $(this.getTipElement());const key = event.key || Keymap[event.keyCode || event.which];const $group = $tip.find(Selector.BUTTONS);const $active = $group.find('.active');let $next;switch (key) {case 'Escape':this.hide();break;case 'ArrowRight':if ($active.length && $active.next().length) {$next = $active.next();}else {$next = $group.children().first();}$active.removeClass('active');$next.addClass('active').focus();break;case 'ArrowLeft':if ($active.length && $active.prev().length) {$next = $active.prev();}else {$next = $group.children().last();}$active.removeClass('active');$next.addClass('active').focus();break;default:break;}}// Static/*** Generates an uui, copied from Bootrap's utils* @param {string} prefix* @returns {string}*/static getUID(prefix) {let uid = prefix;do {// eslint-disable-next-line no-bitwiseuid += ~~(Math.random() * 1000000); // "~~" acts like a faster Math.floor() here} while (document.getElementById(uid));return uid;}static _jQueryInterface(config) {return this.each(function () {let data = $(this).data(DATA_KEY);const _config = typeof config === 'object' ? config : {};_config.rootSelector = $(this).selector || _config.rootSelector; // this.selector removed in jQuery > 3if (!data && /destroy|hide/.test(config)) {return;}if (!data) {data = new Confirmation(this, _config);$(this).data(DATA_KEY, data);}if (typeof config === 'string') {if (typeof data[config] === 'undefined') {throw new TypeError(`No method named "${config}"`);}data[config]();}});}}/*** ------------------------------------------------------------------------* jQuery* ------------------------------------------------------------------------*/$.fn[NAME] = Confirmation._jQueryInterface;$.fn[NAME].Constructor = Confirmation;$.fn[NAME].noConflict = function () {$.fn[NAME] = JQUERY_NO_CONFLICT;return Confirmation._jQueryInterface;};export default Confirmation;