Skip to content

DigitalA11Y

Your Accessibility Partner

  • Home
  • ServicesExpand
    • WCAG Audit Services
    • VPAT/ACR Services
    • Accessibility Consulting
    • PDF Remediation
    • Accessibility Trainings
    • Website Remediation
    • Design Audit
  • Free ToolsExpand
    • Accessibility Checker
    • A11Y Cost Calculator
    • A11Y Bookmarklets
    • Color Contrast Extension
    • WCAG Contrast Checker
  • ResourcesExpand
    • A11Y Articles
    • WCAG Primer
    • ARIA Cheatsheet
    • A11Y Tools
    • A11Y Patterns
    • A11Y Cheatsheets
  • Contact
Search
DigitalA11Y
Your Accessibility Partner
Search

Datepicker with Radio Buttons


Available dates
Provides datepicker upon clicking or arrow keys usage

Code

  • HTML
  • CSS
  • JavaScript
<button href="#" id="before">Focusable element before</button>
<form>
  <div data-adg-datepicker="">
    <div class="control"><br>
      <label for="birthday">Birthday </label><input aria-describedby="birthday_help" id="birthday" type="text" />
      <fieldset hidden="">
        <legend>Available dates</legend>
      </fieldset>
      <div class="description" id="birthday_help">
        Provides datepicker upon clicking or arrow keys usage
      </div>
    </div>
  </div>
</form>
<button href="#" id="after">Focusable element after</button>
@charset "UTF-8";
.adg-visually-hidden {
  position: absolute;
  white-space: nowrap;
  width: 1px;
  height: 1px;
  overflow: hidden;
  border: 0;
  padding: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  margin: -1px;
}

[data-adg-datepicker] {
  position: relative;
}

[data-adg-datepicker-options] {
  position: absolute;
  float: left;
  background-color: lightyellow;
  border: 1px solid;
  padding: 5px 0;
}

[data-adg-datepicker-option] {
  display: block;
}

[data-adg-datepicker-option]:hover,
[data-adg-datepicker-option-selected] {
  cursor: pointer;
  outline: 1px solid;
}

[data-adg-datepicker-alerts] p {
  margin: 0;
}
[data-adg-datepicker-alerts] kbd::before {
  content: "«";
}
[data-adg-datepicker-alerts] kbd::after {
  content: "»";
}

.control {
  margin: 6px 0;
}

input[type=text] {
  width: 140px;
}

label {
  display: inline-block;
  width: 120px;
  vertical-align: top;
}

.description {
  margin-left: 120px;
}

fieldset {
  margin: -1px 0 0 120px;
}
fieldset .control {
  margin: 0;
}
fieldset label {
  width: 100%;
}
(function() {
  var AdgDatepicker;

  AdgDatepicker = (function() {
    var config;

    class AdgDatepicker {
      constructor(el, options = {}) {
        this.$el = $(el);
        this.config = config;
        this.currentDate = this.config["date"];
        this.initInput();
        this.initOptions();
        this.applyCheckedOptionToInput();
      }

      // Executes the given selector on @$el and returns the element. Makes sure exactly one element exists.
      findOne(selector) {
        var result;
        result = this.$el.find(selector);
        switch (result.length) {
          case 0:
            return this.throwMessageAndPrintObjectsToConsole(`No object found for ${selector}!`, {
              result: result
            });
          case 1:
            return $(result.first());
          default:
            return this.throwMessageAndPrintObjectsToConsole(`More than one object found for ${selector}!`, {
              result: result
            });
        }
      }

      name() {
        return "adg-datepicker";
      }

      addAdgDataAttribute($target, name, value = '') {
        return $target.attr(this.adgDataAttributeName(name), value);
      }

      removeAdgDataAttribute($target, name) {
        return $target.removeAttr(this.adgDataAttributeName(name));
      }

      adgDataAttributeName(name = null) {
        var result;
        result = `data-${this.name()}`;
        if (name) {
          result += `-${name}`;
        }
        return result;
      }

      labelOfInput($inputs) {
        return $inputs.map((i, input) => {
          var $input, $label, id;
          $input = $(input);
          id = $input.attr('id');
          $label = this.findOne(`label[for='${id}']`)[0];
          if ($label.length === 0) {
            $label = $input.closest('label');
            if ($label.length === 0) {
              this.throwMessageAndPrintObjectsToConsole("No corresponding input found for input!", {
                input: $input
              });
            }
          }
          return $label;
        });
      }

      show($el) {
        $el.removeAttr('hidden');
        return $el.show();
      }

      // TODO Would be cool to renounce CSS and solely use the hidden attribute. But jQuery's :visible doesn't seem to work with it!?
      // @throwMessageAndPrintObjectsToConsole("Element is still hidden, although hidden attribute was removed! Make sure there's no CSS like display:none or visibility:hidden left on it!", element: $el) if $el.is(':hidden')
      hide($el) {
        $el.attr('hidden', '');
        return $el.hide();
      }

      throwMessageAndPrintObjectsToConsole(message, elements = {}) {
        console.log(elements);
        throw message;
      }

      text(text, options = {}) {
        var key, value;
        text = this.config[`${text}Text`];
        for (key in options) {
          value = options[key];
          text = text.replace(`[${key}]`, value);
        }
        return text;
      }

      initInput() {
        this.$input = this.findOne('input[type="text"]');
        this.$input.attr('autocomplete', 'off');
        this.$input.attr('aria-expanded', 'false');
        return this.attachInputEvents();
      }

      initOptions() {
        this.$optionsContainer = this.findOne('fieldset');
        this.addAdgDataAttribute(this.$optionsContainer, 'options');
        this.$optionsContainerLabel = this.findOne('legend');
        this.$optionsContainerLabel.addClass('adg-visually-hidden');
        this.initDate();
        return this.setSelection(this.currentDate.getDate() - 1, false);
      }

      getFirstMonthDay(date) {
        var m, y;
        y = date.getFullYear();
        m = date.getMonth();
        return new Date(y, m, 1);
      }

      getLastMonthDay(date) {
        var m, y;
        y = date.getFullYear();
        m = date.getMonth();
        return new Date(y, m + 1, 0);
      }

      initDate() {
        var $dateTable, $tr, day, daysOfMonth, firstDay, i, id, j, k, lastDay, len, len1, ref, value, weekday;
        this.$optionsContainer.find("table").remove();
        $dateTable = $(`<table border='1'><caption>${this.config["monthNames"][this.currentDate.getMonth()]} ${this.currentDate.getFullYear()}</caption><thead></thead></table>`);
        ref = this.config["dayNames"];
        for (j = 0, len = ref.length; j < len; j++) {
          weekday = ref[j];
          $dateTable.find("thead").append(`<th>${weekday}</th>`);
        }
        this.$optionsContainer.append($dateTable);
        firstDay = this.getFirstMonthDay(this.currentDate);
        lastDay = this.getLastMonthDay(this.currentDate);
        daysOfMonth = [];
        day = firstDay;
        while (day <= lastDay) {
          daysOfMonth.push(new Date(day));
          day.setDate(day.getDate() + 1);
        }
        
        // Add empty days at beginning
        i = 1;
        firstDay = daysOfMonth[0].getDay();
        while (i < firstDay) {
          daysOfMonth.unshift(null);
          i++;
        }
        
        // Add empty days at end
        i = daysOfMonth[daysOfMonth.length - 1].getDay();
        while (i > 0 && i < 6) {
          daysOfMonth.push(null);
          i++;
        }
        $tr = null;
        for (i = k = 0, len1 = daysOfMonth.length; k < len1; i = ++k) {
          day = daysOfMonth[i];
          if (i % 7 === 0) {
            $tr = $("<tr></tr>");
            $dateTable.append($tr);
          }
          value = day ? (id = `favorite_hobby_${i}`, `<input type='radio' name='hobby' id='${id}' /><label for='${id}'><span class='adg-visually-hidden'>${this.getDayName(day.getDay())}, </span>${day.getDate()}<span class='adg-visually-hidden'> of ${this.config['monthNames'][day.getMonth()]} ${day.getFullYear()}</span></label>`) : "";
          $tr.append(`<td class='control'>${value}</td>`);
        }
        this.$options = this.$optionsContainer.find('input[type="radio"]');
        this.attachOptionsEvents();
        this.addAdgDataAttribute(this.labelOfInput(this.$options), 'option');
        return this.$options.addClass('adg-visually-hidden');
      }

      getDayName(day) {
        if (day === 0) {
          day = 6;
        }
        return this.config['dayNames'][day - 1];
      }

      attachInputEvents() {
        this.attachClickEventToInput();
        this.attachEscapeKeyToInput();
        this.attachEnterKeyToInput();
        this.attachTabKeyToInput();
        return this.attachUpDownKeysToInput();
      }

      attachOptionsEvents() {
        this.attachArrowKeysToOptions();
        this.attachChangeEventToOptions();
        this.attachClickEventToOptionLabels();
        this.attachEnterEventToOptions();
        return this.attachTabEventToOptions();
      }

      attachClickEventToInput() {
        return this.$input.click(() => {
          if (this.$optionsContainer.is(':visible')) {
            return this.hideOptions();
          } else {
            return this.showOptions();
          }
        });
      }

      attachEscapeKeyToInput() {
        return this.$input.keydown((e) => {
          if (e.which === 27) {
            if (this.$optionsContainer.is(':visible')) {
              this.applyCheckedOptionToInputAndResetOptions();
              return e.preventDefault();
            } else if (this.$options.is(':checked')) {
              this.$options.prop('checked', false);
              this.applyCheckedOptionToInputAndResetOptions();
              return e.preventDefault(); // Needed for automatic testing only
            } else {
              return $('body').append('<p>Esc passed on.</p>');
            }
          }
        });
      }

      attachEnterKeyToInput() {
        return this.$input.keydown((e) => {
          if (e.which === 13) {
            if (this.$optionsContainer.is(':visible')) {
              this.applyCheckedOptionToInputAndResetOptions();
              return e.preventDefault(); // Needed for automatic testing only
            } else {
              return $('body').append('<p>Enter passed on.</p>');
            }
          }
        });
      }

      attachTabKeyToInput() {
        return this.$input.keydown((e) => {
          if (e.which === 9) {
            if (this.$optionsContainer.is(':visible')) {
              return this.applyCheckedOptionToInputAndResetOptions();
            }
          }
        });
      }

      attachUpDownKeysToInput() {
        return this.$input.keydown((e) => {
          if (e.which === 38 || e.which === 40) {
            this.showOptions();
            return e.preventDefault(); // TODO: Test!
          }
        });
      }

      showOptions() {
        this.show(this.$optionsContainer);
        this.$input.attr('aria-expanded', 'true');
        if (this.$options.filter(':checked').length === 0) {
          this.currentDate = this.config["date"];
          this.initDate();
          this.setSelection(this.currentDate.getDate() - 1);
        }
        return this.$options.filter(':checked').focus();
      }

      hideOptions() {
        this.hide(this.$optionsContainer);
        this.$input.attr('aria-expanded', 'false');
        return this.$input.focus();
      }

      moveSelection(direction) {
        var currentIndex, maxIndex, upcomingIndex;
        maxIndex = this.$options.length - 1;
        currentIndex = this.$options.index(this.$options.parent().find(':checked')); // TODO: is parent() good here?!
        upcomingIndex = direction === 'left' ? currentIndex <= 0 ? (this.currentDate = this.previousMonth(this.currentDate), this.initDate(), -1) : currentIndex - 1 : direction === 'up' ? currentIndex - 7 < 0 ? (this.currentDate = this.previousMonth(this.currentDate), this.initDate(), -1) : currentIndex - 7 : direction === 'right' ? currentIndex === maxIndex ? (this.currentDate = this.nextMonth(this.currentDate), this.initDate(), 0) : currentIndex + 1 : direction === 'down' ? currentIndex + 7 > maxIndex ? (this.currentDate = this.nextMonth(this.currentDate), this.initDate(), 0) : currentIndex + 7 : void 0; // TODO: Calculate index for the current week day // TODO: Calculate index for the current week day
        return this.setSelection(upcomingIndex);
      }

      setSelection(current, change = true) {
        var $currentOption;
        if (current === -1) {
          current = this.$options.length - 1;
        }
        $currentOption = $(this.$options[current]);
        $currentOption.prop('checked', true);
        if (change) {
          $currentOption.trigger('change');
          return $currentOption.focus();
        }
      }

      previousMonth(now) {
        if (now.getMonth() === 0) {
          return new Date(now.getFullYear() - 1, 11, 1);
        } else {
          return new Date(now.getFullYear(), now.getMonth() - 1, 1);
        }
      }

      nextMonth(now) {
        if (now.getMonth() === 11) {
          return new Date(now.getFullYear() + 1, 11, 1);
        } else {
          return new Date(now.getFullYear(), now.getMonth() + 1, 1);
        }
      }

      attachArrowKeysToOptions() {
        return this.$options.keydown((e) => {
          if (e.which === 37 || e.which === 38 || e.which === 39 || e.which === 40) {
            if (e.which === 37) {
              this.moveSelection('left');
            } else if (e.which === 38) {
              this.moveSelection('up');
            } else if (e.which === 39) {
              this.moveSelection('right');
            } else if (e.which === 40) {
              this.moveSelection('down');
            }
            return e.preventDefault(); // TODO: Test!
          }
        });
      }

      attachChangeEventToOptions() {
        return this.$options.change((e) => {
          return this.applyCheckedOptionToInput();
        });
      }

      applyCheckedOptionToInputAndResetOptions() {
        this.applyCheckedOptionToInput();
        return this.hideOptions();
      }

      applyCheckedOptionToInput() {
        var $checkedOption, $checkedOptionLabel, $previouslyCheckedOptionLabel;
        $previouslyCheckedOptionLabel = $(`[${this.adgDataAttributeName('option-selected')}]`);
        if ($previouslyCheckedOptionLabel.length === 1) {
          this.removeAdgDataAttribute($previouslyCheckedOptionLabel, 'option-selected');
        }
        $checkedOption = this.$options.filter(':checked');
        if ($checkedOption.length === 1) {
          $checkedOptionLabel = this.labelOfInput($checkedOption);
          this.$input.val($.trim($checkedOptionLabel.text()));
          return this.addAdgDataAttribute($checkedOptionLabel, 'option-selected');
        } else {
          return this.$input.val('');
        }
      }

      attachClickEventToOptionLabels() {
        return this.labelOfInput(this.$options).click((e) => {
          return this.hideOptions();
        });
      }

      attachEnterEventToOptions() {
        return this.$options.keydown((e) => {
          if (e.which === 13) {
            this.hideOptions();
            e.preventDefault();
            return e.stopPropagation();
          }
        });
      }

      attachTabEventToOptions() {
        return this.$options.keydown((e) => {
          if (e.which === 9) {
            return this.hideOptions();
          }
        });
      }

    };

    config = {
      date: new Date(),
      dayNames: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
      monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
    };

    return AdgDatepicker;

  }).call(this);

  $(document).ready(function() {
    return $('[data-adg-datepicker]').each(function() {
      return new AdgDatepicker(this);
    });
  });

}).call(this);

