text: /*!
   * jquery-confirm v3.3.0 (http://craftpip.github.io/jquery-confirm/)
   * Author: Boniface Pereira
   * Website: www.craftpip.com
   * Contact: hey@craftpip.com
   *
   * Copyright 2013-2017 jquery-confirm
   * Licensed under MIT (https://github.com/craftpip/jquery-confirm/blob/master/LICENSE)
   */
  
  if (typeof jQuery === 'undefined') {
      throw new Error('jquery-confirm requires jQuery');
  }
  
  var jconfirm, Jconfirm;
  (function ($, window) {
      "use strict";
  
      $.fn.confirm = function (options, option2) {
          if (typeof options === 'undefined') options = {};
          if (typeof options === 'string') {
              options = {
                  content: options,
                  title: (option2) ? option2 : false
              };
          }
          /*
           *  Alias of $.confirm to emulate native confirm()
           */
          $(this).each(function () {
              var $this = $(this);
              if ($this.attr('jc-attached')) {
                  console.warn('jConfirm has already been attached to this element ', $this[0]);
                  return;
              }
  
              $this.on('click', function (e) {
                  e.preventDefault();
                  var jcOption = $.extend({}, options);
                  if ($this.attr('data-title'))
                      jcOption['title'] = $this.attr('data-title');
                  if ($this.attr('data-content'))
                      jcOption['content'] = $this.attr('data-content');
                  if (typeof jcOption['buttons'] == 'undefined')
                      jcOption['buttons'] = {};
  
                  jcOption['$target'] = $this;
                  if ($this.attr('href') && Object.keys(jcOption['buttons']).length == 0) {
                      var buttons = $.extend(true, {}, jconfirm.pluginDefaults.defaultButtons, (jconfirm.defaults || {}).defaultButtons || {});
                      var firstBtn = Object.keys(buttons)[0];
                      jcOption['buttons'] = buttons;
                      jcOption.buttons[firstBtn].action = function () {
                          location.href = $this.attr('href');
                      };
                  }
                  jcOption['closeIcon'] = false;
                  var instance = $.confirm(jcOption);
              });
  
              $this.attr('jc-attached', true);
          });
          return $(this);
      };
      $.confirm = function (options, option2) {
          if (typeof options === 'undefined') options = {};
          if (typeof options === 'string') {
              options = {
                  content: options,
                  title: (option2) ? option2 : false
              };
          }
  
          if (typeof options['buttons'] != 'object')
              options['buttons'] = {};
  
          if (Object.keys(options['buttons']).length == 0) {
              var buttons = $.extend(true, {}, jconfirm.pluginDefaults.defaultButtons, (jconfirm.defaults || {}).defaultButtons || {});
              options['buttons'] = buttons;
          }
  
          /*
           *  Alias of jconfirm
           */
          return jconfirm(options);
      };
      $.alert = function (options, option2) {
          if (typeof options === 'undefined') options = {};
          if (typeof options === 'string') {
              options = {
                  content: options,
                  title: (option2) ? option2 : false
              };
          }
  
          if (typeof options.buttons != 'object')
              options.buttons = {};
  
          if (Object.keys(options['buttons']).length == 0) {
              var buttons = $.extend(true, {}, jconfirm.pluginDefaults.defaultButtons, (jconfirm.defaults || {}).defaultButtons || {});
              var firstBtn = Object.keys(buttons)[0];
              options['buttons'][firstBtn] = buttons[firstBtn];
          }
          /*
           *  Alias of jconfirm
           */
          return jconfirm(options);
      };
      $.dialog = function (options, option2) {
          if (typeof options === 'undefined') options = {};
          if (typeof options === 'string') {
              options = {
                  content: options,
                  title: (option2) ? option2 : false,
                  closeIcon: function () {
                      // Just close the modal
                  }
              };
          }
  
          options['buttons'] = {}; // purge buttons
  
          if (typeof options['closeIcon'] == 'undefined') {
              // Dialog must have a closeIcon.
              options['closeIcon'] = function () {
              }
          }
          /*
           *  Alias of jconfirm
           */
          options.confirmKeys = [13];
          return jconfirm(options);
      };
  
      jconfirm = function (options) {
          if (typeof options === 'undefined') options = {};
          /*
           * initial function for calling.
           */
          var pluginOptions = $.extend(true, {}, jconfirm.pluginDefaults);
          if (jconfirm.defaults) {
              pluginOptions = $.extend(true, pluginOptions, jconfirm.defaults);
          }
  
          /*
           * merge options with plugin defaults.
           */
          pluginOptions = $.extend(true, {}, pluginOptions, options);
          var instance = new Jconfirm(pluginOptions);
          jconfirm.instances.push(instance);
          return instance;
      };
      Jconfirm = function (options) {
          /*
           * constructor function Jconfirm,
           * options = user options.
           */
          $.extend(this, options);
          this._init();
      };
      Jconfirm.prototype = {
          _init: function () {
              var that = this;
  
              if (!jconfirm.instances.length)
                  jconfirm.lastFocused = $('body').find(':focus');
  
              this._id = Math.round(Math.random() * 99999);
              /**
               * contentParsed maintains the contents for $content, before it is put in DOM
               */
              this.contentParsed = $(document.createElement('div'));
  
              if (!this.lazyOpen) {
                  setTimeout(function () {
                      that.open();
                  }, 0);
              }
          },
          _buildHTML: function () {
              var that = this;
  
              // prefix the animation string and store in animationParsed
              this._parseAnimation(this.animation, 'o');
              this._parseAnimation(this.closeAnimation, 'c');
              this._parseBgDismissAnimation(this.backgroundDismissAnimation);
              this._parseColumnClass(this.columnClass);
              this._parseTheme(this.theme);
              this._parseType(this.type);
  
              /*
               * Append html.
               */
              var template = $(this.template);
              template.find('.jconfirm-box').addClass(this.animationParsed).addClass(this.backgroundDismissAnimationParsed).addClass(this.typeParsed);
  
              if (this.typeAnimated)
                  template.find('.jconfirm-box').addClass('jconfirm-type-animated');
  
              if (this.useBootstrap) {
                  template.find('.jc-bs3-row').addClass(this.bootstrapClasses.row);
                  template.find('.jc-bs3-row').addClass('justify-content-md-center justify-content-sm-center justify-content-xs-center justify-content-lg-center');
  
                  template.find('.jconfirm-box-container').addClass(this.columnClassParsed);
  
                  if (this.containerFluid)
                      template.find('.jc-bs3-container').addClass(this.bootstrapClasses.containerFluid);
                  else
                      template.find('.jc-bs3-container').addClass(this.bootstrapClasses.container);
              } else {
                  template.find('.jconfirm-box').css('width', this.boxWidth);
              }
  
              if (this.titleClass)
                  template.find('.jconfirm-title-c').addClass(this.titleClass);
  
              template.addClass(this.themeParsed);
              var ariaLabel = 'jconfirm-box' + this._id;
              template.find('.jconfirm-box').attr('aria-labelledby', ariaLabel).attr('tabindex', -1);
              template.find('.jconfirm-content').attr('id', ariaLabel);
              if (this.bgOpacity !== null)
                  template.find('.jconfirm-bg').css('opacity', this.bgOpacity);
              if (this.rtl)
                  template.addClass('jconfirm-rtl');
  
              this.$el = template.appendTo(this.container);
              this.$jconfirmBoxContainer = this.$el.find('.jconfirm-box-container');
              this.$jconfirmBox = this.$body = this.$el.find('.jconfirm-box');
              this.$jconfirmBg = this.$el.find('.jconfirm-bg');
              this.$title = this.$el.find('.jconfirm-title');
              this.$titleContainer = this.$el.find('.jconfirm-title-c');
              this.$content = this.$el.find('div.jconfirm-content');
              this.$contentPane = this.$el.find('.jconfirm-content-pane');
              this.$icon = this.$el.find('.jconfirm-icon-c');
              this.$closeIcon = this.$el.find('.jconfirm-closeIcon');
              this.$holder = this.$el.find('.jconfirm-holder');
              // this.$content.css(this._getCSS(this.animationSpeed, this.animationBounce));
              this.$btnc = this.$el.find('.jconfirm-buttons');
              this.$scrollPane = this.$el.find('.jconfirm-scrollpane');
  
              that.setStartingPoint();
  
              // for loading content via URL
              this._contentReady = $.Deferred();
              this._modalReady = $.Deferred();
              this.$holder.css({
                  'padding-top': this.offsetTop,
                  'padding-bottom': this.offsetBottom,
              });
  
              this.setTitle();
              this.setIcon();
              this._setButtons();
              this._parseContent();
              this.initDraggable();
  
              if (this.isAjax)
                  this.showLoading(false);
  
              $.when(this._contentReady, this._modalReady).then(function () {
                  if (that.isAjaxLoading)
                      setTimeout(function () {
                          that.isAjaxLoading = false;
                          that.setContent();
                          that.setTitle();
                          that.setIcon();
                          setTimeout(function () {
                              that.hideLoading(false);
                              that._updateContentMaxHeight();
                          }, 100);
                          if (typeof that.onContentReady === 'function')
                              that.onContentReady();
                      }, 50);
                  else {
                      // that.setContent();
                      that._updateContentMaxHeight();
                      that.setTitle();
                      that.setIcon();
                      if (typeof that.onContentReady === 'function')
                          that.onContentReady();
                  }
  
                  // start countdown after content has loaded.
                  if (that.autoClose)
                      that._startCountDown();
              });
  
              this._watchContent();
  
              if (this.animation === 'none') {
                  this.animationSpeed = 1;
                  this.animationBounce = 1;
              }
  
              this.$body.css(this._getCSS(this.animationSpeed, this.animationBounce));
              this.$contentPane.css(this._getCSS(this.animationSpeed, 1));
              this.$jconfirmBg.css(this._getCSS(this.animationSpeed, 1));
              this.$jconfirmBoxContainer.css(this._getCSS(this.animationSpeed, 1));
          },
          _typePrefix: 'jconfirm-type-',
          typeParsed: '',
          _parseType: function (type) {
              this.typeParsed = this._typePrefix + type;
          },
          setType: function (type) {
              var oldClass = this.typeParsed;
              this._parseType(type);
              this.$jconfirmBox.removeClass(oldClass).addClass(this.typeParsed);
          },
          themeParsed: '',
          _themePrefix: 'jconfirm-',
          setTheme: function (theme) {
              var previous = this.theme;
              this.theme = theme || this.theme;
              this._parseTheme(this.theme);
              if (previous)
                  this.$el.removeClass(previous);
              this.$el.addClass(this.themeParsed);
              this.theme = theme;
          },
          _parseTheme: function (theme) {
              var that = this;
              theme = theme.split(',');
              $.each(theme, function (k, a) {
                  if (a.indexOf(that._themePrefix) === -1)
                      theme[k] = that._themePrefix + $.trim(a);
              });
              this.themeParsed = theme.join(' ').toLowerCase();
          },
          backgroundDismissAnimationParsed: '',
          _bgDismissPrefix: 'jconfirm-hilight-',
          _parseBgDismissAnimation: function (bgDismissAnimation) {
              var animation = bgDismissAnimation.split(',');
              var that = this;
              $.each(animation, function (k, a) {
                  if (a.indexOf(that._bgDismissPrefix) === -1)
                      animation[k] = that._bgDismissPrefix + $.trim(a);
              });
              this.backgroundDismissAnimationParsed = animation.join(' ').toLowerCase();
          },
          animationParsed: '',
          closeAnimationParsed: '',
          _animationPrefix: 'jconfirm-animation-',
          setAnimation: function (animation) {
              this.animation = animation || this.animation;
              this._parseAnimation(this.animation, 'o');
          },
          _parseAnimation: function (animation, which) {
              which = which || 'o'; // parse what animation and store where. open or close?
              var animations = animation.split(',');
              var that = this;
              $.each(animations, function (k, a) {
                  if (a.indexOf(that._animationPrefix) === -1)
                      animations[k] = that._animationPrefix + $.trim(a);
              });
              var a_string = animations.join(' ').toLowerCase();
              if (which === 'o')
                  this.animationParsed = a_string;
              else
                  this.closeAnimationParsed = a_string;
  
              return a_string;
          },
          setCloseAnimation: function (closeAnimation) {
              this.closeAnimation = closeAnimation || this.closeAnimation;
              this._parseAnimation(this.closeAnimation, 'c');
          },
          setAnimationSpeed: function (speed) {
              this.animationSpeed = speed || this.animationSpeed;
              // this.$body.css(this._getCSS(this.animationSpeed, this.animationBounce));
          },
          columnClassParsed: '',
          setColumnClass: function (colClass) {
              if (!this.useBootstrap) {
                  console.warn("cannot set columnClass, useBootstrap is set to false");
                  return;
              }
              this.columnClass = colClass || this.columnClass;
              this._parseColumnClass(this.columnClass);
              this.$jconfirmBoxContainer.addClass(this.columnClassParsed);
          },
          _updateContentMaxHeight: function () {
              var height = $(window).height() - (this.$jconfirmBox.outerHeight() - this.$contentPane.outerHeight()) - (this.offsetTop + this.offsetBottom);
              this.$contentPane.css({
                  'max-height': height + 'px'
              });
          },
          setBoxWidth: function (width) {
              if (this.useBootstrap) {
                  console.warn("cannot set boxWidth, useBootstrap is set to true");
                  return;
              }
              this.boxWidth = width;
              this.$jconfirmBox.css('width', width);
          },
          _parseColumnClass: function (colClass) {
              colClass = colClass.toLowerCase();
              var p;
              switch (colClass) {
                  case 'xl':
                  case 'xlarge':
                      p = 'col-md-12';
                      break;
                  case 'l':
                  case 'large':
                      p = 'col-md-8 col-md-offset-2';
                      break;
                  case 'm':
                  case 'medium':
                      p = 'col-md-6 col-md-offset-3';
                      break;
                  case 's':
                  case 'small':
                      p = 'col-md-4 col-md-offset-4';
                      break;
                  case 'xs':
                  case 'xsmall':
                      p = 'col-md-2 col-md-offset-5';
                      break;
                  default:
                      p = colClass;
              }
              this.columnClassParsed = p;
          },
          initDraggable: function () {
              var that = this;
              var $t = this.$titleContainer;
  
              this.resetDrag();
              if (this.draggable) {
                  $t.on('mousedown', function (e) {
                      $t.addClass('jconfirm-hand');
                      that.mouseX = e.clientX;
                      that.mouseY = e.clientY;
                      that.isDrag = true;
                  });
                  $(window).on('mousemove.' + this._id, function (e) {
                      if (that.isDrag) {
                          that.movingX = e.clientX - that.mouseX + that.initialX;
                          that.movingY = e.clientY - that.mouseY + that.initialY;
                          that.setDrag();
                      }
                  });
  
                  $(window).on('mouseup.' + this._id, function () {
                      $t.removeClass('jconfirm-hand');
                      if (that.isDrag) {
                          that.isDrag = false;
                          that.initialX = that.movingX;
                          that.initialY = that.movingY;
                      }
                  })
              }
          },
          resetDrag: function () {
              this.isDrag = false;
              this.initialX = 0;
              this.initialY = 0;
              this.movingX = 0;
              this.movingY = 0;
              this.mouseX = 0;
              this.mouseY = 0;
              this.$jconfirmBoxContainer.css('transform', 'translate(' + 0 + 'px, ' + 0 + 'px)');
          },
          setDrag: function () {
              if (!this.draggable)
                  return;
  
              this.alignMiddle = false;
              var boxWidth = this.$jconfirmBox.outerWidth();
              var boxHeight = this.$jconfirmBox.outerHeight();
              var windowWidth = $(window).width();
              var windowHeight = $(window).height();
              var that = this;
              var dragUpdate = 1;
              if (that.movingX % dragUpdate === 0 || that.movingY % dragUpdate === 0) {
                  if (that.dragWindowBorder) {
                      var leftDistance = (windowWidth / 2) - boxWidth / 2;
                      var topDistance = (windowHeight / 2) - boxHeight / 2;
                      topDistance -= that.dragWindowGap;
                      leftDistance -= that.dragWindowGap;
  
                      if (leftDistance + that.movingX < 0) {
                          that.movingX = -leftDistance;
                      } else if (leftDistance - that.movingX < 0) {
                          that.movingX = leftDistance;
                      }
  
                      if (topDistance + that.movingY < 0) {
                          that.movingY = -topDistance;
                      } else if (topDistance - that.movingY < 0) {
                          that.movingY = topDistance;
                      }
                  }
  
                  that.$jconfirmBoxContainer.css('transform', 'translate(' + that.movingX + 'px, ' + that.movingY + 'px)');
              }
          },
          _scrollTop: function () {
              if (typeof pageYOffset !== 'undefined') {
                  //most browsers except IE before #9
                  return pageYOffset;
              }
              else {
                  var B = document.body; //IE 'quirks'
                  var D = document.documentElement; //IE with doctype
                  D = (D.clientHeight) ? D : B;
                  return D.scrollTop;
              }
          },
          _watchContent: function () {
              var that = this;
              if (this._timer) clearInterval(this._timer);
  
              var prevContentHeight = 0;
              this._timer = setInterval(function () {
                  if (that.smoothContent) {
                      var contentHeight = that.$content.outerHeight() || 0;
                      if (contentHeight !== prevContentHeight) {
                          that.$contentPane.css({
                              'height': contentHeight
                          }).scrollTop(0);
                          prevContentHeight = contentHeight;
                      }
                      var wh = $(window).height();
                      var total = that.offsetTop + that.offsetBottom + that.$jconfirmBox.height() - that.$contentPane.height() + that.$content.height();
                      if (total < wh) {
                          that.$contentPane.addClass('no-scroll');
                      } else {
                          that.$contentPane.removeClass('no-scroll');
                      }
                  }
              }, this.watchInterval);
          },
          _overflowClass: 'jconfirm-overflow',
          _hilightAnimating: false,
          highlight: function () {
              this.hiLightModal();
          },
          hiLightModal: function () {
              var that = this;
              if (this._hilightAnimating)
                  return;
  
              that.$body.addClass('hilight');
              var duration = parseFloat(that.$body.css('animation-duration')) || 2;
              this._hilightAnimating = true;
              setTimeout(function () {
                  that._hilightAnimating = false;
                  that.$body.removeClass('hilight');
              }, duration * 1000);
          },
          _bindEvents: function () {
              var that = this;
              this.boxClicked = false;
  
              this.$scrollPane.click(function (e) { // Ignore propagated clicks
                  if (!that.boxClicked) { // Background clicked
                      /*
                       If backgroundDismiss is a function and its return value is truthy
                       proceed to close the modal.
                       */
                      var buttonName = false;
                      var shouldClose = false;
                      var str;
  
                      if (typeof that.backgroundDismiss == 'function')
                          str = that.backgroundDismiss();
                      else
                          str = that.backgroundDismiss;
  
                      if (typeof str == 'string' && typeof that.buttons[str] != 'undefined') {
                          buttonName = str;
                          shouldClose = false;
                      } else if (typeof str == 'undefined' || !!(str) == true) {
                          shouldClose = true;
                      } else {
                          shouldClose = false;
                      }
  
                      if (buttonName) {
                          var btnResponse = that.buttons[buttonName].action.apply(that);
                          shouldClose = (typeof btnResponse == 'undefined') || !!(btnResponse);
                      }
  
                      if (shouldClose)
                          that.close();
                      else
                          that.hiLightModal();
                  }
                  that.boxClicked = false;
              });
  
              this.$jconfirmBox.click(function (e) {
                  that.boxClicked = true;
              });
  
              var isKeyDown = false;
              $(window).on('jcKeyDown.' + that._id, function (e) {
                  if (!isKeyDown) {
                      isKeyDown = true;
                  }
              });
              $(window).on('keyup.' + that._id, function (e) {
                  if (isKeyDown) {
                      that.reactOnKey(e);
                      isKeyDown = false;
                  }
              });
  
              $(window).on('resize.' + this._id, function () {
                  that._updateContentMaxHeight();
                  setTimeout(function () {
                      that.resetDrag();
                  }, 100);
              });
          },
          _cubic_bezier: '0.36, 0.55, 0.19',
          _getCSS: function (speed, bounce) {
              return {
                  '-webkit-transition-duration': speed / 1000 + 's',
                  'transition-duration': speed / 1000 + 's',
                  '-webkit-transition-timing-function': 'cubic-bezier(' + this._cubic_bezier + ', ' + bounce + ')',
                  'transition-timing-function': 'cubic-bezier(' + this._cubic_bezier + ', ' + bounce + ')'
              };
          },
          _setButtons: function () {
              var that = this;
              /*
               * Settings up buttons
               */
  
              var total_buttons = 0;
              if (typeof this.buttons !== 'object')
                  this.buttons = {};
  
              $.each(this.buttons, function (key, button) {
                  total_buttons += 1;
                  if (typeof button === 'function') {
                      that.buttons[key] = button = {
                          action: button
                      };
                  }
  
                  that.buttons[key].text = button.text || key;
                  that.buttons[key].btnClass = button.btnClass || 'btn-default';
                  that.buttons[key].action = button.action || function () {
                      };
                  that.buttons[key].keys = button.keys || [];
                  that.buttons[key].isHidden = button.isHidden || false;
                  that.buttons[key].isDisabled = button.isDisabled || false;
  
                  $.each(that.buttons[key].keys, function (i, a) {
                      that.buttons[key].keys[i] = a.toLowerCase();
                  });
  
                  var button_element = $('<button type="button" class="btn"></button>')
                      .html(that.buttons[key].text)
                      .addClass(that.buttons[key].btnClass)
                      .prop('disabled', that.buttons[key].isDisabled)
                      .css('display', that.buttons[key].isHidden ? 'none' : '')
                      .click(function (e) {
                          e.preventDefault();
                          var res = that.buttons[key].action.apply(that, [that.buttons[key]]);
                          that.onAction.apply(that, [key, that.buttons[key]]);
                          that._stopCountDown();
                          if (typeof res === 'undefined' || res)
                              that.close();
                      });
  
                  that.buttons[key].el = button_element;
                  that.buttons[key].setText = function (text) {
                      button_element.html(text);
                  };
                  that.buttons[key].addClass = function (className) {
                      button_element.addClass(className);
                  };
                  that.buttons[key].removeClass = function (className) {
                      button_element.removeClass(className);
                  };
                  that.buttons[key].disable = function () {
                      that.buttons[key].isDisabled = true;
                      button_element.prop('disabled', true);
                  };
                  that.buttons[key].enable = function () {
                      that.buttons[key].isDisabled = false;
                      button_element.prop('disabled', false);
                  };
                  that.buttons[key].show = function () {
                      that.buttons[key].isHidden = false;
                      button_element.css('display', '');
                  };
                  that.buttons[key].hide = function () {
                      that.buttons[key].isHidden = true;
                      button_element.css('display', 'none');
                  };
                  /*
                   Buttons are prefixed with $_ or $$ for quick access
                   */
                  that['$_' + key] = that['$$' + key] = button_element;
                  that.$btnc.append(button_element);
              });
  
              if (total_buttons === 0) this.$btnc.hide();
              if (this.closeIcon === null && total_buttons === 0) {
                  /*
                   in case when no buttons are present & closeIcon is null, closeIcon is set to true,
                   set closeIcon to true to explicitly tell to hide the close icon
                   */
                  this.closeIcon = true;
              }
  
              if (this.closeIcon) {
                  if (this.closeIconClass) {
                      // user requires a custom class.
                      var closeHtml = '<i class="' + this.closeIconClass + '"></i>';
                      this.$closeIcon.html(closeHtml);
                  }
  
                  this.$closeIcon.click(function (e) {
                      e.preventDefault();
  
                      var buttonName = false;
                      var shouldClose = false;
                      var str;
  
                      if (typeof that.closeIcon == 'function') {
                          str = that.closeIcon();
                      } else {
                          str = that.closeIcon;
                      }
  
                      if (typeof str == 'string' && typeof that.buttons[str] != 'undefined') {
                          buttonName = str;
                          shouldClose = false;
                      } else if (typeof str == 'undefined' || !!(str) == true) {
                          shouldClose = true;
                      } else {
                          shouldClose = false;
                      }
                      if (buttonName) {
                          var btnResponse = that.buttons[buttonName].action.apply(that);
                          shouldClose = (typeof btnResponse == 'undefined') || !!(btnResponse);
                      }
                      if (shouldClose) {
                          that.close();
                      }
                  });
                  this.$closeIcon.show();
              } else {
                  this.$closeIcon.hide();
              }
          },
          setTitle: function (string, force) {
              force = force || false;
  
              if (typeof string !== 'undefined')
                  if (typeof string == 'string')
                      this.title = string;
                  else if (typeof string == 'function') {
                      if (typeof string.promise == 'function')
                          console.error('Promise was returned from title function, this is not supported.');
  
                      var response = string();
                      if (typeof response == 'string')
                          this.title = response;
                      else
                          this.title = false;
                  } else
                      this.title = false;
  
              if (this.isAjaxLoading && !force)
                  return;
  
              this.$title.html(this.title || '');
              this.updateTitleContainer();
          },
          setIcon: function (iconClass, force) {
              force = force || false;
  
              if (typeof iconClass !== 'undefined')
                  if (typeof iconClass == 'string')
                      this.icon = iconClass;
                  else if (typeof iconClass === 'function') {
                      var response = iconClass();
                      if (typeof response == 'string')
                          this.icon = response;
                      else
                          this.icon = false;
                  }
                  else
                      this.icon = false;
  
              if (this.isAjaxLoading && !force)
                  return;
  
              this.$icon.html(this.icon ? '<i class="' + this.icon + '"></i>' : '');
              this.updateTitleContainer();
          },
          updateTitleContainer: function () {
              if (!this.title && !this.icon) {
                  this.$titleContainer.hide();
              } else {
                  this.$titleContainer.show();
              }
          },
          setContentPrepend: function (content, force) {
              if (!content)
                  return;
  
              this.contentParsed.prepend(content);
          },
          setContentAppend: function (content) {
              if (!content)
                  return;
  
              this.contentParsed.append(content);
          },
          setContent: function (content, force) {
              force = !!force;
              var that = this;
              if (content)
                  this.contentParsed.html('').append(content);
              if (this.isAjaxLoading && !force)
                  return;
  
              this.$content.html('');
              this.$content.append(this.contentParsed);
              setTimeout(function () {
                  that.$body.find('input[autofocus]:visible:first').focus();
              }, 100);
          },
          loadingSpinner: false,
          showLoading: function (disableButtons) {
              this.loadingSpinner = true;
              this.$jconfirmBox.addClass('loading');
              if (disableButtons)
                  this.$btnc.find('button').prop('disabled', true);
  
          },
          hideLoading: function (enableButtons) {
              this.loadingSpinner = false;
              this.$jconfirmBox.removeClass('loading');
              if (enableButtons)
                  this.$btnc.find('button').prop('disabled', false);
  
          },
          ajaxResponse: false,
          contentParsed: '',
          isAjax: false,
          isAjaxLoading: false,
          _parseContent: function () {
              var that = this;
              var e = '&nbsp;';
  
              if (typeof this.content == 'function') {
                  var res = this.content.apply(this);
                  if (typeof res == 'string') {
                      this.content = res;
                  }
                  else if (typeof res == 'object' && typeof res.always == 'function') {
                      // this is ajax loading via promise
                      this.isAjax = true;
                      this.isAjaxLoading = true;
                      res.always(function (data, status, xhr) {
                          that.ajaxResponse = {
                              data: data,
                              status: status,
                              xhr: xhr
                          };
                          that._contentReady.resolve(data, status, xhr);
                          if (typeof that.contentLoaded == 'function')
                              that.contentLoaded(data, status, xhr);
                      });
                      this.content = e;
                  } else {
                      this.content = e;
                  }
              }
  
              if (typeof this.content == 'string' && this.content.substr(0, 4).toLowerCase() === 'url:') {
                  this.isAjax = true;
                  this.isAjaxLoading = true;
                  var u = this.content.substring(4, this.content.length);
                  $.get(u).done(function (html) {
                      that.contentParsed.html(html);
                  }).always(function (data, status, xhr) {
                      that.ajaxResponse = {
                          data: data,
                          status: status,
                          xhr: xhr
                      };
                      that._contentReady.resolve(data, status, xhr);
                      if (typeof that.contentLoaded == 'function')
                          that.contentLoaded(data, status, xhr);
                  });
              }
  
              if (!this.content)
                  this.content = e;
  
              if (!this.isAjax) {
                  this.contentParsed.html(this.content);
                  this.setContent();
                  that._contentReady.resolve();
              }
          },
          _stopCountDown: function () {
              clearInterval(this.autoCloseInterval);
              if (this.$cd)
                  this.$cd.remove();
          },
          _startCountDown: function () {
              var that = this;
              var opt = this.autoClose.split('|');
              if (opt.length !== 2) {
                  console.error('Invalid option for autoClose. example \'close|10000\'');
                  return false;
              }
  
              var button_key = opt[0];
              var time = parseInt(opt[1]);
              if (typeof this.buttons[button_key] === 'undefined') {
                  console.error('Invalid button key \'' + button_key + '\' for autoClose');
                  return false;
              }
  
              var seconds = Math.ceil(time / 1000);
              this.$cd = $('<span class="countdown"> (' + seconds + ')</span>')
                  .appendTo(this['$_' + button_key]);
  
              this.autoCloseInterval = setInterval(function () {
                  that.$cd.html(' (' + (seconds -= 1) + ') ');
                  if (seconds <= 0) {
                      that['$$' + button_key].trigger('click');
                      that._stopCountDown();
                  }
              }, 1000);
          },
          _getKey: function (key) {
              // very necessary keys.
              switch (key) {
                  case 192:
                      return 'tilde';
                  case 13:
                      return 'enter';
                  case 16:
                      return 'shift';
                  case 9:
                      return 'tab';
                  case 20:
                      return 'capslock';
                  case 17:
                      return 'ctrl';
                  case 91:
                      return 'win';
                  case 18:
                      return 'alt';
                  case 27:
                      return 'esc';
                  case 32:
                      return 'space';
              }
  
              // only trust alphabets with this.
              var initial = String.fromCharCode(key);
              if (/^[A-z0-9]+$/.test(initial))
                  return initial.toLowerCase();
              else
                  return false;
          },
          reactOnKey: function (e) {
              var that = this;
  
              /*
               Prevent keyup event if the dialog is not last!
               */
              var a = $('.jconfirm');
              if (a.eq(a.length - 1)[0] !== this.$el[0])
                  return false;
  
              var key = e.which;
              /*
               Do not react if Enter or Space is pressed on input elements
               */
              if (this.$content.find(':input').is(':focus') && /13|32/.test(key))
                  return false;
  
              var keyChar = this._getKey(key);
  
              // If esc is pressed
              if (keyChar === 'esc' && this.escapeKey) {
                  if (this.escapeKey === true) {
                      this.$scrollPane.trigger('click');
                  }
                  else if (typeof this.escapeKey === 'string' || typeof this.escapeKey === 'function') {
                      var buttonKey;
                      if (typeof this.escapeKey === 'function') {
                          buttonKey = this.escapeKey();
                      } else {
                          buttonKey = this.escapeKey;
                      }
  
                      if (buttonKey)
                          if (typeof this.buttons[buttonKey] === 'undefined') {
                              console.warn('Invalid escapeKey, no buttons found with key ' + buttonKey);
                          } else {
                              this['$_' + buttonKey].trigger('click');
                          }
                  }
              }
  
              // check if any button is listening to this key.
              $.each(this.buttons, function (key, button) {
                  if (button.keys.indexOf(keyChar) != -1) {
                      that['$_' + key].trigger('click');
                  }
              });
          },
          setDialogCenter: function () {
              console.info('setDialogCenter is deprecated, dialogs are centered with CSS3 tables');
          },
          _unwatchContent: function () {
              clearInterval(this._timer);
          },
          close: function () {
              var that = this;
  
              if (typeof this.onClose === 'function')
                  this.onClose();
  
              this._unwatchContent();
  
              /*
               unbind the window resize & keyup event.
               */
              $(window).unbind('resize.' + this._id);
              $(window).unbind('keyup.' + this._id);
              $(window).unbind('jcKeyDown.' + this._id);
  
              if (this.draggable) {
                  $(window).unbind('mousemove.' + this._id);
                  $(window).unbind('mouseup.' + this._id);
                  this.$titleContainer.unbind('mousedown');
              }
  
              that.$el.removeClass(that.loadedClass);
              $('body').removeClass('jconfirm-no-scroll-' + that._id);
              that.$jconfirmBoxContainer.removeClass('jconfirm-no-transition');
  
              setTimeout(function () {
                  that.$body.addClass(that.closeAnimationParsed);
                  that.$jconfirmBg.addClass('jconfirm-bg-h');
                  var closeTimer = (that.closeAnimation === 'none') ? 1 : that.animationSpeed;
  
                  setTimeout(function () {
                      that.$el.remove();
  
                      var l = jconfirm.instances;
                      var i = jconfirm.instances.length - 1;
                      for (i; i >= 0; i--) {
                          if (jconfirm.instances[i]._id === that._id) {
                              jconfirm.instances.splice(i, 1);
                          }
                      }
  
                      // Focusing a element, scrolls automatically to that element.
                      // no instances should be open, lastFocused should be true, the lastFocused element must exists in DOM
                      if (!jconfirm.instances.length) {
                          if (that.scrollToPreviousElement && jconfirm.lastFocused && jconfirm.lastFocused.length && $.contains(document, jconfirm.lastFocused[0])) {
                              var $lf = jconfirm.lastFocused;
                              if (that.scrollToPreviousElementAnimate) {
                                  var st = $(window).scrollTop();
                                  var ot = jconfirm.lastFocused.offset().top;
                                  var wh = $(window).height();
                                  if (!(ot > st && ot < (st + wh))) {
                                      var scrollTo = (ot - Math.round((wh / 3)));
                                      $('html, body').animate({
                                          scrollTop: scrollTo
                                      }, that.animationSpeed, 'swing', function () {
                                          // gracefully scroll and then focus.
                                          $lf.focus();
                                      });
                                  } else {
                                      // the element to be focused is already in view.
                                      $lf.focus();
                                  }
                              } else {
                                  $lf.focus();
                              }
                              jconfirm.lastFocused = false;
                          }
                      }
  
                      if (typeof that.onDestroy === 'function')
                          that.onDestroy();
  
                  }, closeTimer * 0.40);
              }, 50);
  
              return true;
          },
          open: function () {
              if (this.isOpen())
                  return false;
  
              // var that = this;
              this._buildHTML();
              this._bindEvents();
              this._open();
  
              return true;
          },
          setStartingPoint: function () {
              var el = false;
  
              if (this.animateFromElement !== true && this.animateFromElement) {
                  el = this.animateFromElement;
                  jconfirm.lastClicked = false;
              } else if (jconfirm.lastClicked && this.animateFromElement === true) {
                  el = jconfirm.lastClicked;
                  jconfirm.lastClicked = false;
              } else {
                  return false;
              }
  
              if (!el)
                  return false;
  
              var offset = el.offset();
  
              var iTop = el.outerHeight() / 2;
              var iLeft = el.outerWidth() / 2;
  
              // placing position of jconfirm modal in center of clicked element
              iTop -= this.$jconfirmBox.outerHeight() / 2;
              iLeft -= this.$jconfirmBox.outerWidth() / 2;
  
              // absolute position on screen
              var sourceTop = offset.top + iTop;
              sourceTop = sourceTop - this._scrollTop();
              var sourceLeft = offset.left + iLeft;
  
              // window halved
              var wh = $(window).height() / 2;
              var ww = $(window).width() / 2;
  
              var targetH = wh - this.$jconfirmBox.outerHeight() / 2;
              var targetW = ww - this.$jconfirmBox.outerWidth() / 2;
  
              sourceTop -= targetH;
              sourceLeft -= targetW;
  
              // Check if the element is inside the viewable window.
              if (Math.abs(sourceTop) > wh || Math.abs(sourceLeft) > ww)
                  return false;
  
              this.$jconfirmBoxContainer.css('transform', 'translate(' + sourceLeft + 'px, ' + sourceTop + 'px)');
          },
          _open: function () {
              var that = this;
              if (typeof that.onOpenBefore === 'function')
                  that.onOpenBefore();
  
              this.$body.removeClass(this.animationParsed);
              this.$jconfirmBg.removeClass('jconfirm-bg-h');
              this.$body.focus();
  
              that.$jconfirmBoxContainer.css('transform', 'translate(' + 0 + 'px, ' + 0 + 'px)');
  
              setTimeout(function () {
                  that.$body.css(that._getCSS(that.animationSpeed, 1));
                  that.$body.css({
                      'transition-property': that.$body.css('transition-property') + ', margin'
                  });
                  that.$jconfirmBoxContainer.addClass('jconfirm-no-transition');
                  that._modalReady.resolve();
                  if (typeof that.onOpen === 'function')
                      that.onOpen();
  
                  that.$el.addClass(that.loadedClass);
              }, this.animationSpeed);
          },
          loadedClass: 'jconfirm-open',
          isClosed: function () {
              return !this.$el || this.$el.css('display') === '';
          },
          isOpen: function () {
              return !this.isClosed();
          },
          toggle: function () {
              if (!this.isOpen())
                  this.open();
              else
                  this.close();
          }
      };
  
      jconfirm.instances = [];
      jconfirm.lastFocused = false;
      jconfirm.pluginDefaults = {
          template: '' +
          '<div class="jconfirm">' +
          '<div class="jconfirm-bg jconfirm-bg-h"></div>' +
          '<div class="jconfirm-scrollpane">' +
          '<div class="jconfirm-row">' +
          '<div class="jconfirm-cell">' +
          '<div class="jconfirm-holder">' +
          '<div class="jc-bs3-container">' +
          '<div class="jc-bs3-row">' +
          '<div class="jconfirm-box-container jconfirm-animated">' +
          '<div class="jconfirm-box" role="dialog" aria-labelledby="labelled" tabindex="-1">' +
          '<div class="jconfirm-closeIcon">&times;</div>' +
          '<div class="jconfirm-title-c">' +
          '<span class="jconfirm-icon-c"></span>' +
          '<span class="jconfirm-title"></span>' +
          '</div>' +
          '<div class="jconfirm-content-pane">' +
          '<div class="jconfirm-content"></div>' +
          '</div>' +
          '<div class="jconfirm-buttons">' +
          '</div>' +
          '<div class="jconfirm-clear">' +
          '</div>' +
          '</div>' +
          '</div>' +
          '</div>' +
          '</div>' +
          '</div>' +
          '</div>' +
          '</div>' +
          '</div></div>',
          title: 'Hello',
          titleClass: '',
          type: 'default',
          typeAnimated: true,
          draggable: true,
          dragWindowGap: 15,
          dragWindowBorder: true,
          animateFromElement: true,
          /**
           * @deprecated
           */
          alignMiddle: true,
          smoothContent: true,
          content: 'Are you sure to continue?',
          buttons: {},
          defaultButtons: {
              ok: {
                  action: function () {
                  }
              },
              close: {
                  action: function () {
                  }
              }
          },
          contentLoaded: function () {
          },
          icon: '',
          lazyOpen: false,
          bgOpacity: null,
          theme: 'light',
          animation: 'scale',
          closeAnimation: 'scale',
          animationSpeed: 400,
          animationBounce: 1,
          escapeKey: true,
          rtl: false,
          container: 'body',
          containerFluid: false,
          backgroundDismiss: false,
          backgroundDismissAnimation: 'shake',
          autoClose: false,
          closeIcon: null,
          closeIconClass: false,
          watchInterval: 100,
          columnClass: 'col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3 col-xs-10 col-xs-offset-1',
          boxWidth: '50%',
          scrollToPreviousElement: true,
          scrollToPreviousElementAnimate: true,
          useBootstrap: true,
          offsetTop: 40,
          offsetBottom: 40,
          bootstrapClasses: {
              container: 'container',
              containerFluid: 'container-fluid',
              row: 'row'
          },
          onContentReady: function () {
  
          },
          onOpenBefore: function () {
  
          },
          onOpen: function () {
  
          },
          onClose: function () {
  
          },
          onDestroy: function () {
  
          },
          onAction: function () {
  
          }
      };
  
      /**
       * This refers to the issue #241 and #246
       *
       * Problem:
       * Button A is clicked (keydown) using the Keyboard ENTER key
       * A opens the jconfirm modal B,
       * B has registered ENTER key for one of its button C
       * A is released (keyup), B gets the keyup event and triggers C.
       *
       * Solution:
       * Register a global keydown event, that tells jconfirm if the keydown originated inside jconfirm
       */
      var keyDown = false;
      $(window).on('keydown', function (e) {
          if (!keyDown) {
              var $target = $(e.target);
              var pass = false;
              if ($target.closest('.jconfirm-box').length)
                  pass = true;
              if (pass)
                  $(window).trigger('jcKeyDown');
  
              keyDown = true;
          }
      });
      $(window).on('keyup', function () {
          keyDown = false;
      });
      jconfirm.lastClicked = false;
      $(document).on('mousedown', 'button, a', function () {
          jconfirm.lastClicked = $(this);
      });
  })(jQuery, window);
  