Autosuggest with Radio Buttons
Code
<p>
<button>Focusable element before</button>
</p>
<form>
<div data-adg-autosuggest="">
<div class="control">
<label for="favorite_hobby_filter">Favorite hobby </label><input aria-describedby="favorite_hobby_filter_help" id="favorite_hobby_filter" type="text" />
<fieldset hidden="">
<legend>Favorite hobby suggestions</legend>
<div class="control">
<input id="favorite_hobby_hiking" name="hobby" type="radio" /><label for="favorite_hobby_hiking">Hiking</label>
</div>
<div class="control">
<input id="favorite_hobby_dancing" name="hobby" type="radio" /><label for="favorite_hobby_dancing">Dancing</label>
</div>
<div class="control">
<input id="favorite_hobby_gardening" name="hobby" type="radio" /><label for="favorite_hobby_gardening">Gardening</label>
</div>
<div class="control">
<input id="favorite_hobby_meditation" name="hobby" type="radio" /><label for="favorite_hobby_meditation">Meditation</label>
</div>
<div class="control">
<input id="favorite_hobby_gaming" name="hobby" type="radio" /><label for="favorite_hobby_gaming">Gaming</label>
</div>
</fieldset>
<div class="description" id="favorite_hobby_filter_help">
Provides auto-suggestions when entering text
</div>
</div>
</div>
</form>
<p>
<button>Focusable element after</button>
</p>
@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-autosuggest-options] {
position: absolute;
z-index: 1;
background-color: lightyellow;
border: 1px solid;
padding: 5px 0;
}
[data-adg-autosuggest-option] {
display: block;
}
[data-adg-autosuggest-option]:hover,
[data-adg-autosuggest-option-selected] {
cursor: pointer;
background-color: #000;
color: lightyellow;
}
[data-adg-autosuggest-alerts] p {
margin: 0;
}
[data-adg-autosuggest-alerts] kbd::before {
content: "«";
}
[data-adg-autosuggest-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 {
min-width: 144px;
}
(function() {
// Tested in JAWS+IE/FF, NVDA+FF
// Known issues:
// - JAWS leaves the input when using up/down without entering something (I guess this is due to screen layout and can be considered intended)
// - Alert not perceivable upon opening options using up/down
// - Possible solution 1: always show options count when filter focused?
// - Possible solution 2: wait a moment before adding the alert?
// - VoiceOver/iOS announces radio buttons as disabled?!
// - iOS doesn't select all text when option was chosen
// In general: alerts seem to be most robust in all relevant browsers, but aren't polite. Maybe we'll find a better mechanism to serve browsers individually?
var AdgAutocomplete;
AdgAutocomplete = (function() {
var config, uniqueIdCount;
class AdgAutocomplete {
constructor(el, options = {}) {
var jsonOptions, key, val;
this.$el = $(el);
this.config = config;
for (key in options) {
val = options[key];
this.config[key] = val;
}
jsonOptions = this.$el.attr(this.adgDataAttributeName());
if (jsonOptions) {
for (key in jsonOptions) {
val = jsonOptions[key];
this.config[key] = val;
}
}
this.debugMessage('start');
this.initFilter();
this.initOptions();
this.initAlerts();
this.applyCheckedOptionToFilter();
this.announceOptionsNumber('');
this.attachEvents();
}
// Prints the given message to the console if config['debug'] is true.
debugMessage(message) {
if (this.config.debugMessage) {
return console.log(`Adg debug: ${message}`);
}
}
// 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-autosuggest";
}
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;
}
uniqueId(name) {
return [this.name(), name, uniqueIdCount++].join('-');
}
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;
}
initFilter() {
this.$filter = this.findOne('input[type="text"]');
this.addAdgDataAttribute(this.$filter, 'filter');
this.$filter.attr('autocomplete', 'off');
return this.$filter.attr('aria-expanded', 'false');
}
initOptions() {
this.$optionsContainer = this.findOne(this.config.optionsContainer);
this.addAdgDataAttribute(this.$optionsContainer, 'options');
this.$optionsContainerLabel = this.findOne(this.config.optionsContainerLabel);
this.$optionsContainerLabel.addClass(this.config.hiddenCssClass);
this.$options = this.$optionsContainer.find('input[type="radio"]');
this.addAdgDataAttribute(this.labelOfInput(this.$options), 'option');
return this.$options.addClass(this.config.hiddenCssClass);
}
initAlerts() {
this.$alertsContainer = $(`<div id='${this.uniqueId(this.config.alertsContainerId)}'></div>`);
this.$optionsContainerLabel.after(this.$alertsContainer);
this.$filter.attr('aria-describedby', [this.$filter.attr('aria-describedby'), this.$alertsContainer.attr('id')].join(' ').trim());
return this.addAdgDataAttribute(this.$alertsContainer, 'alerts');
}
attachEvents() {
this.attachClickEventToFilter();
this.attachChangeEventToFilter();
this.attachEscapeKeyToFilter();
this.attachEnterKeyToFilter();
this.attachTabKeyToFilter();
this.attachUpDownKeysToFilter();
this.attachChangeEventToOptions();
return this.attachClickEventToOptions();
}
attachClickEventToFilter() {
return this.$filter.click(() => {
this.debugMessage('click filter');
if (this.$optionsContainer.is(':visible')) {
return this.hideOptions();
} else {
return this.showOptions();
}
});
}
attachEscapeKeyToFilter() {
return this.$filter.keydown((e) => {
if (e.which === 27) {
if (this.$optionsContainer.is(':visible')) {
this.applyCheckedOptionToFilterAndResetOptions();
return e.preventDefault();
} else if (this.$options.is(':checked')) {
this.$options.prop('checked', false);
this.applyCheckedOptionToFilterAndResetOptions();
return e.preventDefault(); // Needed for automatic testing only
} else {
return $('body').append('<p>Esc passed on.</p>');
}
}
});
}
attachEnterKeyToFilter() {
return this.$filter.keydown((e) => {
if (e.which === 13) {
this.debugMessage('enter');
if (this.$optionsContainer.is(':visible')) {
this.applyCheckedOptionToFilterAndResetOptions();
return e.preventDefault(); // Needed for automatic testing only
} else {
return $('body').append('<p>Enter passed on.</p>');
}
}
});
}
attachTabKeyToFilter() {
return this.$filter.keydown((e) => {
if (e.which === 9) {
this.debugMessage('tab');
if (this.$optionsContainer.is(':visible')) {
return this.applyCheckedOptionToFilterAndResetOptions();
}
}
});
}
attachUpDownKeysToFilter() {
return this.$filter.keydown((e) => {
if (e.which === 38 || e.which === 40) {
if (this.$optionsContainer.is(':visible')) {
if (e.which === 38) {
this.moveSelection('up');
} else {
this.moveSelection('down');
}
} else {
this.showOptions();
}
return e.preventDefault(); // TODO: Test!
}
});
}
showOptions() {
this.debugMessage('(show options)');
this.show(this.$optionsContainer);
return this.$filter.attr('aria-expanded', 'true');
}
hideOptions() {
this.debugMessage('(hide options)');
this.hide(this.$optionsContainer);
return this.$filter.attr('aria-expanded', 'false');
}
moveSelection(direction) {
var $upcomingOption, $visibleOptions, currentIndex, maxIndex, upcomingIndex;
$visibleOptions = this.$options.filter(':visible');
maxIndex = $visibleOptions.length - 1;
currentIndex = $visibleOptions.index($visibleOptions.parent().find(':checked')); // TODO: is parent() good here?!
upcomingIndex = direction === 'up' ? currentIndex <= 0 ? maxIndex : currentIndex - 1 : currentIndex === maxIndex ? 0 : currentIndex + 1;
$upcomingOption = $($visibleOptions[upcomingIndex]);
return $upcomingOption.prop('checked', true).trigger('change');
}
attachChangeEventToOptions() {
return this.$options.change((e) => {
this.debugMessage('option change');
this.applyCheckedOptionToFilter();
return this.$filter.focus().select();
});
}
applyCheckedOptionToFilterAndResetOptions() {
this.applyCheckedOptionToFilter();
this.hideOptions();
return this.filterOptions();
}
applyCheckedOptionToFilter() {
var $checkedOption, $checkedOptionLabel, $previouslyCheckedOptionLabel;
this.debugMessage('(apply option to filter)');
$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.$filter.val($.trim($checkedOptionLabel.text()));
return this.addAdgDataAttribute($checkedOptionLabel, 'option-selected');
} else {
return this.$filter.val('');
}
}
attachClickEventToOptions() {
return this.$options.click((e) => {
this.debugMessage('click option');
return this.hideOptions();
});
}
attachChangeEventToFilter() {
return this.$filter.on('input propertychange paste', (e) => {
this.debugMessage('(filter changed)');
this.filterOptions(e.target.value);
return this.showOptions();
});
}
filterOptions(filter = '') {
var fuzzyFilter, visibleNumber;
fuzzyFilter = this.fuzzifyFilter(filter);
visibleNumber = 0;
this.$options.each((i, el) => {
var $option, $optionContainer, regex;
$option = $(el);
$optionContainer = $option.parent();
regex = new RegExp(fuzzyFilter, 'i');
if (regex.test($optionContainer.text())) {
visibleNumber++;
return this.show($optionContainer);
} else {
return this.hide($optionContainer);
}
});
return this.announceOptionsNumber(filter, visibleNumber);
}
announceOptionsNumber(filter = this.$filter.val(), number = this.$options.length) {
var message;
this.$alertsContainer.find('p').remove(); // Remove previous alerts (I'm not sure whether this is the best solution, maybe hiding them would be more robust?)
message = filter === '' ? this.text('numberInTotal', {
number: number
}) : this.text('numberFiltered', {
number: number,
total: this.$options.length,
filter: `<kbd>${filter}</kbd>`
});
return this.$alertsContainer.append(`<p role='alert'>${message}</p>`);
}
fuzzifyFilter(filter) {
var escapedCharacter, fuzzifiedFilter, i;
i = 0;
fuzzifiedFilter = '';
while (i < filter.length) {
escapedCharacter = filter.charAt(i).replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); // See https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
fuzzifiedFilter += `${escapedCharacter}.*?`;
i++;
}
return fuzzifiedFilter;
}
};
uniqueIdCount = 1;
config = {
debugMessage: false,
hiddenCssClass: 'adg-visually-hidden',
optionsContainer: 'fieldset',
optionsContainerLabel: 'legend',
alertsContainerId: 'alerts',
numberInTotalText: '[number] options in total',
numberFilteredText: '[number] of [total] options for [filter]'
};
return AdgAutocomplete;
}).call(this);
$(document).ready(function() {
return $('[data-adg-autosuggest]').each(function() {
return new AdgAutocomplete(this);
});
});
}).call(this);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiPGFub255bW91cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBVTRKO0VBQUE7Ozs7Ozs7Ozs7O0FBQUEsTUFBQTs7RUFDdEo7OztJQUFOLE1BQUEsZ0JBQUE7TUFhRSxXQUFhLENBQUMsRUFBRCxFQUFLLFVBQVUsQ0FBQSxDQUFmLENBQUE7QUFDZixZQUFBLFdBQUEsRUFBQSxHQUFBLEVBQUE7UUFBSSxJQUFDLENBQUEsR0FBRCxHQUFPLENBQUEsQ0FBRSxFQUFGO1FBRVAsSUFBQyxDQUFBLE1BQUQsR0FBVTtRQUNWLEtBQUEsY0FBQTs7VUFDRSxJQUFDLENBQUEsTUFBTSxDQUFDLEdBQUQsQ0FBUCxHQUFlO1FBRGpCO1FBR0EsV0FBQSxHQUFjLElBQUMsQ0FBQSxHQUFHLENBQUMsSUFBTCxDQUFVLElBQUMsQ0FBQSxvQkFBRCxDQUFBLENBQVY7UUFDZCxJQUFHLFdBQUg7VUFDRSxLQUFBLGtCQUFBOztZQUNFLElBQUMsQ0FBQSxNQUFNLENBQUMsR0FBRCxDQUFQLEdBQWU7VUFEakIsQ0FERjs7UUFJQSxJQUFDLENBQUEsWUFBRCxDQUFjLE9BQWQ7UUFFQSxJQUFDLENBQUEsVUFBRCxDQUFBO1FBQ0EsSUFBQyxDQUFBLFdBQUQsQ0FBQTtRQUNBLElBQUMsQ0FBQSxVQUFELENBQUE7UUFFQSxJQUFDLENBQUEsMEJBQUQsQ0FBQTtRQUNBLElBQUMsQ0FBQSxxQkFBRCxDQUF1QixFQUF2QjtRQUVBLElBQUMsQ0FBQSxZQUFELENBQUE7TUFyQlcsQ0FaZjs7OztNQW9DRSxZQUFjLENBQUMsT0FBRCxDQUFBO1FBQ1osSUFBdUMsSUFBQyxDQUFBLE1BQU0sQ0FBQyxZQUEvQztpQkFBQSxPQUFPLENBQUMsR0FBUixDQUFZLENBQUEsV0FBQSxDQUFBLENBQWMsT0FBZCxDQUFBLENBQVosRUFBQTs7TUFEWSxDQXBDaEI7OztNQXdDRSxPQUFTLENBQUMsUUFBRCxDQUFBO0FBQ1gsWUFBQTtRQUFJLE1BQUEsR0FBUyxJ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cEI7SUFEK0IsQ0FBakM7RUFEZ0IsQ0FBbEI7QUFwUzRKIiwic291cmNlc0NvbnRlbnQiOlsiIyBUZXN0ZWQgaW4gSkFXUytJRS9GRiwgTlZEQStGRlxuI1xuIyBLbm93biBpc3N1ZXM6XG4jIC0gSkFXUyBsZWF2ZXMgdGhlIGlucHV0IHdoZW4gdXNpbmcgdXAvZG93biB3aXRob3V0IGVudGVyaW5nIHNvbWV0aGluZyAoSSBndWVzcyB0aGlzIGlzIGR1ZSB0byBzY3JlZW4gbGF5b3V0IGFuZCBjYW4gYmUgY29uc2lkZXJlZCBpbnRlbmRlZClcbiMgLSBBbGVydCBub3QgcGVyY2VpdmFibGUgdXBvbiBvcGVuaW5nIG9wdGlvbnMgdXNpbmcgdXAvZG93blxuIyAgICAgLSBQb3NzaWJsZSBzb2x1dGlvbiAxOiBhbHdheXMgc2hvdyBvcHRpb25zIGNvdW50IHdoZW4gZmlsdGVyIGZvY3VzZWQ/XG4jICAgICAtIFBvc3NpYmxlIHNvbHV0aW9uIDI6IHdhaXQgYSBtb21lbnQgYmVmb3JlIGFkZGluZyB0aGUgYWxlcnQ/XG4jIC0gVm9pY2VPdmVyL2lPUyBhbm5vdW5jZXMgcmFkaW8gYnV0dG9ucyBhcyBkaXNhYmxlZD8hXG4jIC0gaU9TIGRvZXNuJ3Qgc2VsZWN0IGFsbCB0ZXh0IHdoZW4gb3B0aW9uIHdhcyBjaG9zZW5cbiNcbiMgSW4gZ2VuZXJhbDogYWxlcnRzIHNlZW0gdG8gYmUgbW9zdCByb2J1c3QgaW4gYWxsIHJlbGV2YW50IGJyb3dzZXJzLCBidXQgYXJlbid0IHBvbGl0ZS4gTWF5YmUgd2UnbGwgZmluZCBhIGJldHRlciBtZWNoYW5pc20gdG8gc2VydmUgYnJvd3NlcnMgaW5kaXZpZHVhbGx5P1xuY2xhc3MgQWRnQXV0b2NvbXBsZXRlXG4gIHVuaXF1ZUlkQ291bnQgPSAxXG4gIFxuICBjb25maWcgPVxuICAgIGRlYnVnTWVzc2FnZTogICBmYWxzZVxuICAgIGhpZGRlbkNzc0NsYXNzOiAnYWRnLXZpc3VhbGx5LWhpZGRlbidcbiAgICBcbiAgICBvcHRpb25zQ29udGFpbmVyOiAgICAgICdmaWVsZHNldCdcbiAgICBvcHRpb25zQ29udGFpbmVyTGFiZWw6ICdsZWdlbmQnXG4gICAgYWxlcnRzQ29udGFpbmVySWQ6ICAgICAnYWxlcnRzJ1xuICAgIG51bWJlckluVG90YWxUZXh0OiAgICAgJ1tudW1iZXJdIG9wdGlvbnMgaW4gdG90YWwnXG4gICAgbnVtYmVyRmlsdGVyZWRUZXh0OiAgICAnW251bWJlcl0gb2YgW3RvdGFsXSBvcHRpb25zIGZvciBbZmlsdGVyXSdcbiAgICBcbiAgY29uc3RydWN0b3I6IChlbCwgb3B0aW9ucyA9IHt9KSAtPlxuICAgIEAkZWwgPSAkKGVsKVxuXG4gICAgQGNvbmZpZyA9IGNvbmZpZ1xuICAgIGZvciBrZXksIHZhbCBvZiBvcHRpb25zXG4gICAgICBAY29uZmlnW2tleV0gPSB2YWxcbiAgICAgIFxuICAgIGpzb25PcHRpb25zID0gQCRlbC5hdHRyKEBhZGdEYXRhQXR0cmlidXRlTmFtZSgpKVxuICAgIGlmIGpzb25PcHRpb25zXG4gICAgICBmb3Iga2V5LCB2YWwgb2YganNvbk9wdGlvbnNcbiAgICAgICAgQGNvbmZpZ1trZXldID0gdmFsXG4gICAgXG4gICAgQGRlYnVnTWVzc2FnZSAnc3RhcnQnXG5cbiAgICBAaW5pdEZpbHRlcigpXG4gICAgQGluaXRPcHRpb25zKClcbiAgICBAaW5pdEFsZXJ0cygpXG4gICAgXG4gICAgQGFwcGx5Q2hlY2tlZE9wdGlvblRvRmlsdGVyKClcbiAgICBAYW5ub3VuY2VPcHRpb25zTnVtYmVyKCcnKVxuXG4gICAgQGF0dGFjaEV2ZW50cygpXG4gICAgXG4gICMgUHJpbnRzIHRoZSBnaXZlbiBtZXNzYWdlIHRvIHRoZSBjb25zb2xlIGlmIGNvbmZpZ1snZGVidWcnXSBpcyB0cnVlLlxuICBkZWJ1Z01lc3NhZ2U6IChtZXNzYWdlKSAtPlxuICAgIGNvbnNvbGUubG9nIFwiQWRnIGRlYnVnOiAje21lc3NhZ2V9XCIgaWYgQGNvbmZpZy5kZWJ1Z01lc3NhZ2VcblxuICAjIEV4ZWN1dGVzIHRoZSBnaXZlbiBzZWxlY3RvciBvbiBAJGVsIGFuZCByZXR1cm5zIHRoZSBlbGVtZW50LiBNYWtlcyBzdXJlIGV4YWN0bHkgb25lIGVsZW1lbnQgZXhpc3RzLlxuICBmaW5kT25lOiAoc2VsZWN0b3IpIC0+XG4gICAgcmVzdWx0ID0gQCRlbC5maW5kKHNlbGVjdG9yKVxuICAgIHN3aXRjaCByZXN1bHQubGVuZ3RoXG4gICAgICB3aGVuIDAgdGhlbiBAdGhyb3dNZXNzYWdlQW5kUHJpbnRPYmplY3RzVG9Db25zb2xlIFwiTm8gb2JqZWN0IGZvdW5kIGZvciAje3NlbGVjdG9yfSFcIiwgcmVzdWx0OiByZXN1bHRcbiAgICAgIHdoZW4gMSB0aGVuICQocmVzdWx0LmZpcnN0KCkpXG4gICAgICBlbHNlIEB0aHJvd01lc3NhZ2VBbmRQcmludE9iamVjdHNUb0NvbnNvbGUgXCJNb3JlIHRoYW4gb25lIG9iamVjdCBmb3VuZCBmb3IgI3tzZWxlY3Rvcn0hXCIsIHJlc3VsdDogcmVzdWx0XG4gICAgICAgIFxuICBuYW1lOiAtPlxuICAgIFwiYWRnLWF1dG9zdWdnZXN0XCJcbiAgICAgICAgXG4gIGFkZEFkZ0RhdGFBdHRyaWJ1dGU6ICgkdGFyZ2V0LCBuYW1lLCB2YWx1ZSA9ICcnKSAtPlxuICAgICR0YXJnZXQuYXR0cihAYWRnRGF0YUF0dHJpYnV0ZU5hbWUobmFtZSksIHZhbHVlKVxuICAgICAgICBcbiAgcmVtb3ZlQWRnRGF0YUF0dHJpYnV0ZTogKCR0YXJnZXQsIG5hbWUpIC0+XG4gICAgJHRhcmdldC5yZW1vdmVBdHRyKEBhZGdEYXRhQXR0cmlidXRlTmFtZShuYW1lKSlcbiAgICBcbiAgYWRnRGF0YUF0dHJpYnV0ZU5hbWU6IChuYW1lID0gbnVsbCkgLT5cbiAgICByZXN1bHQgPSBcImRhdGEtI3tAbmFtZSgpfVwiXG4gICAgcmVzdWx0ICs9IFwiLSN7bmFtZX1cIiBpZiBuYW1lXG4gICAgcmVzdWx0XG4gICAgXG4gIHVuaXF1ZUlkOiAobmFtZSkgLT5cbiAgICBbQG5hbWUoKSwgbmFtZSwgdW5pcXVlSWRDb3VudCsrXS5qb2luICctJ1xuICAgIFxuICBsYWJlbE9mSW5wdXQ6ICgkaW5wdXRzKSAtPlxuICAgICRpbnB1dHMubWFwIChpLCBpbnB1dCkgPT5cbiAgICAgICRpbnB1dCA9ICQoaW5wdXQpXG4gICAgICBcbiAgICAgIGlkID0gJGlucHV0LmF0dHIoJ2lkJylcbiAgICAgICRsYWJlbCA9IEBmaW5kT25lKFwibGFiZWxbZm9yPScje2lkfSddXCIpWzBdXG5cbiAgICAgIGlmICRsYWJlbC5sZW5ndGggPT0gMFxuICAgICAgICAkbGFiZWwgPSAkaW5wdXQuY2xvc2VzdCgnbGFiZWwnKVxuICAgICAgICBAdGhyb3dNZXNzYWdlQW5kUHJpbnRPYmplY3RzVG9Db25zb2xlIFwiTm8gY29ycmVzcG9uZGluZyBpbnB1dCBmb3VuZCBmb3IgaW5wdXQhXCIsIGlucHV0OiAkaW5wdXQgaWYgJGxhYmVsLmxlbmd0aCA9PSAwXG5cbiAgICAgICRsYWJlbFxuXG4gIHNob3c6ICgkZWwpIC0+XG4gICAgJGVsLnJlbW92ZUF0dHIoJ2hpZGRlbicpXG4gICAgJGVsLnNob3coKVxuXG4gICAgIyBUT0RPIFdvdWxkIGJlIGNvb2wgdG8gcmVub3VuY2UgQ1NTIGFuZCBzb2xlbHkgdXNlIHRoZSBoaWRkZW4gYXR0cmlidXRlLiBCdXQgalF1ZXJ5J3MgOnZpc2libGUgZG9lc24ndCBzZWVtIHRvIHdvcmsgd2l0aCBpdCE/XG4gICAgIyBAdGhyb3dNZXNzYWdlQW5kUHJpbnRPYmplY3RzVG9Db25zb2xlKFwiRWxlbWVudCBpcyBzdGlsbCBoaWRkZW4sIGFsdGhvdWdoIGhpZGRlbiBhdHRyaWJ1dGUgd2FzIHJlbW92ZWQhIE1ha2Ugc3VyZSB0aGVyZSdzIG5vIENTUyBsaWtlIGRpc3BsYXk6bm9uZSBvciB2aXNpYmlsaXR5OmhpZGRlbiBsZWZ0IG9uIGl0IVwiLCBlbGVtZW50OiAkZWwpIGlmICRlbC5pcygnOmhpZGRlbicpXG5cbiAgaGlkZTogKCRlbCkgLT5cbiAgICAkZWwuYXR0cignaGlkZGVuJywgJycpXG4gICAgJGVsLmhpZGUoKVxuICAgIFxuICB0aHJvd01lc3NhZ2VBbmRQcmludE9iamVjdHNUb0NvbnNvbGU6IChtZXNzYWdlLCBlbGVtZW50cyA9IHt9KSAtPlxuICAgIGNvbnNvbGUubG9nIGVsZW1lbnRzXG4gICAgdGhyb3cgbWVzc2FnZVxuICAgIFxuICB0ZXh0OiAodGV4dCwgb3B0aW9ucyA9IHt9KSAtPlxuICAgIHRleHQgPSBAY29uZmlnW1wiI3t0ZXh0fVRleHRcIl1cbiAgICBcbiAgICBmb3Iga2V5LCB2YWx1ZSBvZiBvcHRpb25zXG4gICAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlIFwiWyN7a2V5fV1cIiwgdmFsdWVcbiAgICAgIFxuICAgIHRleHRcbiAgICBcbiAgaW5pdEZpbHRlcjogLT5cbiAgICBAJGZpbHRlciA9IEBmaW5kT25lKCdpbnB1dFt0eXBlPVwidGV4dFwiXScpXG4gICAgQGFkZEFkZ0RhdGFBdHRyaWJ1dGUoQCRmaWx0ZXIsICdmaWx0ZXInKVxuICAgIEAkZmlsdGVyLmF0dHIoJ2F1dG9jb21wbGV0ZScsICdvZmYnKVxuICAgIEAkZmlsdGVyLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKVxuICAgIFxuICBpbml0T3B0aW9uczogLT5cbiAgICBAJG9wdGlvbnNDb250YWluZXIgPSBAZmluZE9uZShAY29uZmlnLm9wdGlvbnNDb250YWluZXIpXG4gICAgQGFkZEFkZ0RhdGFBdHRyaWJ1dGUoQCRvcHRpb25zQ29udGFpbmVyLCAnb3B0aW9ucycpXG4gICAgXG4gICAgQCRvcHRpb25zQ29udGFpbmVyTGFiZWwgPSBAZmluZE9uZShAY29uZmlnLm9wdGlvbnNDb250YWluZXJMYWJlbClcbiAgICBAJG9wdGlvbnNDb250YWluZXJMYWJlbC5hZGRDbGFzcyhAY29uZmlnLmhpZGRlbkNzc0NsYXNzKVxuICAgIFxuICAgIEAkb3B0aW9ucyA9IEAkb3B0aW9uc0NvbnRhaW5lci5maW5kKCdpbnB1dFt0eXBlPVwicmFkaW9cIl0nKVxuICAgIEBhZGRBZGdEYXRhQXR0cmlidXRlKEBsYWJlbE9mSW5wdXQoQCRvcHRpb25zKSwgJ29wdGlvbicpXG4gICAgQCRvcHRpb25zLmFkZENsYXNzKEBjb25maWcuaGlkZGVuQ3NzQ2xhc3MpXG4gICAgXG4gIGluaXRBbGVydHM6IC0+XG4gICAgQCRhbGVydHNDb250YWluZXIgPSAkKFwiPGRpdiBpZD0nI3tAdW5pcXVlSWQoQGNvbmZpZy5hbGVydHNDb250YWluZXJJZCl9Jz48L2Rpdj5cIilcbiAgICBAJG9wdGlvbnNDb250YWluZXJMYWJlbC5hZnRlcihAJGFsZXJ0c0NvbnRhaW5lcilcbiAgICBAJGZpbHRlci5hdHRyKCdhcmlhLWRlc2NyaWJlZGJ5JywgW0AkZmlsdGVyLmF0dHIoJ2FyaWEtZGVzY3JpYmVkYnknKSwgQCRhbGVydHNDb250YWluZXIuYXR0cignaWQnKV0uam9pbignICcpLnRyaW0oKSlcbiAgICBAYWRkQWRnRGF0YUF0dHJpYnV0ZShAJGFsZXJ0c0NvbnRhaW5lciwgJ2FsZXJ0cycpXG4gIFxuICBhdHRhY2hFdmVudHM6IC0+XG4gICAgQGF0dGFjaENsaWNrRXZlbnRUb0ZpbHRlcigpXG4gICAgQGF0dGFjaENoYW5nZUV2ZW50VG9GaWx0ZXIoKVxuICAgIFxuICAgIEBhdHRhY2hFc2NhcGVLZXlUb0ZpbHRlcigpXG4gICAgQGF0dGFjaEVudGVyS2V5VG9GaWx0ZXIoKVxuICAgIEBhdHRhY2hUYWJLZXlUb0ZpbHRlcigpXG4gICAgQGF0dGFjaFVwRG93bktleXNUb0ZpbHRlcigpXG4gICAgXG4gICAgQGF0dGFjaENoYW5nZUV2ZW50VG9PcHRpb25zKClcbiAgICBAYXR0YWNoQ2xpY2tFdmVudFRvT3B0aW9ucygpXG4gICAgXG4gIGF0dGFjaENsaWNrRXZlbnRUb0ZpbHRlcjogLT5cbiAgICBAJGZpbHRlci5jbGljayA9PlxuICAgICAgQGRlYnVnTWVzc2FnZSAnY2xpY2sgZmlsdGVyJ1xuICAgICAgaWYgQCRvcHRpb25zQ29udGFpbmVyLmlzKCc6dmlzaWJsZScpXG4gICAgICAgIEBoaWRlT3B0aW9ucygpXG4gICAgICBlbHNlXG4gICAgICAgIEBzaG93T3B0aW9ucygpXG4gICAgICBcbiAgYXR0YWNoRXNjYXBlS2V5VG9GaWx0ZXI6IC0+XG4gICAgQCRmaWx0ZXIua2V5ZG93biAoZSkgPT5cbiAgICAgIGlmIGUud2hpY2ggPT0gMjdcbiAgICAgICAgaWYgQCRvcHRpb25zQ29udGFpbmVyLmlzKCc6dmlzaWJsZScpXG4gICAgICAgICAgQGFwcGx5Q2hlY2tlZE9wdGlvblRvRmlsdGVyQW5kUmVzZXRPcHRpb25zKClcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgZWxzZSBpZiBAJG9wdGlvbnMuaXMoJzpjaGVja2VkJylcbiAgICAgICAgICBAJG9wdGlvbnMucHJvcCgnY2hlY2tlZCcsIGZhbHNlKVxuICAgICAgICAgIEBhcHBseUNoZWNrZWRPcHRpb25Ub0ZpbHRlckFuZFJlc2V0T3B0aW9ucygpXG4gICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICAgIGVsc2UgIyBOZWVkZWQgZm9yIGF1dG9tYXRpYyB0ZXN0aW5nIG9ubHlcbiAgICAgICAgICAkKCdib2R5JykuYXBwZW5kKCc8cD5Fc2MgcGFzc2VkIG9uLjwvcD4nKVxuICAgICAgXG4gIGF0dGFjaEVudGVyS2V5VG9GaWx0ZXI6IC0+XG4gICAgQCRmaWx0ZXIua2V5ZG93biAoZSkgPT5cbiAgICAgIGlmIGUud2hpY2ggPT0gMTNcbiAgICAgICAgQGRlYnVnTWVzc2FnZSAnZW50ZXInXG4gICAgICAgIGlmIEAkb3B0aW9uc0NvbnRhaW5lci5pcygnOnZpc2libGUnKVxuICAgICAgICAgIEBhcHBseUNoZWNrZWRPcHRpb25Ub0ZpbHRlckFuZFJlc2V0T3B0aW9ucygpXG4gICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICAgIGVsc2UgIyBOZWVkZWQgZm9yIGF1dG9tYXRpYyB0ZXN0aW5nIG9ubHlcbiAgICAgICAgICAkKCdib2R5JykuYXBwZW5kKCc8cD5FbnRlciBwYXNzZWQgb24uPC9wPicpXG4gICAgICBcbiAgYXR0YWNoVGFiS2V5VG9GaWx0ZXI6IC0+XG4gICAgQCRmaWx0ZXIua2V5ZG93biAoZSkgPT5cbiAgICAgIGlmIGUud2hpY2ggPT0gOVxuICAgICAgICBAZGVidWdNZXNzYWdlICd0YWInXG4gICAgICAgIGlmIEAkb3B0aW9uc0NvbnRhaW5lci5pcygnOnZpc2libGUnKVxuICAgICAgICAgIEBhcHBseUNoZWNrZWRPcHRpb25Ub0ZpbHRlckFuZFJlc2V0T3B0aW9ucygpXG4gICAgICBcbiAgYXR0YWNoVXBEb3duS2V5c1RvRmlsdGVyOiAtPlxuICAgIEAkZmlsdGVyLmtleWRvd24gKGUpID0+XG4gICAgICBpZiBlLndoaWNoID09IDM4IHx8IGUud2hpY2ggPT0gNDBcbiAgICAgICAgaWYgQCRvcHRpb25zQ29udGFpbmVyLmlzKCc6dmlzaWJsZScpXG4gICAgICAgICAgaWYgZS53aGljaCA9PSAzOFxuICAgICAgICAgICAgQG1vdmVTZWxlY3Rpb24oJ3VwJylcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBAbW92ZVNlbGVjdGlvbignZG93bicpXG4gICAgICAgIGVsc2VcbiAgICAgICAgICBAc2hvd09wdGlvbnMoKVxuICAgICAgIFxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCkgIyBUT0RPOiBUZXN0IVxuICAgIFxuICBzaG93T3B0aW9uczogLT5cbiAgICBAZGVidWdNZXNzYWdlICcoc2hvdyBvcHRpb25zKSdcbiAgICBAc2hvdyhAJG9wdGlvbnNDb250YWluZXIpXG4gICAgQCRmaWx0ZXIuYXR0cignYXJpYS1leHBhbmRlZCcsICd0cnVlJylcbiAgICBcbiAgaGlkZU9wdGlvbnM6IC0+XG4gICAgQGRlYnVnTWVzc2FnZSAnKGhpZGUgb3B0aW9ucyknXG4gICAgQGhpZGUoQCRvcHRpb25zQ29udGFpbmVyKVxuICAgIEAkZmlsdGVyLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKVxuICAgIFxuICBtb3ZlU2VsZWN0aW9uOiAoZGlyZWN0aW9uKSAtPlxuICAgICR2aXNpYmxlT3B0aW9ucyA9IEAkb3B0aW9ucy5maWx0ZXIoJzp2aXNpYmxlJylcbiAgICBcbiAgICBtYXhJbmRleCA9ICR2aXNpYmxlT3B0aW9ucy5sZW5ndGggLSAxXG4gICAgY3VycmVudEluZGV4ID0gJHZpc2libGVPcHRpb25zLmluZGV4KCR2aXNpYmxlT3B0aW9ucy5wYXJlbnQoKS5maW5kKCc6Y2hlY2tlZCcpKSAjIFRPRE86IGlzIHBhcmVudCgpIGdvb2QgaGVyZT8hXG4gICAgXG4gICAgdXBjb21pbmdJbmRleCA9IGlmIGRpcmVjdGlvbiA9PSAndXAnXG4gICAgICAgICAgICAgICAgICAgICAgaWYgY3VycmVudEluZGV4IDw9IDBcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4XG4gICAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4IC0gMVxuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgaWYgY3VycmVudEluZGV4ID09IG1heEluZGV4XG4gICAgICAgICAgICAgICAgICAgICAgICAwXG4gICAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ICsgMVxuXG4gICAgJHVwY29taW5nT3B0aW9uID0gJCgkdmlzaWJsZU9wdGlvbnNbdXBjb21pbmdJbmRleF0pXG4gICAgJHVwY29taW5nT3B0aW9uLnByb3AoJ2NoZWNrZWQnLCB0cnVlKS50cmlnZ2VyKCdjaGFuZ2UnKVxuICAgIFxuICBhdHRhY2hDaGFuZ2VFdmVudFRvT3B0aW9uczogLT5cbiAgICBAJG9wdGlvbnMuY2hhbmdlIChlKSA9PlxuICAgICAgQGRlYnVnTWVzc2FnZSAnb3B0aW9uIGNoYW5nZSdcbiAgICAgIEBhcHBseUNoZWNrZWRPcHRpb25Ub0ZpbHRlcigpXG4gICAgICBAJGZpbHRlci5mb2N1cygpLnNlbGVjdCgpXG5cbiAgYXBwbHlDaGVja2VkT3B0aW9uVG9GaWx0ZXJBbmRSZXNldE9wdGlvbnM6IC0+XG4gICAgQGFwcGx5Q2hlY2tlZE9wdGlvblRvRmlsdGVyKClcbiAgICBAaGlkZU9wdGlvbnMoKVxuICAgIEBmaWx0ZXJPcHRpb25zKClcbiAgICAgIFxuICBhcHBseUNoZWNrZWRPcHRpb25Ub0ZpbHRlcjogLT5cbiAgICBAZGVidWdNZXNzYWdlICcoYXBwbHkgb3B0aW9uIHRvIGZpbHRlciknXG4gICAgXG4gICAgJHByZXZpb3VzbHlDaGVja2VkT3B0aW9uTGFiZWwgPSAkKFwiWyN7QGFkZ0RhdGFBdHRyaWJ1dGVOYW1lKCdvcHRpb24tc2VsZWN0ZWQnKX1dXCIpXG4gICAgaWYgJHByZXZpb3VzbHlDaGVja2VkT3B0aW9uTGFiZWwubGVuZ3RoID09IDFcbiAgICAgIEByZW1vdmVBZGdEYXRhQXR0cmlidXRlKCRwcmV2aW91c2x5Q2hlY2tlZE9wdGlvbkxhYmVsLCAnb3B0aW9uLXNlbGVjdGVkJylcbiAgIFxuICAgICRjaGVja2VkT3B0aW9uID0gQCRvcHRpb25zLmZpbHRlcignOmNoZWNrZWQnKVxuICAgIGlmICRjaGVja2VkT3B0aW9uLmxlbmd0aCA9PSAxXG4gICAgICAkY2hlY2tlZE9wdGlvbkxhYmVsID0gQGxhYmVsT2ZJbnB1dCgkY2hlY2tlZE9wdGlvbilcbiAgICAgIEAkZmlsdGVyLnZhbCgkLnRyaW0oJGNoZWNrZWRPcHRpb25MYWJlbC50ZXh0KCkpKVxuICAgICAgQGFkZEFkZ0RhdGFBdHRyaWJ1dGUoJGNoZWNrZWRPcHRpb25MYWJlbCwgJ29wdGlvbi1zZWxlY3RlZCcpXG4gICAgZWxzZVxuICAgICAgQCRmaWx0ZXIudmFsKCcnKVxuICAgICAgXG4gIGF0dGFjaENsaWNrRXZlbnRUb09wdGlvbnM6IC0+XG4gICAgQCRvcHRpb25zLmNsaWNrIChlKSA9PlxuICAgICAgQGRlYnVnTWVzc2FnZSAnY2xpY2sgb3B0aW9uJ1xuICAgICAgQGhpZGVPcHRpb25zKClcbiAgICAgIFxuICBhdHRhY2hDaGFuZ2VFdmVudFRvRmlsdGVyOiAtPlxuICAgIEAkZmlsdGVyLm9uICdpbnB1dCBwcm9wZXJ0eWNoYW5nZSBwYXN0ZScsIChlKSA9PlxuICAgICAgQGRlYnVnTWVzc2FnZSAnKGZpbHRlciBjaGFuZ2VkKSdcbiAgICAgIEBmaWx0ZXJPcHRpb25zKGUudGFyZ2V0LnZhbHVlKVxuICAgICAgQHNob3dPcHRpb25zKClcbiAgICAgIFxuICBmaWx0ZXJPcHRpb25zOiAoZmlsdGVyID0gJycpIC0+XG4gICAgZnV6enlGaWx0ZXIgPSBAZnV6emlmeUZpbHRlcihmaWx0ZXIpXG4gICAgdmlzaWJsZU51bWJlciA9IDBcbiAgICBcbiAgICBAJG9wdGlvbnMuZWFjaCAoaSwgZWwpID0+XG4gICAgICAkb3B0aW9uID0gJChlbClcbiAgICAgICRvcHRpb25Db250YWluZXIgPSAkb3B0aW9uLnBhcmVudCgpXG5cbiAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChmdXp6eUZpbHRlciwgJ2knKVxuICAgICAgaWYgcmVnZXgudGVzdCgkb3B0aW9uQ29udGFpbmVyLnRleHQoKSlcbiAgICAgICAgdmlzaWJsZU51bWJlcisrXG4gICAgICAgIEBzaG93KCRvcHRpb25Db250YWluZXIpXG4gICAgICBlbHNlXG4gICAgICAgIEBoaWRlKCRvcHRpb25Db250YWluZXIpXG4gICAgICAgIFxuICAgIEBhbm5vdW5jZU9wdGlvbnNOdW1iZXIoZmlsdGVyLCB2aXNpYmxlTnVtYmVyKVxuICAgIFxuICBhbm5vdW5jZU9wdGlvbnNOdW1iZXI6IChmaWx0ZXIgPSBAJGZpbHRlci52YWwoKSwgbnVtYmVyID0gQCRvcHRpb25zLmxlbmd0aCkgLT5cbiAgICBAJGFsZXJ0c0NvbnRhaW5lci5maW5kKCdwJykucmVtb3ZlKCkgIyBSZW1vdmUgcHJldmlvdXMgYWxlcnRzIChJJ20gbm90IHN1cmUgd2hldGhlciB0aGlzIGlzIHRoZSBiZXN0IHNvbHV0aW9uLCBtYXliZSBoaWRpbmcgdGhlbSB3b3VsZCBiZSBtb3JlIHJvYnVzdD8pXG4gICAgXG4gICAgbWVzc2FnZSA9IGlmIGZpbHRlciA9PSAnJ1xuICAgICAgICAgICAgICAgIEB0ZXh0KCdudW1iZXJJblRvdGFsJywgbnVtYmVyOiBudW1iZXIpXG4gICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBAdGV4dCgnbnVtYmVyRmlsdGVyZWQnLCBudW1iZXI6IG51bWJlciwgdG90YWw6IEAkb3B0aW9ucy5sZW5ndGgsIGZpbHRlcjogXCI8a2JkPiN7ZmlsdGVyfTwva2JkPlwiKVxuICAgICAgXG4gICAgQCRhbGVydHNDb250YWluZXIuYXBwZW5kKFwiPHAgcm9sZT0nYWxlcnQnPiN7bWVzc2FnZX08L3A+XCIpXG4gICAgICAgIFxuICBmdXp6aWZ5RmlsdGVyOiAoZmlsdGVyKSAtPlxuICAgIGkgPSAwXG4gICAgZnV6emlmaWVkRmlsdGVyID0gJydcbiAgICB3aGlsZSBpIDwgZmlsdGVyLmxlbmd0aFxuICAgICAgZXNjYXBlZENoYXJhY3RlciA9IGZpbHRlci5jaGFyQXQoaSkucmVwbGFjZSgvW1xcLVxcW1xcXVxcL1xce1xcfVxcKFxcKVxcKlxcK1xcP1xcLlxcXFxcXF5cXCRcXHxdL2csIFwiXFxcXCQmXCIpICMgU2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM0NDYxNzAvZXNjYXBlLXN0cmluZy1mb3ItdXNlLWluLWphdmFzY3JpcHQtcmVnZXhcbiAgICAgIGZ1enppZmllZEZpbHRlciArPSBcIiN7ZXNjYXBlZENoYXJhY3Rlcn0uKj9cIlxuICAgICAgaSsrXG4gICAgICBcbiAgICBmdXp6aWZpZWRGaWx0ZXJcbiAgICBcbiQoZG9jdW1lbnQpLnJlYWR5IC0+XG4gICQoJ1tkYXRhLWFkZy1hdXRvc3VnZ2VzdF0nKS5lYWNoIC0+XG4gICAgbmV3IEFkZ0F1dG9jb21wbGV0ZSBAIl19
//# sourceURL=coffeescript