//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiPGFub255bW91cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFBQSxNQUFBOztFQUFNOzs7SUFBTixNQUFBLGNBQUE7TUFNRSxXQUFhLENBQUMsRUFBRCxFQUFLLFVBQVUsQ0FBQSxDQUFmLENBQUE7UUFDWCxJQUFDLENBQUEsR0FBRCxHQUFPLENBQUEsQ0FBRSxFQUFGO1FBQ1AsSUFBQyxDQUFBLE1BQUQsR0FBVTtRQUVWLElBQUMsQ0FBQSxXQUFELEdBQWUsSUFBQyxDQUFBLE1BQU0sQ0FBQyxNQUFEO1FBRXRCLElBQUMsQ0FBQSxTQUFELENBQUE7UUFDQSxJQUFDLENBQUEsV0FBRCxDQUFBO1FBRUEsSUFBQyxDQUFBLHlCQUFELENBQUE7TUFUVyxDQUxmOzs7TUFpQkUsT0FBUyxDQUFDLFFBQUQsQ0FBQTtBQUNYLFlBQUE7UUFBSSxNQUFBLEdBQVMsSUFBQyxDQUFBLEdBQUcsQ0FBQyxJQUFMLENBQVUsUUFBVjtBQUNULGdCQUFPLE1BQU0sQ0FBQyxNQUFkO0FBQUEsZUFDTyxDQURQO21CQUNjLElBQUMsQ0FBQSxvQ0FBRCxDQUFzQyxDQUFBLG9CQUFBLENBQUEsQ0FBdUIsUUFBdkIsQ0FBQSxDQUFBLENBQXRDLEVBQTBFO2NBQUEsTUFBQSxFQUFRO1lBQVIsQ0FBMUU7QUFEZCxlQUVPLENBRlA7bUJBRWMsQ0FBQSxDQUFFLE1BQU0sQ0FBQyxLQUFQLENBQUEsQ0FBRjtBQUZkO21CQUdPLElBQUMsQ0FBQSxvQ0FBRCxDQUFzQyxDQUFBLCtCQUFBLENBQUEsQ0FBa0MsUUFBbEMsQ0FBQSxDQUFBLENBQXRDLEVBQXFGO2NBQUEsTUFBQSxFQUFRO1lBQVIsQ0FBckY7QUFIUDtNQUZPOztNQU9ULElBQU0sQ0FBQSxDQUFBO2VBQ0o7TUFESTs7TUFHTixtQkFBcUIsQ0FBQyxPQUFELEVBQVUsSUFBVixFQUFnQixRQUFRLEVBQXhCLENBQUE7ZUFDbkIsT0FBTyxDQUFDLElBQVIsQ0FBYSxJQUFDLENBQUEsb0JBQUQsQ0FBc0IsSUFBdEIsQ0FBYixFQUEwQyxLQUExQztNQURtQjs7TUFHckIsc0JBQXdCLENBQUMsT0FBRCxFQUFVLElBQVYsQ0FBQTtlQUN0QixPQUFPLENBQUMsVUFBUixDQUFtQixJQUFDLENBQUEsb0JBQUQsQ0FBc0IsSUFBdEIsQ0FBbkI7TUFEc0I7O01BR3hCLG9CQUFzQixDQUFDLE9BQU8sSUFBUixDQUFBO0FBQ3hCLFlBQUE7UUFBSSxNQUFBLEdBQVMsQ0FBQSxLQUFBLENBQUEsQ0FBUSxJQUFDLENBQUEsSUFBRCxDQUFBLENBQVIsQ0FBQTtRQUNULElBQXdCLElBQXhCO1VBQUEsTUFBQSxJQUFVLENBQUEsQ0FBQSxDQUFBLENBQUksSUFBSixDQUFBLEVBQVY7O2VBQ0E7TUFIb0I7O01BS3RCLFlBQWMsQ0FBQyxPQUFELENBQUE7ZUFDWixPQUFPLENBQUMsR0FBUixDQUFZLENBQUMsQ0FBRCxFQUFJLEtBQUosQ0FBQSxHQUFBO0FBQ2hCLGNBQUEsTUFBQSxFQUFBLE1BQUEsRUFBQTtVQUFNLE1BQUEsR0FBUyxDQUFBLENBQUUsS0FBRjtVQUVULEVBQUEsR0FBSyxNQUFNLENBQUMsSUFBUCxDQUFZLElBQVo7VUFDTCxNQUFBLEdBQVMsSUFBQyxDQUFBLE9BQUQsQ0FBUyxDQUFBLFdBQUEsQ0FBQSxDQUFjLEVBQWQsQ0FBQSxFQUFBLENBQVQsQ0FBOEIsQ0FBQyxDQUFEO1VBRXZDLElBQUcsTUFBTSxDQUFDLE1BQVAsS0FBaUIsQ0FBcEI7WUFDRSxNQUFBLEdBQVMsTUFBTSxDQUFDLE9BQVAsQ0FBZSxPQUFmO1lBQ1QsSUFBa0csTUFBTSxDQUFDLE1BQVAsS0FBaUIsQ0FBbkg7Y0FBQSxJQUFDLENBQUEsb0NBQUQsQ0FBc0MseUNBQXRDLEVBQWlGO2dCQUFBLEtBQUEsRUFBTztjQUFQLENBQWpGLEVBQUE7YUFGRjs7aUJBSUE7UUFWVSxDQUFaO01BRFk7O01BYWQsSUFBTSxDQUFDLEdBQUQsQ0FBQTtRQUNKLEdBQUcsQ0FBQyxVQUFKLENBQWUsUUFBZjtlQUNBLEdBQUcsQ0FBQyxJQUFKLENBQUE7TUFGSSxDQW5EUjs7OztNQTBERSxJQUFNLENBQUMsR0FBRCxDQUFBO1FBQ0osR0FBRyxDQUFDLElBQUosQ0FBUyxRQUFULEVBQW1CLEVBQW5CO2VBQ0EsR0FBRyxDQUFDLElBQUosQ0FBQTtNQUZJOztNQUlOLG9DQUFzQyxDQUFDLE9BQUQsRUFBVSxXQUFXLENBQUEsQ0FBckIsQ0FBQTtRQUNwQyxPQUFPLENBQUMsR0FBUixDQUFZLFFBQVo7UUFDQSxNQUFNO01BRjhCOztNQUl0QyxJQUFNLENBQUMsSUFBRCxFQUFPLFVBQVUsQ0FBQSxDQUFqQixDQUFBO0FBQ1IsWUFBQSxHQUFBLEVBQUE7UUFBSSxJQUFBLEdBQU8sSUFBQyxDQUFBLE1BQU0sQ0FBQyxDQUFBLENBQUEsQ0FBRyxJQUFILENBQUEsSUFBQSxDQUFEO1FBRWQsS0FBQSxjQUFBOztVQUNFLElBQUEsR0FBTyxJQUFJLENBQUMsT0FBTCxDQUFhLENBQUEsQ0FBQSxDQUFBLENBQUksR0FBSixDQUFBLENBQUEsQ0FBYixFQUF5QixLQUF6QjtRQURUO2VBR0E7TUFOSTs7TUFRTixTQUFXLENBQUEsQ0FBQTtRQUNULElBQUMsQ0FBQSxNQUFELEdBQVUsSUFBQyxDQUFBLE9BQUQsQ0FBUyxvQkFBVDtRQUNWLElBQUMsQ0FBQSxNQUFNLENBQUMsSUFBUixDQUFhLGNBQWIsRUFBNkIsS0FBN0I7UUFDQSxJQUFDLENBQUEsTUFBTSxDQUFDLElBQVIsQ0FBYSxlQUFiLEVBQThCLE9BQTlCO2VBQ0EsSUFBQyxDQUFBLGlCQUFELENBQUE7TUFKUzs7TUFNWCxXQUFhLENBQUEsQ0FBQTtRQUNYLElBQUMsQ0FBQSxpQkFBRCxHQUFxQixJQUFDLENBQUEsT0FBRCxDQUFTLFVBQVQ7UUFDckIsSUFBQyxDQUFBLG1CQUFELENBQXFCLElBQUMsQ0FBQSxpQkFBdEIsRUFBeUMsU0FBekM7UUFFQSxJQUFDLENBQUEsc0JBQUQsR0FBMEIsSUFBQyxDQUFBLE9BQUQsQ0FBUyxRQUFUO1FBQzFCLElBQUMsQ0FBQSxzQkFBc0IsQ0FBQyxRQUF4QixDQUFpQyxxQkFBakM7UUFFQSxJQUFDLENBQUEsUUFBRCxDQUFBO2VBQ0EsSUFBQyxDQUFBLFlBQUQsQ0FBYyxJQUFDLENBQUEsV0FBVyxDQUFDLE9BQWIsQ0FBQSxDQUFBLEdBQXlCLENBQXZDLEVBQTBDLEtBQTFDO01BUlc7O01BVWIsZ0JBQWtCLENBQUMsSUFBRCxDQUFBO0FBQ3BCLFlBQUEsQ0FBQSxFQUFBO1FBQUksQ0FBQSxHQUFJLElBQUksQ0FBQyxXQUFMLENBQUE7UUFDSixDQUFBLEdBQUksSUFBSSxDQUFDLFFBQUwsQ0FBQTtlQUNKLElBQUksSUFBSixDQUFTLENBQVQsRUFBWSxDQUFaLEVBQWUsQ0FBZjtNQUhnQjs7TUFLbEIsZUFBaUIsQ0FBQyxJQUFELENBQUE7QUFDbkIsWUFBQSxDQUFBLEVBQUE7UUFBSSxDQUFBLEdBQUksSUFBSSxDQUFDLFdBQUwsQ0FBQTtRQUNKLENBQUEsR0FBSSxJQUFJLENBQUMsUUFBTCxDQUFBO2VBQ0osSUFBSSxJQUFKLENBQVMsQ0FBVCxFQUFZLENBQUEsR0FBSSxDQUFoQixFQUFtQixDQUFuQjtNQUhlOztNQUtqQixRQUFVLENBQUEsQ0FBQTtBQUNaLFlBQUEsVUFBQSxFQUFBLEdBQUEsRUFBQSxHQUFBLEVBQUEsV0FBQSxFQUFBLFFBQUEsRUFBQSxDQUFBLEVBQUEsRUFBQSxFQUFBLENBQUEsRUFBQSxDQUFBLEVBQUEsT0FBQSxFQUFBLEdBQUEsRUFBQSxJQUFBLEVBQUEsR0FBQSxFQUFBLEtBQUEsRUFBQTtRQUFJLElBQUMsQ0FBQSxpQkFBaUIsQ0FBQyxJQUFuQixDQUF3QixPQUF4QixDQUFnQyxDQUFDLE1BQWpDLENBQUE7UUFDQSxVQUFBLEdBQWEsQ0FBQSxDQUFFLENBQUEsMkJBQUEsQ0FBQSxDQUE4QixJQUFDLENBQUEsTUFBTSxDQUFDLFlBQUQsQ0FBYyxDQUFDLElBQUMsQ0FBQSxXQUFXLENBQUMsUUFBYixDQUFBLENBQUQsQ0FBbkQsRUFBQSxDQUFBLENBQWdGLElBQUMsQ0FBQSxXQUFXLENBQUMsV0FBYixDQUFBLENBQWhGLENBQUEsaUNBQUEsQ0FBRjtBQUNiO1FBQUEsS0FBQSxxQ0FBQTs7VUFDRSxVQUFVLENBQUMsSUFBWCxDQUFnQixPQUFoQixDQUF3QixDQUFDLE1BQXpCLENBQWdDLENBQUEsSUFBQSxDQUFBLENBQU8sT0FBUCxDQUFBLEtBQUEsQ0FBaEM7UUFERjtRQUdBLElBQUMsQ0FBQSxpQkFBaUIsQ0FBQyxNQUFuQixDQUEwQixVQUExQjtRQUVBLFFBQUEsR0FBVyxJQUFDLENBQUEsZ0JBQUQsQ0FBa0IsSUFBQyxDQUFBLFdBQW5CO1FBQ1gsT0FBQSxHQUFVLElBQUMsQ0FBQSxlQUFELENBQWlCLElBQUMsQ0FBQSxXQUFsQjtRQUVWLFdBQUEsR0FBYztRQUNkLEdBQUEsR0FBTTtBQUNOLGVBQU0sR0FBQSxJQUFPLE9BQWI7VUFDRSxXQUFXLENBQUMsSUFBWixDQUFpQixJQUFJLElBQUosQ0FBUyxHQUFULENBQWpCO1VBQ0EsR0FBRyxDQUFDLE9BQUosQ0FBWSxHQUFHLENBQUMsT0FBSixDQUFBLENBQUEsR0FBZ0IsQ0FBNUI7UUFGRixDQVpKOzs7UUFpQkksQ0FBQSxHQUFJO1FBQ0osUUFBQSxHQUFXLFdBQVcsQ0FBQyxDQUFELENBQUcsQ0FBQyxNQUFmLENBQUE7QUFDWCxlQUFNLENBQUEsR0FBSSxRQUFWO1VBQ0UsV0FBVyxDQUFDLE9BQVosQ0FBb0IsSUFBcEI7VUFDQSxDQUFBO1FBRkYsQ0FuQko7OztRQXdCSSxDQUFBLEdBQUksV0FBVyxDQUFDLFdBQVcsQ0FBQyxNQUFaLEdBQXFCLENBQXRCLENBQXdCLENBQUMsTUFBcEMsQ0FBQTtBQUNKLGVBQU0sQ0FBQSxHQUFJLENBQUosSUFBUyxDQUFBLEdBQUksQ0FBbkI7VUFDRSxXQUFXLENBQUMsSUFBWixDQUFpQixJQUFqQjtVQUNBLENBQUE7UUFGRjtRQUlBLEdBQUEsR0FBTTtRQUNOLEtBQUEsdURBQUE7O1VBQ0UsSUFBRyxDQUFBLEdBQUksQ0FBSixLQUFTLENBQVo7WUFDRSxHQUFBLEdBQU0sQ0FBQSxDQUFFLFdBQUY7WUFDTixVQUFVLENBQUMsTUFBWCxDQUFrQixHQUFsQixFQUZGOztVQUlBLEtBQUEsR0FBVyxHQUFILEdBQ2QsQ0FBZ0IsRUFBQSxHQUFLLENBQUEsZUFBQSxDQUFBLENBQWtCLENBQWxCLENBQUEsQ0FBckIsRUFFZ0IsQ0FBQSxxQ0FBQSxDQUFBLENBQXdDLEVBQXhDLENBQUEsZ0JBQUEsQ0FBQSxDQUE2RCxFQUE3RCxDQUFBLG9DQUFBLENBQUEsQ0FBc0csSUFBQyxDQUFBLFVBQUQsQ0FBWSxHQUFHLENBQUMsTUFBSixDQUFBLENBQVosQ0FBdEcsQ0FBQSxTQUFBLENBQUEsQ0FBMkksR0FBRyxDQUFDLE9BQUosQ0FBQSxDQUEzSSxDQUFBLHNDQUFBLENBQUEsQ0FBaU0sSUFBQyxDQUFBLE1BQU0sQ0FBQyxZQUFELENBQWMsQ0FBQyxHQUFHLENBQUMsUUFBSixDQUFBLENBQUQsQ0FBdE4sRUFBQSxDQUFBLENBQTBPLEdBQUcsQ0FBQyxXQUFKLENBQUEsQ0FBMU8sQ0FBQSxlQUFBLENBRmhCLENBRGMsR0FLRTtVQUNWLEdBQUcsQ0FBQyxNQUFKLENBQVcsQ0FBQSxvQkFBQSxDQUFBLENBQXVCLEtBQXZCLENBQUEsS0FBQSxDQUFYO1FBWEY7UUFhQSxJQUFDLENBQUEsUUFBRCxHQUFZLElBQUMsQ0FBQSxpQkFBaUIsQ0FBQyxJQUFuQixDQUF3QixxQkFBeEI7UUFDWixJQUFDLENBQUEsbUJBQUQsQ0FBQTtRQUVBLElBQUMsQ0FBQSxtQkFBRCxDQUFxQixJQUFDLENBQUEsWUFBRCxDQUFjLElBQUMsQ0FBQSxRQUFmLENBQXJCLEVBQStDLFFBQS9DO2VBQ0EsSUFBQyxDQUFBLFFBQVEsQ0FBQyxRQUFWLENBQW1CLHFCQUFuQjtNQWhEUTs7TUFrRFYsVUFBWSxDQUFDLEdBQUQsQ0FBQTtRQUNWLElBQVcsR0FBQSxLQUFPLENBQWxCO1VBQUEsR0FBQSxHQUFNLEVBQU47O2VBQ0EsSUFBQyxDQUFBLE1BQU0sQ0FBQyxVQUFELENBQVksQ0FBQyxHQUFBLEdBQU0sQ0FBUDtNQUZUOztNQUlaLGlCQUFtQixDQUFBLENBQUE7UUFDakIsSUFBQyxDQUFBLHVCQUFELENBQUE7UUFFQSxJQUFDLENBQUEsc0JBQUQsQ0FBQTtRQUNBLElBQUMsQ0FBQSxxQkFBRCxDQUFBO1FBQ0EsSUFBQyxDQUFBLG1CQUFELENBQUE7ZUFDQSxJQUFDLENBQUEsdUJBQUQsQ0FBQTtNQU5pQjs7TUFRbkIsbUJBQXFCLENBQUEsQ0FBQTtRQUNuQixJQUFDLENBQUEsd0JBQUQsQ0FBQTtRQUNBLElBQUMsQ0FBQSwwQkFBRCxDQUFBO1FBQ0EsSUFBQyxDQUFBLDhCQUFELENBQUE7UUFDQSxJQUFDLENBQUEseUJBQUQsQ0FBQTtlQUNBLElBQUMsQ0FBQSx1QkFBRCxDQUFBO01BTG1COztNQU9yQix1QkFBeUIsQ0FBQSxDQUFBO2VBQ3ZCLElBQUMsQ0FBQSxNQUFNLENBQUMsS0FBUixDQUFjLENBQUEsQ0FBQSxHQUFBO1VBQ1osSUFBRyxJQUFDLENBQUEsaUJBQWlCLENBQUMsRUFBbkIsQ0FBc0IsVUFBdEIsQ0FBSDttQkFDRSxJQUFDLENBQUEsV0FBRCxDQUFBLEVBREY7V0FBQSxNQUFBO21CQUdFLElBQUMsQ0FBQSxXQUFELENBQUEsRUFIRjs7UUFEWSxDQUFkO01BRHVCOztNQU96QixzQkFBd0IsQ0FBQSxDQUFBO2VBQ3RCLElBQUMsQ0FBQSxNQUFNLENBQUMsT0FBUixDQUFnQixDQUFDLENBQUQsQ0FBQSxHQUFBO1VBQ2QsSUFBRyxDQUFDLENBQUMsS0FBRixLQUFXLEVBQWQ7WUFDRSxJQUFHLElBQUMsQ0FBQSxpQkFBaUIsQ0FBQyxFQUFuQixDQUFzQixVQUF0QixDQUFIO2NBQ0UsSUFBQyxDQUFBLHdDQUFELENBQUE7cUJBQ0EsQ0FBQyxDQUFDLGNBQUYsQ0FBQSxFQUZGO2FBQUEsTUFHSyxJQUFHLElBQUMsQ0FBQSxRQUFRLENBQUMsRUFBVixDQUFhLFVBQWIsQ0FBSDtjQUNILElBQUMsQ0FBQSxRQUFRLENBQUMsSUFBVixDQUFlLFNBQWYsRUFBMEIsS0FBMUI7Y0FDQSxJQUFDLENBQUEsd0NBQUQsQ0FBQTtxQkFDQSxDQUFDLENBQUMsY0FBRixDQUFBLEVBSEc7YUFBQSxNQUFBO3FCQUtILENBQUEsQ0FBRSxNQUFGLENBQVMsQ0FBQyxNQUFWLENBQWlCLHVCQUFqQixFQUxHO2FBSlA7O1FBRGMsQ0FBaEI7TUFEc0I7O01BYXhCLHFCQUF1QixDQUFBLENBQUE7ZUFDckIsSUFBQyxDQUFBLE1BQU0sQ0FBQyxPQUFSLENBQWdCLENBQUMsQ0FBRCxDQUFBLEdBQUE7VUFDZCxJQUFHLENBQUMsQ0FBQyxLQUFGLEtBQVcsRUFBZDtZQUNFLElBQUcsSUFBQyxDQUFBLGlCQUFpQixDQUFDLEVBQW5CLENBQXNCLFVBQXRCLENBQUg7Y0FDRSxJQUFDLENBQUEsd0NBQUQsQ0FBQTtxQkFDQSxDQUFDLENBQUMsY0FBRixDQUFBLEVBRkY7YUFBQSxNQUFBO3FCQUlFLENBQUEsQ0FBRSxNQUFGLENBQVMsQ0FBQyxNQUFWLENBQWlCLHlCQUFqQixFQUpGO2FBREY7O1FBRGMsQ0FBaEI7TUFEcUI7O01BU3ZCLG1CQUFxQixDQUFBLENBQUE7ZUFDbkIsSUFBQyxDQUFBLE1BQU0sQ0FBQyxPQUFSLENBQWdCLENBQUMsQ0FBRCxDQUFBLEdBQUE7VUFDZCxJQUFHLENBQUMsQ0FBQyxLQUFGLEtBQVcsQ0FBZDtZQUNFLElBQUcsSUFBQyxDQUFBLGlCQUFpQixDQUFDLEVBQW5CLENBQXNCLFVBQXRCLENBQUg7cUJBQ0UsSUFBQyxDQUFBLHdDQUFELENBQUEsRUFERjthQURGOztRQURjLENBQWhCO01BRG1COztNQU1yQix1QkFBeUIsQ0FBQSxDQUFBO2VBQ3ZCLElBQUMsQ0FBQSxNQUFNLENBQUMsT0FBUixDQUFnQixDQUFDLENBQUQsQ0FBQSxHQUFBO1VBQ2QsSUFBRyxDQUFDLENBQUMsS0FBRixLQUFXLEVBQVgsSUFBaUIsQ0FBQyxDQUFDLEtBQUYsS0FBVyxFQUEvQjtZQUNFLElBQUMsQ0FBQSxXQUFELENBQUE7bUJBQ0EsQ0FBQyxDQUFDLGNBQUYsQ0FBQSxFQUZGOztRQURjLENBQWhCO01BRHVCOztNQU16QixXQUFhLENBQUEsQ0FBQTtRQUNYLElBQUMsQ0FBQSxJQUFELENBQU0sSUFBQyxDQUFBLGlCQUFQO1FBQ0EsSUFBQyxDQUFBLE1BQU0sQ0FBQyxJQUFSLENBQWEsZUFBYixFQUE4QixNQUE5QjtRQUVBLElBQUcsSUFBQyxDQUFBLFFBQVEsQ0FBQyxNQUFWLENBQWlCLFVBQWpCLENBQTRCLENBQUMsTUFBN0IsS0FBdUMsQ0FBMUM7VUFDRSxJQUFDLENBQUEsV0FBRCxHQUFlLElBQUMsQ0FBQSxNQUFNLENBQUMsTUFBRDtVQUN0QixJQUFDLENBQUEsUUFBRCxDQUFBO1VBQ0EsSUFBQyxDQUFBLFlBQUQsQ0FBYyxJQUFDLENBQUEsV0FBVyxDQUFDLE9BQWIsQ0FBQSxDQUFBLEdBQXlCLENBQXZDLEVBSEY7O2VBS0EsSUFBQyxDQUFBLFFBQVEsQ0FBQyxNQUFWLENBQWlCLFVBQWpCLENBQTRCLENBQUMsS0FBN0IsQ0FBQTtNQVRXOztNQVdiLFdBQWEsQ0FBQSxDQUFBO1FBQ1gsSUFBQyxDQUFBLElBQUQsQ0FBTSxJQUFDLENBQUEsaUJBQVA7UUFDQSxJQUFDLENBQUEsTUFBTSxDQUFDLElBQVIsQ0FBYSxlQUFiLEVBQThCLE9BQTlCO2VBQ0EsSUFBQyxDQUFBLE1BQU0sQ0FBQyxLQUFSLENBQUE7TUFIVzs7TUFLYixhQUFlLENBQUMsU0FBRCxDQUFBO0FBQ2pCLFlBQUEsWUFBQSxFQUFBLFFBQUEsRUFBQTtRQUFJLFFBQUEsR0FBVyxJQUFDLENBQUEsUUFBUSxDQUFDLE1BQVYsR0FBbUI7UUFDOUIsWUFBQSxHQUFlLElBQUMsQ0FBQSxRQUFRLENBQUMsS0FBVixDQUFnQixJQUFDLENBQUEsUUFBUSxDQUFDLE1BQVYsQ0FBQSxDQUFrQixDQUFDLElBQW5CLENBQXdCLFVBQXhCLENBQWhCLEVBRG5CO1FBR0ksYUFBQSxHQUFtQixTQUFBLEtBQWEsTUFBaEIsR0FDSyxZQUFBLElBQWdCLENBQW5CLEdBQ3RCLENBQXdCLElBQUMsQ0FBQSxXQUFELEdBQWUsSUFBQyxDQUFBLGFBQUQsQ0FBZSxJQUFDLENBQUEsV0FBaEIsQ0FBdkMsRUFDd0IsSUFBQyxDQUFBLFFBQUQsQ0FBQSxDQUR4QixFQUV3QixDQUFDLENBRnpCLENBRHNCLEdBS0UsWUFBQSxHQUFlLENBTm5CLEdBT1EsU0FBQSxLQUFhLElBQWhCLEdBQ0EsWUFBQSxHQUFlLENBQWYsR0FBbUIsQ0FBdEIsR0FDdEIsQ0FBd0IsSUFBQyxDQUFBLFdBQUQsR0FBZSxJQUFDLENBQUEsYUFBRCxDQUFlLElBQUMsQ0FBQSxXQUFoQixDQUF2QyxFQUN3QixJQUFDLENBQUEsUUFBRCxDQUFBLENBRHhCLEVBRXdCLENBQUMsQ0FGekIsQ0FEc0IsR0FLRSxZQUFBLEdBQWUsQ0FOZCxHQU9HLFNBQUEsS0FBYSxPQUFoQixHQUNBLFlBQUEsS0FBZ0IsUUFBbkIsR0FDdEIsQ0FBd0IsSUFBQyxDQUFBLFdBQUQsR0FBZSxJQUFDLENBQUEsU0FBRCxDQUFXLElBQUMsQ0FBQSxXQUFaLENBQXZDLEVBQ3dCLElBQUMsQ0FBQSxRQUFELENBQUEsQ0FEeEIsRUFFd0IsQ0FGeEIsQ0FEc0IsR0FLRSxZQUFBLEdBQWUsQ0FOZCxHQU9HLFNBQUEsS0FBYSxNQUFoQixHQUNBLFlBQUEsR0FBZSxDQUFmLEdBQW1CLFFBQXRCLEdBQ3RCLENBQXdCLElBQUMsQ0FBQSxXQUFELEdBQWUsSUFBQyxDQUFBLFNBQUQsQ0FBVyxJQUFDLENBQUEsV0FBWixDQUF2QyxFQUN3QixJQUFDLENBQUEsUUFBRCxDQUFBLENBRHhCLEVBRXdCLENBRnhCLENBRHNCLEdBS0UsWUFBQSxHQUFlLENBTmQsR0FBQSxPQXhCekI7ZUFnQ0ksSUFBQyxDQUFBLFlBQUQsQ0FBYyxhQUFkO01BakNhOztNQW1DZixZQUFjLENBQUMsT0FBRCxFQUFVLFNBQVMsSUFBbkIsQ0FBQTtBQUNoQixZQUFBO1FBQUksSUFBRyxPQUFBLEtBQVcsQ0FBQyxDQUFmO1VBQ0UsT0FBQSxHQUFVLElBQUMsQ0FBQSxRQUFRLENBQUMsTUFBVixHQUFtQixFQUQvQjs7UUFHQSxjQUFBLEdBQWlCLENBQUEsQ0FBRSxJQUFDLENBQUEsUUFBUSxDQUFDLE9BQUQsQ0FBWDtRQUNqQixjQUFjLENBQUMsSUFBZixDQUFvQixTQUFwQixFQUErQixJQUEvQjtRQUVBLElBQUcsTUFBSDtVQUNFLGNBQWMsQ0FBQyxPQUFmLENBQXVCLFFBQXZCO2lCQUNBLGNBQWMsQ0FBQyxLQUFmLENBQUEsRUFGRjs7TUFQWTs7TUFXZCxhQUFlLENBQUMsR0FBRCxDQUFBO1FBQ2IsSUFBRyxHQUFHLENBQUMsUUFBSixDQUFBLENBQUEsS0FBa0IsQ0FBckI7aUJBQ0UsSUFBSSxJQUFKLENBQVMsR0FBRyxDQUFDLFdBQUosQ0FBQSxDQUFBLEdBQW9CLENBQTdCLEVBQWdDLEVBQWhDLEVBQW9DLENBQXBDLEVBREY7U0FBQSxNQUFBO2lCQUdFLElBQUksSUFBSixDQUFTLEdBQUcsQ0FBQyxXQUFKLENBQUEsQ0FBVCxFQUE0QixHQUFHLENBQUMsUUFBSixDQUFBLENBQUEsR0FBaUIsQ0FBN0MsRUFBZ0QsQ0FBaEQsRUFIRjs7TUFEYTs7TUFNZixTQUFXLENBQUMsR0FBRCxDQUFBO1FBQ1QsSUFBRyxHQUFHLENBQUMsUUFBSixDQUFBLENBQUEsS0FBa0IsRUFBckI7aUJBQ0UsSUFBSSxJQUFKLENBQVMsR0FBRyxDQUFDLFdBQUosQ0FBQSxDQUFBLEdBQW9CLENBQTdCLEVBQWdDLEVBQWhDLEVBQW9DLENBQXBDLEVBREY7U0FBQSxNQUFBO2lCQUdFLElBQUksSUFBSixDQUFTLEdBQUcsQ0FBQyxXQUFKLENBQUEsQ0FBVCxFQUE0QixHQUFHLENBQUMsUUFBSixDQUFBLENBQUEsR0FBaUIsQ0FBN0MsRUFBZ0QsQ0FBaEQsRUFIRjs7TUFEUzs7TUFNWCx3QkFBMEIsQ0FBQSxDQUFBO2VBQ3hCLElBQUMsQ0FBQSxRQUFRLENBQUMsT0FBVixDQUFrQixDQUFDLENBQUQsQ0FBQSxHQUFBO1VBQ2hCLElBQUcsQ0FBQyxDQUFDLEtBQUYsS0FBVyxFQUFYLElBQWlCLENBQUMsQ0FBQyxLQUFGLEtBQVcsRUFBNUIsSUFBa0MsQ0FBQyxDQUFDLEtBQUYsS0FBVyxFQUE3QyxJQUFtRCxDQUFDLENBQUMsS0FBRixLQUFXLEVBQWpFO1lBQ0UsSUFBRyxDQUFDLENBQUMsS0FBRixLQUFXLEVBQWQ7Y0FDRSxJQUFDLENBQUEsYUFBRCxDQUFlLE1BQWYsRUFERjthQUFBLE1BRUssSUFBRyxDQUFDLENBQUMsS0FBRixLQUFXLEVBQWQ7Y0FDSCxJQUFDLENBQUEsYUFBRCxDQUFlLElBQWYsRUFERzthQUFBLE1BRUEsSUFBRyxDQUFDLENBQUMsS0FBRixLQUFXLEVBQWQ7Y0FDSCxJQUFDLENBQUEsYUFBRCxDQUFlLE9BQWYsRUFERzthQUFBLE1BRUEsSUFBRyxDQUFDLENBQUMsS0FBRixLQUFXLEVBQWQ7Y0FDSCxJQUFDLENBQUEsYUFBRCxDQUFlLE1BQWYsRUFERzs7bUJBR0wsQ0FBQyxDQUFDLGNBQUYsQ0FBQSxFQVZGOztRQURnQixDQUFsQjtNQUR3Qjs7TUFjMUIsMEJBQTRCLENBQUEsQ0FBQTtlQUMxQixJQUFDLENBQUEsUUFBUSxDQUFDLE1BQVYsQ0FBaUIsQ0FBQyxDQUFELENBQUEsR0FBQTtpQkFDZixJQUFDLENBQUEseUJBQUQsQ0FBQTtRQURlLENBQWpCO01BRDBCOztNQUk1Qix3Q0FBMEMsQ0FBQSxDQUFBO1FBQ3hDLElBQUMsQ0FBQSx5QkFBRCxDQUFBO2VBQ0EsSUFBQyxDQUFBLFdBQUQsQ0FBQTtNQUZ3Qzs7TUFJMUMseUJBQTJCLENBQUEsQ0FBQTtBQUM3QixZQUFBLGNBQUEsRUFBQSxtQkFBQSxFQUFBO1FBQUksNkJBQUEsR0FBZ0MsQ0FBQSxDQUFFLENBQUEsQ0FBQSxDQUFBLENBQUksSUFBQyxDQUFBLG9CQUFELENBQXNCLGlCQUF0QixDQUFKLENBQUEsQ0FBQSxDQUFGO1FBQ2hDLElBQUcsNkJBQTZCLENBQUMsTUFBOUIsS0FBd0MsQ0FBM0M7VUFDRSxJQUFDLENBQUEsc0JBQUQsQ0FBd0IsNkJBQXhCLEVBQXVELGlCQUF2RCxFQURGOztRQUdBLGNBQUEsR0FBaUIsSUFBQyxDQUFBLFFBQVEsQ0FBQyxNQUFWLENBQWlCLFVBQWpCO1FBQ2pCLElBQUcsY0FBYyxDQUFDLE1BQWYsS0FBeUIsQ0FBNUI7VUFDRSxtQkFBQSxHQUFzQixJQUFDLENBQUEsWUFBRCxDQUFjLGNBQWQ7VUFDdEIsSUFBQyxDQUFBLE1BQU0sQ0FBQyxHQUFSLENBQVksQ0FBQyxDQUFDLElBQUYsQ0FBTyxtQkFBbUIsQ0FBQyxJQUFwQixDQUFBLENBQVAsQ0FBWjtpQkFDQSxJQUFDLENBQUEsbUJBQUQsQ0FBcUIsbUJBQXJCLEVBQTBDLGlCQUExQyxFQUhGO1NBQUEsTUFBQTtpQkFLRSxJQUFDLENBQUEsTUFBTSxDQUFDLEdBQVIsQ0FBWSxFQUFaLEVBTEY7O01BTnlCOztNQWEzQiw4QkFBZ0MsQ0FBQSxDQUFBO2VBQzlCLElBQUMsQ0FBQSxZQUFELENBQWMsSUFBQyxDQUFBLFFBQWYsQ0FBd0IsQ0FBQyxLQUF6QixDQUErQixDQUFDLENBQUQsQ0FBQSxHQUFBO2lCQUM3QixJQUFDLENBQUEsV0FBRCxDQUFBO1FBRDZCLENBQS9CO01BRDhCOztNQUloQyx5QkFBMkIsQ0FBQSxDQUFBO2VBQ3pCLElBQUMsQ0FBQSxRQUFRLENBQUMsT0FBVixDQUFrQixDQUFDLENBQUQsQ0FBQSxHQUFBO1VBQ2hCLElBQUcsQ0FBQyxDQUFDLEtBQUYsS0FBVyxFQUFkO1lBQ0UsSUFBQyxDQUFBLFdBQUQsQ0FBQTtZQUNBLENBQUMsQ0FBQyxjQUFGLENBQUE7bUJBQ0EsQ0FBQyxDQUFDLGVBQUYsQ0FBQSxFQUhGOztRQURnQixDQUFsQjtNQUR5Qjs7TUFPM0IsdUJBQXlCLENBQUEsQ0FBQTtlQUN2QixJQUFDLENBQUEsUUFBUSxDQUFDLE9BQVYsQ0FBa0IsQ0FBQyxDQUFELENBQUEsR0FBQTtVQUNoQixJQUFHLENBQUMsQ0FBQyxLQUFGLEtBQVcsQ0FBZDttQkFDRSxJQUFDLENBQUEsV0FBRCxDQUFBLEVBREY7O1FBRGdCLENBQWxCO01BRHVCOztJQTNVM0I7O0lBQ0UsTUFBQSxHQUNFO01BQUEsSUFBQSxFQUFZLElBQUksSUFBSixDQUFBLENBQVo7TUFDQSxRQUFBLEVBQVksQ0FBQyxRQUFELEVBQVcsU0FBWCxFQUFzQixXQUF0QixFQUFtQyxVQUFuQyxFQUErQyxRQUEvQyxFQUF5RCxVQUF6RCxFQUFxRSxRQUFyRSxDQURaO01BRUEsVUFBQSxFQUFZLENBQUMsU0FBRCxFQUFZLFVBQVosRUFBd0IsT0FBeEIsRUFBaUMsT0FBakMsRUFBMEMsS0FBMUMsRUFBaUQsTUFBakQsRUFBeUQsTUFBekQsRUFBaUUsUUFBakUsRUFBMkUsV0FBM0UsRUFBd0YsU0FBeEYsRUFBbUcsVUFBbkcsRUFBK0csVUFBL0c7SUFGWjs7Ozs7O0VBOFVKLENBQUEsQ0FBRSxRQUFGLENBQVcsQ0FBQyxLQUFaLENBQWtCLFFBQUEsQ0FBQSxDQUFBO1dBQ2hCLENBQUEsQ0FBRSx1QkFBRixDQUEwQixDQUFDLElBQTNCLENBQWdDLFFBQUEsQ0FBQSxDQUFBO2FBQzlCLElBQUksYUFBSixDQUFrQixJQUFsQjtJQUQ4QixDQUFoQztFQURnQixDQUFsQjtBQWhWQSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEFkZ0RhdGVwaWNrZXJcbiAgY29uZmlnID1cbiAgICBkYXRlOiAgICAgICBuZXcgRGF0ZSgpXG4gICAgZGF5TmFtZXM6ICAgW1wiTW9uZGF5XCIsIFwiVHVlc2RheVwiLCBcIldlZG5lc2RheVwiLCBcIlRodXJzZGF5XCIsIFwiRnJpZGF5XCIsIFwiU2F0dXJkYXlcIiwgXCJTdW5kYXlcIl1cbiAgICBtb250aE5hbWVzOiBbXCJKYW51YXJ5XCIsIFwiRmVicnVhcnlcIiwgXCJNYXJjaFwiLCBcIkFwcmlsXCIsIFwiTWF5XCIsIFwiSnVuZVwiLCBcIkp1bHlcIiwgXCJBdWd1c3RcIiwgXCJTZXB0ZW1iZXJcIiwgXCJPY3RvYmVyXCIsIFwiTm92ZW1iZXJcIiwgXCJEZWNlbWJlclwiXVxuICBcbiAgY29uc3RydWN0b3I6IChlbCwgb3B0aW9ucyA9IHt9KSAtPlxuICAgIEAkZWwgPSAkKGVsKVxuICAgIEBjb25maWcgPSBjb25maWdcbiAgICBcbiAgICBAY3VycmVudERhdGUgPSBAY29uZmlnW1wiZGF0ZVwiXVxuXG4gICAgQGluaXRJbnB1dCgpXG4gICAgQGluaXRPcHRpb25zKClcblxuICAgIEBhcHBseUNoZWNrZWRPcHRpb25Ub0lucHV0KClcblxuICAjIEV4ZWN1dGVzIHRoZSBnaXZlbiBzZWxlY3RvciBvbiBAJGVsIGFuZCByZXR1cm5zIHRoZSBlbGVtZW50LiBNYWtlcyBzdXJlIGV4YWN0bHkgb25lIGVsZW1lbnQgZXhpc3RzLlxuICBmaW5kT25lOiAoc2VsZWN0b3IpIC0+XG4gICAgcmVzdWx0ID0gQCRlbC5maW5kKHNlbGVjdG9yKVxuICAgIHN3aXRjaCByZXN1bHQubGVuZ3RoXG4gICAgICB3aGVuIDAgdGhlbiBAdGhyb3dNZXNzYWdlQW5kUHJpbnRPYmplY3RzVG9Db25zb2xlIFwiTm8gb2JqZWN0IGZvdW5kIGZvciAje3NlbGVjdG9yfSFcIiwgcmVzdWx0OiByZXN1bHRcbiAgICAgIHdoZW4gMSB0aGVuICQocmVzdWx0LmZpcnN0KCkpXG4gICAgICBlbHNlIEB0aHJvd01lc3NhZ2VBbmRQcmludE9iamVjdHNUb0NvbnNvbGUgXCJNb3JlIHRoYW4gb25lIG9iamVjdCBmb3VuZCBmb3IgI3tzZWxlY3Rvcn0hXCIsIHJlc3VsdDogcmVzdWx0XG4gICAgICAgIFxuICBuYW1lOiAtPlxuICAgIFwiYWRnLWRhdGVwaWNrZXJcIlxuICAgICAgICBcbiAgYWRkQWRnRGF0YUF0dHJpYnV0ZTogKCR0YXJnZXQsIG5hbWUsIHZhbHVlID0gJycpIC0+XG4gICAgJHRhcmdldC5hdHRyKEBhZGdEYXRhQXR0cmlidXRlTmFtZShuYW1lKSwgdmFsdWUpXG4gICAgICAgIFxuICByZW1vdmVBZGdEYXRhQXR0cmlidXRlOiAoJHRhcmdldCwgbmFtZSkgLT5cbiAgICAkdGFyZ2V0LnJlbW92ZUF0dHIoQGFkZ0RhdGFBdHRyaWJ1dGVOYW1lKG5hbWUpKVxuICAgIFxuICBhZGdEYXRhQXR0cmlidXRlTmFtZTogKG5hbWUgPSBudWxsKSAtPlxuICAgIHJlc3VsdCA9IFwiZGF0YS0je0BuYW1lKCl9XCJcbiAgICByZXN1bHQgKz0gXCItI3tuYW1lfVwiIGlmIG5hbWVcbiAgICByZXN1bHRcbiAgICBcbiAgbGFiZWxPZklucHV0OiAoJGlucHV0cykgLT5cbiAgICAkaW5wdXRzLm1hcCAoaSwgaW5wdXQpID0+XG4gICAgICAkaW5wdXQgPSAkKGlucHV0KVxuICAgICAgXG4gICAgICBpZCA9ICRpbnB1dC5hdHRyKCdpZCcpXG4gICAgICAkbGFiZWwgPSBAZmluZE9uZShcImxhYmVsW2Zvcj0nI3tpZH0nXVwiKVswXVxuXG4gICAgICBpZiAkbGFiZWwubGVuZ3RoID09IDBcbiAgICAgICAgJGxhYmVsID0gJGlucHV0LmNsb3Nlc3QoJ2xhYmVsJylcbiAgICAgICAgQHRocm93TWVzc2FnZUFuZFByaW50T2JqZWN0c1RvQ29uc29sZSBcIk5vIGNvcnJlc3BvbmRpbmcgaW5wdXQgZm91bmQgZm9yIGlucHV0IVwiLCBpbnB1dDogJGlucHV0IGlmICRsYWJlbC5sZW5ndGggPT0gMFxuXG4gICAgICAkbGFiZWxcblxuICBzaG93OiAoJGVsKSAtPlxuICAgICRlbC5yZW1vdmVBdHRyKCdoaWRkZW4nKVxuICAgICRlbC5zaG93KClcblxuICAgICMgVE9ETyBXb3VsZCBiZSBjb29sIHRvIHJlbm91bmNlIENTUyBhbmQgc29sZWx5IHVzZSB0aGUgaGlkZGVuIGF0dHJpYnV0ZS4gQnV0IGpRdWVyeSdzIDp2aXNpYmxlIGRvZXNuJ3Qgc2VlbSB0byB3b3JrIHdpdGggaXQhP1xuICAgICMgQHRocm93TWVzc2FnZUFuZFByaW50T2JqZWN0c1RvQ29uc29sZShcIkVsZW1lbnQgaXMgc3RpbGwgaGlkZGVuLCBhbHRob3VnaCBoaWRkZW4gYXR0cmlidXRlIHdhcyByZW1vdmVkISBNYWtlIHN1cmUgdGhlcmUncyBubyBDU1MgbGlrZSBkaXNwbGF5Om5vbmUgb3IgdmlzaWJpbGl0eTpoaWRkZW4gbGVmdCBvbiBpdCFcIiwgZWxlbWVudDogJGVsKSBpZiAkZWwuaXMoJzpoaWRkZW4nKVxuXG4gIGhpZGU6ICgkZWwpIC0+XG4gICAgJGVsLmF0dHIoJ2hpZGRlbicsICcnKVxuICAgICRlbC5oaWRlKClcbiAgICBcbiAgdGhyb3dNZXNzYWdlQW5kUHJpbnRPYmplY3RzVG9Db25zb2xlOiAobWVzc2FnZSwgZWxlbWVudHMgPSB7fSkgLT5cbiAgICBjb25zb2xlLmxvZyBlbGVtZW50c1xuICAgIHRocm93IG1lc3NhZ2VcbiAgICBcbiAgdGV4dDogKHRleHQsIG9wdGlvbnMgPSB7fSkgLT5cbiAgICB0ZXh0ID0gQGNvbmZpZ1tcIiN7dGV4dH1UZXh0XCJdXG4gICAgXG4gICAgZm9yIGtleSwgdmFsdWUgb2Ygb3B0aW9uc1xuICAgICAgdGV4dCA9IHRleHQucmVwbGFjZSBcIlsje2tleX1dXCIsIHZhbHVlXG4gICAgICBcbiAgICB0ZXh0XG5cbiAgaW5pdElucHV0OiAtPlxuICAgIEAkaW5wdXQgPSBAZmluZE9uZSgnaW5wdXRbdHlwZT1cInRleHRcIl0nKVxuICAgIEAkaW5wdXQuYXR0cignYXV0b2NvbXBsZXRlJywgJ29mZicpXG4gICAgQCRpbnB1dC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgJ2ZhbHNlJylcbiAgICBAYXR0YWNoSW5wdXRFdmVudHMoKVxuXG4gIGluaXRPcHRpb25zOiAtPlxuICAgIEAkb3B0aW9uc0NvbnRhaW5lciA9IEBmaW5kT25lKCdmaWVsZHNldCcpXG4gICAgQGFkZEFkZ0RhdGFBdHRyaWJ1dGUoQCRvcHRpb25zQ29udGFpbmVyLCAnb3B0aW9ucycpXG5cbiAgICBAJG9wdGlvbnNDb250YWluZXJMYWJlbCA9IEBmaW5kT25lKCdsZWdlbmQnKVxuICAgIEAkb3B0aW9uc0NvbnRhaW5lckxhYmVsLmFkZENsYXNzKCdhZGctdmlzdWFsbHktaGlkZGVuJylcbiAgICBcbiAgICBAaW5pdERhdGUoKVxuICAgIEBzZXRTZWxlY3Rpb24oQGN1cnJlbnREYXRlLmdldERhdGUoKSAtIDEsIGZhbHNlKVxuICAgIFxuICBnZXRGaXJzdE1vbnRoRGF5OiAoZGF0ZSkgLT5cbiAgICB5ID0gZGF0ZS5nZXRGdWxsWWVhcigpXG4gICAgbSA9IGRhdGUuZ2V0TW9udGgoKVxuICAgIG5ldyBEYXRlKHksIG0sIDEpXG4gICAgXG4gIGdldExhc3RNb250aERheTogKGRhdGUpIC0+XG4gICAgeSA9IGRhdGUuZ2V0RnVsbFllYXIoKVxuICAgIG0gPSBkYXRlLmdldE1vbnRoKClcbiAgICBuZXcgRGF0ZSh5LCBtICsgMSwgMClcbiAgICBcbiAgaW5pdERhdGU6ICgpIC0+XG4gICAgQCRvcHRpb25zQ29udGFpbmVyLmZpbmQoXCJ0YWJsZVwiKS5yZW1vdmUoKVxuICAgICRkYXRlVGFibGUgPSAkKFwiPHRhYmxlIGJvcmRlcj0nMSc+PGNhcHRpb24+I3tAY29uZmlnW1wibW9udGhOYW1lc1wiXVtAY3VycmVudERhdGUuZ2V0TW9udGgoKV19ICN7QGN1cnJlbnREYXRlLmdldEZ1bGxZZWFyKCl9PC9jYXB0aW9uPjx0aGVhZD48L3RoZWFkPjwvdGFibGU+XCIpXG4gICAgZm9yIHdlZWtkYXkgaW4gQGNvbmZpZ1tcImRheU5hbWVzXCJdXG4gICAgICAkZGF0ZVRhYmxlLmZpbmQoXCJ0aGVhZFwiKS5hcHBlbmQoXCI8dGg+I3t3ZWVrZGF5fTwvdGg+XCIpXG4gICAgICBcbiAgICBAJG9wdGlvbnNDb250YWluZXIuYXBwZW5kKCRkYXRlVGFibGUpXG4gICAgXG4gICAgZmlyc3REYXkgPSBAZ2V0Rmlyc3RNb250aERheShAY3VycmVudERhdGUpXG4gICAgbGFzdERheSA9IEBnZXRMYXN0TW9udGhEYXkoQGN1cnJlbnREYXRlKVxuICAgIFxuICAgIGRheXNPZk1vbnRoID0gW11cbiAgICBkYXkgPSBmaXJzdERheVxuICAgIHdoaWxlIGRheSA8PSBsYXN0RGF5XG4gICAgICBkYXlzT2ZNb250aC5wdXNoIG5ldyBEYXRlKGRheSlcbiAgICAgIGRheS5zZXREYXRlIGRheS5nZXREYXRlKCkgKyAxXG4gICAgICBcbiAgICAjIEFkZCBlbXB0eSBkYXlzIGF0IGJlZ2lubmluZ1xuICAgIGkgPSAxXG4gICAgZmlyc3REYXkgPSBkYXlzT2ZNb250aFswXS5nZXREYXkoKVxuICAgIHdoaWxlIGkgPCBmaXJzdERheVxuICAgICAgZGF5c09mTW9udGgudW5zaGlmdCBudWxsXG4gICAgICBpKytcbiAgICAgIFxuICAgICMgQWRkIGVtcHR5IGRheXMgYXQgZW5kXG4gICAgaSA9IGRheXNPZk1vbnRoW2RheXNPZk1vbnRoLmxlbmd0aCAtIDFdLmdldERheSgpXG4gICAgd2hpbGUgaSA+IDAgJiYgaSA8IDZcbiAgICAgIGRheXNPZk1vbnRoLnB1c2ggbnVsbFxuICAgICAgaSsrXG4gICAgICBcbiAgICAkdHIgPSBudWxsXG4gICAgZm9yIGRheSwgaSBpbiBkYXlzT2ZNb250aFxuICAgICAgaWYgaSAlIDcgPT0gMFxuICAgICAgICAkdHIgPSAkKFwiPHRyPjwvdHI+XCIpXG4gICAgICAgICRkYXRlVGFibGUuYXBwZW5kKCR0cilcbiAgICAgICAgXG4gICAgICB2YWx1ZSA9IGlmIGRheVxuICAgICAgICAgICAgICAgIGlkID0gXCJmYXZvcml0ZV9ob2JieV8je2l9XCJcblxuICAgICAgICAgICAgICAgIFwiPGlucHV0IHR5cGU9J3JhZGlvJyBuYW1lPSdob2JieScgaWQ9JyN7aWR9JyAvPjxsYWJlbCBmb3I9JyN7aWR9Jz48c3BhbiBjbGFzcz0nYWRnLXZpc3VhbGx5LWhpZGRlbic+I3tAZ2V0RGF5TmFtZShkYXkuZ2V0RGF5KCkpfSwgPC9zcGFuPiN7ZGF5LmdldERhdGUoKX08c3BhbiBjbGFzcz0nYWRnLXZpc3VhbGx5LWhpZGRlbic+IG9mICN7QGNvbmZpZ1snbW9udGhOYW1lcyddW2RheS5nZXRNb250aCgpXX0gI3tkYXkuZ2V0RnVsbFllYXIoKX08L3NwYW4+PC9sYWJlbD5cIlxuICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgXCJcIlxuICAgICAgJHRyLmFwcGVuZChcIjx0ZCBjbGFzcz0nY29udHJvbCc+I3t2YWx1ZX08L3RkPlwiKVxuICAgICAgXG4gICAgQCRvcHRpb25zID0gQCRvcHRpb25zQ29udGFpbmVyLmZpbmQoJ2lucHV0W3R5cGU9XCJyYWRpb1wiXScpXG4gICAgQGF0dGFjaE9wdGlvbnNFdmVudHMoKVxuXG4gICAgQGFkZEFkZ0RhdGFBdHRyaWJ1dGUoQGxhYmVsT2ZJbnB1dChAJG9wdGlvbnMpLCAnb3B0aW9uJylcbiAgICBAJG9wdGlvbnMuYWRkQ2xhc3MoJ2FkZy12aXN1YWxseS1oaWRkZW4nKVxuICAgIFxuICBnZXREYXlOYW1lOiAoZGF5KSAtPlxuICAgIGRheSA9IDYgaWYgZGF5ID09IDBcbiAgICBAY29uZmlnWydkYXlOYW1lcyddW2RheSAtIDFdXG5cbiAgYXR0YWNoSW5wdXRFdmVudHM6IC0+XG4gICAgQGF0dGFjaENsaWNrRXZlbnRUb0lucHV0KClcblxuICAgIEBhdHRhY2hFc2NhcGVLZXlUb0lucHV0KClcbiAgICBAYXR0YWNoRW50ZXJLZXlUb0lucHV0KClcbiAgICBAYXR0YWNoVGFiS2V5VG9JbnB1dCgpXG4gICAgQGF0dGFjaFVwRG93bktleXNUb0lucHV0KClcblxuICBhdHRhY2hPcHRpb25zRXZlbnRzOiAtPlxuICAgIEBhdHRhY2hBcnJvd0tleXNUb09wdGlvbnMoKVxuICAgIEBhdHRhY2hDaGFuZ2VFdmVudFRvT3B0aW9ucygpXG4gICAgQGF0dGFjaENsaWNrRXZlbnRUb09wdGlvbkxhYmVscygpXG4gICAgQGF0dGFjaEVudGVyRXZlbnRUb09wdGlvbnMoKVxuICAgIEBhdHRhY2hUYWJFdmVudFRvT3B0aW9ucygpXG5cbiAgYXR0YWNoQ2xpY2tFdmVudFRvSW5wdXQ6IC0+XG4gICAgQCRpbnB1dC5jbGljayA9PlxuICAgICAgaWYgQCRvcHRpb25zQ29udGFpbmVyLmlzKCc6dmlzaWJsZScpXG4gICAgICAgIEBoaWRlT3B0aW9ucygpXG4gICAgICBlbHNlXG4gICAgICAgIEBzaG93T3B0aW9ucygpXG5cbiAgYXR0YWNoRXNjYXBlS2V5VG9JbnB1dDogLT5cbiAgICBAJGlucHV0LmtleWRvd24gKGUpID0+XG4gICAgICBpZiBlLndoaWNoID09IDI3XG4gICAgICAgIGlmIEAkb3B0aW9uc0NvbnRhaW5lci5pcygnOnZpc2libGUnKVxuICAgICAgICAgIEBhcHBseUNoZWNrZWRPcHRpb25Ub0lucHV0QW5kUmVzZXRPcHRpb25zKClcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgZWxzZSBpZiBAJG9wdGlvbnMuaXMoJzpjaGVja2VkJylcbiAgICAgICAgICBAJG9wdGlvbnMucHJvcCgnY2hlY2tlZCcsIGZhbHNlKVxuICAgICAgICAgIEBhcHBseUNoZWNrZWRPcHRpb25Ub0lucHV0QW5kUmVzZXRPcHRpb25zKClcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgZWxzZSAjIE5lZWRlZCBmb3IgYXV0b21hdGljIHRlc3Rpbmcgb25seVxuICAgICAgICAgICQoJ2JvZHknKS5hcHBlbmQoJzxwPkVzYyBwYXNzZWQgb24uPC9wPicpXG5cbiAgYXR0YWNoRW50ZXJLZXlUb0lucHV0OiAtPlxuICAgIEAkaW5wdXQua2V5ZG93biAoZSkgPT5cbiAgICAgIGlmIGUud2hpY2ggPT0gMTNcbiAgICAgICAgaWYgQCRvcHRpb25zQ29udGFpbmVyLmlzKCc6dmlzaWJsZScpXG4gICAgICAgICAgQGFwcGx5Q2hlY2tlZE9wdGlvblRvSW5wdXRBbmRSZXNldE9wdGlvbnMoKVxuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKVxuICAgICAgICBlbHNlICMgTmVlZGVkIGZvciBhdXRvbWF0aWMgdGVzdGluZyBvbmx5XG4gICAgICAgICAgJCgnYm9keScpLmFwcGVuZCgnPHA+RW50ZXIgcGFzc2VkIG9uLjwvcD4nKVxuXG4gIGF0dGFjaFRhYktleVRvSW5wdXQ6IC0+XG4gICAgQCRpbnB1dC5rZXlkb3duIChlKSA9PlxuICAgICAgaWYgZS53aGljaCA9PSA5XG4gICAgICAgIGlmIEAkb3B0aW9uc0NvbnRhaW5lci5pcygnOnZpc2libGUnKVxuICAgICAgICAgIEBhcHBseUNoZWNrZWRPcHRpb25Ub0lucHV0QW5kUmVzZXRPcHRpb25zKClcblxuICBhdHRhY2hVcERvd25LZXlzVG9JbnB1dDogLT5cbiAgICBAJGlucHV0LmtleWRvd24gKGUpID0+XG4gICAgICBpZiBlLndoaWNoID09IDM4IHx8IGUud2hpY2ggPT0gNDBcbiAgICAgICAgQHNob3dPcHRpb25zKClcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpICMgVE9ETzogVGVzdCFcblxuICBzaG93T3B0aW9uczogLT5cbiAgICBAc2hvdyhAJG9wdGlvbnNDb250YWluZXIpXG4gICAgQCRpbnB1dC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgJ3RydWUnKVxuICAgIFxuICAgIGlmIEAkb3B0aW9ucy5maWx0ZXIoJzpjaGVja2VkJykubGVuZ3RoID09IDBcbiAgICAgIEBjdXJyZW50RGF0ZSA9IEBjb25maWdbXCJkYXRlXCJdXG4gICAgICBAaW5pdERhdGUoKVxuICAgICAgQHNldFNlbGVjdGlvbihAY3VycmVudERhdGUuZ2V0RGF0ZSgpIC0gMSlcblxuICAgIEAkb3B0aW9ucy5maWx0ZXIoJzpjaGVja2VkJykuZm9jdXMoKVxuXG4gIGhpZGVPcHRpb25zOiAtPlxuICAgIEBoaWRlKEAkb3B0aW9uc0NvbnRhaW5lcilcbiAgICBAJGlucHV0LmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKVxuICAgIEAkaW5wdXQuZm9jdXMoKVxuXG4gIG1vdmVTZWxlY3Rpb246IChkaXJlY3Rpb24pIC0+XG4gICAgbWF4SW5kZXggPSBAJG9wdGlvbnMubGVuZ3RoIC0gMVxuICAgIGN1cnJlbnRJbmRleCA9IEAkb3B0aW9ucy5pbmRleChAJG9wdGlvbnMucGFyZW50KCkuZmluZCgnOmNoZWNrZWQnKSkgIyBUT0RPOiBpcyBwYXJlbnQoKSBnb29kIGhlcmU/IVxuICAgIFxuICAgIHVwY29taW5nSW5kZXggPSBpZiBkaXJlY3Rpb24gPT0gJ2xlZnQnXG4gICAgICAgICAgICAgICAgICAgICAgaWYgY3VycmVudEluZGV4IDw9IDBcbiAgICAgICAgICAgICAgICAgICAgICAgIEBjdXJyZW50RGF0ZSA9IEBwcmV2aW91c01vbnRoKEBjdXJyZW50RGF0ZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIEBpbml0RGF0ZSgpXG4gICAgICAgICAgICAgICAgICAgICAgICAtMVxuICAgICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCAtIDFcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiBkaXJlY3Rpb24gPT0gJ3VwJ1xuICAgICAgICAgICAgICAgICAgICAgIGlmIGN1cnJlbnRJbmRleCAtIDcgPCAwXG4gICAgICAgICAgICAgICAgICAgICAgICBAY3VycmVudERhdGUgPSBAcHJldmlvdXNNb250aChAY3VycmVudERhdGUpXG4gICAgICAgICAgICAgICAgICAgICAgICBAaW5pdERhdGUoKVxuICAgICAgICAgICAgICAgICAgICAgICAgLTEgIyBUT0RPOiBDYWxjdWxhdGUgaW5kZXggZm9yIHRoZSBjdXJyZW50IHdlZWsgZGF5XG4gICAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4IC0gN1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIGRpcmVjdGlvbiA9PSAncmlnaHQnXG4gICAgICAgICAgICAgICAgICAgICAgaWYgY3VycmVudEluZGV4ID09IG1heEluZGV4XG4gICAgICAgICAgICAgICAgICAgICAgICBAY3VycmVudERhdGUgPSBAbmV4dE1vbnRoKEBjdXJyZW50RGF0ZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIEBpbml0RGF0ZSgpXG4gICAgICAgICAgICAgICAgICAgICAgICAwXG4gICAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ICsgMVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIGRpcmVjdGlvbiA9PSAnZG93bidcbiAgICAgICAgICAgICAgICAgICAgICBpZiBjdXJyZW50SW5kZXggKyA3ID4gbWF4SW5kZXhcbiAgICAgICAgICAgICAgICAgICAgICAgIEBjdXJyZW50RGF0ZSA9IEBuZXh0TW9udGgoQGN1cnJlbnREYXRlKVxuICAgICAgICAgICAgICAgICAgICAgICAgQGluaXREYXRlKClcbiAgICAgICAgICAgICAgICAgICAgICAgIDAgIyBUT0RPOiBDYWxjdWxhdGUgaW5kZXggZm9yIHRoZSBjdXJyZW50IHdlZWsgZGF5XG4gICAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ICsgN1xuXG4gICAgQHNldFNlbGVjdGlvbih1cGNvbWluZ0luZGV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHNldFNlbGVjdGlvbjogKGN1cnJlbnQsIGNoYW5nZSA9IHRydWUpIC0+XG4gICAgaWYgY3VycmVudCA9PSAtMVxuICAgICAgY3VycmVudCA9IEAkb3B0aW9ucy5sZW5ndGggLSAxXG4gICAgICBcbiAgICAkY3VycmVudE9wdGlvbiA9ICQoQCRvcHRpb25zW2N1cnJlbnRdKVxuICAgICRjdXJyZW50T3B0aW9uLnByb3AoJ2NoZWNrZWQnLCB0cnVlKVxuICBcbiAgICBpZiBjaGFuZ2VcbiAgICAgICRjdXJyZW50T3B0aW9uLnRyaWdnZXIoJ2NoYW5nZScpXG4gICAgICAkY3VycmVudE9wdGlvbi5mb2N1cygpXG4gICAgXG4gIHByZXZpb3VzTW9udGg6IChub3cpIC0+XG4gICAgaWYgbm93LmdldE1vbnRoKCkgPT0gMFxuICAgICAgbmV3IERhdGUobm93LmdldEZ1bGxZZWFyKCkgLSAxLCAxMSwgMSlcbiAgICBlbHNlXG4gICAgICBuZXcgRGF0ZShub3cuZ2V0RnVsbFllYXIoKSwgbm93LmdldE1vbnRoKCkgLSAxLCAxKVxuICAgIFxuICBuZXh0TW9udGg6IChub3cpIC0+XG4gICAgaWYgbm93LmdldE1vbnRoKCkgPT0gMTFcbiAgICAgIG5ldyBEYXRlKG5vdy5nZXRGdWxsWWVhcigpICsgMSwgMTEsIDEpXG4gICAgZWxzZVxuICAgICAgbmV3IERhdGUobm93LmdldEZ1bGxZZWFyKCksIG5vdy5nZXRNb250aCgpICsgMSwgMSlcblxuICBhdHRhY2hBcnJvd0tleXNUb09wdGlvbnM6IC0+XG4gICAgQCRvcHRpb25zLmtleWRvd24gKGUpID0+XG4gICAgICBpZiBlLndoaWNoID09IDM3IHx8IGUud2hpY2ggPT0gMzggfHwgZS53aGljaCA9PSAzOSB8fCBlLndoaWNoID09IDQwXG4gICAgICAgIGlmIGUud2hpY2ggPT0gMzdcbiAgICAgICAgICBAbW92ZVNlbGVjdGlvbignbGVmdCcpXG4gICAgICAgIGVsc2UgaWYgZS53aGljaCA9PSAzOFxuICAgICAgICAgIEBtb3ZlU2VsZWN0aW9uKCd1cCcpXG4gICAgICAgIGVsc2UgaWYgZS53aGljaCA9PSAzOVxuICAgICAgICAgIEBtb3ZlU2VsZWN0aW9uKCdyaWdodCcpXG4gICAgICAgIGVsc2UgaWYgZS53aGljaCA9PSA0MFxuICAgICAgICAgIEBtb3ZlU2VsZWN0aW9uKCdkb3duJylcbiAgICAgICAgICBcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpICMgVE9ETzogVGVzdCFcbiAgXG4gIGF0dGFjaENoYW5nZUV2ZW50VG9PcHRpb25zOiAtPlxuICAgIEAkb3B0aW9ucy5jaGFuZ2UgKGUpID0+XG4gICAgICBAYXBwbHlDaGVja2VkT3B0aW9uVG9JbnB1dCgpXG5cbiAgYXBwbHlDaGVja2VkT3B0aW9uVG9JbnB1dEFuZFJlc2V0T3B0aW9uczogLT5cbiAgICBAYXBwbHlDaGVja2VkT3B0aW9uVG9JbnB1dCgpXG4gICAgQGhpZGVPcHRpb25zKClcblxuICBhcHBseUNoZWNrZWRPcHRpb25Ub0lucHV0OiAtPlxuICAgICRwcmV2aW91c2x5Q2hlY2tlZE9wdGlvbkxhYmVsID0gJChcIlsje0BhZGdEYXRhQXR0cmlidXRlTmFtZSgnb3B0aW9uLXNlbGVjdGVkJyl9XVwiKVxuICAgIGlmICRwcmV2aW91c2x5Q2hlY2tlZE9wdGlvbkxhYmVsLmxlbmd0aCA9PSAxXG4gICAgICBAcmVtb3ZlQWRnRGF0YUF0dHJpYnV0ZSgkcHJldmlvdXNseUNoZWNrZWRPcHRpb25MYWJlbCwgJ29wdGlvbi1zZWxlY3RlZCcpXG5cbiAgICAkY2hlY2tlZE9wdGlvbiA9IEAkb3B0aW9ucy5maWx0ZXIoJzpjaGVja2VkJylcbiAgICBpZiAkY2hlY2tlZE9wdGlvbi5sZW5ndGggPT0gMVxuICAgICAgJGNoZWNrZWRPcHRpb25MYWJlbCA9IEBsYWJlbE9mSW5wdXQoJGNoZWNrZWRPcHRpb24pXG4gICAgICBAJGlucHV0LnZhbCgkLnRyaW0oJGNoZWNrZWRPcHRpb25MYWJlbC50ZXh0KCkpKVxuICAgICAgQGFkZEFkZ0RhdGFBdHRyaWJ1dGUoJGNoZWNrZWRPcHRpb25MYWJlbCwgJ29wdGlvbi1zZWxlY3RlZCcpXG4gICAgZWxzZVxuICAgICAgQCRpbnB1dC52YWwoJycpXG5cbiAgYXR0YWNoQ2xpY2tFdmVudFRvT3B0aW9uTGFiZWxzOiAtPlxuICAgIEBsYWJlbE9mSW5wdXQoQCRvcHRpb25zKS5jbGljayAoZSkgPT5cbiAgICAgIEBoaWRlT3B0aW9ucygpXG5cbiAgYXR0YWNoRW50ZXJFdmVudFRvT3B0aW9uczogLT5cbiAgICBAJG9wdGlvbnMua2V5ZG93biAoZSkgPT5cbiAgICAgIGlmIGUud2hpY2ggPT0gMTNcbiAgICAgICAgQGhpZGVPcHRpb25zKClcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKClcblxuICBhdHRhY2hUYWJFdmVudFRvT3B0aW9uczogLT5cbiAgICBAJG9wdGlvbnMua2V5ZG93biAoZSkgPT5cbiAgICAgIGlmIGUud2hpY2ggPT0gOVxuICAgICAgICBAaGlkZU9wdGlvbnMoKVxuICAgIFxuJChkb2N1bWVudCkucmVhZHkgLT5cbiAgJCgnW2RhdGEtYWRnLWRhdGVwaWNrZXJdJykuZWFjaCAtPlxuICAgIG5ldyBBZGdEYXRlcGlja2VyIEAiXX0=
//# sourceURL=coffeescript

