if (typeof(BotDetect) == "undefined") { // start single inclusion guard

  BotDetect = function(captchaId, instanceId, inputId, autoUppercaseInput, autoFocusInput, autoClearInput, autoReloadExpiredImage, autoReloadPeriod, autoReloadTimeout, soundStartDelay, limitSoundRegeneration) {
    this.Id = captchaId;
    this.InstanceId = instanceId;

    // Captcha image properties
    var imageId = captchaId + "_CaptchaImage";
    this.Image = document.getElementById(imageId);
    this.ImagePlaceholder = this.Image.parentNode;

    this.ControlsDisabled = false;

    // check for Captcha Reload icon presence
    var reloadLinkId = captchaId + "_ReloadLink";
    var reloadLink = document.getElementById(reloadLinkId);
    if (reloadLink) {
      // show Captcha Reload icon
      reloadLink.style.cssText = 'display: inline-block !important';

      // init reloading elements
      this.NewImage = null;
      this.ProgressIndicator = null;
      this.ReloadTimer = null;
      this.ReloadTimerTicks = 0;

      // Captcha image auto-reloading
      this.AutoReloadPeriod = Math.max((autoReloadPeriod - 10), 10) * 1000;
      this.AutoReloadTimeout = autoReloadTimeout * 1000;
      this.AutoReloadExpiredImage = autoReloadExpiredImage;
      this.AutoReloadPeriodSum = 0;
      this.AutoReloading = false;
      if (autoReloadExpiredImage) {
        if (this.AutoReloadTimer) { clearTimeout(this.AutoReloadTimer); }
        var self = this;
        this.AutoReloadTimer = setTimeout(
          function() {
            clearTimeout(self.AutoReloadTimer);
            if (self.AutoReloadPeriodSum >= self.AutoReloadTimeout) { self.DisableControls(); self.SessionExpired = true; return; }
            self.AutoReloading = true;
            self.ReloadImage();
            self.AutoReloading = false;
            self.AutoReloadPeriodSum += self.AutoReloadPeriod;
            self = null;
          },
          self.AutoReloadPeriod
        );
      }
    }

    // pre-load disabled reload icon
    var reloadIcon = document.getElementById(this.Id + "_ReloadIcon");
    if (reloadIcon) {
      this.ReloadIconSrc = document.getElementById(this.Id + "_ReloadIcon").src;
      this.DisabledReloadIconSrc = null;
      var preloadedReloadIcon = document.createElement('img');
      var self2 = this;
      preloadedReloadIcon.onload = function() {
        self2.DisabledReloadIconSrc = this.src;
        self2 = null;
      };
      preloadedReloadIcon.src = this.ReloadIconSrc.replace('icon', 'disabled-icon');
    }

    // Captcha sound properties
    this.SoundStartDelay = soundStartDelay;
    this.LimitSoundRegeneration = limitSoundRegeneration;
    this.SoundPlayed = false;
    this.SoundPlayDelayed = false;
    var soundLinkId = captchaId + "_SoundLink";
    var soundLink = document.getElementById(soundLinkId);
    if (soundLink) {
      this.SoundUrl = soundLink.href;
    }
    var soundPlaceholderId = captchaId + "_AudioPlaceholder";
    this.SoundPlaceholder = document.getElementById(soundPlaceholderId);

    // pre-load disabled sound icon
    var soundIcon = document.getElementById(this.Id + "_SoundIcon");
    if (soundIcon) {
      this.SoundIconSrc = document.getElementById(this.Id + "_SoundIcon").src;
      this.DisabledSoundIconSrc = null;
      var preloadedSoundIcon = document.createElement('img');
      var self3 = this;
      preloadedSoundIcon.onload = function() {
        self3.DisabledSoundIconSrc = this.src;
        self3 = null;
      };
      preloadedSoundIcon.src = this.SoundIconSrc.replace('icon', 'disabled-icon');
    }

    // Captcha input textbox properties
    this.ValidationUrl = this.Image.src.replace('get=image', 'get=validation-result');

    // Captcha help link properties
    this.FollowHelpLink = true;

    // Captcha code user input element registration, helpers & processing
    if (!inputId) return;
    this.InputId = inputId;
    var input = document.getElementById(inputId);
    if (!input) return;

    input.Captcha = this; // allow access to the BotDetect object via the input element

    // automatic input processing
    this.AutoFocusInput = autoFocusInput;
    this.AutoClearInput = autoClearInput;
    if (autoUppercaseInput) {
      input.style.textTransform = 'uppercase';
    }
  };

  BotDetect.Init = function(captchaId, instanceId, inputId, autoUppercaseInput, autoFocusInput, autoClearInput, autoReloadExpiredImage, autoReloadPeriod, autoReloadTimeout, soundStartDelay, limitSoundRegeneration) {
    var inputIdString = null;
    if (inputId) {
      inputIdString = "'" + inputId + "'";
    }

    var actualInitialization = new Function("if (document.getElementById('" + captchaId + "_CaptchaImage')) { window['" + captchaId + "'] = new BotDetect('" + captchaId + "', '" + instanceId + "', " + inputIdString + ", " + autoUppercaseInput + ", " + autoFocusInput + ", " + autoClearInput + ", " + autoReloadExpiredImage + ", " + autoReloadPeriod + ", " + autoReloadTimeout + ", " + soundStartDelay + ", " + limitSoundRegeneration + "); window['" + captchaId + "'].PostInit(); }");

    if (typeof(window.jQuery) != "undefined") {
      // jQuery initalization
      jQuery(actualInitialization);
    } else {
      // regular initialization
      BotDetect.RegisterHandler(window, 'domready', actualInitialization, false);
    }

    // back button image reload to avoid cache issues
    if (window.opera) {
      BotDetect.RegisterHandler(window, 'popstate', function (e) { window[captchaId].ReloadImage(); }, false);
    } else if (window.chrome) {
      BotDetect.RegisterHandler(window, 'domready', function (e) { var el = document.getElementById("BDC_BackWorkaround_" + captchaId); if (el.value == "0") { el.value = "1"; } else { el.value = "0"; window[captchaId].ReloadImage(); } }, false);
    } else { // firefox & safari
      BotDetect.RegisterHandler(window, 'pageshow', function (e) { var el = document.getElementById("BDC_BackWorkaround_" + captchaId); if (el.value == "0") { el.value = "1"; } else { window[captchaId].ReloadImage(); } }, false);
    }
  };


  // constants
  BotDetect.ReloadTimerMaxTicks = 100;
  BotDetect.ReloadTimerDelay = 250;
  BotDetect.MillisecondsInAMinute = 60000;
  BotDetect.AjaxTimeout = 10000;
  BotDetect.MinSoundCooldown = 2000;


  // CAPTCHA image reloading
  BotDetect.prototype.ReloadImage = function() {
    if (this.Image && !this.ReloadInProgress && !this.SessionExpired && (!this.ControlsDisabled || this.SoundPlayDelayed)) {
      this.ReloadInProgress = true;
      this.DisableControls();
      this.ProgressIndicator = document.createElement('span');
      this.ProgressIndicator.className = 'BDC_ProgressIndicator';
      this.ProgressIndicator.appendChild(document.createTextNode('.'));
      this.PreReloadImage();

      var imageUrl = BotDetect.UpdateTimestamp(this.Image.src);
      this.InitNewImage(imageUrl);

      this.ImagePlaceholder.innerHTML = '';
      this.ImagePlaceholder.appendChild(this.ProgressIndicator);

      this.ShowProgress();
    }
  };

  BotDetect.prototype.InitNewImage = function(imageUrl) {
    this.NewImage = document.createElement('img');
    var self = this;
    this.NewImage.onload = function() {
      if (self.NewImage && self.ImagePlaceholder && self.ProgressIndicator) {
        self.ImagePlaceholder.innerHTML = '';
        self.ImagePlaceholder.appendChild(self.NewImage);
        self.Image = self.NewImage;
        self.ProgressIndicator = null;
        self.PostReloadImage();
        self = null;
      }
    };
    this.NewImage.id = this.Image.id;
    this.NewImage.alt = this.Image.alt;
    this.NewImage.src = imageUrl;
  };

  BotDetect.prototype.ShowProgress = function() {
    if (this.ProgressIndicator && (this.ReloadTimerTicks < BotDetect.ReloadTimerMaxTicks)) {
      this.ReloadTimerTicks = this.ReloadTimerTicks + 1;
      this.UpdateProgressIndicator();
      var self = this;
      this.ReloadTimer = setTimeout(function() { self.ShowProgress(); self = null; }, BotDetect.ReloadTimerDelay);
    } else {
      clearTimeout(this.ReloadTimer);
      this.ReloadTimerTicks = 0;
      this.ReloadInProgress = false;
    }
  };

  BotDetect.prototype.UpdateProgressIndicator = function() {
    if (0 == this.ProgressIndicator.childNodes.length) {
      this.ProgressIndicator.appendChild(document.createTextNode('.'));
      return;
    }
    if (0 === this.ReloadTimerTicks % 5) {
      this.ProgressIndicator.firstChild.nodeValue = '.';
    } else {
      this.ProgressIndicator.firstChild.nodeValue = this.ProgressIndicator.firstChild.nodeValue + '.';
    }
  };


  // CAPTCHA sound playing
  BotDetect.prototype.PlaySound = function() {
    if (!document.getElementById || this.SoundPlayingInProgess || (this.ControlsDisabled && !this.SoundPlayDelayed)) { return; }

    this.DisableControls();
    
    if (this.LimitSoundRegeneration && !BotDetect.SoundReplaySupported()) {
      // reload the captcha image and play the new sound
      if (this.SoundPlayed) {
        this.SoundPlayDelayed = true;
        this.ReloadImage();
        return;
      }
    }

    this.SoundPlayingInProgess = true;

    if (BotDetect.UseHtml5Audio()) { // html5 audio
      var self = this;
      var sound = document.getElementById('BDC_CaptchaSoundAudio_' + this.Id);
      if (sound) { // replay existing audio, with the correct delay
        sound.currentTime = 0;

        this.SoundStartDelayTimer = setTimeout(
          function() {
            if (self) {
              clearTimeout(self.SoundStartDelayTimer);
              self.PrePlaySound();
              var sound = document.getElementById('BDC_CaptchaSoundAudio_' + self.Id);
              sound.play();
            }
          },
          this.SoundStartDelay
        );

      } else { // play new audio
        this.SoundPlaceholder.innerHTML = '';
        var soundUrl = this.SoundUrl;
        soundUrl = BotDetect.UpdateTimestamp(soundUrl);
        soundUrl = BotDetect.DetectSsl(soundUrl);
        sound = new Audio(soundUrl);
        sound.id = 'BDC_CaptchaSoundAudio_' + this.Id;
        sound.type = 'audio/wav';
        sound.autobuffer = false;
        sound.loop = false;
        sound.autoplay = false;
        sound.preload = 'auto';
        this.SoundPlaceholder.appendChild(sound);

        sound.load();
        BotDetect.RegisterHandler( // start counting the starting delay only when the sound is loaded
          sound,
          'canplay',
          function() {
            if (self) {
              self.SoundStartDelayTimer = setTimeout(
                function() {
                  clearTimeout(self.SoundStartDelayTimer);
                  self.PrePlaySound();
                  var sound = document.getElementById('BDC_CaptchaSoundAudio_' + self.Id);
                  sound.play();
                },
                self.SoundStartDelay
              );
            }
          },
          false
        );
      }

      // enable controls & other after-play cleanup
      BotDetect.RegisterHandler(
        sound,
        'ended',
        function() {
          if (self) {
            var sound = document.getElementById('BDC_CaptchaSoundAudio_' + self.Id);
            if (sound.duration == 1) { // Android 4.0.4 issue
              sound.play();
            } else {
              self.SoundPlayingInProgess = false;
              self.EnableControls();
              self = null;
            }
          }
        },
        false
      );

    } else { // xhtml embed + object
      this.SoundPlaceholder.innerHTML = '';
      var self = this;
      this.SoundStartDelayTimer = setTimeout(
        function() {
          clearTimeout(self.SoundStartDelayTimer);
          self.PrePlaySound();
          self.StartXhtmlSoundPlayback();
        },
        this.SoundStartDelay
      );
    }

    this.SoundPlayed = true;
  };


  BotDetect.prototype.StartXhtmlSoundPlayback = function() {
    var soundUrl = this.SoundUrl;
    soundUrl = BotDetect.UpdateTimestamp(soundUrl);
    soundUrl = BotDetect.DetectSsl(soundUrl);

    var objectSrc = "<object id='BDC_CaptchaSoundObject_" + this.Id + "' classid='clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95' height='0' width='0' style='width:0; height:0;'><param name='AutoStart' value='1' /><param name='Volume' value='0' /><param name='PlayCount' value='1' /><param name='FileName' value='" + soundUrl + "' /><embed id='BDC_CaptchaSoundEmbed' src='" + soundUrl + "' autoplay='true' hidden='true' volume='100' type='" + BotDetect.GetMimeType() + "' style='display:inline;' /></object>";

    this.SoundPlaceholder.innerHTML = objectSrc;

    var self = this;
    this.SoundCooldownTimer = setTimeout(
      function() {
        if (self) {
          clearTimeout(self.SoundCooldownTimer);
          self.SoundPlayingInProgess = false;
          self.EnableControls();
          self = null;
        }
      },
      BotDetect.MinSoundCooldown
    );
  };


  // input element access
  BotDetect.prototype.GetInputElement = function() {
    return document.getElementById(this.InputId);
  };

  // CAPTCHA Ajax validation
  BotDetect.prototype.StartAjaxValidation = function() {
    this.PreAjaxValidate();
    if (BotDetect.AjaxError) { return; }
    var input = this.GetInputElement();
    if (!input || !input.value || input.value.length < 0) {
      this.AjaxValidationFailed();
      return;
    }
    this.StartValidationRequest();
  };

  BotDetect.prototype.StartValidationRequest = function() {
    var input = this.GetInputElement();
    var url = this.ValidationUrl + '&i=' + input.value;
    var self = this;
    var callback = function(y) {
      clearTimeout(self.AjaxTimer);
      if (200 != y.status) { self.AjaxValidationError(); self = null; return; }
      var validationResult = false;
      var parsed = BotDetect.ParseJson(y.responseText);
      if (parsed) {
        validationResult = parsed;
      }
      self.EndValidationRequest(validationResult);
      self = null;
    }
    this.AjaxTimer = setTimeout(self.AjaxValidationError, BotDetect.AjaxTimeout);
    BotDetect.Get(url, callback);
  };

  BotDetect.prototype.EndValidationRequest = function(result) {
    if (result) {
      this.AjaxValidationPassed();
    } else {
      this.AjaxValidationFailed();
    }
  };

  BotDetect.ParseJson = function(jsonString) {
    var resultObj = null;
    if ("undefined" != typeof(JSON) && "function" == typeof(JSON.parse)) {
      resultObj = JSON.parse(jsonString);
    }
    if (!resultObj) {
      resultObj = eval('(' + jsonString + ')');
    }
    return resultObj;
  };


  // custom CAPTCHA events

  BotDetect.prototype.PostInit = function() {
  };

  BotDetect.prototype.PreReloadImage = function() {
    this.ClearInput();
    this.FocusInput();
  };

  BotDetect.prototype.PostReloadImage = function() {
    this.ValidationUrl = this.Image.src.replace('get=image', 'get=validation-result');

    if (this.AutoReloadExpiredImage) {
      if (this.AutoReloadTimer) { clearTimeout(this.AutoReloadTimer); }
      var self = this;
      this.AutoReloadTimer = setTimeout(
        function() {
          clearTimeout(self.AutoReloadTimer);
          if (self.AutoReloadPeriodSum >= self.AutoReloadTimeout) { self.DisableControls(); self.SessionExpired = true; return; }
          self.AutoReloading = true;
          self.ReloadImage();
          self.AutoReloading = false;
          self.AutoReloadPeriodSum += self.AutoReloadPeriod;
          self = null;
        },
        self.AutoReloadPeriod
      );
    }

    if (this.SoundIconSrc) {
      this.SoundPlaceholder.innerHTML = '';
      this.SoundPlayed = false;
      if (this.SoundPlayDelayed) {
        this.PlaySound();
        this.SoundPlayDelayed = false;
      } else {
        this.EnableControls();
      }
    } else {
      this.EnableControls();
    }
  };

  BotDetect.prototype.PrePlaySound = function() {
    this.FocusInput();
  };

  BotDetect.prototype.OnHelpLinkClick = function() {
  };

  BotDetect.prototype.PreAjaxValidate = function() {
  };

  BotDetect.prototype.AjaxValidationFailed = function() {
    this.ReloadImage();
  };

  BotDetect.prototype.AjaxValidationPassed = function() {
  };

  BotDetect.prototype.AjaxValidationError = function() {
    BotDetect.Xhr().abort();
    BotDetect.AjaxError = true;
  };

  BotDetect.RegisterCustomHandler = function(eventName, userHandler) {
    var oldHandler = BotDetect.prototype[eventName];
    BotDetect.prototype[eventName] = function() {
      userHandler.call(this);
      oldHandler.call(this);
    }
  };

  // input processing
  BotDetect.prototype.FocusInput = function() {
    var input = this.GetInputElement();
    if (!this.AutoFocusInput || !input) return;
    if (this.AutoReloading) return;
    input.focus();
  };

  BotDetect.prototype.ClearInput = function() {
    var input = this.GetInputElement();
    if (!this.AutoClearInput || !input) return;
    input.value = '';
  };


  // helpers

  BotDetect.UpdateTimestamp = function(url) {
    var i = url.indexOf('&d=');
    if (-1 !== i) {
      url = url.substring(0, i);
    }
    return url + '&d=' + BotDetect.GetTimestamp();
  };

  BotDetect.GetTimestamp = function() {
    var d = new Date();
    var t = d.getTime() + (d.getTimezoneOffset() * BotDetect.MillisecondsInAMinute);
    return t;
  };

  BotDetect.DetectSsl = function(url) {
    var i = url.indexOf('&e=');
    if(-1 !== i) {
      var len = url.length;
      url = url.substring(0, i) + url.substring(i+4, len);
    }
    if (document.location.protocol === "https:") {
      url = url + '&e=1';
    }
    return url;
  };

  BotDetect.GetMimeType = function() {
    var mimeType = "audio/x-wav";
    return mimeType;
  };

  BotDetect.UseHtml5Audio = function() {
    var html5SoundSupported = false;
    if (BotDetect.DetectAndroid() || BotDetect.DetectIOS()) {
      html5SoundSupported = true;  // Android says it can't play audio even when it can; assuming iOS uses Html5 simplifies further browser checks
    } else {
      var browserCompatibilityCheck = document.createElement('audio');
      html5SoundSupported = (
        !!(browserCompatibilityCheck.canPlayType) &&
        !!(browserCompatibilityCheck.canPlayType("audio/wav")) &&
        !BotDetect.DetectIncompatibleAudio() // some browsers say they support the audio even when they have issues playing it
      );
    }
    return html5SoundSupported;
  };

  BotDetect.DetectIncompatibleAudio = function() {
    return BotDetect.DetectFirefox3() || BotDetect.DetectSafariSsl();
  };

  BotDetect.DetectAndroid = function() {
    var detected = false;
    if (navigator && navigator.userAgent) {
      var matches = navigator.userAgent.match(/Linux; U; Android/);
      if (matches) {
        detected = true;
      }
    }
    return detected;
  };

  BotDetect.DetectIOS = function() {
    var detected = false;
    if (navigator && navigator.userAgent) {
      var matches = navigator.userAgent.match(/like Mac OS/);
      if (matches) {
        detected = true;
      }
    }
    return detected;
  };

  BotDetect.DetectFirefox3 = function() {
    var detected = false;
    if (navigator && navigator.userAgent) {
      var matches = navigator.userAgent.match(/(Firefox)\/(3\.6\.[^;\+,\/\s]+)/);
      if (matches) {
        detected = true;
      }
    }
    return detected;
  };

  BotDetect.DetectSafariSsl = function() {
    var detected = false;
    if (navigator && navigator.userAgent) {
      var matches = navigator.userAgent.match(/Safari/);
      if (matches) {
        matches = navigator.userAgent.match(/Chrome/);
        if (!matches && document.location.protocol === "https:") {
          detected = true;
        }
      }
    }
    return detected;
  };

  BotDetect.DetectAndroidBelow41 = function() {
    var detected = false;
    if (navigator && navigator.userAgent) {
      var i = navigator.userAgent.indexOf("Android");
      if (i >= 0) {
        var v = parseFloat(navigator.userAgent.slice(i+8));
        if (v < 4.1) {
         detected = true;
        }
      }
    }
    return detected;
  }

  BotDetect.SoundReplaySupported = function() {
    return (BotDetect.UseHtml5Audio() &&
                !BotDetect.DetectAndroidBelow41());
  };

  BotDetect.prototype.DisableControls = function() {
    this.ControlsDisabled = true;
    this.DisableReloadIcon();
    this.DisableSoundIcon();
  }

  BotDetect.prototype.EnableControls = function() {
    this.ControlsDisabled = false;
    this.EnableReloadIcon();
    this.EnableSoundIcon();
  }

  BotDetect.prototype.DisableReloadIcon = function() {
    if (this.ReloadIconSrc) {
       if (this.DisabledReloadIconSrc) {
        document.getElementById(this.Id + "_ReloadIcon").src = this.DisabledReloadIconSrc;
      }
    }
  };

  BotDetect.prototype.EnableReloadIcon = function() {
    if (this.ReloadIconSrc) {
      if (this.DisabledReloadIconSrc) {
        document.getElementById(this.Id + "_ReloadIcon").src = this.ReloadIconSrc;
      }
    }
  };

  BotDetect.prototype.DisableSoundIcon = function() {
    if (this.SoundIconSrc) {
       if (this.DisabledSoundIconSrc) {
        document.getElementById(this.Id + "_SoundIcon").src = this.DisabledSoundIconSrc;
      }
    }
  };

  BotDetect.prototype.EnableSoundIcon = function() {
    if (this.SoundIconSrc) {
      if (this.DisabledSoundIconSrc) {
        document.getElementById(this.Id + "_SoundIcon").src = this.SoundIconSrc;
      }
    }
  };

  // standard events & handlers
  BotDetect.RegisterHandler = function(target, eventType, functionRef, capture) {
    // special case
    if (eventType == "domready") {
      BotDetect.RegisterDomReadyHandler(functionRef);
      return;
    }
    // normal event registration
    if (typeof target.addEventListener != "undefined") {
      target.addEventListener(eventType, functionRef, capture);
    } else if (typeof target.attachEvent != "undefined") {
      var functionString = eventType + functionRef;
      target["e" + functionString] = functionRef;
      target[functionString] = function(event) {
        if (typeof event == "undefined") {
          event = window.event;
        }
        target["e" + functionString](event);
      };
      target.attachEvent("on" + eventType, target[functionString]);
    } else {
      eventType = "on" + eventType;
      if (typeof target[eventType] == "function") {
        var oldListener = target[eventType];
        target[eventType] = function() {
          oldListener();
          return functionRef();
        };
      } else {
        target[eventType] = functionRef;
      }
    }
  };

  // earlier than window.load, if possible
  BotDetect.RegisterDomReadyHandler = function(functionRef) {
    if (document.addEventListener) {
      document.addEventListener("DOMContentLoaded",
        function(){
          document.removeEventListener("DOMContentLoaded", arguments.callee, false);
          functionRef();
        },
        false
      );
      return;
    }
    else if (document.attachEvent) {
      var called = false;
      document.attachEvent("onreadystatechange",
        function(){
          if (document.readyState === "complete") {
            document.detachEvent("onreadystatechange", arguments.callee);
            functionRef();
            called = true;
          }
        }
      );
      if (document.documentElement.doScroll && window == window.top) {
        (function() {
          if (called) return;
          try {
            document.documentElement.doScroll("left");
          } catch (error) {
            setTimeout(arguments.callee, 1);
            return;
          }
          functionRef();
          called = true;
        })();
      }
      return;
    } else {
      BotDetect.RegisterHandler(window, 'load', functionRef, false);
    }
  };


  // Ajax helper
  BotDetect.Xhr = function() {
    var x = null;
    try { x = new XMLHttpRequest(); return x; } catch (e) {}
    try { x = new ActiveXObject('MSXML2.XMLHTTP.5.0'); return x; } catch (e) {}
    try { x = new ActiveXObject('MSXML2.XMLHTTP.4.0'); return x; } catch (e) {}
    try { x = new ActiveXObject('MSXML2.XMLHTTP.3.0'); return x; } catch (e) {}
    try { x = new ActiveXObject('MSXML2.XMLHTTP'); return x; } catch (e) {}
    try { x = new ActiveXObject('Microsoft.XMLHTTP'); return x; } catch (e) {}
    return x;
  };

  BotDetect.Get = function(url, callback) {
    BotDetect.AjaxError = false;
    var x = BotDetect.Xhr();
    if (x && 0 == x.readyState) {
      x.onreadystatechange = function() {
        if(4 == x.readyState) {
          callback(x);
        }
      }
      x.open('GET', url, true);
      x.send();
    }
  };

} // end single inclusion guard