document.write('<div id="saasForm121161743"></div>');
var SaaSFormStyles = "body .xdsoft_datetimepicker { z-index: 1999999999; } @media (max-width: 639px) { body div:not(.scFormContainerModal) form[name^='scForm'] .body-div.responsive { width: 100% !important; } } @media (max-width: 639px) { body form[name^='scForm'] .body-div.responsive input[type='radio'], body form[name^='scForm'] .body-div.responsive input[type='checkbox'] { width: 2em; height: 2em; } body form[name^='scForm'] .body-div.responsive .address { width: 100% !important; } body form[name^='scForm'] .body-div.responsive .vehicleYear, body form[name^='scForm'] .body-div.responsive .vehicleMake, body form[name^='scForm'] .body-div.responsive .vehicleModel { width: 100% !important; flex: none !important; } body form[name^='scForm'] .body-div.responsive .inputContainer { width: 100% !important; flex: none !important; } body form[name^='scForm'] .body-div.responsive .inputContainer .firstName, body form[name^='scForm'] .body-div.responsive .inputContainer .lastName { width: 100% !important; } body form[name^='scForm'] .body-div.responsive .inputContainer select.input { width: 100% !important; height: 36px; } body form[name^='scForm'] .body-div.responsive .inputContainer .options.input > div, body form[name^='scForm'] .body-div.responsive .inputContainer #otherDiv { height: 2.5em !important; } body form[name^='scForm'] .body-div.responsive .inputContainer input { max-width: 100% !important; height: 28px; box-sizing: content-box; } body form[name^='scForm'] .body-div.responsive .inputContainer > div { width: 100% !important; flex: none !important; } body form[name^='scForm'] .body-div.responsive .prefix.aCode { display: none !important; } } body form[name^='scForm'] .body-div .hiddenElement { display: none !important; height: 0px; min-height: 0px; } body form[name^='scForm'] .body-div table { box-sizing: content-box; line-height: normal; font-size: inherit; border: 0; padding: 0; margin: 0; } body form[name^='scForm'] .body-div table tr { line-height: normal; border: 0; padding: 0; box-sizing: content-box; margin: 0; } body form[name^='scForm'] .body-div table tr td { line-height: normal; box-sizing: content-box; border: 0; padding: 0; margin: 0; } body form[name^='scForm'] .body-div table tr td .label { background: transparent; text-align: inherit; text-shadow: initial; white-space: normal; } body form[name^='scForm'] .body-div table tr td input { height: auto; border-radius: 3px; font-size: 100%; line-height: normal; } body form[name^='scForm'] .body-div table tr td div { line-height: normal; box-sizing: content-box; } body form[name^='scForm'] .body-div table tr td .inputContainer { height: auto; } body form[name^='scForm'] .body-div table tr td textarea { font-family: Arial, Helvetica, sans-serif; } body form[name^='scForm'] .body-div .thankYouContainer { position: absolute; top: 0; left: 0; background: rgba(255, 255, 255, 0.6); height: 100%; width: 100%; display: flex; justify-content: center; align-items: center; } body form[name^='scForm'] .body-div .thankYouContainer .thankYouMessage { padding: 1em 1em 0 1em; margin: 0 1em 1em 1em; background: white; border: 1px solid rgba(0, 0, 0, 0.3); border-radius: 0.28rem; position: relative; } body form[name^='scForm'] .body-div .thankYouContainer .closeThankYou { position: absolute; top: 0; right: 0; background: 0; border: 0; font-weight: bold; font-size: 20px; font-family: Tahoma; line-height: 20px; padding: 0 5px 5px 5px; }";/*global jQuery, grecaptchaFormSiteKey */
if (typeof jQueryScriptOutputted == 'undefined') var jQueryScriptOutputted = false;
var errorStyles = '.errorTip {  display: inline-block;  position:absolute; }  .errorTip .errorInner{    position: relative;  background: #d54333;  border: 2px solid #661e1e;    padding:5px;border-radius:7px;color:white;font-size:14px;  cursor:pointer;  max-width:350px;  box-shadow: 3px 3px 10px rgba(0,0,0,0.3);  }.errorInner:after, .errorInner:before {  right: 100%;  border: solid transparent;  content: " ";  height: 0;  width: 0;  position: absolute;  pointer-events: none;}.errorInner:after {  border-color: rgba(213, 67, 51, 0);  border-right-color: #d54333;  border-width: 10px;  top: 50%;  margin-top: -10px;}.errorInner:before {  border-color: rgba(102, 30, 30, 0);  border-right-color: #661e1e;  border-width: 13px;  top: 50%;  margin-top: -13px;}';
if (typeof scFormLoadStart == 'undefined') var scFormLoadStart = false;
if (typeof scFormLoaded == 'undefined') var scFormLoaded = false;
if (typeof scPortableLoaded == 'undefined') var scPortableLoaded = false;
if (typeof scTimeoutLoaded == 'undefined') var scTimeoutLoaded = false;
if (typeof scButtonLoaded == 'undefined') var scButtonLoaded = false;
if (typeof scScriptsLoading == 'undefined') var scScriptsLoading = false;
if (typeof scScriptsLoaded == 'undefined') var scScriptsLoaded = false;
if (typeof SaaSFormStyles === 'undefined') var SaaSFormStyles = '';
if (window.formGrecaptchaElements === undefined) {
  window.formGrecaptchaElements = {};
}

// Gets jQuery
function scInitJQuery() {
    //if the jQuery object isn't available
    if (typeof(jQuery) == 'undefined') {
        if (! jQueryScriptOutputted) {
            //only output the script once..
            jQueryScriptOutputted = true;
            var script = document.createElement("SCRIPT");
            script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js';
            script.type = 'text/javascript';
            document.getElementsByTagName("head")[0].appendChild(script);
            scLoadScripts();
        }
        setTimeout("scInitJQuery()", 50);
    } else if (!scScriptsLoading){
      scLoadScripts();
    }
}

// Adds error styles and validation script
function scLoadScripts() {
  scScriptsLoading = true;
  if (scScriptsLoaded) return true;

  if (typeof jQuery != 'undefined') {
    var script = document.createElement("SCRIPT");
    script.src = scAppUrl+'channels/form/js/formValidation.js';
    script.type = 'text/javascript';
    document.getElementsByTagName("head")[0].appendChild(script);

    var vehicleValidate = document.createElement('SCRIPT');
    vehicleValidate.src = scAppUrl + '/channels/form/js/automotive.js';
    vehicleValidate.type = 'text/javascript';
    document.getElementsByTagName("head")[0].appendChild(vehicleValidate);

    var gApi = document.createElement("SCRIPT");
    gApi.src = "https://www.google.com/recaptcha/api.js?onload=formGrecaptchaLoadCallback&render=explicit";
    gApi.type = "text/javascript";
    document.getElementsByTagName("head")[0].appendChild(gApi);

    var script2 = document.createElement("SCRIPT");
    script2.src = scAppUrl + 'thirdparty/jquery-datetimepicker/jquery.datetimepicker.js';
    script2.type = 'text/javascript';
    document.getElementsByTagName('head')[0].appendChild(script2);

    var style = document.createElement('LINK');
    style.href = scAppUrl + 'thirdparty/jquery-datetimepicker/jquery.datetimepicker.css';
    style.type = 'text/css';
    style.rel = 'stylesheet';
   
    var scriptMoment = document.createElement("SCRIPT");
    scriptMoment.src = scAppUrl + 'thirdparty/js_libs/moment/moment.min.js';
    scriptMoment.type = 'text/javascript';
    document.getElementsByTagName('head')[0].appendChild(scriptMoment);
    
    document.getElementsByTagName('head')[0].appendChild(style);
    jQuery( "<style>"+SaaSFormStyles+errorStyles+"</style>" ).appendTo( "head" );
    scScriptsLoaded = true;


    saasBindKeys();
  }
  else{
    setTimeout(function() { 
      scLoadScripts(); 
    }, 50);
  }
}

