1/*! 2 * sweetalert2 v5.1.1 3 * Released under the MIT License. 4 */ 5(function (global, factory) { 6 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 7 typeof define === 'function' && define.amd ? define(factory) : 8 (global.Sweetalert2 = factory()); 9}(this, function () { 'use strict'; 10 11 var swalPrefix = 'swal2-'; 12 13 var prefix = function(items) { 14 var result = {}; 15 for (var i in items) { 16 result[items[i]] = swalPrefix + items[i]; 17 } 18 return result; 19 }; 20 21 var swalClasses = prefix([ 22 'container', 23 'in', 24 'modal', 25 'overlay', 26 'close', 27 'content', 28 'spacer', 29 'confirm', 30 'cancel', 31 'icon', 32 'image', 33 'input', 34 'file', 35 'range', 36 'select', 37 'radio', 38 'checkbox', 39 'textarea', 40 'validationerror', 41 'progresssteps', 42 'activeprogressstep', 43 'progresscircle', 44 'progressline' 45 ]); 46 47 var iconTypes = prefix([ 48 'success', 49 'warning', 50 'info', 51 'question', 52 'error' 53 ]); 54 55 var defaultParams = { 56 title: '', 57 text: '', 58 html: '', 59 type: null, 60 customClass: '', 61 animation: true, 62 allowOutsideClick: true, 63 allowEscapeKey: true, 64 showConfirmButton: true,
65 showCancelButton: false, 66 preConfirm: null, 67 confirmButtonText: 'OK', 68 confirmButtonColor: '#3085d6', 69 confirmButtonClass: null, 70 cancelButtonText: 'Cancel', 71 cancelButtonColor: '#aaa', 72 cancelButtonClass: null, 73 buttonsStyling: true, 74 reverseButtons: false, 75 focusCancel: false, 76 showCloseButton: false, 77 showLoaderOnConfirm: false, 78 imageUrl: null, 79 imageWidth: null, 80 imageHeight: null, 81 imageClass: null, 82 timer: null, 83 width: 500, 84 padding: 20, 85 background: '#fff', 86 input: null, 87 inputPlaceholder: '', 88 inputValue: '', 89 inputOptions: {}, 90 inputAutoTrim: true, 91 inputClass: null, 92 inputAttributes: {}, 93 inputValidator: null, 94 progressSteps: [], 95 currentProgressStep: null, 96 progressStepsDistance: '40px', 97 onOpen: null, 98 onClose: null 99 }; 100 101 var sweetHTML = '<div class="' + swalClasses.modal + '" style="display: none" tabIndex="-1">' + 102 '<ul class="' + swalClasses.progresssteps + '"></ul>' + 103 '<div class="' + swalClasses.icon + ' ' + iconTypes.error + '">' + 104 '<span class="x-mark"><span class="line left"></span><span class="line right"></span></span>' + 105 '</div>' + 106 '<div class="' + swalClasses.icon + ' ' + iconTypes.question + '">?</div>' + 107 '<div class="' + swalClasses.icon + ' ' + iconTypes.warning + '">!</div>' + 108 '<div class="' + swalClasses.icon + ' ' + iconTypes.info + '">i</div>' + 109 '<div class="' + swalClasses.icon + ' ' + iconTypes.success + '">' + 110 '<span class="line tip"></span> <span class="line long"></span>' + 111 '<div class="placeholder"></div> <div class="fix"></div>' + 112 '</div>' + 113 '<img class="' + swalClasses.image + '">' + 114 '<h2></h2>' + 115 '<div class="' + swalClasses.content + '"></div>' + 116 '<input class="' + swalClasses.input + '">' + 117 '<input type="file" class="' + swalClasses.file + '">' + 118 '<div class="' + swalClasses.range + '">' + 119 '<output></output>' + 120 '<input type="range">' + 121 '</div>' + 122 '<select class="' + swalClasses.select + '"></select>' + 123 '<div class="' + swalClasses.radio + '"></div>' + 124 '<label for="' + swalClasses.checkbox + '" class="' + swalClasses.checkbox + '">' + 125 '<input type="checkbox">' + 126 '</label>' + 127 '<textarea class="' + swalClasses.textarea + '"></textarea>' + 128 '<div class="' + swalClasses.validationerror + '"></div>' + 129 '<hr class="' + swalClasses.spacer + '">' + 130 '<button type="button" class="' + swalClasses.confirm + '">OK</button>' + 131 '<button type="button" class="' + swalClasses.cancel + '">Cancel</button>' + 132 '<span class="' + swalClasses.close + '">×</span>' + 133 '</div>'; 134 135 var sweetContainer; 136 137 var existingSweetContainers = document.getElementsByClassName(swalClasses.container); 138 139 if (existingSweetContainers.length) { 140 sweetContainer = existingSweetContainers[0]; 141 } else { 142 sweetContainer = document.createElement('div'); 143 sweetContainer.className = swalClasses.container; 144 sweetContainer.innerHTML = sweetHTML; 145 } 146 147 var extend = function(a, b) { 148 for (var key in b) { 149 if (b.hasOwnProperty(key)) { 150 a[key] = b[key]; 151 } 152 } 153 154 return a; 155 }; 156 157 158 /* 159 * Set hover, active and focus-states for buttons (source: http://www.sitepoint.com/javascript-generate-lighter-darker-color) 160 */ 161 var colorLuminance = function(hex, lum) { 162 // Validate hex string 163 hex = String(hex).replace(/[^0-9a-f]/gi, ''); 164 if (hex.length < 6) { 165 hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; 166 } 167 lum = lum || 0; 168 169 // Convert to decimal and change luminosity 170 var rgb = '#'; 171 for (var i = 0; i < 3; i++) { 172 var c = parseInt(hex.substr(i * 2, 2), 16); 173 c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); 174 rgb += ('00' + c).substr(c.length); 175 } 176 177 return rgb; 178 }; 179 180 // Remember state in cases where opening and handling a modal will fiddle with it. 181 var states = { 182 previousWindowKeyDown: null, 183 previousActiveElement: null, 184 previousBodyPadding: null 185 }; 186 187 /* 188 * Add modal + overlay to DOM 189 */ 190 var init = function() { 191 if (typeof document === 'undefined') { 192 console.error('SweetAlert2 requires document to initialize'); 193 return; 194 } else if (document.getElementsByClassName(swalClasses.container).length) { 195 return; 196 } 197 198 document.body.appendChild(sweetContainer); 199 200 var modal = getModal(); 201 var input = getChildByClass(modal, swalClasses.input); 202 var file = getChildByClass(modal, swalClasses.file); 203 var range = modal.querySelector('.' + swalClasses.range + ' input'); 204 var select = getChildByClass(modal, swalClasses.select); 205 var checkbox = modal.querySelector('.' + swalClasses.checkbox + ' input'); 206 var textarea = getChildByClass(modal, swalClasses.textarea); 207 208 input.oninput = function() { 209 sweetAlert.resetValidationError(); 210 }; 211 212 input.onkeyup = function(event) { 213 event.stopPropagation(); 214 if (event.keyCode === 13) { 215 sweetAlert.clickConfirm(); 216 } 217 }; 218 219 file.onchange = function() { 220 sweetAlert.resetValidationError(); 221 }; 222 223 range.oninput = function() { 224 sweetAlert.resetValidationError(); 225 range.previousSibling.value = range.value; 226 }; 227 228 range.onchange = function() { 229 sweetAlert.resetValidationError(); 230 range.previousSibling.value = range.value; 231 }; 232 233 select.onchange = function() { 234 sweetAlert.resetValidationError(); 235 }; 236 237 checkbox.onchange = function() { 238 sweetAlert.resetValidationError(); 239 }; 240 241 textarea.oninput = function() { 242 sweetAlert.resetValidationError(); 243 }; 244 245 return modal; 246 }; 247 248 /* 249 * Manipulate DOM 250 */ 251 var elementByClass = function(className) { 252 return sweetContainer.querySelector('.' + className); 253 }; 254 255 var getModal = function() { 256 return document.body.querySelector('.' + swalClasses.modal) || init(); 257 }; 258 259 var getIcons = function() { 260 var modal = getModal(); 261 return modal.querySelectorAll('.' + swalClasses.icon); 262 }; 263 264 var getSpacer = function() { 265 return elementByClass(swalClasses.spacer); 266 }; 267 268 var getProgressSteps = function() { 269 return elementByClass(swalClasses.progresssteps); 270 }; 271 272 var getValidationError = function() { 273 return elementByClass(swalClasses.validationerror); 274 }; 275 276 var getConfirmButton = function() { 277 return elementByClass(swalClasses.confirm); 278 }; 279 280 var getCancelButton = function() { 281 return elementByClass(swalClasses.cancel); 282 }; 283 284 var getCloseButton = function() { 285 return elementByClass(swalClasses.close); 286 }; 287 288 var getFocusableElements = function(focusCancel) { 289 var buttons = [getConfirmButton(), getCancelButton()]; 290 if (focusCancel) { 291 buttons.reverse(); 292 } 293 return buttons.concat(Array.prototype.slice.call( 294 getModal().querySelectorAll('button:not([class^=' + swalPrefix + ']), input:not([type=hidden]), textarea, select') 295 )); 296 }; 297 298 var hasClass = function(elem, className) { 299 return elem.classList.contains(className); 300 }; 301 302 var focusInput = function(input) { 303 input.focus(); 304 305 // place cursor at end of text in text input 306 if (input.type !== 'file') { 307 // http://stackoverflow.com/a/2345915/1331425 308 var val = input.value; 309 input.value = ''; 310 input.value = val; 311 } 312 }; 313 314 var addClass = function(elem, className) { 315 if (!elem || !className) { 316 return; 317 } 318 var classes = className.split(/\s+/);
319 classes.forEach(function(className) { 320 elem.classList.add(className); 321 }); 322 }; 323 324 var removeClass = function(elem, className) { 325 if (!elem || !className) { 326 return; 327 } 328 var classes = className.split(/\s+/); 329 classes.forEach(function(className) { 330 elem.classList.remove(className); 331 }); 332 }; 333 334 var getChildByClass = function(elem, className) { 335 for (var i = 0; i < elem.childNodes.length; i++) { 336 if (hasClass(elem.childNodes[i], className)) { 337 return elem.childNodes[i]; 338 } 339 } 340 }; 341 342 var show = function(elem, display) { 343 if (!display) { 344 display = 'block'; 345 } 346 elem.style.opacity = ''; 347 elem.style.display = display; 348 }; 349 350 var hide = function(elem) { 351 elem.style.opacity = ''; 352 elem.style.display = 'none'; 353 }; 354 355 var empty = function(elem) { 356 while (elem.firstChild) { 357 elem.removeChild(elem.firstChild); 358 } 359 }; 360 361 // borrowed from jqeury $(elem).is(':visible') implementation 362 var isVisible = function(elem) { 363 return elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length; 364 }; 365 366 var removeStyleProperty = function(elem, property) { 367 if (elem.style.removeProperty) { 368 elem.style.removeProperty(property); 369 } else { 370 elem.style.removeAttribute(property); 371 } 372 }; 373 374 var fireClick = function(node) { 375 // Taken from http://www.nonobtrusive.com/2011/11/29/programatically-fire-crossbrowser-click-event-with-javascript/ 376 // Then fixed for today's Chrome browser. 377 if (typeof MouseEvent === 'function') { 378 // Up-to-date approach 379 var mevt = new MouseEvent('click', { 380 view: window, 381 bubbles: false, 382 cancelable: true 383 }); 384 node.dispatchEvent(mevt); 385 } else if (document.createEvent) { 386 // Fallback 387 var evt = document.createEvent('MouseEvents'); 388 evt.initEvent('click', false, false); 389 node.dispatchEvent(evt); 390 } else if (document.createEventObject) { 391 node.fireEvent('onclick'); 392 } else if (typeof node.onclick === 'function') { 393 node.onclick(); 394 } 395 }; 396 397 var stopEventPropagation = function(e) { 398 // In particular, make sure the space bar doesn't scroll the main window. 399 if (typeof e.stopPropagation === 'function') { 400 e.stopPropagation(); 401 e.preventDefault(); 402 } else if (window.event && window.event.hasOwnProperty('cancelBubble')) { 403 window.event.cancelBubble = true; 404 } 405 }; 406 407 var animationEndEvent = (function() { 408 var testEl = document.createElement('div'), 409 transEndEventNames = { 410 'WebkitAnimation': 'webkitAnimationEnd', 411 'OAnimation': 'oAnimationEnd oanimationend', 412 'msAnimation': 'MSAnimationEnd', 413 'animation': 'animationend' 414 }; 415 for (var i in transEndEventNames) { 416 if (transEndEventNames.hasOwnProperty(i) && 417 testEl.style[i] !== undefined) { 418 return transEndEventNames[i]; 419 } 420 } 421 422 return false; 423 })(); 424 425 426 // Reset the page to its previous state 427 var resetPrevState = function() { 428 var modal = getModal(); 429 window.onkeydown = states.previousWindowKeyDown; 430 if (states.previousActiveElement && states.previousActiveElement.focus) { 431 states.previousActiveElement.focus(); 432 } 433 clearTimeout(modal.timeout); 434 }; 435 436 // Measure width of scrollbar 437 // https://github.com/twbs/bootstrap/blob/master/js/modal.js#L279-L286 438 var measureScrollbar = function() { 439 var scrollDiv = document.createElement('div'); 440 scrollDiv.style.width = '50px'; 441 scrollDiv.style.height = '50px'; 442 scrollDiv.style.overflow = 'scroll'; 443 document.body.appendChild(scrollDiv); 444 var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; 445 document.body.removeChild(scrollDiv); 446 return scrollbarWidth; 447 }; 448 449 // JavaScript Debounce Function 450 // https://davidwalsh.name/javascript-debounce-function 451 var debounce = function(func, wait, immediate) { 452 var timeout; 453 return function() { 454 var context = this, args = arguments; 455 var later = function() { 456 timeout = null;
457 if (!immediate) func.apply(context, args); 458 }; 459 var callNow = immediate && !timeout; 460 clearTimeout(timeout); 461 timeout = setTimeout(later, wait); 462 if (callNow) func.apply(context, args); 463 }; 464 }; 465 466 var modalParams = extend({}, defaultParams); 467 var queue = []; 468 var swal2Observer; 469 470 /* 471 * Set type, text and actions on modal 472 */ 473 var setParameters = function(params) { 474 var modal = getModal(); 475 476 for (var param in params) { 477 if (!defaultParams.hasOwnProperty(param) && param !== 'extraParams') { 478 console.warn('SweetAlert2: Unknown parameter "' + param + '"'); 479 } 480 } 481 482 // set modal width and margin-left 483 modal.style.width = (typeof params.width === 'number') ? params.width + 'px' : params.width; 484 485 modal.style.padding = params.padding + 'px'; 486 modal.style.background = params.background; 487 488 var $title = modal.querySelector('h2'); 489 var $content = modal.querySelector('.' + swalClasses.content); 490 var $confirmBtn = getConfirmButton(); 491 var $cancelBtn = getCancelButton(); 492 var $closeButton = modal.querySelector('.' + swalClasses.close); 493 494 // Title 495 $title.innerHTML = params.title.split('\n').join('<br>'); 496 497 // Content 498 var i; 499 if (params.text || params.html) { 500 if (typeof params.html === 'object') { 501 $content.innerHTML = ''; 502 if (0 in params.html) { 503 for (i = 0; i in params.html; i++) { 504 $content.appendChild(params.html[i].cloneNode(true)); 505 } 506 } else { 507 $content.appendChild(params.html.cloneNode(true)); 508 } 509 } else { 510 $content.innerHTML = params.html || (params.text.split('\n').join('<br>')); 511 } 512 show($content); 513 } else { 514 hide($content); 515 } 516 517 // Close button 518 if (params.showCloseButton) { 519 show($closeButton); 520 } else { 521 hide($closeButton); 522 } 523 524 // Custom Class 525 modal.className = swalClasses.modal; 526 if (params.customClass) { 527 addClass(modal, params.customClass); 528 } 529 530 // Progress steps 531 var progressStepsContainer = getProgressSteps(); 532 var currentProgressStep = parseInt(params.currentProgressStep === null? sweetAlert$1.getQueueStep() : params.currentProgressStep, 10); 533 if (params.progressSteps.length) { 534 show(progressStepsContainer); 535 empty(progressStepsContainer); 536 if (currentProgressStep >= params.progressSteps.length) { 537 console.warn( 538 'SweetAlert2: Invalid currentProgressStep parameter, it should be less than progressSteps.length ' + 539 '(currentProgressStep like JS arrays starts from 0)' 540 ); 541 } 542 params.progressSteps.forEach(function(step, index) { 543 var circle = document.createElement('li'); 544 addClass(circle, swalClasses.progresscircle); 545 circle.innerHTML = step; 546 if (index === currentProgressStep) { 547 addClass(circle, swalClasses.activeprogressstep); 548 } 549 progressStepsContainer.appendChild(circle); 550 if (index !== params.progressSteps.length - 1) { 551 var line = document.createElement('li'); 552 addClass(line, swalClasses.progressline); 553 line.style.width = params.progressStepsDistance; 554 progressStepsContainer.appendChild(line); 555 } 556 }); 557 } else { 558 hide(progressStepsContainer); 559 } 560 561 // Icon 562 var icons = getIcons(); 563 for (i = 0; i < icons.length; i++) { 564 hide(icons[i]); 565 } 566 if (params.type) { 567 var validType = false;
568 for (var iconType in iconTypes) { 569 if (params.type === iconType) { 570 validType = true; 571 break; 572 } 573 } 574 if (!validType) { 575 console.error('SweetAlert2: Unknown alert type: ' + params.type); 576 return false; 577 } 578 var $icon = modal.querySelector('.' + swalClasses.icon + '.' + iconTypes[params.type]); 579 show($icon); 580 581 // Animate icon 582 switch (params.type) { 583 case 'success': 584 addClass($icon, 'animate'); 585 addClass($icon.querySelector('.tip'), 'animate-success-tip'); 586 addClass($icon.querySelector('.long'), 'animate-success-long'); 587 break; 588 case 'error': 589 addClass($icon, 'animate-error-icon'); 590 addClass($icon.querySelector('.x-mark'), 'animate-x-mark'); 591 break; 592 case 'warning': 593 addClass($icon, 'pulse-warning'); 594 break; 595 default: 596 break; 597 } 598 599 } 600 601 // Custom image 602 var $customImage = modal.querySelector('.' + swalClasses.image); 603 if (params.imageUrl) { 604 $customImage.setAttribute('src', params.imageUrl); 605 show($customImage); 606 607 if (params.imageWidth) { 608 $customImage.setAttribute('width', params.imageWidth); 609 } else { 610 $customImage.removeAttribute('width'); 611 } 612 613 if (params.imageHeight) { 614 $customImage.setAttribute('height', params.imageHeight); 615 } else { 616 $customImage.removeAttribute('height'); 617 } 618 619 $customImage.className = swalClasses.image; 620 if (params.imageClass) { 621 addClass($customImage, params.imageClass); 622 } 623 } else { 624 hide($customImage); 625 } 626 627 // Cancel button 628 if (params.showCancelButton) { 629 $cancelBtn.style.display = 'inline-block'; 630 } else { 631 hide($cancelBtn); 632 } 633 634 // Confirm button 635 if (params.showConfirmButton) { 636 removeStyleProperty($confirmBtn, 'display'); 637 } else { 638 hide($confirmBtn); 639 } 640 641 // Buttons spacer 642 var spacer = getSpacer(); 643 if (!params.showConfirmButton && !params.showCancelButton) { 644 hide(spacer); 645 } else { 646 show(spacer); 647 } 648 649 // Edit text on cancel and confirm buttons 650 $confirmBtn.innerHTML = params.confirmButtonText; 651 $cancelBtn.innerHTML = params.cancelButtonText; 652 653 // Set buttons to selected background colors 654 if (params.buttonsStyling) { 655 $confirmBtn.style.backgroundColor = params.confirmButtonColor; 656 $cancelBtn.style.backgroundColor = params.cancelButtonColor; 657 } 658 659 // Add buttons custom classes 660 $confirmBtn.className = swalClasses.confirm; 661 addClass($confirmBtn, params.confirmButtonClass); 662 $cancelBtn.className = swalClasses.cancel; 663 addClass($cancelBtn, params.cancelButtonClass); 664 665 // Buttons styling 666 if (params.buttonsStyling) { 667 addClass($confirmBtn, 'styled'); 668 addClass($cancelBtn, 'styled'); 669 } else { 670 removeClass($confirmBtn, 'styled'); 671 removeClass($cancelBtn, 'styled'); 672 673 $confirmBtn.style.backgroundColor = $confirmBtn.style.borderLeftColor = $confirmBtn.style.borderRightColor = ''; 674 $cancelBtn.style.backgroundColor = $cancelBtn.style.borderLeftColor = $cancelBtn.style.borderRightColor = ''; 675 } 676 677 // CSS animation 678 if (params.animation === true) { 679 removeClass(modal, 'no-animation'); 680 } else { 681 addClass(modal, 'no-animation'); 682 } 683 }; 684 685 /* 686 * Animations 687 */ 688 var openModal = function(animation, onComplete) { 689 var modal = getModal(); 690 if (animation) { 691 addClass(modal, 'show-swal2'); 692 addClass(sweetContainer, 'fade'); 693 removeClass(modal, 'hide-swal2'); 694 } else { 695 removeClass(modal, 'fade'); 696 } 697 show(modal); 698 699 // scrolling is 'hidden' until animation is done, after that 'auto' 700 sweetContainer.style.overflowY = 'hidden'; 701 if (animationEndEvent && !hasClass(modal, 'no-animation')) { 702 modal.addEventListener(animationEndEvent, function swalCloseEventFinished() { 703 modal.removeEventListener(animationEndEvent, swalCloseEventFinished); 704 sweetContainer.style.overflowY = 'auto'; 705 }); 706 } else { 707 sweetContainer.style.overflowY = 'auto'; 708 } 709 710 addClass(sweetContainer, 'in'); 711 addClass(document.body, swalClasses.in); 712 fixScrollbar(); 713 states.previousActiveElement = document.activeElement; 714 if (onComplete !== null && typeof onComplete === 'function') { 715 onComplete.call(this, modal); 716 } 717 }; 718 719 function fixScrollbar() { 720 // for queues, do not do this more than once 721 if (states.previousBodyPadding !== null) { 722 return; 723 } 724 // if the body has overflow 725 if (document.body.scrollHeight > window.innerHeight) { 726 // add padding so the content doesn't shift after removal of scrollbar 727 states.previousBodyPadding = document.body.style.paddingRight; 728 document.body.style.paddingRight = measureScrollbar() + 'px'; 729 } 730 } 731 732 function undoScrollbar() { 733 if (states.previousBodyPadding !== null) { 734 document.body.style.paddingRight = states.previousBodyPadding; 735 states.previousBodyPadding = null; 736 } 737 } 738 739 function modalDependant() { 740 if (arguments[0] === undefined) { 741 console.error('SweetAlert2 expects at least 1 attribute!'); 742 return false;
743 } 744 745 var params = extend({}, modalParams); 746 747 switch (typeof arguments[0]) { 748 749 case 'string': 750 params.title = arguments[0]; 751 params.text = arguments[1] || ''; 752 params.type = arguments[2] || ''; 753 754 break; 755 756 case 'object': 757 extend(params, arguments[0]); 758 params.extraParams = arguments[0].extraParams; 759 760 if (params.input === 'email' && params.inputValidator === null) { 761 params.inputValidator = function(email) { 762 return new Promise(function(resolve, reject) { 763 var emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/; 764 if (emailRegex.test(email)) { 765 resolve(); 766 } else { 767 reject('Invalid email address'); 768 } 769 }); 770 }; 771 } 772 773 break; 774 775 default: 776 console.error('SweetAlert2: Unexpected type of argument! Expected "string" or "object", got ' + typeof arguments[0]); 777 return false; 778 } 779 780 setParameters(params); 781 782 // Modal interactions 783 var modal = getModal(); 784 785 return new Promise(function(resolve, reject) { 786 // Close on timer 787 if (params.timer) { 788 modal.timeout = setTimeout(function() { 789 sweetAlert$1.closeModal(params.onClose); 790 reject('timer'); 791 }, params.timer); 792 } 793 794 // Get input element by specified type or, if type isn't specified, by params.input 795 var getInput = function(inputType) { 796 inputType = inputType || params.input; 797 switch (inputType) { 798 case 'select': 799 case 'textarea': 800 case 'file': 801 return getChildByClass(modal, swalClasses[inputType]); 802 case 'checkbox': 803 return modal.querySelector('.' + swalClasses.checkbox + ' input'); 804 case 'radio': 805 return modal.querySelector('.' + swalClasses.radio + ' input:checked') || 806 modal.querySelector('.' + swalClasses.radio + ' input:first-child'); 807 case 'range': 808 return modal.querySelector('.' + swalClasses.range + ' input'); 809 default: 810 return getChildByClass(modal, swalClasses.input); 811 } 812 }; 813 814 // Get the value of the modal input 815 var getInputValue = function() { 816 var input = getInput(); 817 if (!input) { 818 return null; 819 } 820 switch (params.input) { 821 case 'checkbox': 822 return input.checked ? 1 : 0; 823 case 'radio': 824 return input.checked ? input.value : null; 825 case 'file': 826 return input.files.length ? input.files[0] : null; 827 default: 828 return params.inputAutoTrim? input.value.trim() : input.value; 829 } 830 }; 831 832 // input autofocus 833 if (params.input) { 834 setTimeout(function() { 835 var input = getInput(); 836 if (input) { 837 focusInput(input); 838 } 839 }, 0); 840 } 841 842 var confirm = function(value) { 843 if (params.showLoaderOnConfirm) { 844 sweetAlert$1.showLoading(); 845 } 846 847 if (params.preConfirm) { 848 params.preConfirm(value, params.extraParams).then( 849 function(preConfirmValue) { 850 sweetAlert$1.closeModal(params.onClose); 851 resolve(preConfirmValue || value); 852 }, 853 function(error) { 854 sweetAlert$1.hideLoading(); 855 if (error) { 856 sweetAlert$1.showValidationError(error); 857 } 858 } 859 ); 860 } else { 861 sweetAlert$1.closeModal(params.onClose); 862 resolve(value); 863 } 864 }; 865 866 // Mouse interactions 867 var onButtonEvent = function(event) { 868 var e = event || window.event; 869 var target = e.target || e.srcElement; 870 var confirmBtn = getConfirmButton(); 871 var cancelBtn = getCancelButton(); 872 var targetedConfirm = confirmBtn === target || confirmBtn.contains(target); 873 var targetedCancel = cancelBtn === target || cancelBtn.contains(target); 874 875 switch (e.type) { 876 case 'mouseover': 877 case 'mouseup': 878 if (params.buttonsStyling) { 879 if (targetedConfirm) { 880 confirmBtn.style.backgroundColor = colorLuminance(params.confirmButtonColor, -0.1); 881 } else if (targetedCancel) { 882 cancelBtn.style.backgroundColor = colorLuminance(params.cancelButtonColor, -0.1); 883 } 884 } 885 break; 886 case 'mouseout': 887 if (params.buttonsStyling) { 888 if (targetedConfirm) { 889 confirmBtn.style.backgroundColor = params.confirmButtonColor; 890 } else if (targetedCancel) { 891 cancelBtn.style.backgroundColor = params.cancelButtonColor; 892 } 893 } 894 break; 895 case 'mousedown': 896 if (params.buttonsStyling) { 897 if (targetedConfirm) { 898 confirmBtn.style.backgroundColor = colorLuminance(params.confirmButtonColor, -0.2); 899 } else if (targetedCancel) { 900 cancelBtn.style.backgroundColor = colorLuminance(params.cancelButtonColor, -0.2); 901 } 902 } 903 break; 904 case 'click': 905 // Clicked 'confirm' 906 if (targetedConfirm && sweetAlert$1.isVisible()) { 907 if (params.input) { 908 var inputValue = getInputValue(); 909 910 if (params.inputValidator) { 911 sweetAlert$1.disableInput(); 912 params.inputValidator(inputValue, params.extraParams).then( 913 function() { 914 sweetAlert$1.enableInput(); 915 confirm(inputValue); 916 }, 917 function(error) { 918 sweetAlert$1.enableInput(); 919 if (error) { 920 sweetAlert$1.showValidationError(error); 921 } 922 } 923 ); 924 } else { 925 confirm(inputValue); 926 } 927 928 } else { 929 confirm(true); 930 } 931 932 // Clicked 'cancel' 933 } else if (targetedCancel && sweetAlert$1.isVisible()) { 934 sweetAlert$1.closeModal(params.onClose); 935 reject('cancel'); 936 } 937 938 break; 939 default: 940 } 941 }; 942 943 var $buttons = modal.querySelectorAll('button'); 944 var i; 945 for (i = 0; i < $buttons.length; i++) { 946 $buttons[i].onclick = onButtonEvent; 947 $buttons[i].onmouseover = onButtonEvent; 948 $buttons[i].onmouseout = onButtonEvent; 949 $buttons[i].onmousedown = onButtonEvent; 950 } 951 952 // Closing modal by close button 953 getCloseButton().onclick = function() { 954 sweetAlert$1.closeModal(params.onClose); 955 reject('close'); 956 }; 957 958 // Closing modal by overlay click 959 sweetContainer.onclick = function(e) { 960 if (e.target !== sweetContainer) { 961 return; 962 } 963 if (params.allowOutsideClick) { 964 sweetAlert$1.closeModal(params.onClose); 965 reject('overlay'); 966 } 967 }; 968 969 var $confirmButton = getConfirmButton(); 970 var $cancelButton = getCancelButton(); 971 972 // Reverse buttons if neede d 973 if (params.reverseButtons) { 974 $confirmButton.parentNode.insertBefore($cancelButton, $confirmButton); 975 } else { 976 $confirmButton.parentNode.insertBefore($confirmButton, $cancelButton); 977 } 978 979 // Focus handling 980 function setFocus(index, increment) { 981 var focusableElements = getFocusableElements(params.focusCancel); 982 // search for visible elements and select the next possible match 983 for (var i = 0; i < focusableElements.length; i++) { 984 index = index + increment; 985 986 // rollover to first item 987 if (index === focusableElements.length) { 988 index = 0; 989 990 // go to last item 991 } else if (index === -1) { 992 index = focusableElements.length - 1; 993 } 994 995 // determine if element is visible 996 var el = focusableElements[index]; 997 if (isVisible(el)) { 998 return el.focus(); 999 } 1000 } 1001 } 1002 1003 function handleKeyDown(event) { 1004 var e = event || window.event; 1005 var keyCode = e.keyCode || e.which; 1006 1007 if ([9, 13, 32, 27].indexOf(keyCode) === -1) { 1008 // Don't do work on keys we don't care about. 1009 return; 1010 } 1011 1012 var $targetElement = e.target || e.srcElement; 1013 1014 var focusableElements = getFocusableElements(params.focusCancel); 1015 var btnIndex = -1; // Find the button - note, this is a nodelist, not an array.
1016 for (var i = 0; i < focusableElements.length; i++) { 1017 if ($targetElement === focusableElements[i]) { 1018 btnIndex = i; 1019 break; 1020 } 1021 } 1022 1023 // TAB 1024 if (keyCode === 9) { 1025 if (!e.shiftKey) { 1026 // Cycle to the next button 1027 setFocus(btnIndex, 1); 1028 } else { 1029 // Cycle to the prev button 1030 setFocus(btnIndex, -1); 1031 } 1032 1033 stopEventPropagation(e); 1034 1035 } else { 1036 if (keyCode === 13 || keyCode === 32) { 1037 if (btnIndex === -1) { 1038 // ENTER/SPACE clicked outside of a button. 1039 if (params.focusCancel) { 1040 fireClick($cancelButton, e); 1041 } else { 1042 fireClick($confirmButton, e); 1043 } 1044 } 1045 } else if (keyCode === 27 && params.allowEscapeKey === true) { 1046 sweetAlert$1.closeModal(params.onClose); 1047 reject('esc'); 1048 } 1049 } 1050 } 1051 1052 states.previousWindowKeyDown = window.onkeydown; 1053 window.onkeydown = handleKeyDown; 1054 1055 // Loading state 1056 if (params.buttonsStyling) { 1057 $confirmButton.style.borderLeftColor = params.confirmButtonColor; 1058 $confirmButton.style.borderRightColor = params.confirmButtonColor; 1059 } 1060 1061 /** 1062 * Show spinner instead of Confirm button and disable Cancel button 1063 */ 1064 sweetAlert$1.showLoading = sweetAlert$1.enableLoading = function() { 1065 show(getSpacer()); 1066 show($confirmButton, 'inline-block'); 1067 addClass($confirmButton, 'loading'); 1068 addClass(modal, 'loading'); 1069 $confirmButton.disabled = true; 1070 $cancelButton.disabled = true; 1071 }; 1072 1073 /** 1074 * Show spinner instead of Confirm button and disable Cancel button 1075 */ 1076 sweetAlert$1.hideLoading = sweetAlert$1.disableLoading = function() { 1077 if (!params.showConfirmButton) { 1078 hide($confirmButton); 1079 if (!params.showCancelButton) { 1080 hide(getSpacer()); 1081 } 1082 } 1083 removeClass($confirmButton, 'loading'); 1084 removeClass(modal, 'loading'); 1085 $confirmButton.disabled = false; 1086 $cancelButton.disabled = false; 1087 }; 1088 1089 sweetAlert$1.enableButtons = function() { 1090 $confirmButton.disabled = false; 1091 $cancelButton.disabled = false; 1092 }; 1093 1094 sweetAlert$1.disableButtons = function() { 1095 $confirmButton.disabled = true; 1096 $cancelButton.disabled = true; 1097 }; 1098 1099 sweetAlert$1.enableConfirmButton = function() { 1100 $confirmButton.disabled = false; 1101 }; 1102 1103 sweetAlert$1.disableConfirmButton = function() { 1104 $confirmButton.disabled = true; 1105 }; 1106 1107 sweetAlert$1.enableInput = function() { 1108 var input = getInput(); 1109 if (!input) { 1110 return false; 1111 } 1112 if (input.type === 'radio') { 1113 var radiosContainer = input.parentNode.parentNode; 1114 var radios = radiosContainer.querySelectorAll('input'); 1115 for (var i = 0; i < radios.length; i++) { 1116 radios[i].disabled = false; 1117 } 1118 } else { 1119 input.disabled = false; 1120 } 1121 }; 1122 1123 sweetAlert$1.disableInput = function() { 1124 var input = getInput(); 1125 if (!input) { 1126 return false; 1127 } 1128 if (input && input.type === 'radio') { 1129 var radiosContainer = input.parentNode.parentNode; 1130 var radios = radiosContainer.querySelectorAll('input'); 1131 for (var i = 0; i < radios.length; i++) { 1132 radios[i].disabled = true; 1133 } 1134 } else { 1135 input.disabled = true; 1136 } 1137 }; 1138 1139 // Set modal min-height to disable scrolling inside the modal 1140 sweetAlert$1.recalculateHeight = debounce(function() { 1141 var modal = getModal(); 1142 var prevState = modal.style.display; 1143 modal.style.minHeight = ''; 1144 show(modal); 1145 modal.style.minHeight = (modal.scrollHeight + 1) + 'px'; 1146 modal.style.display = prevState; 1147 }, 50); 1148 1149 // Show block with validation error 1150 sweetAlert$1.showValidationError = function(error) {
1151 var validationError = getValidationError(); 1152 validationError.innerHTML = error; 1153 show(validationError); 1154 1155 var input = getInput(); 1156 focusInput(input); 1157 addClass(input, 'error'); 1158 }; 1159 1160 // Hide block with validation error 1161 sweetAlert$1.resetValidationError = function() { 1162 var validationError = getValidationError(); 1163 hide(validationError); 1164 sweetAlert$1.recalculateHeight(); 1165 1166 var input = getInput(); 1167 if (input) { 1168 removeClass(input, 'error'); 1169 } 1170 }; 1171 1172 sweetAlert$1.getProgressSteps = function() { 1173 return params.progressSteps; 1174 }; 1175 1176 sweetAlert$1.setProgressSteps = function(progressSteps) { 1177 params.progressSteps = progressSteps; 1178 setParameters(params); 1179 }; 1180 1181 sweetAlert$1.showProgressSteps = function() { 1182 show(getProgressSteps()); 1183 }; 1184 1185 sweetAlert$1.hideProgressSteps = function() { 1186 hide(getProgressSteps()); 1187 }; 1188 1189 sweetAlert$1.enableButtons(); 1190 sweetAlert$1.hideLoading(); 1191 sweetAlert$1.resetValidationError(); 1192 1193 // inputs 1194 var inputTypes = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea']; 1195 var input; 1196 for (i = 0; i < inputTypes.length; i++) { 1197 var inputClass = swalClasses[inputTypes[i]]; 1198 var inputContainer = getChildByClass(modal, inputClass); 1199 input = getInput(inputTypes[i]); 1200 1201 // set attributes 1202 if (input) { 1203 for (var j in input.attributes) { 1204 if (input.attributes.hasOwnProperty(j)) { 1205 var attrName = input.attributes[j].name; 1206 if (attrName !== 'type' && attrName !== 'value') { 1207 input.removeAttribute(attrName); 1208 } 1209 } 1210 } 1211 for (var attr in params.inputAttributes) { 1212 input.setAttribute(attr, params.inputAttributes[attr]); 1213 } 1214 } 1215 1216 // set class 1217 inputContainer.className = inputClass; 1218 if (params.inputClass) { 1219 addClass(inputContainer, params.inputClass); 1220 } 1221 1222 hide(inputContainer); 1223 } 1224 1225 var populateInputOptions; 1226 switch (params.input) { 1227 case 'text': 1228 case 'email': 1229 case 'password': 1230 case 'number': 1231 case 'tel': 1232 input = getChildByClass(modal, swalClasses.input); 1233 input.value = params.inputValue; 1234 input.placeholder = params.inputPlaceholder; 1235 input.type = params.input; 1236 show(input); 1237 break; 1238 case 'file': 1239 input = getChildByClass(modal, swalClasses.file); 1240 input.placeholder = params.inputPlaceholder; 1241 input.type = params.input; 1242 show(input); 1243 break; 1244 case 'range': 1245 var range = getChildByClass(modal, swalClasses.range); 1246 var rangeInput = range.querySelector('input'); 1247 var rangeOutput = range.querySelector('output'); 1248 rangeInput.value = params.inputValue; 1249 rangeInput.type = params.input; 1250 rangeOutput.value = params.inputValue; 1251 show(range); 1252 break; 1253 case 'select': 1254 var select = getChildByClass(modal, swalClasses.select); 1255 select.innerHTML = ''; 1256 if (params.inputPlaceholder) { 1257 var placeholder = document.createElement('option'); 1258 placeholder.innerHTML = params.inputPlaceholder; 1259 placeholder.value = ''; 1260 placeholder.disabled = true; 1261 placeholder.selected = true; 1262 select.appendChild(placeholder); 1263 } 1264 populateInputOptions = function(inputOptions) { 1265 for (var optionValue in inputOptions) { 1266 var option = document.createElement('option'); 1267 option.value = optionValue; 1268 option.innerHTML = inputOptions[optionValue]; 1269 if (params.inputValue === optionValue) { 1270 option.selected = true; 1271 } 1272 select.appendChild(option); 1273 } 1274 show(select); 1275 select.focus(); 1276 }; 1277 break; 1278 case 'radio': 1279 var radio = getChildByClass(modal, swalClasses.radio); 1280 radio.innerHTML = ''; 1281 populateInputOptions = function(inputOptions) { 1282 for (var radioValue in inputOptions) { 1283 var id = 1; 1284 var radioInput = document.createElement('input'); 1285 var radioLabel = document.createElement('label'); 1286 var radioLabelSpan = document.createElement('span'); 1287 radioInput.type = 'radio'; 1288 radioInput.name = swalClasses.radio; 1289 radioInput.value = radioValue; 1290 radioInput.id = swalClasses.radio + '-' + (id++); 1291 if (params.inputValue === radioValue) { 1292 radioInput.checked = true; 1293 } 1294 radioLabelSpan.innerHTML = inputOptions[radioValue]; 1295 radioLabel.appendChild(radioInput); 1296 radioLabel.appendChild(radioLabelSpan); 1297 radioLabel.for = radioInput.id; 1298 radio.appendChild(radioLabel); 1299 } 1300 show(radio); 1301 var radios = radio.querySelectorAll('input'); 1302 if (radios.length) { 1303 radios[0].focus(); 1304 } 1305 }; 1306 break; 1307 case 'checkbox': 1308 var checkbox = getChildByClass(modal, swalClasses.checkbox); 1309 var checkboxInput = getInput('checkbox'); 1310 checkboxInput.type = 'checkbox'; 1311 checkboxInput.value = 1; 1312 checkboxInput.id = swalClasses.checkbox; 1313 checkboxInput.checked = Boolean(params.inputValue); 1314 var label = checkbox.getElementsByTagName('span'); 1315 if (label.length) { 1316 checkbox.removeChild(label[0]); 1317 } 1318 label = document.createElement('span'); 1319 label.innerHTML = params.inputPlaceholder; 1320 checkbox.appendChild(label); 1321 show(checkbox); 1322 break; 1323 case 'textarea': 1324 var textarea = getChildByClass(modal, swalClasses.textarea); 1325 textarea.value = params.inputValue; 1326 textarea.placeholder = params.inputPlaceholder; 1327 show(textarea); 1328 break; 1329 case null: 1330 break; 1331 default: 1332 console.error('SweetAlert2: Unexpected type of input! Expected "text" or "email" or "password", "select", "checkbox", "textarea" or "file", got "' + params.input + '"'); 1333 break; 1334 } 1335 1336 if (params.input === 'select' || params.input === 'radio') { 1337 if (params.inputOptions instanceof Promise) { 1338 sweetAlert$1.showLoading(); 1339 params.inputOptions.then(function(inputOptions) { 1340 sweetAlert$1.hideLoading(); 1341 populateInputOptions(inputOptions); 1342 }); 1343 } else if (typeof params.inputOptions === 'object') { 1344 populateInputOptions(params.inputOptions); 1345 } else { 1346 console.error('SweetAlert2: Unexpected type of inputOptions! Expected object or Promise, got ' + typeof params.inputOptions); 1347 } 1348 } 1349 1350 openModal(params.animation, params.onOpen); 1351 1352 // Focus the first element (input or button) 1353 setFocus(-1, 1); 1354 1355 // fix scroll 1356 sweetContainer.scrollTop = 0; 1357 1358 // Observe changes inside the modal and adjust height 1359 if (typeof MutationObserver !== 'undefined' && !swal2Observer) { 1360 swal2Observer = new MutationObserver(sweetAlert$1.recalculateHeight); 1361 swal2Observer.observe(modal, {childList: true, characterData: true, subtree: true}); 1362 } 1363 }); 1364 } 1365 1366 // SweetAlert function 1367 function sweetAlert$1() { 1368 // Copy arguments to the local args variable 1369 var args = arguments; 1370 1371 if (sweetAlert$1.isVisible()) { 1372 sweetAlert$1.close(); 1373 } 1374 1375 return modalDependant.apply(this, args); 1376 } 1377 1378 /* 1379 * Global function to determine if swal2 modal is visible 1380 */ 1381 sweetAlert$1.isVisible = function() { 1382 var modal = getModal(); 1383 return isVisible(modal); 1384 }; 1385 1386 /* 1387 * Global function for chaining sweetAlert modals 1388 */ 1389 sweetAlert$1.queue = function(steps) { 1390 queue = steps; 1391 var modal = getModal(); 1392 var resetQueue = function() { 1393 queue = []; 1394 modal.removeAttribute('data-queue-step'); 1395 }; 1396 return new Promise(function(resolve, reject) { 1397 (function step(i, callback) { 1398 if (i < queue.length) { 1399 modal.setAttribute('data-queue-step', i); 1400 1401 sweetAlert$1(queue[i]).then(function() { 1402 step(i+1, callback); 1403 }, function(dismiss) { 1404 resetQueue(); 1405 reject(dismiss); 1406 }); 1407 } else { 1408 resetQueue(); 1409 resolve(); 1410 } 1411 })(0); 1412 }); 1413 }; 1414 1415 /* 1416 * Global function for getting the index of current modal in queue 1417 */ 1418 sweetAlert$1.getQueueStep = function() { 1419 return getModal().getAttribute('data-queue-step'); 1420 }; 1421 1422 /* 1423 * Global function for inserting a modal to the queue 1424 */ 1425 sweetAlert$1.insertQueueStep = function(step, index) { 1426 if (index && index < queue.length) { 1427 return queue.splice(index, 0, step); 1428 } 1429 return queue.push(step); 1430 }; 1431 1432 /* 1433 * Global function for deleting a modal from the queue 1434 */ 1435 sweetAlert$1.deleteQueueStep = function(index) { 1436 if (typeof queue[index] !== 'undefined') { 1437 queue.splice(index, 1); 1438 } 1439 }; 1440 1441 /* 1442 * Global function to close sweetAlert 1443 */ 1444 sweetAlert$1.close = sweetAlert$1.closeModal = function(onComplete) { 1445 var modal = getModal(); 1446 removeClass(modal, 'show-swal2'); 1447 addClass(modal, 'hide-swal2'); 1448 1449 // Reset icon animations 1450 var $successIcon = modal.querySelector('.' + swalClasses.icon + '.' + iconTypes.success); 1451 removeClass($successIcon, 'animate'); 1452 removeClass($successIcon.querySelector('.tip'), 'animate-success-tip'); 1453 removeClass($successIcon.querySelector('.long'), 'animate-success-long'); 1454 1455 var $errorIcon = modal.querySelector('.' + swalClasses.icon + '.' + iconTypes.error); 1456 removeClass($errorIcon, 'animate-error-icon'); 1457 removeClass($errorIcon.querySelector('.x-mark'), 'animate-x-mark'); 1458 1459 var $warningIcon = modal.querySelector('.' + swalClasses.icon + '.' + iconTypes.warning); 1460 removeClass($warningIcon, 'pulse-warning'); 1461 1462 resetPrevState(); 1463 1464 // If animation is supported, animate 1465 if (animationEndEvent && !hasClass(modal, 'no-animation')) { 1466 modal.addEventListener(animationEndEvent, function swalCloseEventFinished() { 1467 modal.removeEventListener(animationEndEvent, swalCloseEventFinished); 1468 if (hasClass(modal, 'hide-swal2')) { 1469 hide(modal); 1470 removeClass(sweetContainer, 'in'); 1471 removeClass(document.body, swalClasses.in); 1472 undoScrollbar(); 1473 } 1474 }); 1475 } else { 1476 // Otherwise, hide immediately 1477 hide(modal); 1478 removeClass(sweetContainer, 'in'); 1479 removeClass(document.body, swalClasses.in); 1480 undoScrollbar(); 1481 } 1482 if (onComplete !== null && typeof onComplete === 'function') { 1483 onComplete.call(this, modal); 1484 } 1485 }; 1486 1487 /* 1488 * Global function to click 'Confirm' button 1489 */ 1490 sweetAlert$1.clickConfirm = function() { 1491 getConfirmButton().click(); 1492 }; 1493 1494 /* 1495 * Global function to click 'Cancel' button 1496 */ 1497 sweetAlert$1.clickCancel = function() { 1498 getCancelButton().click(); 1499 }; 1500 1501 /** 1502 * Set default params for each popup 1503 * @param {Object} userParams 1504 */ 1505 sweetAlert$1.setDefaults = function(userParams) { 1506 if (!userParams) { 1507 throw new Error('userParams is required'); 1508 } 1509 if (typeof userParams !== 'object') { 1510 throw new Error('userParams has to be a object'); 1511 } 1512 1513 extend(modalParams, userParams); 1514 }; 1515 1516 /** 1517 * Reset default params for each popup 1518 */ 1519 sweetAlert$1.resetDefaults = function() { 1520 modalParams = extend({}, defaultParams); 1521 }; 1522 1523 sweetAlert$1.version = ''; 1524 1525 window.sweetAlert = window.swalTwo = sweetAlert$1; 1526 1527 if (typeof Promise === 'function') { 1528 Promise.prototype.done = Promise.prototype.done || function() { 1529 return this.catch(function() { 1530 // Catch promise rejections silently. 1531 // https://github.com/limonte/sweetalert2/issues/177 1532 }); 1533 }; 1534 } else { 1535 console.warn('SweetAlert2: Please inlude Promise polyfill BEFORE including sweetalert2.js if IE10+ support needed.'); 1536 } 1537 1538 return sweetAlert$1; 1539 1540}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.