Company

  • About
  • Blog
  • Careers
  • Contact

Services

  • Accessibility Audits
  • Accessibility Consulting
  • VPAT/ACR
  • Accessibility Trainings

Compliance

  • WCAG
  • ADA
  • Section 508
  • EN 301 549
  • EAA
  • AODA Compliance Services — Make Your Digital Assets Accessible in Ontario
  • ACA

Resources

  • Accessibility Resources
  • Understanding WCAG
  • WCAG Checklist
  • Understanding WAI-ARIA

Legal

  • Privacy Policy
  • Terms and Conditions
  • Disclaimer
  • Accessibility Statement for digitala11y.com
  • Sitemap

© 2025 DigitalA11Y
All Rights Reserved

Linkedin Twitter Facebook Instagram YouTube

DigitalA11Y
Plot No 108, 3rd Cross Rd, Saipuri Colony,
Hastinapuri Colony, Sainikpuri, Secunderabad -500094
Telangana, India.

Tel:(+91)99082 66680,
E-mail: [email protected]

Scroll to top
  • Home
  • Services
    • WCAG Audit Services
    • VPAT/ACR Services
    • Accessibility Consulting
    • PDF Remediation
    • Accessibility Trainings
    • Website Remediation
    • Design Audit
  • Free Tools
    • Accessibility Checker
    • A11Y Cost Calculator
    • A11Y Bookmarklets
    • Color Contrast Extension
    • WCAG Contrast Checker
  • Resources
    • A11Y Articles
    • WCAG Primer
    • ARIA Cheatsheet
    • A11Y Tools
    • A11Y Patterns
    • A11Y Cheatsheets
  • Contact