/**
 * Bind the escape key to hide modal forms
 *
 * @return void
 */
function saasBindKeys() {
  jQuery(document).keyup(function(e) {
    if (e.keyCode == 27) { 
      saasRemoveModal();
    }   // esc
  });
}

/**
 * Called by the (thirdparty) Grecaptcha JS after it has loaded
 * Initalizes any captchas that have not yet been rendered
 *
 * @return void
 */
function formGrecaptchaLoadCallback () {
  var i;
  var elements = window.formGrecaptchaElements;
  for (i in elements) {
    if (elements.hasOwnProperty(i)) {
      if (!elements[i].rendered) {
        elements[i].form.renderGrecaptchaElement();
      }
    }
  }
}

/**
 * Load a form using the config passed from the server
 *
 * @param object config Form config: 
 *                      {
 *                        id: random unique id
 *                        formId: form's id
 *                        type: "portable" or "modal"
 *                        target: the form's desired target attribute
 *                        targetElement: id of element that the form will be inserted into
 *                        formHtml: the actual html of the form
 *                        thankYouHtml: the html of the thank you message
 *                        modal: modal config (timeout length, button, etc)
 *                      }
 */
function SaaSForm (config) {
  /**
   * Internal Data
   */
  var form = {
    id: config.id,
    formId: config.formId,
    type: config.type,
    targetElement: config.targetElement,
    container: undefined,
    element: undefined,
    context: this,
    formHtml: config.formHtml,
    thankYouHtml: config.thankYouHtml.replace(/\\"/g, '"'),
    defaultValues: {},
    googleMaps: config.googleMaps,
    submissionToken: config.submissionToken,
  };

  /**
   * Expose methods
   */
  this.renderGrecaptchaElement = renderGrecaptchaElement;
  this.getElement = getElement;

  init();

  /**
   * Initialize the form if jQuery has been loaded. This method will place the form's HTML into the container
   * element and bind the relevant events.
   */
  function init () {
    if (window.jQuery !== undefined) {

      switch(form.type) {
      case 'portable':
        initPortable();
        break;
      case 'modal':
        initModal();
        break;
      }
      /**
       * Trigger the load event. Users can listen to the event to run additional logic once the form has loaded
       */
      jQuery(document).trigger("portableFormDisplayed", [form.element, form.formId, form.context]);

    } else {
      /**
       * Wait for jQuery to load
       */
      setTimeout(function () {
        init();
      }, 50);
    }
  }

  /**
   * Initialize a portable form. Create the form's container withhin the target element and set up the form
   *
   * @return void
   */
  function initPortable () {
    var formId;
    if (typeof form.formId === "string") {
      formId = form.formId.replace(/\./g, "\\.");  
    } else {
      formId = form.formId;  
    }
    var container = form.container = jQuery('#' + config.targetElement);
    container.html('<div id="scPortableForm-' + form.formId +'"></div>');
    var element = form.element = form.container.find('#scPortableForm-' + formId);
    element.append(form.formHtml.replace(/(\\')/g, "'"));
    // Remove style tags in HTML elements only
    element.find("[id^='HTMLElement']").each(function () {
      $(this).find("style").remove();
    });
    element.find('form').attr('id', 'scInlineForm-' + form.formId);
    element.find('.scVerifyEmail').hide();
    if (element.find('.footer-div').length > 0) {
      element.find('.footer-div').appendTo(element.find('.body-div'));
      jQuery('.body-div').css('height','auto');
    }

    element.find('form').submit(function(e) {
      onSubmit(e);
    });

    let hiddenSubmissionToken = document.createElement('input');
    hiddenSubmissionToken.type = 'hidden';
    hiddenSubmissionToken.name = 'submissionToken';
    hiddenSubmissionToken.value = form.submissionToken;
    element.find('form').append(hiddenSubmissionToken);

    var style, script, googleMapsPreview = element.find('#google_maps_button');
    if (googleMapsPreview[0]) {
      googleMapsPreview[0].onclick = null;
      googleMapsPreview[0].onclick = portableMapPreview;

      style = document.createElement('LINK');
      style.href = scAppUrl + 'thirdparty/js_libs/jquery-perfect-scrollbar/perfect-scrollbar.min.css';
      style.type = 'text/css';
      style.rel = 'stylesheet';
     
      script = document.createElement("SCRIPT");
      script.src = scAppUrl + 'thirdparty/js_libs/jquery-perfect-scrollbar/perfect-scrollbar.min.js';
      script.type = 'text/javascript';
      document.getElementsByTagName('head')[0].appendChild(script);

      script = document.createElement("SCRIPT");
      script.src = scAppUrl + 'channels/common/js_libs/dialog/dialog.js';
      script.type = 'text/javascript';
      document.getElementsByTagName('head')[0].appendChild(script);
    }

    var googleMapsAutocomplete = element.find('#google_map_autocomplete_container');
    if (form.googleMaps && googleMapsAutocomplete[0]) {
      script = document.createElement("SCRIPT");
      script.src = 'https://maps.googleapis.com/maps/api/js?key=' + form.googleMaps +
                   '&libraries=places&callback=initMap';
      script.type = 'text/javascript';
      document.getElementsByTagName('head')[0].appendChild(script);
    }

    if (isMobile()) {
      element.find('.body-div').css('width', '100%');
      element.find('td').css('width', '100%');
    }

    storeDefaultValues();
    setupDatePickers();
    setupCaptchas();
    setupDefaultValues();
  }

  /**
   * Initialize a modal form. Create the form's container on the body and set up the form
   *
   * @return void
   */
  function initModal () {
    jQuery('body').append('<div class="scFormContainerModal" id="scFormContainerModal-' + form.id + '" style="display:none; background-color: rgba(0,0,0,0.3); top: 0; position: fixed; z-index: 8999999; width: 100%; height: 100%;">' + form.formHtml.replace(/(\\')/g, "'") + '</div>');
    
    var container = form.element = jQuery('#scFormContainerModal-' + form.id);
    if (container.find('.footer-div').length > 0) {
      container.find('.footer-div').appendTo(container.find('.body-div'));
      jQuery('.body-div').css('height','auto');
    }
    container.find('form').css('margin-top', '6%');
    container.find('.body-div').css('box-shadow', '0px 1px 4px #333');
    // Remove style tags in HTML elements only
    container.find("[id^='HTMLElement']").each(function () {
      $(this).find("style").remove();
    });
    container.find('div:first').css('background', 'transparent');
    container.find('.body-div').css('position', 'relative');
    container.find('.body-div').css('margin', '0 auto');
    container.find('.body-div').append("<div class='scModalFormCloseButton' style='position: absolute;top: 0;right: 0px;background-color: #333;color: white;padding: 3px 6px;font-size: 10px;border-radius: 10px;font-family: Arial;cursor: pointer;'>X</div>");
    container.find('.scVerifyEmail').hide();
    jQuery('.scModalFormCloseButton').click(function() {
      saasRemoveModal();
    });

    container.find('form').submit(function(e) {
      onSubmit(e);
    });

    let hiddenSubmissionToken = document.createElement('input');
    hiddenSubmissionToken.type = 'hidden';
    hiddenSubmissionToken.name = 'submissionToken';
    hiddenSubmissionToken.value = form.submissionToken;
    container.find('form').append(hiddenSubmissionToken);

    var script, style, googleMapsPreview = container.find('#google_maps_button');
    if (googleMapsPreview[0]) {
      googleMapsPreview[0].onclick = null;
      googleMapsPreview[0].onclick = portableMapPreview;

      style = document.createElement('LINK');
      style.href = scAppUrl + 'thirdparty/js_libs/jquery-perfect-scrollbar/perfect-scrollbar.min.css';
      style.type = 'text/css';
      style.rel = 'stylesheet';
     
      script = document.createElement("SCRIPT");
      script.src = scAppUrl + 'thirdparty/js_libs/jquery-perfect-scrollbar/perfect-scrollbar.min.js';
      script.type = 'text/javascript';
      document.getElementsByTagName('head')[0].appendChild(script);

      script = document.createElement("SCRIPT");
      script.src = scAppUrl + 'channels/common/js_libs/dialog/dialog.js';
      script.type = 'text/javascript';
      document.getElementsByTagName('head')[0].appendChild(script);
    }

    var googleMapsAutocomplete = container.find('#google_map_autocomplete_container');
    if (form.googleMaps && googleMapsAutocomplete[0]) {
      script = document.createElement("SCRIPT");
      script.src = 'https://maps.googleapis.com/maps/api/js?key=' + form.googleMaps +
                   '&libraries=places&callback=initMap';
      script.type = 'text/javascript';
      document.getElementsByTagName('head')[0].appendChild(script);
    }

    storeDefaultValues();
    setupDatePickers();
    setupCaptchas();
    setupDefaultValues();

    if (typeof config.modal.timeoutDisplay != 'undefined' && config.modal.timeoutDisplay) {
      shouldShowForm();
    }

    if (typeof config.modal.displayButton != 'undefined' && config.modal.displayButton) {
      loadButton();
    
    }
  }

  /**
   * Scan the fields and store any default values so they can be used later for validation. 
   * We only care about required fields
   *
   * @return void
   */
  function storeDefaultValues() {
    form.element.find('input.required,select.required').each(function () {
      form.defaultValues[jQuery(this).attr('name')] = jQuery.trim(jQuery(this).val());
    });
  }


  /**
   * Validate the form before submission
   *
   * @return bool
   */
  function validate() {
    var hasError = false;
    var element = form.element;

    element.find('div[id]:not(.EditorRow)').each(function () {
      var field = jQuery(this);
      var idParts = field.attr('id').split('_');
      if (idParts.length == 2) {
        switch (idParts[0]) {
          case "RankedChoiceElement":
            hasError = validateRankedChoice(field) || hasError;
            break;
          case "MatrixElement":
            hasError = validateMatrix(field) || hasError;
            break;
          case "AutocompleteAddressElement":
          case "AddressElement":
            hasError = validateAddress(field) || hasError;
            break;
          case "ListWidget":
          case "CheckboxElement":
            hasError = validateCheckbox(field) || hasError;
            break;
          case "CountryElement":
            hasError = validateCountry(field) || hasError;
            break;
          case "RadioElement":
            hasError = validateCheckbox(field) || hasError;
            break;
          case "VoiceElement":
            hasError = validateNumber(field, true) || hasError;
            break;
          case "SMSElement":
            hasError = validateNumber(field) || hasError;
            break;
          case "FaxElement":
            hasError = validateNumber(field) || hasError;
            break;
          case "EmailElement":
            hasError = validateEmail(field) || hasError;
            break;
          case "UploadElement":
            hasError = validateFile(field) || hasError;
            break;
          default:
            hasError = validateField(field) || hasError;
            break;
        }
      }
    });
    return !hasError;
  }

  /**
   * Check if a given field is required
   *
   * @param jQueryObject field The field (top level table element) jQuery object
   *
   * @return bool
   */
  function fieldIsRequired(field) {
    return field.find('.required:not(.prefix)').length > 0;
  }

  /**
   * Render the error message that exists in a given field.
   *
   * @param jQueryObject field The field (top level table element) jQuery object
   * @param string       alt   An alternate error message (if applicable)
   *
   * @return void
   */
  function renderError(field, alt) {
    field.find('.errorMessage').css('display', 'block');
    if (typeof alt != 'undefined') {
      field.find('.errorMessage').text(alt);
    }
  }

  /**
   * Validate a country dropdown field
   *
   * @param jQueryObject field The field (top level table element) jQuery object
   *
   * @return bool
   */
  function validateCountry(field) {
    var hasError = false;
    if (fieldIsRequired(field)) {
      field.find('select').filter('.required:not(.prefix)').each(function () {
        if (jQuery(this).is(":visible") && jQuery.trim(jQuery(this).val()) === '--') {
          hasError = true;
        }
      });
    }

    if (hasError) {
      renderError(field);
    }

    return hasError;
  }

  /**
   * Validate a text field
   *
   * @param jQueryObject field The field (top level table element) jQuery object
   *
   * @return bool
   */
  function validateField(field) {
    var hasError = false;
    if (fieldIsRequired(field)) {
      field.find('input,select,textarea').filter('.required:not(.prefix)').each(function () {
        if (jQuery(this).is(":visible") && jQuery.trim(jQuery(this).val()) === '') {
          hasError = true;
        }
      });
    }

    field.find('[data-minlimit]').each(function () {
      var value = jQuery(this).val().trim();
      if (value !== "" && value.length < jQuery(this).data('minlimit')) {
        hasError = true;
      }
    });

    if (hasError) {
      renderError(field);
    }

    return hasError;
  }

  /**
   * Validate a phone number field
   *
   * @param jQueryObject field         The field (top level table element) jQuery object
   * @param boolean      tooShortError If true, show "The provided phone number is too short"
   *
   * @return bool
   */
  function validateNumber(field, tooShortError) {
    var hasError = false;
    var value = field.find('.prefix').val().trim() + field.find('.numberInput').val().trim();
    if ((fieldIsRequired(field) && value === "") || (value.length > 0 && (value.length < 5 || value.search(/[a-zA-Z]+/) != -1))) {
      hasError = true;
      if (value.length > 0 && value.length < 5 && tooShortError) {
        renderError(field, "The provided phone number is too short");
      }
      renderError(field);
    }

    return hasError;
  }

  /**
   * Validate an email field
   *
   * @param jQueryObject field The field (top level table element) jQuery object
   *
   * @return bool
   */
  function validateEmail(field) {
    var hasError = false;
    var input, value;
    var emailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    input = field.find('input[type="text"]');
    value = input.val().trim();
    if (fieldIsRequired(field)) {
      if (value === "" || value === form.defaultValues[input.attr('name')]) {
        hasError = true;
      }
    }

    if (value.length > 0 && emailRegex.test(value) === false) {
      hasError = true;
    }

    if (hasError) {
      renderError(field);
    }

    return hasError;
  }

  /**
   * Validate a file upload. if it's required ensure that it has a file to check. Then confirm that the extension is allowed
   *
   * @param jqueryObject field The field to validate
   *
   * @return bool
   */
  function validateFile (field) {
    var hasError = false;
    var input;
    var value;
    var validExtensions = [
    "xml", "docx", "bmp", "ppt", "xls", 
    "csv", "txt", "gif", "mp3", "doc",
    "odt", "png", "jpeg", "jpg",  "pdf",
    "eps", "ai", "svg", "ait", "fxg",
    "svgz", "xlsx", "mp4", "mov", "mpg", "mpeg"];

    input = field.find('input[type=file]');
    value = input.val().trim();
    var ext = value.split(".")[1];
    if (fieldIsRequired(field)) {
      if (value === "" || ext === "") {
        hasError = true;
      }
    }
    if (value) {
      if (validExtensions.includes(ext)) {
        hasError = false;
      } else {
        hasError = true;
      }
    }

    if (hasError) {
      renderError(field);
    }
    return hasError;
  }

  /**
   * Validate an address. If its required, ensure that at least: address1, country, city and zip are completed.
   *
   * @param jQueryObject field The field (top level table element) jQuery object
   *
   * @return bool
   */
  function validateAddress(field) {
    var hasError = false;
    var inputs = [
      'address1[value]',
      'country[value]',
      'city[value]',
      'zip[value]',
    ];
    var i;
    if (fieldIsRequired(field)) {
      for (i = 0; i < inputs.length; i++) {
        if (field.find('[name="' + inputs[i] + '"]').val().trim() === "") {
          hasError = true;
        }
      }
    }

    if (hasError) {
      renderError(field);
    }
    return hasError;
  }

  /**
   * Validate a checkbox. If its required ensure that at least one has been checked
   *
   * @param jQueryObject field The field (top level table element) jQuery object
   *
   * @return bool
   */
  function validateCheckbox(field) {
    var hasError = false;
    if (fieldIsRequired(field)) {
      if (field.find("input:checked").length === 0) {
        hasError = true;
        renderError(field);
      } else {
        field.find("input:checked").parent().each(function () {
          if (jQuery(this).find("input[type=text]").length !== 0) {
            if (jQuery(this).find("input[type=text]").val().trim() === '') {
              hasError = true;
              renderError(field);
            }
          }
        });
      }
    }

    return hasError;
  }

  /**
   * Validate a radio matrix. Ensure that for each question at least one radio has been checked
   *
   * @param jQueryObject field The field (top level table element) jQuery object
   *
   * @return bool
   */
  function validateMatrix(field) {
    var hasError = false;
    var choices = [];
    var choice;
    var i;
    if (fieldIsRequired(field)) {
      field.find('input[type="radio"]').each(function () {
        var name = jQuery(this).attr('name');
        if (choices.indexOf(name) === -1) {
          choices.push(name);
        }
      });

      if (choices.length > 0) {
        for (i = 0; i < choices.length; i++) {
          choice = choices[i];
          if (!jQuery('input[name="' + choice + '"]').is(":checked") || 
              jQuery('input[name="' + choice + '"]:checked').val() == '') {
            hasError = true;
            renderError(field);
          }
        }
      }
    }

    return hasError;
  }

  /**
   * Validate a ranked choice element. Ensure that for each rank there is at least one options selected,
   * as well as not more than one rank for the same option.
   * 
   * @param jQuery field The field (top level element)
   * 
   * @return bool
   */
  function validateRankedChoice(field) {
    var hasError = false;
    var choices = [];
    var choice;
    var i;
    
    field.find('input[type="radio"]').each(function () {
      var name = jQuery(this).attr('name');
      if (choices.indexOf(name) === -1) {
        choices.push(name);
      }
    });

    if (fieldIsRequired(field)) {
      for (i = 0; i < choices.length; i++) {
        choice = choices[i];
        if (!jQuery('input[name="' + choice + '"]').is(":checked") ||
          jQuery('input[name="' + choice + '"]:checked').val() == 'null'
        ) {
          hasError = true;
          renderError(field);
        }
      }
    }

    var answers = [];
    for (i = 0; i < choices.length; i++) {
      choice = choices[i];
      var val = jQuery('input[name="' + choice + '"]:checked').val();
      if (val) {
        if (answers.indexOf(val) !== -1) {
          hasError = true;
          renderError(field);
        } else {
          answers.push(val);
        }
      }
    }

    return hasError;
  }

  /**
   * Get the form's jQuery element 
   *
   * @return jQueryObject
   */
  function getElement() {
    return form.element;
  }

  /**
   * Internal method for configuring a captcha to be rendered. If the captcha library has not yet loaded: 
   * store the data elsewhere for the formGrecaptchaLoadCallback to use.
   *
   * @return void
   */
  function _renderGrecaptchaElement () {
    window.formGrecaptchaElements[form.id] = {
      form: form.context,
      rendered: false,
    };

    if (window.grecaptcha !== undefined) {
      renderGrecaptchaElement(); 
    }
  }

  /**
   * Render the captcha using the Google Recaptcha library. This method is also exposed
   * for the formGrecaptchaLoadCallback to use.
   *
   * @return void
   */
  function renderGrecaptchaElement() {
    var captcha =  window.formGrecaptchaElements[form.id];
    if (captcha.rendered === false) {
      var captchaElement = form.element.find('.recaptcha');
      captcha.widgetId = window.grecaptcha.render(captchaElement[0], {
        sitekey: grecaptchaFormSiteKey,
        callback: function () {
          form.element.find('input[type="submit"]').attr('disabled', false);
        },
        "expired-callback": function () {
          form.element.find('input[type="submit"]').attr('disabled', true);
        }
      });
      captcha.rendered = true;
      form.element.find('input[type="submit"]').attr('disabled', true);
    }
  }

  /**
   * Submission event for the form. Validates the fields and then "posts" the data.
   *
   * @param DOMEvent e The submission event from the form
   *
   * @return void
   */
  function onSubmit (e) {
    cleanErrors();
    if (validate()) {

      //Disable Submit Element so only one copy of the form can be submitted
      form.element.find('input[type="submit"]').each(function(){
        jQuery(this).attr('disabled', true);
      });

      if (config.target == "_self") {
        e.preventDefault();
        var data = form.element.find('form').serializeArray();
        var html = "";
        html += '<div class="thankYouContainer">';
        html +=   '<div class="thankYouMessage">';
        html +=     mergeValues(form.thankYouHtml, data);
        html +=     '<button type="button" class="closeThankYou" aria-label="Close thank you message">x</button>';
        html +=   "</div>";
        html += "</div>";
        jQuery('body').append('<iframe id="saasPortableIframeForm-' + form.id+'" style="display:none"><html><body></body></html></iframe>');
        jQuery(document).trigger("portableFormSubmitted", [form.element, form.formId, form.context]);
        setTimeout(function() {
          var iframe = jQuery("#saasPortableIframeForm-" + form.id);
          iframe.contents().find("body").append(form.element.find('form').clone());
          iframe.contents().find('form').unbind('submit');
          form.element.find('select').each(function () {
            var name = jQuery(this).attr('name');
            iframe.contents().find('[name="' + name + '"]').val(jQuery(this).val());
          });
          iframe.contents().find('form').submit();
          form.element.find('.body-div').css('position', 'relative').append(html);
          form.element.find('.closeThankYou').click(function () {
            form.element.find('.thankYouContainer').remove();
          });
          form.element.find('input[type="submit"]').attr('disabled', false);
        }, 100);
      }
    } else {
      e.preventDefault();
    }
  }

  /**
   * Return all errors to their default hidden state
   *
   * @return void
   */
  function cleanErrors() {
    form.element.find('.errorMessage').css('display', 'none');
  }

  /**
   * Load the button used for modal forms. Bind the show callback to its click event
   *
   * @return void
   */
  function loadButton() {
    // Build the button
    jQuery('body').append('<div class="scModalButton" id="scButtonContainer-' + form.id + '" style="position:fixed; z-index:10000000000;"></div>');

    var container = jQuery('#scButtonContainer-' + form.id);
    var modal = config.modal;

    var button = jQuery("<button />");
    var span = jQuery("<span />");
    span.text(modal.buttonText);
    button.append(span);
    container.append(button);

    container.css({'background-color': modal.buttonColor,
      'color': modal.buttonTextColor,
      'border': '1px solid #999',
      'box-shadow': '0px 0px 3px rgba(0,0,0,0.3) inset'
    });
    container.find('button').css({'color': 'inherit',
      'text-decoration': 'none',
      'font-family': 'Arial',
      'font-size': '16px',
      'padding': '5px 50px',
      'border': '0',
      'background': 'transparent',
      'cursor': 'pointer',
      'display': 'block'
    });
    container.find('button').click(function () {
      showModal();
    });

    switch(modal.buttonPosition){
    case "topLeft":
      container.css({left: '5%', 'top':0});
      break;
    case 'topCenter':
      container.css({'width': container.width(), 'margin': 'auto', 'position': 'relative', 'left': '0px'});
      container.find('a').css({'width': 'auto', 'height': 'auto'});
      container.wrap('<div style="position:fixed; top:0; left:0; width:100%; text-align:center;"></div>');
      break;
    case 'topRight':
      container.css({'top':0, 'right':'5%'});
      break;
    case 'bottomCenter':
      container.css({'width': container.width(), 'margin': 'auto', 'position': 'relative', 'left': '0px'});
      container.find('a').css({'width': 'auto', 'height': 'auto'});
      container.wrap('<div style="position:fixed; bottom:0; left:0; width:100%; text-align:center;"></div>');
      break;
    case "bottomRight":
      container.css({right: '5%', bottom:0});
      break;
    case "bottomLeft":
      container.css({left: '5%', bottom:0});
      break;
    case "centerLeft":
      container.css({top:'50%'});
      container.css('-webkit-transform', 'rotate(90deg)');
      container.css('-moz-transform', 'rotate(90deg)');
      container.css('-ms-transform', 'rotate(90deg)');
      container.css('-o-transform', 'rotate(90deg)');
      container.css('transform', 'rotate(90deg)');

      /* also accepts left, right, top, bottom coordinates; not required, but a good idea for styling */
      container.css('-webkit-transform-origin', '50% 50%');
      container.css('-moz-transform-origin', '50% 50%');
      container.css('-ms-transform-origin', '50% 50%');
      container.css('-o-transform-origin', '50% 50%');
      container.css('transform-origin', '50% 50%');

      /* Should be unset in IE9+ I think. */
      container.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=3)');

      // Fix the position
      container.css("left", -container.width()/2 + container.height()/2 + "px");
      break;
    case "centerRight":
      container.css({top:'50%'});
      container.css('-webkit-transform', 'rotate(-90deg)');
      container.css('-moz-transform', 'rotate(-90deg)');
      container.css('-ms-transform', 'rotate(-90deg)');
      container.css('-o-transform', 'rotate(-90deg)');
      container.css('transform', 'rotate(-90deg)');

      /* also accepts left, right, top, bottom coordinates; not required, but a good idea for styling */
      container.css('-webkit-transform-origin', '50% 50%');
      container.css('-moz-transform-origin', '50% 50%');
      container.css('-ms-transform-origin', '50% 50%');
      container.css('-o-transform-origin', '50% 50%');
      container.css('transform-origin', '50% 50%');

      /* Should be unset in IE9+ I think. */
      container.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=3)');

      // Fix the position
      container.css('right', -container.width()/2 + container.height()/2 + 'px');
      break;
    }
  }

  /**
   * Determine if the form should pop up for modal forms configured to auto-show after X seconds.
   * If the form should appear, this method will call the show function
   *
   * @return void
   */
  function shouldShowForm() {

    /**
     * Stupid stuff to support ie hating cookies
     */

    var hasShown = false;

    if (Storage !== undefined && localStorage !== undefined) {

      hasShown = localStorage.getItem('scForm'+ form.formId);
      localStorage.setItem('scForm' + form.formId, 1);
    }

    /*global scPreview
     */
    if (!hasShown || (typeof scPreview != 'undefined' && scPreview)){
      var timeOut = 4000;
      if (typeof config.modal.loadAfter != 'undefined')
        timeOut = parseInt(config.modal.loadAfter)*1000;

      setTimeout(function() {
        showModal();
      }, timeOut);
    }
  }

  /**
   * Set up the captcha elements if there are any
   *
   * @return void
   */
  function setupCaptchas() {
    if (form.element.find('#CaptchaElement_0').length > 0) {
      form.element.find('form').attr('target', '_blank');
      _renderGrecaptchaElement();
    }
  }


  /**
   * Convert defualt values into placeholders
   */
  function setupDefaultValues() {
    form.element.find('input[type=text]').each(function() {
      jQuery(this).attr('placeholder', this.value);
      this.value = '';
    });
  }


  /**
   * Set up the date and time pickers if there are any
   *
   * @return void
   */
  function setupDatePickers() {
    var element = getElement();
    if (element.find('.datePicker').length > 0 || element.find('.dateTimePicker').length > 0) {

      /**
       * Wait for date picker and moment libraries to have loaded
       */

      if (jQuery().datetimepicker !== undefined && window.moment) {
        var i, picker, pickerName, pickerSettings, pickerOptions;
        var datepickers = element.find('.datePicker');
        for (i = 0; i < datepickers.length; i++) {
          picker = datepickers[i];
          pickerName = picker.id.replace('_input', '[settings]').trim();
          pickerSettings = $('input[name="' + pickerName + '"]').val();
          if (pickerSettings) {
            pickerSettings = pickerSettings.replace(/\\\'/g, '"');
            pickerSettings = JSON.parse(pickerSettings);
            pickerOptions = pickerSettings.settings;
            
            if (pickerSettings.hasOwnProperty('min')) {
              if (pickerSettings.min.amount > 0) {
                pickerOptions.minDate = moment().add(pickerSettings.min.amount, pickerSettings.min.unit)
                                        .format('YYYY-MM-DD');
              } else {
                pickerOptions.minDate = moment().subtract(Math.abs(pickerSettings.min.amount), pickerSettings.min.unit)
                                      .format('YYYY-MM-DD');
              }
            }
            if (pickerOptions.hasOwnProperty('minDate')) {
              if (moment(pickerOptions.minDate, 'YYYY-MM-DD').isAfter()) {
                pickerOptions.startDate = pickerOptions.minDate;
              }
              if (pickerOptions.disabledWeekDays.length != 7) {
                while (pickerOptions.disabledWeekDays.includes(moment(pickerOptions.startDate).day())) {
                  pickerOptions.startDate = moment(pickerOptions.startDate).add(1, 'days').format('YYYY-MM-DD');
                }
              }
            }

            if (pickerSettings.hasOwnProperty('max')) {
              if (pickerSettings.max.amount > 0) {
                pickerOptions.maxDate = moment().add(pickerSettings.max.amount, pickerSettings.max.unit)
                                      .format('YYYY-MM-DD');
              } else {
                pickerOptions.maxDate = moment().subtract(Math.abs(pickerSettings.max.amount), pickerSettings.max.unit)
                                      .format('YYYY-MM-DD');
              }
            }
            if (pickerOptions.hasOwnProperty('maxDate')) {
              if (moment(pickerOptions.maxDate, 'YYYY-MM-DD').isBefore()) {
                pickerOptions.startDate = pickerOptions.maxDate;
              }
              if (pickerOptions.disabledWeekDays.length != 7) {
                while (pickerOptions.disabledWeekDays.includes(moment(pickerOptions.startDate).day())) {
                  pickerOptions.startDate = moment(pickerOptions.startDate).subtract(1, 'days').format('YYYY-MM-DD');
                }
              }
            }

            // If no dates are selectable, reset startDate and disable the time picker so a time can't be chosen on a disabled date.
            if (moment(pickerOptions.maxDate, 'YYYY-MM-DD').isBefore(moment(pickerOptions.minDate, 'YYYY-MM-DD')) || 
                moment(pickerOptions.startDate, 'YYYY-MM-DD').isBefore(moment(pickerOptions.minDate, 'YYYY-MM-DD')) || 
                moment(pickerOptions.startDate, 'YYYY-MM-DD').isAfter(moment(pickerOptions.maxDate, 'YYYY-MM-DD')) ||
                pickerOptions.disabledWeekDays.length == 7) {
              pickerOptions.timepicker = false;
              pickerOptions.startDate = '';
            }

            $('#' + picker.id).datetimepicker(pickerOptions);
          } else {
            element.find('.datePicker').datetimepicker({
              format: 'Y-m-d',
              closeOnDateSelect: true,
              timepicker: false
            });
          }
        }

        datepickers = $('.dateTimePicker');
        for (i = 0; i < datepickers.length; i++) {
          picker = datepickers[i];
          pickerName = picker.id.replace('_input', '[settings]').trim();
          pickerSettings = $('input[name="' + pickerName + '"]').val();
          if (pickerSettings) {
            pickerSettings = pickerSettings.replace(/\\\'/g, '"');
            pickerSettings = JSON.parse(pickerSettings);
            pickerOptions = pickerSettings.settings;
            pickerOptions.validateOnBlur = false;
            
            if (pickerSettings.hasOwnProperty('min')) {
              if (pickerSettings.min.amount > 0) {
                pickerOptions.minDate = moment().add(pickerSettings.min.amount, pickerSettings.min.unit)
                                        .format('YYYY-MM-DD');
              } else {
                pickerOptions.minDate = moment().subtract(Math.abs(pickerSettings.min.amount), pickerSettings.min.unit)
                                      .format('YYYY-MM-DD');
              }
            }
            if (pickerOptions.hasOwnProperty('minDate')) {
              if (moment(pickerOptions.minDate, 'YYYY-MM-DD').isAfter()) {
                pickerOptions.startDate = pickerOptions.minDate;
              }
              if (pickerOptions.disabledWeekDays.length != 7) {
                while (pickerOptions.disabledWeekDays.includes(moment(pickerOptions.startDate).day())) {
                  pickerOptions.startDate = moment(pickerOptions.startDate).add(1, 'days').format('YYYY-MM-DD');
                }
              }
            }

            if (pickerSettings.hasOwnProperty('max')) {
              if (pickerSettings.max.amount > 0) {
                pickerOptions.maxDate = moment().add(pickerSettings.max.amount, pickerSettings.max.unit)
                                      .format('YYYY-MM-DD');
              } else {
                pickerOptions.maxDate = moment().subtract(Math.abs(pickerSettings.max.amount), pickerSettings.max.unit)
                                      .format('YYYY-MM-DD');
              }
            }
            if (pickerOptions.hasOwnProperty('maxDate')) {
              if (moment(pickerOptions.maxDate, 'YYYY-MM-DD').isBefore()) {
                pickerOptions.startDate = pickerOptions.maxDate;
              }
              if (pickerOptions.disabledWeekDays.length != 7) {
                while (pickerOptions.disabledWeekDays.includes(moment(pickerOptions.startDate).day())) {
                  pickerOptions.startDate = moment(pickerOptions.startDate).subtract(1, 'days').format('YYYY-MM-DD');
                }
              }
            }

            // If no dates are selectable, reset startDate and disable the time picker so a time can't be chosen on a disabled date.
            if (moment(pickerOptions.maxDate, 'YYYY-MM-DD').isBefore(moment(pickerOptions.minDate, 'YYYY-MM-DD')) || 
                moment(pickerOptions.startDate, 'YYYY-MM-DD').isBefore(moment(pickerOptions.minDate, 'YYYY-MM-DD')) || 
                moment(pickerOptions.startDate, 'YYYY-MM-DD').isAfter(moment(pickerOptions.maxDate, 'YYYY-MM-DD')) ||
                pickerOptions.disabledWeekDays.length == 7) {
              pickerOptions.timepicker = false;
              pickerOptions.startDate = '';
            }

            $('#' + picker.id).datetimepicker(pickerOptions);
          } else {
              element.find('.dateTimePicker').datetimepicker({
                format: 'Y-m-d H:i',
                closeOnDateSelect: false,
                validateOnBlur: false
              });
          }
        }
      } else {
        setTimeout(function() {
          setupDatePickers();
        },50);
      }
    }

    const days = [...Array(31).keys()].map(i => `<option value="${i + 1}">${i + 1}</option>`);
    const months = [
      'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'
    ].map((m, i) => `<option value="${i + 1}">${m} (${i + 1})</option>`);
    const startYear = new Date().getFullYear();
    const years = [...Array(120).keys()].map(i => `<option value="${startYear - i}">${startYear - i}</option>`);

    const dateChanged = (el) => {
      const currentElement = $(el.target).attr('data-name');
      if (currentElement) {
        const day = $(`#${currentElement} .dayInput`).val();
        const month = $(`#${currentElement} .monthInput`).val();
        const year = $(`#${currentElement} .yearInput`).val();
        $(`#${currentElement} .value`).val(`${year}-${month}-${day}`);
      }
    };
    const dayInput = $('.dayInput');
    dayInput.change(dateChanged);
    dayInput.append(days);
    const monthInput = $('.monthInput');

    const handleDaysOnMonthChange = (el) => {
      const currentElementNode = $(el.target);
      const currentInputContainer = currentElementNode.parent();
      
      let checkDay = 31;
      const month = currentInputContainer.find('.monthInput').val();
      const currentlySelectedYear = currentInputContainer.find('.yearInput').val();

      for (let i = 0; i < 4; i++) {
        const checkMonth = new Date(`${currentlySelectedYear}-${month}-${checkDay}`).getMonth();
        if (checkMonth == month - 1) {
          // month has this many days
          break;
        }
        checkDay--;
      }

      let currentDays = currentInputContainer.find('.dayInput option');
      let difference = currentDays.length - checkDay;
    
      // We're removing days days
      if (difference > 0) {
        for (let i = difference; i > 0; --i) {
          currentDays = currentInputContainer.find('.dayInput option');
          currentDays.last().remove();
        }
      // We're adding days
      } else if (difference < 0) {
        for (let i = currentDays.length; i < currentDays.length - difference; ++i) {
          currentInputContainer.find('.dayInput').append(`<option value='${i+1}'>${i+1}</option>`);
        }
      }

      dateChanged(el);
    };

    monthInput.change(handleDaysOnMonthChange);

    monthInput.append(months);
    const yearInput = $('.yearInput');
    // Do day-confirming function to handle leap years
    yearInput.change(handleDaysOnMonthChange);
    yearInput.append(years);
  }

  /**
   * Fade the modal form in. 
   *
   * @return void
   */
  function showModal() {
    form.element.fadeIn();
    saasSetupModal(form.element);

    jQuery(document).trigger("portableFormDisplayed", [form.element, form.formId, form.context]);
  }


  /**
   * Merge the submitted values into the given html. Used for the thank you message to support things like
   * "Thanks %%name%% for your submission"
   *
   * @param string html   The original html with merge tags
   * @param object values The values submitted by the user
   * 
   * @return string The html with the values merged in
   */
  function mergeValues (html, values) {
    var post = {};
    var i;
    var name;
    for (i in values) {
      if (values.hasOwnProperty(i)) {
        name = values[i].name.slice(0,values[i].name.indexOf('['));

        if (typeof post[name] == 'undefined') {
          post[name] = {column: '', separator: '', 'value': []};
        }

        if (values[i].name.indexOf('[column]') != -1) {
          post[name].column = values[i].value;
        }

        if (values[i].name.indexOf('[value]') != -1) {
          post[name].value.push(values[i].value);
        }

        if (values[i].name.indexOf('[separator]') != -1) {
          post[name].separator = values[i].value;
        }
      }
    }

    for (i in post)  {
      if (post.hasOwnProperty(i)) {
        if (post[i].column != ''){
          var val = post[i].value.join(post[i].separator);
          var regex = new RegExp('(%%'+cleanRegex(post[i].column)+'%%)', 'gi');
          html = html.replace(regex, val);
        }
      }
    }

    return html;
  }

  /**
   * Cleans a given string for regex
   *
   * @param string str String to clean
   * 
   * @return string
   */
  function cleanRegex(str) {
    return str.replace(/(?=[/\\^$*+?.()|{}[\]])/g, "\\");
  }


  /**
   * Checks if the form is (likely) on a mobile browser
   *
   * @return bool
   */
  function isMobile() {
    return saasIsMobile();
  }

  /**
   * Callback to display a google map in a modal dialog
   */
  function portableMapPreview () {
    if (!form.googleMaps) {
      //a key must be available
      alert({
        title: 'Error',
        content: 'An unexpected error occurred.'
      });
      return;
    }

    var element = getElement();
    var query = '';
    var piece = element.find("input[name='address1[value]']").val();
    if (piece) {
      query += piece + " ";
    }
    piece = element.find("input[name='address2[value]']").val();
    if (piece) {
      query += piece + " ";
    }
    piece = element.find("select[name='country[value]']").val();
    if (piece) {
      query += piece + " ";
    }
    piece = element.find("input[name='city[value]']").val();
    if (piece) {
      query += piece + " ";
    }
    piece = element.find("input[name='state[value]']").val();
    if (piece) {
      query += piece + " ";
    }
    piece = element.find("input[name='zip[value]']").val();
    if (piece) {
      query += piece + " ";
    }
    query = query.trim();

    if (query === '') {
      //a query must be provided
      alert({
        title: 'Error',
        content: 'No address information available.'
      });
      return;
    }

    var frame = '<iframe class="formGoogleMapsFrame" frameborder="0" fullscreen src="https://www.google.com/maps/' +
      'embed/v1/place?key=' + form.googleMaps + '&q=' + encodeURIComponent(query) + '"></iframe>';
    alert({
      title: 'Google Map View',
      content: frame,
      height: $(window).height(),
      width: $(window).width() - 20
    });
  }

} // end SaaSForm

/**
 * Google maps JS library callback
 */
var autocomplete;
function initMap (data) {
  var input = document.getElementById('google_map_autocomplete');
  var options = {
    fields: ["address_components"],
    types: ['address']
  };
  autocomplete = new google.maps.places.Autocomplete(input, options);
  autocomplete.addListener('place_changed', fillAddress);
}

/**
 * Google Maps Autocomplete listener
 */
function fillAddress() {
  var place = autocomplete.getPlace();
  var address1 = $('input[name="address1[value]"]');
  var address2 = $('input[name="address2[value]"]');
  var country = $('select[name="country[value]"]');
  var city = $('input[name="city[value]"]');
  var state = $('input[name="state[value]"]');
  var zip = $('input[name="zip[value]"]');

  address1.val('');
  address2.val('');
  country.val('');
  city.val('');
  state.val('');
  zip.val('');

  var component, address = '', code = '', locality = '';
  place.address_components.forEach(function (component) {
    switch (component.types[0]) {
      case 'street_number':
      case 'street_address':
        address = component.long_name + ' ' + address;
        break;
      case 'route': 
        address = address + component.long_name;
        break;
      case 'postal_code': 
      case 'postal_code_prefix': 
        code = component.long_name + code;
        break;
      case 'postal_code_suffix': 
        code = code + '-' + component.long_name;
        break;
      case 'sublocality_level_1':
        if (locality === '') {
          locality = component.long_name;
        }
        break;
      case 'postal_town':
      case 'locality':
        locality = component.long_name;
        break;
      case 'administrative_area_level_1': 
        state.val(component.short_name);
        break;
      case 'country': 
        country.val(component.long_name);
        break;
    }
  });
  address1.val(address);
  zip.val(code);
  city.val(locality);
}

/**
 * Google Maps Error Listener
 */
function gm_authFailure () {
  alert('There was an error connecting to Google Maps. Please fill the address out manually.');
}


/**
 * Removes the current modal window
 *
 */
function saasRemoveModal() {
  //Todo - add more effects
  jQuery('.scFormContainerModal').fadeOut(400);
  jQuery('.scModalButton').fadeIn();
}

/**
 * Public method for displaying a modal form
 */
function scDisplayModalForm(id) {
  var displayed = false; // Prevent duplicates

  jQuery('.scFormContainerModal').each(function () {
    var form = jQuery(this).find('form[name="scForm' + id + '"]');
    if (form.length > 0 && !displayed) {
      jQuery(this).fadeIn();
      saasSetupModal(jQuery(this));
      displayed = true;
    }
  });

}

function saasSetupModal(element) {
  var body = element.find('.body-div');

  /**
   * If the modal form is greater then 80% of the window, give it a scrollbar
   */

  if (body.height() > jQuery(window).height() * 0.8) {
    body.css({
      'max-height': '80%',
      'overflow-x': 'hidden',
      'overflow-y': 'scroll',
      'padding-right': '10px',
      'position': 'absolute',
      'left': '50%',
      'margin-left': '-' + body.width()/2 + 'px'
    });
  }

  jQuery('.scModalButton').fadeOut();

  if (saasIsMobile()) {
    element.css('position', 'absolute');
    var left = body.offset().left - 25;
    jQuery('html body').animate({scrollTop:0, scrollLeft:left+"px"}, 800);
  }

  if (body.hasClass('formError')) {
    body.css('width', '400px');
    body.find('.body-div > div:first').css({
      'background': 'white',
      'padding': '20px',
      'border-radius': '4px'
    });
  }
}

/**
 * Checks if the form is (likely) on a mobile browser
 *
 * @return bool
 */
function saasIsMobile() {
  var check = false;
  (function(a,b){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
  return check;
}

window.addEventListener('message', function (msg) {
  if (msg && msg.data && msg.data.header && msg.data.error) {
    let thankYouParagraphs = jQuery('.thankYouMessage p');
    if (thankYouParagraphs.length) {
      thankYouParagraphs[0].innerText = msg.data.header;
      thankYouParagraphs[1].innerText = msg.data.error;
    }
  }
}, false);
var grecaptchaFormSiteKey = "6LeteH8UAAAAAEpoZrVIE2lvLL2PUSBkRhVZvtQA";var scAppUrl = "https://app.simplycast.com/";scInitJQuery();new SaaSForm({"id":121161743,"formId":"753","type":"portable","target":"_parent","targetElement":"saasForm121161743","formHtml":"<form name=\"scForm753\" action=\"https:\/\/app.simplycast.com\/?q=forms\/submissionHandler\" target=\"_parent\" method=\"post\" enctype=\"multipart\/form-data\" style=\"height: 100%;\"><div class=\"scVerifyEmail\"><label for=\"email_again\">Email (Leave blank):<\/label><input name=\"email_again\" id=\"email_again\"\/><\/div><html> <style type=\"text\/css\"> p{ margin: 0; padding: 0; } a{ text-decoration: none; } table td { border-collapse: collapse; } .topToolItem{ z-index:1000; } <\/style> <style id=\"customStyles\" type=\"text\/css\"> <\/style> <div style=\"background-color: transparent;\"> <div class=\"body-div\" style=\"width: 350px; margin: 0px; min-width: 200px; font-size: 16px; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; font-style: normal; font-weight: 400; font-variant: normal; color: rgb(0, 0, 0); border-color: rgb(0, 0, 0); border-width: 0px; background-color: rgb(183, 214, 170); border-radius: 0px; border-style: solid; text-decoration: none;\"><table id=\"EditorRow_0\" style=\"table-layout: fixed; border-spacing: 0px; min-height: 85px; line-height: normal;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"> <tbody style=\"line-height: normal;\"><tr> <td id=\"LabelElement_0\" style=\"table-layout: fixed; overflow: hidden; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" valign=\"top\" width=\"350\"> <div style=\"padding: 5px; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\"> <span id=\"LabelElement_0_label\" class=\"label\" style=\"padding-left: 5px; display: inline-block; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\">Join Flower Farm News, our monthly email newsletter, for news of the farm, online specials, and gardening tips!<\/span> <\/div> <\/td> <\/tr> <\/tbody><\/table> <table id=\"EditorRow_1\" style=\"table-layout: fixed; border-spacing: 0px; min-height: 40px; line-height: normal;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"> <tbody style=\"line-height: normal;\"><tr> <td id=\"TextElement_0\" class=\"\" style=\"table-layout: fixed; overflow: hidden; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" valign=\"top\" width=\"350\"> <div style=\"padding: 5px; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\"> <span style=\"display: inline-block; padding: 3px; width: 90%; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" id=\"TextElement_0_label\" class=\"label\">Name<\/span> <div class=\"inputContainer\" style=\"margin-left: 3px; display: inline-block; width: 98%; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\"> <input data-chartype=\"\" class=\"input \" id=\"TextElement_0_input\" name=\"TextElement_0[value]\" maxlength=\"500\" style=\"border-radius: 3px; padding: 3px; border: 1px solid rgb(206, 206, 206); font-size: 100%; width: 98%; line-height: normal;\" value=\"\" type=\"text\"> <input style=\"line-height: normal;\" name=\"TextElement_0[label]\" value=\"Name\" type=\"hidden\"> <input style=\"line-height: normal;\" name=\"TextElement_0[type]\" value=\"Text\" type=\"hidden\"> <input style=\"line-height: normal;\" name=\"TextElement_0[column]\" value=\"Click to Edit\" type=\"hidden\"> <\/div> <div class=\"small-description\" style=\"font-size: 10px; padding: 3px; width: 99%; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" id=\"TextElement_0_description\"><\/div> <\/div> <\/td> <\/tr> <\/tbody><\/table> <table id=\"EditorRow_2\" style=\"table-layout: fixed; border-spacing: 0px; min-height: 40px; line-height: normal;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"> <tbody style=\"line-height: normal;\"><tr> <td id=\"EmailElement_0\" class=\"\" style=\"table-layout: fixed; overflow: hidden; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" valign=\"top\" width=\"350\"> <div style=\"padding: 5px; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\"> <span style=\"display: inline-block; padding: 3px; width: 90%; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" id=\"EmailElement_0_label\" class=\"label\">Email<samp style=\"color: rgb(255, 0, 0); margin-left: 4px; line-height: normal; font-family: monospace; font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\">*<\/samp><\/span> <div class=\"inputContainer\" style=\"margin-left: 3px; display: inline-block; width: 98%; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\"> <input class=\"required\" id=\"EmailElement_0_input\" name=\"EmailElement_0[value]\" style=\"border-radius: 3px; padding: 3px; border: 1px solid rgb(206, 206, 206); font-size: 100%; width: 98%; line-height: normal;\" value=\"user@example.com\" type=\"text\"> <input style=\"line-height: normal;\" name=\"EmailElement_0[label]\" value=\"Email\" type=\"hidden\"> <input style=\"line-height: normal;\" name=\"EmailElement_0[type]\" value=\"Email\" type=\"hidden\"> <input style=\"line-height: normal;\" name=\"EmailElement_0[column]\" value=\"email\" type=\"hidden\"> <\/div> <div class=\"small-description\" style=\"font-size: 10px; padding: 3px; width: 99%; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" id=\"EmailElement_0_description\"><\/div> <div class=\"errorMessage\" style=\"color: rgb(255, 0, 0); display: none; margin-left: 14px; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\">Please enter a valid email address<\/div> <\/div> <\/td> <\/tr> <\/tbody><\/table> <table id=\"EditorRow_3\" style=\"table-layout: fixed; border-spacing: 0px; min-height: 40px; line-height: normal;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"> <tbody style=\"line-height: normal;\"><tr> <td id=\"TextElement_1\" class=\"\" style=\"table-layout: fixed; overflow: hidden; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" valign=\"top\" width=\"350\"> <div style=\"padding: 5px; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\"> <span style=\"display: inline-block; padding: 3px; width: 90%; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" id=\"TextElement_1_label\" class=\"label\">Zipcode<\/span> <div class=\"inputContainer\" style=\"margin-left: 3px; display: inline-block; width: 98%; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\"> <input data-chartype=\"\" class=\"input \" id=\"TextElement_1_input\" name=\"TextElement_1[value]\" maxlength=\"500\" style=\"border-radius: 3px; padding: 3px; border: 1px solid rgb(206, 206, 206); font-size: 100%; width: 98%; line-height: normal;\" value=\"\" type=\"text\"> <input style=\"line-height: normal;\" name=\"TextElement_1[label]\" value=\"Zipcode\" type=\"hidden\"> <input style=\"line-height: normal;\" name=\"TextElement_1[type]\" value=\"Text\" type=\"hidden\"> <input style=\"line-height: normal;\" name=\"TextElement_1[column]\" value=\"Click to Edit\" type=\"hidden\"> <\/div> <div class=\"small-description\" style=\"font-size: 10px; padding: 3px; width: 99%; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" id=\"TextElement_1_description\"><\/div> <\/div> <\/td> <\/tr> <\/tbody><\/table> <table id=\"EditorRow_4\" style=\"table-layout: fixed; border-spacing: 0px; min-height: 40px; line-height: normal;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"> <tbody style=\"line-height: normal;\"><tr> <td id=\"SubmitElement_0\" style=\"table-layout: fixed; overflow: hidden; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" valign=\"top\" width=\"350\"> <div style=\"padding: 5px; text-align: left; line-height: normal; font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" class=\"submitContainer\"> <input id=\"SubmitElement_0_input\" name=\"SubmitElement_0\" class=\"submit notDefault\" value=\"Submit\" style=\"font-family: Arial,\\'DejaVu Sans\\',\\'Liberation Sans\\',Freesans,sans-serif; font-style: normal; font-variant: normal; height: 20px; border-color: rgb(0, 0, 0); border-radius: 3px; line-height: normal;\" type=\"submit\"> <\/div> <\/td> <\/tr> <\/tbody><\/table> <\/div> <div data-width=\"\" class=\"footer-div\" style=\"width: 350px; min-width: 200px; margin: 0px; font-family: Arial,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\"> <table id=\"EditorRow_5\" style=\"table-layout: fixed; border-spacing: 0px; min-height: 40px;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"> <tbody><tr> <td id=\"Footer_0\" style=\"table-layout: fixed; overflow: hidden; background-color: transparent; font-family: Arial,sans-serif; color: rgb(0, 0, 0); font-size: 16px; text-decoration: none; font-weight: 400; font-style: normal;\" valign=\"top\" width=\"350\"> <div style=\"text-align: center; padding: 0px; font-family: Arial,sans-serif; color: rgb(0, 0, 0); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\"> <a style=\"font-family: Arial,sans-serif; color: rgb(0, 0, 255); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal;\" target=\"_blank\" href=\"http:\/\/simplyca.st\/eNn5\" title=\"Email Marketing Powered By SimplyCast\"> <img style=\"font-family: Arial,sans-serif; color: rgb(0, 0, 255); font-size: 16px; background-color: transparent; text-decoration: none; font-weight: 400; font-style: normal; max-height: 68px;\" id=\"footerImage\" src=\"https:\/\/app.simplycast.com\/images\/simplycast\/powered_by_transparent.png\" alt=\"Email Marketing Powered by SimplyCast\" title=\"Powered By SimplyCast\" height=\"68\" width=\"202\"> <\/a> <\/div> <\/td> <\/tr> <\/tbody><\/table> <\/div> <\/div><\/html><input type=\"hidden\" name=\"form\" value=\"753\"><\/form>","thankYouHtml":"<center> <br\/> <p style=\"font-weight:bold; font-size:18px;\">Thank You!<\/p> <br\/> <p style=\"font-size:14px; padding:0 10px;\">Your submission has been confirmed. Please check your inbox for an email with instructions for how to opt-in.<\/p> <br\/> <button type=\"button\" style=\"min-width: 80px; padding:5px; position: relative; z-index: 0; border-radius: 3px; text-decoration: none; text-align: center; box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.3); border-collapse: separate; background-position: center; background-color:#3b5899; display:none;;\" onclick=\"saasRemoveModal(true)\"> <span style=\"margin: 2px; line-height: 10px; color:white;\">Close<\/span> <\/button> <br\/> <br\/> <\/center>","modal":{"timeoutDisplay":false,"loadAfter":"4","displayButton":false,"buttonText":"Newsletter Signup","buttonPosition":"bottomLeft","buttonColor":"rgb(108, 167, 84)","buttonTextColor":"rgb(255, 255, 255)"},"googleMaps":null,"submissionToken":"o6Q4A1NRom9uL6dNIqautj8E1F0h5PlYvSZvJ39Ql5SVMBU3K3sWoIRwPsWQc69lk"});