From b3a2fa2983b6802e0f03b3459ab8fefb756fef53 Mon Sep 17 00:00:00 2001 From: Tieson Trowbridge Date: Sun, 15 Jun 2025 18:12:43 -0400 Subject: [PATCH] WIP updates for prompt validation --- CHANGELOG.md | 7 ++++- README.md | 5 +-- bootbox.js | 53 +++++++++++++++++++++++--------- dist/bootbox.all.js | 30 ++++++++++++++---- dist/bootbox.all.min.js | 4 +-- dist/bootbox.js | 53 +++++++++++++++++++++++--------- dist/bootbox.locales.js | 2 +- dist/bootbox.locales.min.js | 2 +- dist/bootbox.min.js | 4 +-- header.txt | 2 +- package-lock.json | 4 +-- package.json | 2 +- templates/umd-header-locales.txt | 2 +- templates/umd-header.txt | 2 +- tests/prompt.test.js | 31 ++++++++++++++++--- 15 files changed, 150 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5fbb516..1e80c88b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ -## 6.0.4 (Latest Release) +## 6.0.5 (Latest Release) + +- Updates prompt input validation to apply `was-validated` class to form when **OK** button is clicked +- Updates prompt input to trigger form submit when "enter" key is pressed + +### 6.0.4 - Updates `step` to allow setting value for date inputs diff --git a/README.md b/README.md index e19464d8..68bd3db6 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,10 @@ Bootbox **3.3.0** is the *last* release to support Bootstrap 2.2.x. Much more dependency information can be found [on the Bootbox website](http://bootboxjs.com/getting-started.html#bootbox-dependencies). -## 6.0.4 (Latest Release) +## 6.0.5 (Latest Release) -- Updates `step` to allow setting value for date inputs +- Updates prompt input validation to apply `was-validated` class to form when **OK** button is clicked +- Updates prompt input to trigger form submit when "enter" key is pressed For a full list of releases and changes please see [the changelog](https://github.com/bootboxjs/bootbox/blob/master/CHANGELOG.md). diff --git a/bootbox.js b/bootbox.js index 062610f2..7c047b6f 100644 --- a/bootbox.js +++ b/bootbox.js @@ -1,6 +1,6 @@ /*! @preserve * bootbox.js - * version: 6.0.4 + * version: 6.0.5 * author: Nick Payne * license: MIT * http://bootboxjs.com/ @@ -10,10 +10,12 @@ if (typeof define === 'function' && define.amd) { // AMD define(['jquery'], factory); - } else if (typeof exports === 'object') { + } + else if (typeof exports === 'object') { // Node, CommonJS-like module.exports = factory(require('jquery')); - } else { + } + else { // Browser globals (root is window) root.bootbox = factory(root.jQuery); } @@ -22,7 +24,7 @@ let exports = {}; - let VERSION = '6.0.4'; + let VERSION = '6.0.5'; exports.VERSION = VERSION; let locales = { @@ -171,7 +173,8 @@ if (arguments.length === 2) { // Allow passing of single key/value... values[arguments[0]] = arguments[1]; - } else { + } + else { // ... and as an object too values = arguments[0]; } @@ -581,6 +584,8 @@ options.buttons.confirm.callback = function () { let value; + form.addClass('was-validated'); + if (options.inputType === 'checkbox') { value = input.find('input:checked').map(function () { return $(this).val(); @@ -589,25 +594,32 @@ // prevents button callback from being called if no checkboxes have been checked return false; } - } else if (options.inputType === 'radio') { + } + else if (options.inputType === 'radio') { value = input.find('input:checked').val(); } else { let el = input[0]; + + // this must be done every time; otherwise, input is reported invalid even if value is valid + el.setCustomValidity(''); + // trigger built-in validation if checkValidity() function is defined if (el.checkValidity && !el.checkValidity()) { // If a custom error message was provided, add it now if(options.errorMessage){ el.setCustomValidity(options.errorMessage); } - if(el.reportValidity) { + // trigger built-in validation message if reportValidity() function is defined + if (el.reportValidity) { el.reportValidity(); } // prevents button callback from being called return false; - } else { + } + else { if (options.inputType === 'select' && options.multiple === true) { value = input.find('option:selected').map(function () { return $(this).val(); @@ -617,7 +629,7 @@ value = input.val(); } } - } + } return options.callback.call(this, value); }; @@ -638,6 +650,15 @@ // Create the input based on the supplied type input = $(templates.inputs[options.inputType]); + if (options.inputType !== 'textarea') { + input.on('keydown', function(ev) { + if (ev.key === 'Enter') { + ev.preventDefault(); + promptDialog.find('.bootbox-accept').trigger('click'); + } + }); + } + switch (options.inputType) { case 'text': case 'textarea': @@ -661,9 +682,9 @@ input.prop({ 'required': true }); } - if (options.rows && !isNaN(parseInt(options.rows))) { - if (options.inputType === 'textarea') { - input.attr({ 'rows': options.rows }); + if (options.inputType === 'textarea') { + if (options.rows && !isNaN(parseInt(options.rows))) { + input.attr({ rows: options.rows }); } } break; @@ -855,6 +876,8 @@ // Fix for SammyJS (or similar JS routing library) hijacking the form post. e.stopPropagation(); + form.removeClass('was-validated'); + // @TODO can we actually click *the* button object instead? // e.g. buttons.confirm.click() or similar promptDialog.find('.bootbox-accept').trigger('click'); @@ -914,7 +937,8 @@ if (argsLength === 2 || typeof args[0] === 'string') { options[properties[0]] = args[0]; options[properties[1]] = args[1]; - } else { + } + else { options = args[0]; } @@ -1035,7 +1059,8 @@ // Make sure backdrop is either true, false, or 'static' if (!options.backdrop) { options.backdrop = (options.backdrop === false || options.backdrop === 0) ? false : 'static'; - } else { + } + else { options.backdrop = typeof options.backdrop === 'string' && options.backdrop.toLowerCase() === 'static' ? 'static' : true; } diff --git a/dist/bootbox.all.js b/dist/bootbox.all.js index c691c7c7..ca469a9b 100644 --- a/dist/bootbox.all.js +++ b/dist/bootbox.all.js @@ -1,6 +1,6 @@ /*! @preserve * bootbox.js - * version: 6.0.4 + * version: 6.0.5 * author: Nick Payne * license: MIT * http://bootboxjs.com/ @@ -22,7 +22,7 @@ let exports = {}; - let VERSION = '6.0.4'; + let VERSION = '6.0.5'; exports.VERSION = VERSION; let locales = { @@ -585,6 +585,8 @@ options.buttons.confirm.callback = function() { let value; + form.addClass('was-validated'); + if (options.inputType === 'checkbox') { value = input.find('input:checked').map(function() { return $(this).val(); @@ -598,12 +600,17 @@ } else { let el = input[0]; + // this must be done every time; otherwise, input is reported invalid even if value is valid + el.setCustomValidity(''); + + // trigger built-in validation if checkValidity() function is defined if (el.checkValidity && !el.checkValidity()) { // If a custom error message was provided, add it now if (options.errorMessage) { el.setCustomValidity(options.errorMessage); } + // trigger built-in validation message if reportValidity() function is defined if (el.reportValidity) { el.reportValidity(); } @@ -640,6 +647,15 @@ // Create the input based on the supplied type input = $(templates.inputs[options.inputType]); + if (options.inputType !== 'textarea') { + input.on('keydown', function(ev) { + if (ev.key === 'Enter') { + ev.preventDefault(); + promptDialog.find('.bootbox-accept').trigger('click'); + } + }); + } + switch (options.inputType) { case 'text': case 'textarea': @@ -665,10 +681,10 @@ }); } - if (options.rows && !isNaN(parseInt(options.rows))) { - if (options.inputType === 'textarea') { + if (options.inputType === 'textarea') { + if (options.rows && !isNaN(parseInt(options.rows))) { input.attr({ - 'rows': options.rows + rows: options.rows }); } } @@ -864,6 +880,8 @@ // Fix for SammyJS (or similar JS routing library) hijacking the form post. e.stopPropagation(); + form.removeClass('was-validated'); + // @TODO can we actually click *the* button object instead? // e.g. buttons.confirm.click() or similar promptDialog.find('.bootbox-accept').trigger('click'); @@ -1204,7 +1222,7 @@ /*! @preserve * bootbox.locales.js - * version: 6.0.4 + * version: 6.0.5 * author: Nick Payne * license: MIT * http://bootboxjs.com/ diff --git a/dist/bootbox.all.min.js b/dist/bootbox.all.min.js index 10b38270..0f9cacc9 100644 --- a/dist/bootbox.all.min.js +++ b/dist/bootbox.all.min.js @@ -1,7 +1,7 @@ /** * Bootbox.js — alert, confirm, prompt, and flexible dialogs for the Bootstrap framework - * @version: 6.0.4 + * @version: 6.0.5 * @project: https://github.com/bootboxjs/bootbox * @license: MIT http://bootboxjs.com/license.txt */ -((e,t)=>{'function'==typeof define&&define.amd?define(['jquery'],t):'object'==typeof exports?module.exports=t(require('jquery')):e.bootbox=t(e.jQuery)})(this,function t(s,c){let r={};r.VERSION='6.0.4';let i={en:{OK:'OK',CANCEL:'Cancel',CONFIRM:'OK'}},d={dialog:'',header:'',footer:'',closeButton:'',form:'
',button:'',option:'',promptMessage:'
',inputs:{text:'',textarea:'',email:'',select:'',checkbox:'
',radio:'
',date:'',time:'',number:'',password:'',range:''}},p={locale:'en',backdrop:'static',animate:!0,className:null,closeButton:!0,show:!0,container:'body',value:'',inputType:'text',errorMessage:null,swapButtonOrder:!1,centerVertical:!1,multiple:!1,scrollable:!1,reusable:!1,relatedTarget:null,size:null,id:null};function l(e,t,o){return s.extend(!0,{},e,((e,t)=>{var o=e.length;let a={};if(o<1||2{var r={};for(let e=0,t=o.length;e((t=i[t])||i.en)[e])(n,a)}}return r})(t=r&&r[0]&&(o=r[0].locale||p.locale,r[0].swapButtonOrder||p.swapButtonOrder)?t.reverse():t,o)};{e=l(e,r,a);var n=t;let o={};return f(n,function(e,t){o[t]=!0}),f(e.buttons,function(e){if(o[e]===c)throw new Error('button key "'+e+'" is not allowed (options are '+n.join(' ')+')')}),e}}function b(e){return Object.keys(e).length}function f(e,o){let a=0;s.each(e,function(e,t){o(e,t,a++)})}function m(e){e.data.dialog.find('.bootbox-accept').first().trigger('focus')}function h(e){e.target===e.data.dialog[0]&&e.data.dialog.remove()}function C(e){e.target===e.data.dialog[0]&&(e.data.dialog.off('escape.close.bb'),e.data.dialog.off('click'))}function O(e,t,o){e.stopPropagation(),e.preventDefault(),'function'==typeof o&&!1===o.call(t,e)||t.modal('hide')}function w(e){return/([01][0-9]|2[0-3]):[0-5][0-9]?:[0-5][0-9]/.test(e)}function g(e){return/(\d{4})-(\d{2})-(\d{2})/.test(e)}return r.locales=function(e){return e?i[e]:i},r.addLocale=function(e,o){return s.each(['OK','CANCEL','CONFIRM'],function(e,t){if(!o[t])throw new Error('Please supply a translation for "'+t+'"')}),i[e]={OK:o.OK,CANCEL:o.CANCEL,CONFIRM:o.CONFIRM},r},r.removeLocale=function(e){if('en'===e)throw new Error('"en" is used as the default and fallback locale and cannot be removed.');return delete i[e],r},r.setLocale=function(e){return r.setDefaults('locale',e)},r.setDefaults=function(){let e={};return 2===arguments.length?e[arguments[0]]=arguments[1]:e=arguments[0],s.extend(p,e),r},r.hideAll=function(){return s('.bootbox').modal('hide'),r},r.init=function(e){return t(e||s)},r.dialog=function(e){if(s.fn.modal===c)throw new Error('"$.fn.modal" is not defined; please double check you have included the Bootstrap JavaScript library. See https://getbootstrap.com/docs/5.3/getting-started/introduction/ for more details.');e=(a=>{let r,n;if('object'!=typeof a)throw new Error('Please supply an object of options');if(a.message)return(a=s.extend({},p,a)).backdrop?a.backdrop='string'!=typeof a.backdrop||'static'!==a.backdrop.toLowerCase()||'static':a.backdrop=!1!==a.backdrop&&0!==a.backdrop&&'static',a.buttons||(a.buttons={}),r=a.buttons,n=b(r),f(r,function(e,t,o){if('object'!=typeof(t='function'==typeof t?r[e]={callback:t}:t))throw new Error('button with key "'+e+'" must be an object');if(t.label||(t.label=e),!t.className){let e=!1;e=a.swapButtonOrder?0===o:o===n-1,n<=2&&e?t.className='btn-primary':t.className='btn-secondary btn-default'}}),a;throw new Error('"message" option must not be null or an empty string.')})(e),s.fn.modal.Constructor.VERSION?(e.fullBootstrapVersion=s.fn.modal.Constructor.VERSION,a=e.fullBootstrapVersion.indexOf('.'),e.bootstrap=e.fullBootstrapVersion.substring(0,a)):(e.bootstrap='2',e.fullBootstrapVersion='2.3.2',console.warn('Bootbox will *mostly* work with Bootstrap 2, but we do not officially support it. Please upgrade, if possible.'));let o=s(d.dialog);var t=o.find('.modal-dialog'),a=o.find('.modal-body'),r=s(d.header);let n=s(d.footer);var l=e.buttons;let i={onEscape:e.onEscape};if(a.find('.bootbox-body').html(e.message),0{let a=!1,r=!0,n=!0;if('date'===e)t===c||(r=g(t))?o===c||(n=g(o))||console.warn('Browsers which natively support the "date" input type expect date values to be of the form "YYYY-MM-DD" (see ISO-8601 https://www.iso.org/iso-8601-date-and-time-format.html). Bootbox does not enforce this rule, but your max value may not be enforced by this browser.'):console.warn('Browsers which natively support the "date" input type expect date values to be of the form "YYYY-MM-DD" (see ISO-8601 https://www.iso.org/iso-8601-date-and-time-format.html). Bootbox does not enforce this rule, but your min value may not be enforced by this browser.');else if('time'===e){if(t!==c&&!(r=w(t)))throw new Error('"min" is not a valid time. See https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time for more information.');if(o!==c&&!(n=w(o)))throw new Error('"max" is not a valid time. See https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time for more information.')}else{if(t!==c&&isNaN(t))throw r=!1,new Error('"min" must be a valid number. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-min for more information.');if(o!==c&&isNaN(o))throw n=!1,new Error('"max" must be a valid number. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-max for more information.')}if(r&&n){if(o').attr('label',t.group)),o=r[t.group]);var a=s(d.option);a.attr('value',t.value).text(t.text),o.append(a)}),f(r,function(e,t){l.append(t)}),l.val(n.value),n.bootstrap<5&&l.removeClass('form-select').addClass('form-control');break;case'checkbox':let t=Array.isArray(n.value)?n.value:[n.value];if(!(i=n.inputOptions||[]).length)throw new Error('prompt with "inputType" set to "checkbox" requires at least one option');l=s('
'),f(i,function(e,o){if(o.value===c||o.text===c)throw new Error('each option needs a "value" property and a "text" property');let a=s(d.inputs[n.inputType]);a.find('input').attr('value',o.value),a.find('label').append('\n'+o.text),f(t,function(e,t){t===o.value&&a.find('input').prop('checked',!0)}),l.append(a)});break;case'radio':if(n.value!==c&&Array.isArray(n.value))throw new Error('prompt with "inputType" set to "radio" requires a single, non-array value for "value"');if(!(i=n.inputOptions||[]).length)throw new Error('prompt with "inputType" set to "radio" requires at least one option');l=s('
');let a=!0;f(i,function(e,t){if(t.value===c||t.text===c)throw new Error('each option needs a "value" property and a "text" property');var o=s(d.inputs[n.inputType]);o.find('input').attr('value',t.value),o.find('label').append('\n'+t.text),n.value!==c&&t.value===n.value&&(o.find('input').prop('checked',!0),a=!1),l.append(o)}),a&&l.find('input[type="radio"]').first().prop('checked',!0)}return e.append(l),e.on('submit',function(e){e.preventDefault(),e.stopPropagation(),t.find('.bootbox-accept').trigger('click')}),n.message&&''!==n.message.trim()&&(a=s(d.promptMessage).html(n.message),e.prepend(a)),n.message=e,(t=r.dialog(n)).off('shown.bs.modal',m),t.on('shown.bs.modal',function(){l.focus()}),!0===o&&t.modal('show'),t},r}),((e,t)=>{'function'==typeof define&&define.amd?define(['bootbox'],t):'object'==typeof module&&module.exports?t(require('./bootbox')):t(e.bootbox)})(this,function(e){e.addLocale('ar',{OK:'موافق',CANCEL:'الغاء',CONFIRM:'تأكيد'}),e.addLocale('az',{OK:'OK',CANCEL:'İmtina et',CONFIRM:'Təsdiq et'}),e.addLocale('bg-BG',{OK:'Ок',CANCEL:'Отказ',CONFIRM:'Потвърждавам'}),e.addLocale('cs',{OK:'OK',CANCEL:'Zrušit',CONFIRM:'Potvrdit'}),e.addLocale('da',{OK:'OK',CANCEL:'Annuller',CONFIRM:'Accepter'}),e.addLocale('de',{OK:'OK',CANCEL:'Abbrechen',CONFIRM:'Akzeptieren'}),e.addLocale('el',{OK:'Εντάξει',CANCEL:'Ακύρωση',CONFIRM:'Επιβεβαίωση'}),e.addLocale('en',{OK:'OK',CANCEL:'Cancel',CONFIRM:'OK'}),e.addLocale('es',{OK:'OK',CANCEL:'Cancelar',CONFIRM:'Aceptar'}),e.addLocale('et',{OK:'OK',CANCEL:'Katkesta',CONFIRM:'OK'}),e.addLocale('eu',{OK:'OK',CANCEL:'Ezeztatu',CONFIRM:'Onartu'}),e.addLocale('fa',{OK:'قبول',CANCEL:'لغو',CONFIRM:'تایید'}),e.addLocale('fi',{OK:'OK',CANCEL:'Peruuta',CONFIRM:'OK'}),e.addLocale('fr',{OK:'OK',CANCEL:'Annuler',CONFIRM:'Confirmer'}),e.addLocale('he',{OK:'אישור',CANCEL:'ביטול',CONFIRM:'אישור'}),e.addLocale('hr',{OK:'OK',CANCEL:'Odustani',CONFIRM:'Potvrdi'}),e.addLocale('hu',{OK:'OK',CANCEL:'Mégsem',CONFIRM:'Megerősít'}),e.addLocale('id',{OK:'OK',CANCEL:'Batal',CONFIRM:'OK'}),e.addLocale('it',{OK:'OK',CANCEL:'Annulla',CONFIRM:'Conferma'}),e.addLocale('ja',{OK:'OK',CANCEL:'キャンセル',CONFIRM:'OK'}),e.addLocale('ka',{OK:'OK',CANCEL:'გაუქმება',CONFIRM:'დადასტურება'}),e.addLocale('ko',{OK:'OK',CANCEL:'취소',CONFIRM:'확인'}),e.addLocale('lt',{OK:'Gerai',CANCEL:'Atšaukti',CONFIRM:'Patvirtinti'}),e.addLocale('lv',{OK:'Labi',CANCEL:'Atcelt',CONFIRM:'Apstiprināt'}),e.addLocale('nl',{OK:'OK',CANCEL:'Annuleren',CONFIRM:'Accepteren'}),e.addLocale('no',{OK:'OK',CANCEL:'Avbryt',CONFIRM:'OK'}),e.addLocale('pl',{OK:'OK',CANCEL:'Anuluj',CONFIRM:'Potwierdź'}),e.addLocale('pt-BR',{OK:'OK',CANCEL:'Cancelar',CONFIRM:'Sim'}),e.addLocale('pt',{OK:'OK',CANCEL:'Cancelar',CONFIRM:'Confirmar'}),e.addLocale('ru',{OK:'OK',CANCEL:'Отмена',CONFIRM:'Применить'}),e.addLocale('sk',{OK:'OK',CANCEL:'Zrušiť',CONFIRM:'Potvrdiť'}),e.addLocale('sl',{OK:'OK',CANCEL:'Prekliči',CONFIRM:'Potrdi'}),e.addLocale('sq',{OK:'OK',CANCEL:'Anulo',CONFIRM:'Prano'}),e.addLocale('sv',{OK:'OK',CANCEL:'Avbryt',CONFIRM:'OK'}),e.addLocale('sw',{OK:'Sawa',CANCEL:'Ghairi',CONFIRM:'Thibitisha'}),e.addLocale('ta',{OK:'சரி',CANCEL:'ரத்து செய்',CONFIRM:'உறுதி செய்'}),e.addLocale('th',{OK:'ตกลง',CANCEL:'ยกเลิก',CONFIRM:'ยืนยัน'}),e.addLocale('tr',{OK:'Tamam',CANCEL:'İptal',CONFIRM:'Onayla'}),e.addLocale('uk',{OK:'OK',CANCEL:'Відміна',CONFIRM:'Прийняти'}),e.addLocale('vi',{OK:'OK',CANCEL:'Hủy bỏ',CONFIRM:'Xác nhận'}),e.addLocale('zh-CN',{OK:'OK',CANCEL:'取消',CONFIRM:'确认'}),e.addLocale('zh-TW',{OK:'OK',CANCEL:'取消',CONFIRM:'確認'})}); \ No newline at end of file +((e,t)=>{'function'==typeof define&&define.amd?define(['jquery'],t):'object'==typeof exports?module.exports=t(require('jquery')):e.bootbox=t(e.jQuery)})(this,function t(s,c){let r={};r.VERSION='6.0.5';let i={en:{OK:'OK',CANCEL:'Cancel',CONFIRM:'OK'}},d={dialog:'',header:'',footer:'',closeButton:'',form:'
',button:'',option:'',promptMessage:'
',inputs:{text:'',textarea:'',email:'',select:'',checkbox:'
',radio:'
',date:'',time:'',number:'',password:'',range:''}},p={locale:'en',backdrop:'static',animate:!0,className:null,closeButton:!0,show:!0,container:'body',value:'',inputType:'text',errorMessage:null,swapButtonOrder:!1,centerVertical:!1,multiple:!1,scrollable:!1,reusable:!1,relatedTarget:null,size:null,id:null};function l(e,t,o){return s.extend(!0,{},e,((e,t)=>{var o=e.length;let a={};if(o<1||2{var r={};for(let e=0,t=o.length;e((t=i[t])||i.en)[e])(n,a)}}return r})(t=r&&r[0]&&(o=r[0].locale||p.locale,r[0].swapButtonOrder||p.swapButtonOrder)?t.reverse():t,o)};{e=l(e,r,a);var n=t;let o={};return f(n,function(e,t){o[t]=!0}),f(e.buttons,function(e){if(o[e]===c)throw new Error('button key "'+e+'" is not allowed (options are '+n.join(' ')+')')}),e}}function b(e){return Object.keys(e).length}function f(e,o){let a=0;s.each(e,function(e,t){o(e,t,a++)})}function m(e){e.data.dialog.find('.bootbox-accept').first().trigger('focus')}function h(e){e.target===e.data.dialog[0]&&e.data.dialog.remove()}function C(e){e.target===e.data.dialog[0]&&(e.data.dialog.off('escape.close.bb'),e.data.dialog.off('click'))}function O(e,t,o){e.stopPropagation(),e.preventDefault(),'function'==typeof o&&!1===o.call(t,e)||t.modal('hide')}function w(e){return/([01][0-9]|2[0-3]):[0-5][0-9]?:[0-5][0-9]/.test(e)}function g(e){return/(\d{4})-(\d{2})-(\d{2})/.test(e)}return r.locales=function(e){return e?i[e]:i},r.addLocale=function(e,o){return s.each(['OK','CANCEL','CONFIRM'],function(e,t){if(!o[t])throw new Error('Please supply a translation for "'+t+'"')}),i[e]={OK:o.OK,CANCEL:o.CANCEL,CONFIRM:o.CONFIRM},r},r.removeLocale=function(e){if('en'===e)throw new Error('"en" is used as the default and fallback locale and cannot be removed.');return delete i[e],r},r.setLocale=function(e){return r.setDefaults('locale',e)},r.setDefaults=function(){let e={};return 2===arguments.length?e[arguments[0]]=arguments[1]:e=arguments[0],s.extend(p,e),r},r.hideAll=function(){return s('.bootbox').modal('hide'),r},r.init=function(e){return t(e||s)},r.dialog=function(e){if(s.fn.modal===c)throw new Error('"$.fn.modal" is not defined; please double check you have included the Bootstrap JavaScript library. See https://getbootstrap.com/docs/5.3/getting-started/introduction/ for more details.');e=(a=>{let r,n;if('object'!=typeof a)throw new Error('Please supply an object of options');if(a.message)return(a=s.extend({},p,a)).backdrop?a.backdrop='string'!=typeof a.backdrop||'static'!==a.backdrop.toLowerCase()||'static':a.backdrop=!1!==a.backdrop&&0!==a.backdrop&&'static',a.buttons||(a.buttons={}),r=a.buttons,n=b(r),f(r,function(e,t,o){if('object'!=typeof(t='function'==typeof t?r[e]={callback:t}:t))throw new Error('button with key "'+e+'" must be an object');if(t.label||(t.label=e),!t.className){let e=!1;e=a.swapButtonOrder?0===o:o===n-1,n<=2&&e?t.className='btn-primary':t.className='btn-secondary btn-default'}}),a;throw new Error('"message" option must not be null or an empty string.')})(e),s.fn.modal.Constructor.VERSION?(e.fullBootstrapVersion=s.fn.modal.Constructor.VERSION,a=e.fullBootstrapVersion.indexOf('.'),e.bootstrap=e.fullBootstrapVersion.substring(0,a)):(e.bootstrap='2',e.fullBootstrapVersion='2.3.2',console.warn('Bootbox will *mostly* work with Bootstrap 2, but we do not officially support it. Please upgrade, if possible.'));let o=s(d.dialog);var t=o.find('.modal-dialog'),a=o.find('.modal-body'),r=s(d.header);let n=s(d.footer);var l=e.buttons;let i={onEscape:e.onEscape};if(a.find('.bootbox-body').html(e.message),0{let a=!1,r=!0,n=!0;if('date'===e)t===c||(r=g(t))?o===c||(n=g(o))||console.warn('Browsers which natively support the "date" input type expect date values to be of the form "YYYY-MM-DD" (see ISO-8601 https://www.iso.org/iso-8601-date-and-time-format.html). Bootbox does not enforce this rule, but your max value may not be enforced by this browser.'):console.warn('Browsers which natively support the "date" input type expect date values to be of the form "YYYY-MM-DD" (see ISO-8601 https://www.iso.org/iso-8601-date-and-time-format.html). Bootbox does not enforce this rule, but your min value may not be enforced by this browser.');else if('time'===e){if(t!==c&&!(r=w(t)))throw new Error('"min" is not a valid time. See https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time for more information.');if(o!==c&&!(n=w(o)))throw new Error('"max" is not a valid time. See https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time for more information.')}else{if(t!==c&&isNaN(t))throw r=!1,new Error('"min" must be a valid number. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-min for more information.');if(o!==c&&isNaN(o))throw n=!1,new Error('"max" must be a valid number. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-max for more information.')}if(r&&n){if(o').attr('label',t.group)),o=r[t.group]);var a=s(d.option);a.attr('value',t.value).text(t.text),o.append(a)}),f(r,function(e,t){l.append(t)}),l.val(n.value),n.bootstrap<5&&l.removeClass('form-select').addClass('form-control');break;case'checkbox':let t=Array.isArray(n.value)?n.value:[n.value];if(!(i=n.inputOptions||[]).length)throw new Error('prompt with "inputType" set to "checkbox" requires at least one option');l=s('
'),f(i,function(e,o){if(o.value===c||o.text===c)throw new Error('each option needs a "value" property and a "text" property');let a=s(d.inputs[n.inputType]);a.find('input').attr('value',o.value),a.find('label').append('\n'+o.text),f(t,function(e,t){t===o.value&&a.find('input').prop('checked',!0)}),l.append(a)});break;case'radio':if(n.value!==c&&Array.isArray(n.value))throw new Error('prompt with "inputType" set to "radio" requires a single, non-array value for "value"');if(!(i=n.inputOptions||[]).length)throw new Error('prompt with "inputType" set to "radio" requires at least one option');l=s('
');let a=!0;f(i,function(e,t){if(t.value===c||t.text===c)throw new Error('each option needs a "value" property and a "text" property');var o=s(d.inputs[n.inputType]);o.find('input').attr('value',t.value),o.find('label').append('\n'+t.text),n.value!==c&&t.value===n.value&&(o.find('input').prop('checked',!0),a=!1),l.append(o)}),a&&l.find('input[type="radio"]').first().prop('checked',!0)}return o.append(l),o.on('submit',function(e){e.preventDefault(),e.stopPropagation(),o.removeClass('was-validated'),t.find('.bootbox-accept').trigger('click')}),n.message&&''!==n.message.trim()&&(a=s(d.promptMessage).html(n.message),o.prepend(a)),n.message=o,(t=r.dialog(n)).off('shown.bs.modal',m),t.on('shown.bs.modal',function(){l.focus()}),!0===e&&t.modal('show'),t},r}),((e,t)=>{'function'==typeof define&&define.amd?define(['bootbox'],t):'object'==typeof module&&module.exports?t(require('./bootbox')):t(e.bootbox)})(this,function(e){e.addLocale('ar',{OK:'موافق',CANCEL:'الغاء',CONFIRM:'تأكيد'}),e.addLocale('az',{OK:'OK',CANCEL:'İmtina et',CONFIRM:'Təsdiq et'}),e.addLocale('bg-BG',{OK:'Ок',CANCEL:'Отказ',CONFIRM:'Потвърждавам'}),e.addLocale('cs',{OK:'OK',CANCEL:'Zrušit',CONFIRM:'Potvrdit'}),e.addLocale('da',{OK:'OK',CANCEL:'Annuller',CONFIRM:'Accepter'}),e.addLocale('de',{OK:'OK',CANCEL:'Abbrechen',CONFIRM:'Akzeptieren'}),e.addLocale('el',{OK:'Εντάξει',CANCEL:'Ακύρωση',CONFIRM:'Επιβεβαίωση'}),e.addLocale('en',{OK:'OK',CANCEL:'Cancel',CONFIRM:'OK'}),e.addLocale('es',{OK:'OK',CANCEL:'Cancelar',CONFIRM:'Aceptar'}),e.addLocale('et',{OK:'OK',CANCEL:'Katkesta',CONFIRM:'OK'}),e.addLocale('eu',{OK:'OK',CANCEL:'Ezeztatu',CONFIRM:'Onartu'}),e.addLocale('fa',{OK:'قبول',CANCEL:'لغو',CONFIRM:'تایید'}),e.addLocale('fi',{OK:'OK',CANCEL:'Peruuta',CONFIRM:'OK'}),e.addLocale('fr',{OK:'OK',CANCEL:'Annuler',CONFIRM:'Confirmer'}),e.addLocale('he',{OK:'אישור',CANCEL:'ביטול',CONFIRM:'אישור'}),e.addLocale('hr',{OK:'OK',CANCEL:'Odustani',CONFIRM:'Potvrdi'}),e.addLocale('hu',{OK:'OK',CANCEL:'Mégsem',CONFIRM:'Megerősít'}),e.addLocale('id',{OK:'OK',CANCEL:'Batal',CONFIRM:'OK'}),e.addLocale('it',{OK:'OK',CANCEL:'Annulla',CONFIRM:'Conferma'}),e.addLocale('ja',{OK:'OK',CANCEL:'キャンセル',CONFIRM:'OK'}),e.addLocale('ka',{OK:'OK',CANCEL:'გაუქმება',CONFIRM:'დადასტურება'}),e.addLocale('ko',{OK:'OK',CANCEL:'취소',CONFIRM:'확인'}),e.addLocale('lt',{OK:'Gerai',CANCEL:'Atšaukti',CONFIRM:'Patvirtinti'}),e.addLocale('lv',{OK:'Labi',CANCEL:'Atcelt',CONFIRM:'Apstiprināt'}),e.addLocale('nl',{OK:'OK',CANCEL:'Annuleren',CONFIRM:'Accepteren'}),e.addLocale('no',{OK:'OK',CANCEL:'Avbryt',CONFIRM:'OK'}),e.addLocale('pl',{OK:'OK',CANCEL:'Anuluj',CONFIRM:'Potwierdź'}),e.addLocale('pt-BR',{OK:'OK',CANCEL:'Cancelar',CONFIRM:'Sim'}),e.addLocale('pt',{OK:'OK',CANCEL:'Cancelar',CONFIRM:'Confirmar'}),e.addLocale('ru',{OK:'OK',CANCEL:'Отмена',CONFIRM:'Применить'}),e.addLocale('sk',{OK:'OK',CANCEL:'Zrušiť',CONFIRM:'Potvrdiť'}),e.addLocale('sl',{OK:'OK',CANCEL:'Prekliči',CONFIRM:'Potrdi'}),e.addLocale('sq',{OK:'OK',CANCEL:'Anulo',CONFIRM:'Prano'}),e.addLocale('sv',{OK:'OK',CANCEL:'Avbryt',CONFIRM:'OK'}),e.addLocale('sw',{OK:'Sawa',CANCEL:'Ghairi',CONFIRM:'Thibitisha'}),e.addLocale('ta',{OK:'சரி',CANCEL:'ரத்து செய்',CONFIRM:'உறுதி செய்'}),e.addLocale('th',{OK:'ตกลง',CANCEL:'ยกเลิก',CONFIRM:'ยืนยัน'}),e.addLocale('tr',{OK:'Tamam',CANCEL:'İptal',CONFIRM:'Onayla'}),e.addLocale('uk',{OK:'OK',CANCEL:'Відміна',CONFIRM:'Прийняти'}),e.addLocale('vi',{OK:'OK',CANCEL:'Hủy bỏ',CONFIRM:'Xác nhận'}),e.addLocale('zh-CN',{OK:'OK',CANCEL:'取消',CONFIRM:'确认'}),e.addLocale('zh-TW',{OK:'OK',CANCEL:'取消',CONFIRM:'確認'})}); \ No newline at end of file diff --git a/dist/bootbox.js b/dist/bootbox.js index 062610f2..7c047b6f 100644 --- a/dist/bootbox.js +++ b/dist/bootbox.js @@ -1,6 +1,6 @@ /*! @preserve * bootbox.js - * version: 6.0.4 + * version: 6.0.5 * author: Nick Payne * license: MIT * http://bootboxjs.com/ @@ -10,10 +10,12 @@ if (typeof define === 'function' && define.amd) { // AMD define(['jquery'], factory); - } else if (typeof exports === 'object') { + } + else if (typeof exports === 'object') { // Node, CommonJS-like module.exports = factory(require('jquery')); - } else { + } + else { // Browser globals (root is window) root.bootbox = factory(root.jQuery); } @@ -22,7 +24,7 @@ let exports = {}; - let VERSION = '6.0.4'; + let VERSION = '6.0.5'; exports.VERSION = VERSION; let locales = { @@ -171,7 +173,8 @@ if (arguments.length === 2) { // Allow passing of single key/value... values[arguments[0]] = arguments[1]; - } else { + } + else { // ... and as an object too values = arguments[0]; } @@ -581,6 +584,8 @@ options.buttons.confirm.callback = function () { let value; + form.addClass('was-validated'); + if (options.inputType === 'checkbox') { value = input.find('input:checked').map(function () { return $(this).val(); @@ -589,25 +594,32 @@ // prevents button callback from being called if no checkboxes have been checked return false; } - } else if (options.inputType === 'radio') { + } + else if (options.inputType === 'radio') { value = input.find('input:checked').val(); } else { let el = input[0]; + + // this must be done every time; otherwise, input is reported invalid even if value is valid + el.setCustomValidity(''); + // trigger built-in validation if checkValidity() function is defined if (el.checkValidity && !el.checkValidity()) { // If a custom error message was provided, add it now if(options.errorMessage){ el.setCustomValidity(options.errorMessage); } - if(el.reportValidity) { + // trigger built-in validation message if reportValidity() function is defined + if (el.reportValidity) { el.reportValidity(); } // prevents button callback from being called return false; - } else { + } + else { if (options.inputType === 'select' && options.multiple === true) { value = input.find('option:selected').map(function () { return $(this).val(); @@ -617,7 +629,7 @@ value = input.val(); } } - } + } return options.callback.call(this, value); }; @@ -638,6 +650,15 @@ // Create the input based on the supplied type input = $(templates.inputs[options.inputType]); + if (options.inputType !== 'textarea') { + input.on('keydown', function(ev) { + if (ev.key === 'Enter') { + ev.preventDefault(); + promptDialog.find('.bootbox-accept').trigger('click'); + } + }); + } + switch (options.inputType) { case 'text': case 'textarea': @@ -661,9 +682,9 @@ input.prop({ 'required': true }); } - if (options.rows && !isNaN(parseInt(options.rows))) { - if (options.inputType === 'textarea') { - input.attr({ 'rows': options.rows }); + if (options.inputType === 'textarea') { + if (options.rows && !isNaN(parseInt(options.rows))) { + input.attr({ rows: options.rows }); } } break; @@ -855,6 +876,8 @@ // Fix for SammyJS (or similar JS routing library) hijacking the form post. e.stopPropagation(); + form.removeClass('was-validated'); + // @TODO can we actually click *the* button object instead? // e.g. buttons.confirm.click() or similar promptDialog.find('.bootbox-accept').trigger('click'); @@ -914,7 +937,8 @@ if (argsLength === 2 || typeof args[0] === 'string') { options[properties[0]] = args[0]; options[properties[1]] = args[1]; - } else { + } + else { options = args[0]; } @@ -1035,7 +1059,8 @@ // Make sure backdrop is either true, false, or 'static' if (!options.backdrop) { options.backdrop = (options.backdrop === false || options.backdrop === 0) ? false : 'static'; - } else { + } + else { options.backdrop = typeof options.backdrop === 'string' && options.backdrop.toLowerCase() === 'static' ? 'static' : true; } diff --git a/dist/bootbox.locales.js b/dist/bootbox.locales.js index a6b5ca07..72484322 100644 --- a/dist/bootbox.locales.js +++ b/dist/bootbox.locales.js @@ -1,6 +1,6 @@ /*! @preserve * bootbox.locales.js - * version: 6.0.4 + * version: 6.0.5 * author: Nick Payne * license: MIT * http://bootboxjs.com/ diff --git a/dist/bootbox.locales.min.js b/dist/bootbox.locales.min.js index f154139f..e34ac5c8 100644 --- a/dist/bootbox.locales.min.js +++ b/dist/bootbox.locales.min.js @@ -1,6 +1,6 @@ /** * Bootbox.js — alert, confirm, prompt, and flexible dialogs for the Bootstrap framework - * @version: 6.0.4 + * @version: 6.0.5 * @project: https://github.com/bootboxjs/bootbox * @license: MIT http://bootboxjs.com/license.txt */ diff --git a/dist/bootbox.min.js b/dist/bootbox.min.js index b62cdec8..5c78800d 100644 --- a/dist/bootbox.min.js +++ b/dist/bootbox.min.js @@ -1,7 +1,7 @@ /** * Bootbox.js — alert, confirm, prompt, and flexible dialogs for the Bootstrap framework - * @version: 6.0.4 + * @version: 6.0.5 * @project: https://github.com/bootboxjs/bootbox * @license: MIT http://bootboxjs.com/license.txt */ -((t,e)=>{'function'==typeof define&&define.amd?define(['jquery'],e):'object'==typeof exports?module.exports=e(require('jquery')):t.bootbox=e(t.jQuery)})(this,function e(s,p){let r={};r.VERSION='6.0.4';let l={en:{OK:'OK',CANCEL:'Cancel',CONFIRM:'OK'}},c={dialog:'',header:'',footer:'',closeButton:'',form:'
',button:'',option:'',promptMessage:'
',inputs:{text:'',textarea:'',email:'',select:'',checkbox:'
',radio:'
',date:'',time:'',number:'',password:'',range:''}},u={locale:'en',backdrop:'static',animate:!0,className:null,closeButton:!0,show:!0,container:'body',value:'',inputType:'text',errorMessage:null,swapButtonOrder:!1,centerVertical:!1,multiple:!1,scrollable:!1,reusable:!1,relatedTarget:null,size:null,id:null};function i(t,e,o){return s.extend(!0,{},t,((t,e)=>{var o=t.length;let a={};if(o<1||2{var r={};for(let t=0,e=o.length;t((e=l[e])||l.en)[t])(n,a)}}return r})(e=r&&r[0]&&(o=r[0].locale||u.locale,r[0].swapButtonOrder||u.swapButtonOrder)?e.reverse():e,o)};{t=i(t,r,a);var n=e;let o={};return f(n,function(t,e){o[e]=!0}),f(t.buttons,function(t){if(o[t]===p)throw new Error('button key "'+t+'" is not allowed (options are '+n.join(' ')+')')}),t}}function b(t){return Object.keys(t).length}function f(t,o){let a=0;s.each(t,function(t,e){o(t,e,a++)})}function m(t){t.data.dialog.find('.bootbox-accept').first().trigger('focus')}function h(t){t.target===t.data.dialog[0]&&t.data.dialog.remove()}function w(t){t.target===t.data.dialog[0]&&(t.data.dialog.off('escape.close.bb'),t.data.dialog.off('click'))}function g(t,e,o){t.stopPropagation(),t.preventDefault(),'function'==typeof o&&!1===o.call(e,t)||e.modal('hide')}function y(t){return/([01][0-9]|2[0-3]):[0-5][0-9]?:[0-5][0-9]/.test(t)}function v(t){return/(\d{4})-(\d{2})-(\d{2})/.test(t)}return r.locales=function(t){return t?l[t]:l},r.addLocale=function(t,o){return s.each(['OK','CANCEL','CONFIRM'],function(t,e){if(!o[e])throw new Error('Please supply a translation for "'+e+'"')}),l[t]={OK:o.OK,CANCEL:o.CANCEL,CONFIRM:o.CONFIRM},r},r.removeLocale=function(t){if('en'===t)throw new Error('"en" is used as the default and fallback locale and cannot be removed.');return delete l[t],r},r.setLocale=function(t){return r.setDefaults('locale',t)},r.setDefaults=function(){let t={};return 2===arguments.length?t[arguments[0]]=arguments[1]:t=arguments[0],s.extend(u,t),r},r.hideAll=function(){return s('.bootbox').modal('hide'),r},r.init=function(t){return e(t||s)},r.dialog=function(t){if(s.fn.modal===p)throw new Error('"$.fn.modal" is not defined; please double check you have included the Bootstrap JavaScript library. See https://getbootstrap.com/docs/5.3/getting-started/introduction/ for more details.');t=(a=>{let r,n;if('object'!=typeof a)throw new Error('Please supply an object of options');if(a.message)return(a=s.extend({},u,a)).backdrop?a.backdrop='string'!=typeof a.backdrop||'static'!==a.backdrop.toLowerCase()||'static':a.backdrop=!1!==a.backdrop&&0!==a.backdrop&&'static',a.buttons||(a.buttons={}),r=a.buttons,n=b(r),f(r,function(t,e,o){if('object'!=typeof(e='function'==typeof e?r[t]={callback:e}:e))throw new Error('button with key "'+t+'" must be an object');if(e.label||(e.label=t),!e.className){let t=!1;t=a.swapButtonOrder?0===o:o===n-1,n<=2&&t?e.className='btn-primary':e.className='btn-secondary btn-default'}}),a;throw new Error('"message" option must not be null or an empty string.')})(t),s.fn.modal.Constructor.VERSION?(t.fullBootstrapVersion=s.fn.modal.Constructor.VERSION,a=t.fullBootstrapVersion.indexOf('.'),t.bootstrap=t.fullBootstrapVersion.substring(0,a)):(t.bootstrap='2',t.fullBootstrapVersion='2.3.2',console.warn('Bootbox will *mostly* work with Bootstrap 2, but we do not officially support it. Please upgrade, if possible.'));let o=s(c.dialog);var e=o.find('.modal-dialog'),a=o.find('.modal-body'),r=s(c.header);let n=s(c.footer);var i=t.buttons;let l={onEscape:t.onEscape};if(a.find('.bootbox-body').html(t.message),0{let a=!1,r=!0,n=!0;if('date'===t)e===p||(r=v(e))?o===p||(n=v(o))||console.warn('Browsers which natively support the "date" input type expect date values to be of the form "YYYY-MM-DD" (see ISO-8601 https://www.iso.org/iso-8601-date-and-time-format.html). Bootbox does not enforce this rule, but your max value may not be enforced by this browser.'):console.warn('Browsers which natively support the "date" input type expect date values to be of the form "YYYY-MM-DD" (see ISO-8601 https://www.iso.org/iso-8601-date-and-time-format.html). Bootbox does not enforce this rule, but your min value may not be enforced by this browser.');else if('time'===t){if(e!==p&&!(r=y(e)))throw new Error('"min" is not a valid time. See https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time for more information.');if(o!==p&&!(n=y(o)))throw new Error('"max" is not a valid time. See https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time for more information.')}else{if(e!==p&&isNaN(e))throw r=!1,new Error('"min" must be a valid number. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-min for more information.');if(o!==p&&isNaN(o))throw n=!1,new Error('"max" must be a valid number. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-max for more information.')}if(r&&n){if(o').attr('label',e.group)),o=r[e.group]);var a=s(c.option);a.attr('value',e.value).text(e.text),o.append(a)}),f(r,function(t,e){i.append(e)}),i.val(n.value),n.bootstrap<5&&i.removeClass('form-select').addClass('form-control');break;case'checkbox':let e=Array.isArray(n.value)?n.value:[n.value];if(!(l=n.inputOptions||[]).length)throw new Error('prompt with "inputType" set to "checkbox" requires at least one option');i=s('
'),f(l,function(t,o){if(o.value===p||o.text===p)throw new Error('each option needs a "value" property and a "text" property');let a=s(c.inputs[n.inputType]);a.find('input').attr('value',o.value),a.find('label').append('\n'+o.text),f(e,function(t,e){e===o.value&&a.find('input').prop('checked',!0)}),i.append(a)});break;case'radio':if(n.value!==p&&Array.isArray(n.value))throw new Error('prompt with "inputType" set to "radio" requires a single, non-array value for "value"');if(!(l=n.inputOptions||[]).length)throw new Error('prompt with "inputType" set to "radio" requires at least one option');i=s('
');let a=!0;f(l,function(t,e){if(e.value===p||e.text===p)throw new Error('each option needs a "value" property and a "text" property');var o=s(c.inputs[n.inputType]);o.find('input').attr('value',e.value),o.find('label').append('\n'+e.text),n.value!==p&&e.value===n.value&&(o.find('input').prop('checked',!0),a=!1),i.append(o)}),a&&i.find('input[type="radio"]').first().prop('checked',!0)}return t.append(i),t.on('submit',function(t){t.preventDefault(),t.stopPropagation(),e.find('.bootbox-accept').trigger('click')}),n.message&&''!==n.message.trim()&&(a=s(c.promptMessage).html(n.message),t.prepend(a)),n.message=t,(e=r.dialog(n)).off('shown.bs.modal',m),e.on('shown.bs.modal',function(){i.focus()}),!0===o&&e.modal('show'),e},r}); \ No newline at end of file +((t,e)=>{'function'==typeof define&&define.amd?define(['jquery'],e):'object'==typeof exports?module.exports=e(require('jquery')):t.bootbox=e(t.jQuery)})(this,function e(s,p){let r={};r.VERSION='6.0.5';let l={en:{OK:'OK',CANCEL:'Cancel',CONFIRM:'OK'}},c={dialog:'',header:'',footer:'',closeButton:'',form:'
',button:'',option:'',promptMessage:'
',inputs:{text:'',textarea:'',email:'',select:'',checkbox:'
',radio:'
',date:'',time:'',number:'',password:'',range:''}},u={locale:'en',backdrop:'static',animate:!0,className:null,closeButton:!0,show:!0,container:'body',value:'',inputType:'text',errorMessage:null,swapButtonOrder:!1,centerVertical:!1,multiple:!1,scrollable:!1,reusable:!1,relatedTarget:null,size:null,id:null};function i(t,e,o){return s.extend(!0,{},t,((t,e)=>{var o=t.length;let a={};if(o<1||2{var r={};for(let t=0,e=o.length;t((e=l[e])||l.en)[t])(n,a)}}return r})(e=r&&r[0]&&(o=r[0].locale||u.locale,r[0].swapButtonOrder||u.swapButtonOrder)?e.reverse():e,o)};{t=i(t,r,a);var n=e;let o={};return f(n,function(t,e){o[e]=!0}),f(t.buttons,function(t){if(o[t]===p)throw new Error('button key "'+t+'" is not allowed (options are '+n.join(' ')+')')}),t}}function b(t){return Object.keys(t).length}function f(t,o){let a=0;s.each(t,function(t,e){o(t,e,a++)})}function m(t){t.data.dialog.find('.bootbox-accept').first().trigger('focus')}function h(t){t.target===t.data.dialog[0]&&t.data.dialog.remove()}function w(t){t.target===t.data.dialog[0]&&(t.data.dialog.off('escape.close.bb'),t.data.dialog.off('click'))}function g(t,e,o){t.stopPropagation(),t.preventDefault(),'function'==typeof o&&!1===o.call(e,t)||e.modal('hide')}function y(t){return/([01][0-9]|2[0-3]):[0-5][0-9]?:[0-5][0-9]/.test(t)}function v(t){return/(\d{4})-(\d{2})-(\d{2})/.test(t)}return r.locales=function(t){return t?l[t]:l},r.addLocale=function(t,o){return s.each(['OK','CANCEL','CONFIRM'],function(t,e){if(!o[e])throw new Error('Please supply a translation for "'+e+'"')}),l[t]={OK:o.OK,CANCEL:o.CANCEL,CONFIRM:o.CONFIRM},r},r.removeLocale=function(t){if('en'===t)throw new Error('"en" is used as the default and fallback locale and cannot be removed.');return delete l[t],r},r.setLocale=function(t){return r.setDefaults('locale',t)},r.setDefaults=function(){let t={};return 2===arguments.length?t[arguments[0]]=arguments[1]:t=arguments[0],s.extend(u,t),r},r.hideAll=function(){return s('.bootbox').modal('hide'),r},r.init=function(t){return e(t||s)},r.dialog=function(t){if(s.fn.modal===p)throw new Error('"$.fn.modal" is not defined; please double check you have included the Bootstrap JavaScript library. See https://getbootstrap.com/docs/5.3/getting-started/introduction/ for more details.');t=(a=>{let r,n;if('object'!=typeof a)throw new Error('Please supply an object of options');if(a.message)return(a=s.extend({},u,a)).backdrop?a.backdrop='string'!=typeof a.backdrop||'static'!==a.backdrop.toLowerCase()||'static':a.backdrop=!1!==a.backdrop&&0!==a.backdrop&&'static',a.buttons||(a.buttons={}),r=a.buttons,n=b(r),f(r,function(t,e,o){if('object'!=typeof(e='function'==typeof e?r[t]={callback:e}:e))throw new Error('button with key "'+t+'" must be an object');if(e.label||(e.label=t),!e.className){let t=!1;t=a.swapButtonOrder?0===o:o===n-1,n<=2&&t?e.className='btn-primary':e.className='btn-secondary btn-default'}}),a;throw new Error('"message" option must not be null or an empty string.')})(t),s.fn.modal.Constructor.VERSION?(t.fullBootstrapVersion=s.fn.modal.Constructor.VERSION,a=t.fullBootstrapVersion.indexOf('.'),t.bootstrap=t.fullBootstrapVersion.substring(0,a)):(t.bootstrap='2',t.fullBootstrapVersion='2.3.2',console.warn('Bootbox will *mostly* work with Bootstrap 2, but we do not officially support it. Please upgrade, if possible.'));let o=s(c.dialog);var e=o.find('.modal-dialog'),a=o.find('.modal-body'),r=s(c.header);let n=s(c.footer);var i=t.buttons;let l={onEscape:t.onEscape};if(a.find('.bootbox-body').html(t.message),0{let a=!1,r=!0,n=!0;if('date'===t)e===p||(r=v(e))?o===p||(n=v(o))||console.warn('Browsers which natively support the "date" input type expect date values to be of the form "YYYY-MM-DD" (see ISO-8601 https://www.iso.org/iso-8601-date-and-time-format.html). Bootbox does not enforce this rule, but your max value may not be enforced by this browser.'):console.warn('Browsers which natively support the "date" input type expect date values to be of the form "YYYY-MM-DD" (see ISO-8601 https://www.iso.org/iso-8601-date-and-time-format.html). Bootbox does not enforce this rule, but your min value may not be enforced by this browser.');else if('time'===t){if(e!==p&&!(r=y(e)))throw new Error('"min" is not a valid time. See https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time for more information.');if(o!==p&&!(n=y(o)))throw new Error('"max" is not a valid time. See https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time for more information.')}else{if(e!==p&&isNaN(e))throw r=!1,new Error('"min" must be a valid number. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-min for more information.');if(o!==p&&isNaN(o))throw n=!1,new Error('"max" must be a valid number. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-max for more information.')}if(r&&n){if(o').attr('label',e.group)),o=r[e.group]);var a=s(c.option);a.attr('value',e.value).text(e.text),o.append(a)}),f(r,function(t,e){i.append(e)}),i.val(n.value),n.bootstrap<5&&i.removeClass('form-select').addClass('form-control');break;case'checkbox':let e=Array.isArray(n.value)?n.value:[n.value];if(!(l=n.inputOptions||[]).length)throw new Error('prompt with "inputType" set to "checkbox" requires at least one option');i=s('
'),f(l,function(t,o){if(o.value===p||o.text===p)throw new Error('each option needs a "value" property and a "text" property');let a=s(c.inputs[n.inputType]);a.find('input').attr('value',o.value),a.find('label').append('\n'+o.text),f(e,function(t,e){e===o.value&&a.find('input').prop('checked',!0)}),i.append(a)});break;case'radio':if(n.value!==p&&Array.isArray(n.value))throw new Error('prompt with "inputType" set to "radio" requires a single, non-array value for "value"');if(!(l=n.inputOptions||[]).length)throw new Error('prompt with "inputType" set to "radio" requires at least one option');i=s('
');let a=!0;f(l,function(t,e){if(e.value===p||e.text===p)throw new Error('each option needs a "value" property and a "text" property');var o=s(c.inputs[n.inputType]);o.find('input').attr('value',e.value),o.find('label').append('\n'+e.text),n.value!==p&&e.value===n.value&&(o.find('input').prop('checked',!0),a=!1),i.append(o)}),a&&i.find('input[type="radio"]').first().prop('checked',!0)}return o.append(i),o.on('submit',function(t){t.preventDefault(),t.stopPropagation(),o.removeClass('was-validated'),e.find('.bootbox-accept').trigger('click')}),n.message&&''!==n.message.trim()&&(a=s(c.promptMessage).html(n.message),o.prepend(a)),n.message=o,(e=r.dialog(n)).off('shown.bs.modal',m),e.on('shown.bs.modal',function(){i.focus()}),!0===t&&e.modal('show'),e},r}); \ No newline at end of file diff --git a/header.txt b/header.txt index 67e638c1..713afb0c 100644 --- a/header.txt +++ b/header.txt @@ -1,6 +1,6 @@ /** * Bootbox.js — alert, confirm, prompt, and flexible dialogs for the Bootstrap framework - * @version: 6.0.4 + * @version: 6.0.5 * @project: https://github.com/bootboxjs/bootbox * @license: MIT http://bootboxjs.com/license.txt */ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1a489c00..3f511edb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bootbox", - "version": "6.0.4", + "version": "6.0.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bootbox", - "version": "6.0.4", + "version": "6.0.6", "license": "MIT", "devDependencies": { "@popperjs/core": "^2.11.8", diff --git a/package.json b/package.json index b98f2925..d950cd08 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bootbox", - "version": "6.0.4", + "version": "6.0.6", "description": "Wrappers for JavaScript alert(), confirm(), prompt(), and other flexible dialogs using the Bootstrap framework", "directories": { "test": "tests" diff --git a/templates/umd-header-locales.txt b/templates/umd-header-locales.txt index fe3e0a36..b3c0d3fb 100644 --- a/templates/umd-header-locales.txt +++ b/templates/umd-header-locales.txt @@ -1,6 +1,6 @@ /*! @preserve * bootbox.locales.js - * version: 6.0.4 + * version: 6.0.5 * author: Nick Payne * license: MIT * http://bootboxjs.com/ diff --git a/templates/umd-header.txt b/templates/umd-header.txt index 6ab8417c..69abce63 100644 --- a/templates/umd-header.txt +++ b/templates/umd-header.txt @@ -1,6 +1,6 @@ /*! @preserve * bootbox.js - * version: 6.0.4 + * version: 6.0.5 * author: Nick Payne * license: MIT * http://bootboxjs.com/ diff --git a/tests/prompt.test.js b/tests/prompt.test.js index 472071f9..d7465c31 100644 --- a/tests/prompt.test.js +++ b/tests/prompt.test.js @@ -28,7 +28,6 @@ describe('bootbox.prompt', function () { }); }); - describe('where the argument is an object', function () { beforeEach(function () { this.options = {}; @@ -60,7 +59,6 @@ describe('bootbox.prompt', function () { }); }); - describe('with a callback function', function () { beforeEach(function () { return this.options.callback = function () { @@ -72,7 +70,6 @@ describe('bootbox.prompt', function () { }); }); - describe('with a title and a callback', function () { beforeEach(function () { var _this = this; @@ -113,7 +110,6 @@ describe('bootbox.prompt', function () { }); }); - describe('with two arguments', function () { describe('where the second argument is not a function', function () { beforeEach(function () { @@ -1570,6 +1566,9 @@ describe('bootbox.prompt', function () { beforeEach(function () { return this.dialog.find('.bootbox-accept').trigger('click'); }); + it('should set the `was-validated` class', function () { + return expect(this.dialog.find('.bootbox-form').hasClass('was-validated')).to.equal(true); + }); return it('should not invoke the callback', function () { return expect(this.callback).to.not.have.been.called; }); @@ -1644,6 +1643,9 @@ describe('bootbox.prompt', function () { beforeEach(function () { return this.dialog.find('.bootbox-accept').trigger('click'); }); + it('should set the `was-validated` class', function () { + return expect(this.dialog.find('.bootbox-form').hasClass('was-validated')).to.equal(true); + }); return it('should not invoke the callback', function () { return expect(this.callback).to.not.have.been.called; }); @@ -1718,6 +1720,9 @@ describe('bootbox.prompt', function () { beforeEach(function () { return this.dialog.find('.bootbox-accept').trigger('click'); }); + it('should set the `was-validated` class', function () { + return expect(this.dialog.find('.bootbox-form').hasClass('was-validated')).to.equal(true); + }); return it('should not invoke the callback', function () { return expect(this.callback).to.not.have.been.called; }); @@ -1792,6 +1797,9 @@ describe('bootbox.prompt', function () { beforeEach(function () { return this.dialog.find('.bootbox-accept').trigger('click'); }); + it('should set the `was-validated` class', function () { + return expect(this.dialog.find('.bootbox-form').hasClass('was-validated')).to.equal(true); + }); return it('should not invoke the callback', function () { return expect(this.callback).to.not.have.been.called; }); @@ -1866,6 +1874,9 @@ describe('bootbox.prompt', function () { beforeEach(function () { return this.dialog.find('.bootbox-accept').trigger('click'); }); + it('should set the `was-validated` class', function () { + return expect(this.dialog.find('.bootbox-form').hasClass('was-validated')).to.equal(true); + }); return it('should not invoke the callback', function () { return expect(this.callback).to.not.have.been.called; }); @@ -1940,6 +1951,9 @@ describe('bootbox.prompt', function () { beforeEach(function () { return this.dialog.find('.bootbox-accept').trigger('click'); }); + it('should set the `was-validated` class', function () { + return expect(this.dialog.find('.bootbox-form').hasClass('was-validated')).to.equal(true); + }); return it('should not invoke the callback', function () { return expect(this.callback).to.not.have.been.called; }); @@ -2014,6 +2028,9 @@ describe('bootbox.prompt', function () { beforeEach(function () { return this.dialog.find('.bootbox-accept').trigger('click'); }); + it('should set the `was-validated` class', function () { + return expect(this.dialog.find('.bootbox-form').hasClass('was-validated')).to.equal(true); + }); return it('should not invoke the callback', function () { return expect(this.callback).to.not.have.been.called; }); @@ -2569,6 +2586,9 @@ describe('bootbox.prompt', function () { beforeEach(function () { return this.dialog.find('.bootbox-accept').trigger('click'); }); + it('should set the `was-validated` class', function () { + return expect(this.dialog.find('.bootbox-form').hasClass('was-validated')).to.equal(true); + }); return it('should not invoke the callback', function () { return expect(this.callback).to.not.have.been.called; }); @@ -2577,6 +2597,9 @@ describe('bootbox.prompt', function () { beforeEach(function () { return this.dialog.find('.bootbox-form').trigger('submit'); }); + it('should set the `was-validated` class', function () { + return expect(this.dialog.find('.bootbox-form').hasClass('was-validated')).to.equal(true); + }); return it('should not invoke the callback', function () { return expect(this.callback).to.not.have.been.called; });