bosca-ceoil-electron/assets/index.js

1284 lines
800 KiB
JavaScript
Raw Normal View History

2019-07-21 17:01:39 +02:00
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/player.ts");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./instruments.yaml":
/*!**************************!*\
!*** ./instruments.yaml ***!
\**************************/
/*! no static exports found */
/***/ (function(module, exports) {
const doc = [({"midi.piano1":({"index":0, "duration":"short", "category":["MIDI", "Piano", "Grand Piano"]}), "midi.chrom1":({"index":8, "duration":"constant", "category":["MIDI", "Bells", "Celesta"]}), "midi.organ1":({"index":16, "duration":"instant", "category":["MIDI", "Organ", "Drawbar Organ"]}), "midi.guitar1":({"index":24, "duration":"short", "category":["MIDI", "Guitar", "Nylon Guitar"]}), "midi.bass1":({"index":32, "duration":"instant", "category":["MIDI", "Bass", "Acoustic Bass"]}), "midi.strings1":({"index":40, "duration":"mini", "category":["MIDI", "Strings", "Violin"]}), "midi.ensemble1":({"index":48, "duration":"mid", "category":["MIDI", "Ensemble", "String Ensemble 1"]}), "midi.brass1":({"index":56, "duration":"mini", "category":["MIDI", "Brass", "Trumpet"]}), "midi.reed1":({"index":64, "duration":"mini", "category":["MIDI", "Reed", "Soprano Sax"]}), "midi.pipe1":({"index":72, "duration":"mini", "category":["MIDI", "Pipe", "Piccolo"]}), "midi.lead1":({"index":80, "duration":"mini", "category":["MIDI", "Lead", "Square Lead"]}), "midi.pad1":({"index":88, "duration":"long", "category":["MIDI", "Pads", "New Age Pad"]}), "midi.fx1":({"index":96, "duration":"mega", "category":["MIDI", "Synth", "Rain"]}), "midi.world1":({"index":104, "duration":"extended", "category":["MIDI", "World", "Sitar"]}), "midi.percus1":({"index":112, "duration":"long", "category":["MIDI", "Drums", "Tinkle Bell"]}), "midi.se1":({"index":120, "duration":"mini", "category":["MIDI", "Effects", "Fret Noise"]}), "square":({"index":128, "duration":"infinite", "category":["Chiptune", "Square Wave"]})})];
module.exports = doc.length <= 1 ? doc[0] : doc;
/***/ }),
/***/ "./node_modules/dialog-polyfill/dist/dialog-polyfill.esm.js":
/*!******************************************************************!*\
!*** ./node_modules/dialog-polyfill/dist/dialog-polyfill.esm.js ***!
\******************************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
// nb. This is for IE10 and lower _only_.
var supportCustomEvent = window.CustomEvent;
if (!supportCustomEvent || typeof supportCustomEvent === 'object') {
supportCustomEvent = function CustomEvent(event, x) {
x = x || {};
var ev = document.createEvent('CustomEvent');
ev.initCustomEvent(event, !!x.bubbles, !!x.cancelable, x.detail || null);
return ev;
};
supportCustomEvent.prototype = window.Event.prototype;
}
/**
* @param {Element} el to check for stacking context
* @return {boolean} whether this el or its parents creates a stacking context
*/
function createsStackingContext(el) {
while (el && el !== document.body) {
var s = window.getComputedStyle(el);
var invalid = function(k, ok) {
return !(s[k] === undefined || s[k] === ok);
};
if (s.opacity < 1 ||
invalid('zIndex', 'auto') ||
invalid('transform', 'none') ||
invalid('mixBlendMode', 'normal') ||
invalid('filter', 'none') ||
invalid('perspective', 'none') ||
s['isolation'] === 'isolate' ||
s.position === 'fixed' ||
s.webkitOverflowScrolling === 'touch') {
return true;
}
el = el.parentElement;
}
return false;
}
/**
* Finds the nearest <dialog> from the passed element.
*
* @param {Element} el to search from
* @return {HTMLDialogElement} dialog found
*/
function findNearestDialog(el) {
while (el) {
if (el.localName === 'dialog') {
return /** @type {HTMLDialogElement} */ (el);
}
el = el.parentElement;
}
return null;
}
/**
* Blur the specified element, as long as it's not the HTML body element.
* This works around an IE9/10 bug - blurring the body causes Windows to
* blur the whole application.
*
* @param {Element} el to blur
*/
function safeBlur(el) {
if (el && el.blur && el !== document.body) {
el.blur();
}
}
/**
* @param {!NodeList} nodeList to search
* @param {Node} node to find
* @return {boolean} whether node is inside nodeList
*/
function inNodeList(nodeList, node) {
for (var i = 0; i < nodeList.length; ++i) {
if (nodeList[i] === node) {
return true;
}
}
return false;
}
/**
* @param {HTMLFormElement} el to check
* @return {boolean} whether this form has method="dialog"
*/
function isFormMethodDialog(el) {
if (!el || !el.hasAttribute('method')) {
return false;
}
return el.getAttribute('method').toLowerCase() === 'dialog';
}
/**
* @param {!HTMLDialogElement} dialog to upgrade
* @constructor
*/
function dialogPolyfillInfo(dialog) {
this.dialog_ = dialog;
this.replacedStyleTop_ = false;
this.openAsModal_ = false;
// Set a11y role. Browsers that support dialog implicitly know this already.
if (!dialog.hasAttribute('role')) {
dialog.setAttribute('role', 'dialog');
}
dialog.show = this.show.bind(this);
dialog.showModal = this.showModal.bind(this);
dialog.close = this.close.bind(this);
if (!('returnValue' in dialog)) {
dialog.returnValue = '';
}
if ('MutationObserver' in window) {
var mo = new MutationObserver(this.maybeHideModal.bind(this));
mo.observe(dialog, {attributes: true, attributeFilter: ['open']});
} else {
// IE10 and below support. Note that DOMNodeRemoved etc fire _before_ removal. They also
// seem to fire even if the element was removed as part of a parent removal. Use the removed
// events to force downgrade (useful if removed/immediately added).
var removed = false;
var cb = function() {
removed ? this.downgradeModal() : this.maybeHideModal();
removed = false;
}.bind(this);
var timeout;
var delayModel = function(ev) {
if (ev.target !== dialog) { return; } // not for a child element
var cand = 'DOMNodeRemoved';
removed |= (ev.type.substr(0, cand.length) === cand);
window.clearTimeout(timeout);
timeout = window.setTimeout(cb, 0);
};
['DOMAttrModified', 'DOMNodeRemoved', 'DOMNodeRemovedFromDocument'].forEach(function(name) {
dialog.addEventListener(name, delayModel);
});
}
// Note that the DOM is observed inside DialogManager while any dialog
// is being displayed as a modal, to catch modal removal from the DOM.
Object.defineProperty(dialog, 'open', {
set: this.setOpen.bind(this),
get: dialog.hasAttribute.bind(dialog, 'open')
});
this.backdrop_ = document.createElement('div');
this.backdrop_.className = 'backdrop';
this.backdrop_.addEventListener('click', this.backdropClick_.bind(this));
}
dialogPolyfillInfo.prototype = {
get dialog() {
return this.dialog_;
},
/**
* Maybe remove this dialog from the modal top layer. This is called when
* a modal dialog may no longer be tenable, e.g., when the dialog is no
* longer open or is no longer part of the DOM.
*/
maybeHideModal: function() {
if (this.dialog_.hasAttribute('open') && document.body.contains(this.dialog_)) { return; }
this.downgradeModal();
},
/**
* Remove this dialog from the modal top layer, leaving it as a non-modal.
*/
downgradeModal: function() {
if (!this.openAsModal_) { return; }
this.openAsModal_ = false;
this.dialog_.style.zIndex = '';
// This won't match the native <dialog> exactly because if the user set top on a centered
// polyfill dialog, that top gets thrown away when the dialog is closed. Not sure it's
// possible to polyfill this perfectly.
if (this.replacedStyleTop_) {
this.dialog_.style.top = '';
this.replacedStyleTop_ = false;
}
// Clear the backdrop and remove from the manager.
this.backdrop_.parentNode && this.backdrop_.parentNode.removeChild(this.backdrop_);
dialogPolyfill.dm.removeDialog(this);
},
/**
* @param {boolean} value whether to open or close this dialog
*/
setOpen: function(value) {
if (value) {
this.dialog_.hasAttribute('open') || this.dialog_.setAttribute('open', '');
} else {
this.dialog_.removeAttribute('open');
this.maybeHideModal(); // nb. redundant with MutationObserver
}
},
/**
* Handles clicks on the fake .backdrop element, redirecting them as if
* they were on the dialog itself.
*
* @param {!Event} e to redirect
*/
backdropClick_: function(e) {
if (!this.dialog_.hasAttribute('tabindex')) {
// Clicking on the backdrop should move the implicit cursor, even if dialog cannot be
// focused. Create a fake thing to focus on. If the backdrop was _before_ the dialog, this
// would not be needed - clicks would move the implicit cursor there.
var fake = document.createElement('div');
this.dialog_.insertBefore(fake, this.dialog_.firstChild);
fake.tabIndex = -1;
fake.focus();
this.dialog_.removeChild(fake);
} else {
this.dialog_.focus();
}
var redirectedEvent = document.createEvent('MouseEvents');
redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
this.dialog_.dispatchEvent(redirectedEvent);
e.stopPropagation();
},
/**
* Focuses on the first focusable element within the dialog. This will always blur the current
* focus, even if nothing within the dialog is found.
*/
focus_: function() {
// Find element with `autofocus` attribute, or fall back to the first form/tabindex control.
var target = this.dialog_.querySelector('[autofocus]:not([disabled])');
if (!target && this.dialog_.tabIndex >= 0) {
target = this.dialog_;
}
if (!target) {
// Note that this is 'any focusable area'. This list is probably not exhaustive, but the
// alternative involves stepping through and trying to focus everything.
var opts = ['button', 'input', 'keygen', 'select', 'textarea'];
var query = opts.map(function(el) {
return el + ':not([disabled])';
});
// TODO(samthor): tabindex values that are not numeric are not focusable.
query.push('[tabindex]:not([disabled]):not([tabindex=""])'); // tabindex != "", not disabled
target = this.dialog_.querySelector(query.join(', '));
}
safeBlur(document.activeElement);
target && target.focus();
},
/**
* Sets the zIndex for the backdrop and dialog.
*
* @param {number} dialogZ
* @param {number} backdropZ
*/
updateZIndex: function(dialogZ, backdropZ) {
if (dialogZ < backdropZ) {
throw new Error('dialogZ should never be < backdropZ');
}
this.dialog_.style.zIndex = dialogZ;
this.backdrop_.style.zIndex = backdropZ;
},
/**
* Shows the dialog. If the dialog is already open, this does nothing.
*/
show: function() {
if (!this.dialog_.open) {
this.setOpen(true);
this.focus_();
}
},
/**
* Show this dialog modally.
*/
showModal: function() {
if (this.dialog_.hasAttribute('open')) {
throw new Error('Failed to execute \'showModal\' on dialog: The element is already open, and therefore cannot be opened modally.');
}
if (!document.body.contains(this.dialog_)) {
throw new Error('Failed to execute \'showModal\' on dialog: The element is not in a Document.');
}
if (!dialogPolyfill.dm.pushDialog(this)) {
throw new Error('Failed to execute \'showModal\' on dialog: There are too many open modal dialogs.');
}
if (createsStackingContext(this.dialog_.parentElement)) {
console.warn('A dialog is being shown inside a stacking context. ' +
'This may cause it to be unusable. For more information, see this link: ' +
'https://github.com/GoogleChrome/dialog-polyfill/#stacking-context');
}
this.setOpen(true);
this.openAsModal_ = true;
// Optionally center vertically, relative to the current viewport.
if (dialogPolyfill.needsCentering(this.dialog_)) {
dialogPolyfill.reposition(this.dialog_);
this.replacedStyleTop_ = true;
} else {
this.replacedStyleTop_ = false;
}
// Insert backdrop.
this.dialog_.parentNode.insertBefore(this.backdrop_, this.dialog_.nextSibling);
// Focus on whatever inside the dialog.
this.focus_();
},
/**
* Closes this HTMLDialogElement. This is optional vs clearing the open
* attribute, however this fires a 'close' event.
*
* @param {string=} opt_returnValue to use as the returnValue
*/
close: function(opt_returnValue) {
if (!this.dialog_.hasAttribute('open')) {
throw new Error('Failed to execute \'close\' on dialog: The element does not have an \'open\' attribute, and therefore cannot be closed.');
}
this.setOpen(false);
// Leave returnValue untouched in case it was set directly on the element
if (opt_returnValue !== undefined) {
this.dialog_.returnValue = opt_returnValue;
}
// Triggering "close" event for any attached listeners on the <dialog>.
var closeEvent = new supportCustomEvent('close', {
bubbles: false,
cancelable: false
});
this.dialog_.dispatchEvent(closeEvent);
}
};
var dialogPolyfill = {};
dialogPolyfill.reposition = function(element) {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
element.style.top = Math.max(scrollTop, topValue) + 'px';
};
dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
for (var i = 0; i < document.styleSheets.length; ++i) {
var styleSheet = document.styleSheets[i];
var cssRules = null;
// Some browsers throw on cssRules.
try {
cssRules = styleSheet.cssRules;
} catch (e) {}
if (!cssRules) { continue; }
for (var j = 0; j < cssRules.length; ++j) {
var rule = cssRules[j];
var selectedNodes = null;
// Ignore errors on invalid selector texts.
try {
selectedNodes = document.querySelectorAll(rule.selectorText);
} catch(e) {}
if (!selectedNodes || !inNodeList(selectedNodes, element)) {
continue;
}
var cssTop = rule.style.getPropertyValue('top');
var cssBottom = rule.style.getPropertyValue('bottom');
if ((cssTop && cssTop !== 'auto') || (cssBottom && cssBottom !== 'auto')) {
return true;
}
}
}
return false;
};
dialogPolyfill.needsCentering = function(dialog) {
var computedStyle = window.getComputedStyle(dialog);
if (computedStyle.position !== 'absolute') {
return false;
}
// We must determine whether the top/bottom specified value is non-auto. In
// WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
// Firefox returns the used value. So we do this crazy thing instead: check
// the inline style and then go through CSS rules.
if ((dialog.style.top !== 'auto' && dialog.style.top !== '') ||
(dialog.style.bottom !== 'auto' && dialog.style.bottom !== '')) {
return false;
}
return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
};
/**
* @param {!Element} element to force upgrade
*/
dialogPolyfill.forceRegisterDialog = function(element) {
if (window.HTMLDialogElement || element.showModal) {
console.warn('This browser already supports <dialog>, the polyfill ' +
'may not work correctly', element);
}
if (element.localName !== 'dialog') {
throw new Error('Failed to register dialog: The element is not a dialog.');
}
new dialogPolyfillInfo(/** @type {!HTMLDialogElement} */ (element));
};
/**
* @param {!Element} element to upgrade, if necessary
*/
dialogPolyfill.registerDialog = function(element) {
if (!element.showModal) {
dialogPolyfill.forceRegisterDialog(element);
}
};
/**
* @constructor
*/
dialogPolyfill.DialogManager = function() {
/** @type {!Array<!dialogPolyfillInfo>} */
this.pendingDialogStack = [];
var checkDOM = this.checkDOM_.bind(this);
// The overlay is used to simulate how a modal dialog blocks the document.
// The blocking dialog is positioned on top of the overlay, and the rest of
// the dialogs on the pending dialog stack are positioned below it. In the
// actual implementation, the modal dialog stacking is controlled by the
// top layer, where z-index has no effect.
this.overlay = document.createElement('div');
this.overlay.className = '_dialog_overlay';
this.overlay.addEventListener('click', function(e) {
this.forwardTab_ = undefined;
e.stopPropagation();
checkDOM([]); // sanity-check DOM
}.bind(this));
this.handleKey_ = this.handleKey_.bind(this);
this.handleFocus_ = this.handleFocus_.bind(this);
this.zIndexLow_ = 100000;
this.zIndexHigh_ = 100000 + 150;
this.forwardTab_ = undefined;
if ('MutationObserver' in window) {
this.mo_ = new MutationObserver(function(records) {
var removed = [];
records.forEach(function(rec) {
for (var i = 0, c; c = rec.removedNodes[i]; ++i) {
if (!(c instanceof Element)) {
continue;
} else if (c.localName === 'dialog') {
removed.push(c);
}
removed = removed.concat(c.querySelectorAll('dialog'));
}
});
removed.length && checkDOM(removed);
});
}
};
/**
* Called on the first modal dialog being shown. Adds the overlay and related
* handlers.
*/
dialogPolyfill.DialogManager.prototype.blockDocument = function() {
document.documentElement.addEventListener('focus', this.handleFocus_, true);
document.addEventListener('keydown', this.handleKey_);
this.mo_ && this.mo_.observe(document, {childList: true, subtree: true});
};
/**
* Called on the first modal dialog being removed, i.e., when no more modal
* dialogs are visible.
*/
dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
document.documentElement.removeEventListener('focus', this.handleFocus_, true);
document.removeEventListener('keydown', this.handleKey_);
this.mo_ && this.mo_.disconnect();
};
/**
* Updates the stacking of all known dialogs.
*/
dialogPolyfill.DialogManager.prototype.updateStacking = function() {
var zIndex = this.zIndexHigh_;
for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) {
dpi.updateZIndex(--zIndex, --zIndex);
if (i === 0) {
this.overlay.style.zIndex = --zIndex;
}
}
// Make the overlay a sibling of the dialog itself.
var last = this.pendingDialogStack[0];
if (last) {
var p = last.dialog.parentNode || document.body;
p.appendChild(this.overlay);
} else if (this.overlay.parentNode) {
this.overlay.parentNode.removeChild(this.overlay);
}
};
/**
* @param {Element} candidate to check if contained or is the top-most modal dialog
* @return {boolean} whether candidate is contained in top dialog
*/
dialogPolyfill.DialogManager.prototype.containedByTopDialog_ = function(candidate) {
while (candidate = findNearestDialog(candidate)) {
for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) {
if (dpi.dialog === candidate) {
return i === 0; // only valid if top-most
}
}
candidate = candidate.parentElement;
}
return false;
};
dialogPolyfill.DialogManager.prototype.handleFocus_ = function(event) {
if (this.containedByTopDialog_(event.target)) { return; }
if (document.activeElement === document.documentElement) { return; }
event.preventDefault();
event.stopPropagation();
safeBlur(/** @type {Element} */ (event.target));
if (this.forwardTab_ === undefined) { return; } // move focus only from a tab key
var dpi = this.pendingDialogStack[0];
var dialog = dpi.dialog;
var position = dialog.compareDocumentPosition(event.target);
if (position & Node.DOCUMENT_POSITION_PRECEDING) {
if (this.forwardTab_) {
// forward
dpi.focus_();
} else if (event.target !== document.documentElement) {
// backwards if we're not already focused on <html>
document.documentElement.focus();
}
}
return false;
};
dialogPolyfill.DialogManager.prototype.handleKey_ = function(event) {
this.forwardTab_ = undefined;
if (event.keyCode === 27) {
event.preventDefault();
event.stopPropagation();
var cancelEvent = new supportCustomEvent('cancel', {
bubbles: false,
cancelable: true
});
var dpi = this.pendingDialogStack[0];
if (dpi && dpi.dialog.dispatchEvent(cancelEvent)) {
dpi.dialog.close();
}
} else if (event.keyCode === 9) {
this.forwardTab_ = !event.shiftKey;
}
};
/**
* Finds and downgrades any known modal dialogs that are no longer displayed. Dialogs that are
* removed and immediately readded don't stay modal, they become normal.
*
* @param {!Array<!HTMLDialogElement>} removed that have definitely been removed
*/
dialogPolyfill.DialogManager.prototype.checkDOM_ = function(removed) {
// This operates on a clone because it may cause it to change. Each change also calls
// updateStacking, which only actually needs to happen once. But who removes many modal dialogs
// at a time?!
var clone = this.pendingDialogStack.slice();
clone.forEach(function(dpi) {
if (removed.indexOf(dpi.dialog) !== -1) {
dpi.downgradeModal();
} else {
dpi.maybeHideModal();
}
});
};
/**
* @param {!dialogPolyfillInfo} dpi
* @return {boolean} whether the dialog was allowed
*/
dialogPolyfill.DialogManager.prototype.pushDialog = function(dpi) {
var allowed = (this.zIndexHigh_ - this.zIndexLow_) / 2 - 1;
if (this.pendingDialogStack.length >= allowed) {
return false;
}
if (this.pendingDialogStack.unshift(dpi) === 1) {
this.blockDocument();
}
this.updateStacking();
return true;
};
/**
* @param {!dialogPolyfillInfo} dpi
*/
dialogPolyfill.DialogManager.prototype.removeDialog = function(dpi) {
var index = this.pendingDialogStack.indexOf(dpi);
if (index === -1) { return; }
this.pendingDialogStack.splice(index, 1);
if (this.pendingDialogStack.length === 0) {
this.unblockDocument();
}
this.updateStacking();
};
dialogPolyfill.dm = new dialogPolyfill.DialogManager();
dialogPolyfill.formSubmitter = null;
dialogPolyfill.useValue = null;
/**
* Installs global handlers, such as click listers and native method overrides. These are needed
* even if a no dialog is registered, as they deal with <form method="dialog">.
*/
if (window.HTMLDialogElement === undefined) {
/**
* If HTMLFormElement translates method="DIALOG" into 'get', then replace the descriptor with
* one that returns the correct value.
*/
var testForm = document.createElement('form');
testForm.setAttribute('method', 'dialog');
if (testForm.method !== 'dialog') {
var methodDescriptor = Object.getOwnPropertyDescriptor(HTMLFormElement.prototype, 'method');
if (methodDescriptor) {
// nb. Some older iOS and older PhantomJS fail to return the descriptor. Don't do anything
// and don't bother to update the element.
var realGet = methodDescriptor.get;
methodDescriptor.get = function() {
if (isFormMethodDialog(this)) {
return 'dialog';
}
return realGet.call(this);
};
var realSet = methodDescriptor.set;
methodDescriptor.set = function(v) {
if (typeof v === 'string' && v.toLowerCase() === 'dialog') {
return this.setAttribute('method', v);
}
return realSet.call(this, v);
};
Object.defineProperty(HTMLFormElement.prototype, 'method', methodDescriptor);
}
}
/**
* Global 'click' handler, to capture the <input type="submit"> or <button> element which has
* submitted a <form method="dialog">. Needed as Safari and others don't report this inside
* document.activeElement.
*/
document.addEventListener('click', function(ev) {
dialogPolyfill.formSubmitter = null;
dialogPolyfill.useValue = null;
if (ev.defaultPrevented) { return; } // e.g. a submit which prevents default submission
var target = /** @type {Element} */ (ev.target);
if (!target || !isFormMethodDialog(target.form)) { return; }
var valid = (target.type === 'submit' && ['button', 'input'].indexOf(target.localName) > -1);
if (!valid) {
if (!(target.localName === 'input' && target.type === 'image')) { return; }
// this is a <input type="image">, which can submit forms
dialogPolyfill.useValue = ev.offsetX + ',' + ev.offsetY;
}
var dialog = findNearestDialog(target);
if (!dialog) { return; }
dialogPolyfill.formSubmitter = target;
}, false);
/**
* Replace the native HTMLFormElement.submit() method, as it won't fire the
* submit event and give us a chance to respond.
*/
var nativeFormSubmit = HTMLFormElement.prototype.submit;
var replacementFormSubmit = function () {
if (!isFormMethodDialog(this)) {
return nativeFormSubmit.call(this);
}
var dialog = findNearestDialog(this);
dialog && dialog.close();
};
HTMLFormElement.prototype.submit = replacementFormSubmit;
/**
* Global form 'dialog' method handler. Closes a dialog correctly on submit
* and possibly sets its return value.
*/
document.addEventListener('submit', function(ev) {
var form = /** @type {HTMLFormElement} */ (ev.target);
if (!isFormMethodDialog(form)) { return; }
ev.preventDefault();
var dialog = findNearestDialog(form);
if (!dialog) { return; }
// Forms can only be submitted via .submit() or a click (?), but anyway: sanity-check that
// the submitter is correct before using its value as .returnValue.
var s = dialogPolyfill.formSubmitter;
if (s && s.form === form) {
dialog.close(dialogPolyfill.useValue || s.value);
} else {
dialog.close();
}
dialogPolyfill.formSubmitter = null;
}, true);
}
/* harmony default export */ __webpack_exports__["default"] = (dialogPolyfill);
/***/ }),
/***/ "./node_modules/tone/build/Tone.js":
/*!*****************************************!*\
!*** ./node_modules/tone/build/Tone.js ***!
\*****************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
!function(t,e){ true?module.exports=e():undefined}("undefined"!=typeof self?self:this,function(){return function(t){var e={};function i(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,i),o.l=!0,o.exports}return i.m=t,i.c=e,i.d=function(t,e,n){i.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:n})},i.r=function(t){Object.defineProperty(t,"__esModule",{value:!0})},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=155)}([function(t,e,i){(function(n){var o,s;
/**
* Tone.js
* @author Yotam Mann
* @license http://opensource.org/licenses/MIT MIT License
* @copyright 2014-2019 Yotam Mann
*/o=[i(153)],void 0===(s=function(t){"use strict";var e=function(){if(!(this instanceof e))throw new Error("constructor needs to be called with the 'new' keyword")};return e.prototype.toString=function(){for(var t in e){var i=t[0].match(/^[A-Z]$/),n=e[t]===this.constructor;if(e.isFunction(e[t])&&i&&n)return t}return"Tone"},e.prototype.dispose=function(){return this},e.prototype.set=function(t,i,n){if(e.isObject(t))n=i;else if(e.isString(t)){var o={};o[t]=i,t=o}t:for(var s in t){i=t[s];var r=this;if(-1!==s.indexOf(".")){for(var a=s.split("."),l=0;l<a.length-1;l++)if((r=r[a[l]])instanceof e){a.splice(0,l+1);var h=a.join(".");r.set(h,i);continue t}s=a[a.length-1]}var u=r[s];e.isUndef(u)||(e.Signal&&u instanceof e.Signal||e.Param&&u instanceof e.Param?u.value!==i&&(e.isUndef(n)?u.value=i:u.rampTo(i,n)):u instanceof AudioParam?u.value!==i&&(u.value=i):e.TimeBase&&u instanceof e.TimeBase?r[s]=i:u instanceof e?u.set(i):u!==i&&(r[s]=i))}return this},e.prototype.get=function(t){e.isUndef(t)?t=this._collectDefaults(this.constructor):e.isString(t)&&(t=[t]);for(var i={},n=0;n<t.length;n++){var o=t[n],s=this,r=i;if(-1!==o.indexOf(".")){for(var a=o.split("."),l=0;l<a.length-1;l++){var h=a[l];r[h]=r[h]||{},r=r[h],s=s[h]}o=a[a.length-1]}var u=s[o];e.isObject(t[o])?r[o]=u.get():e.Signal&&u instanceof e.Signal?r[o]=u.value:e.Param&&u instanceof e.Param?r[o]=u.value:u instanceof AudioParam?r[o]=u.value:u instanceof e?r[o]=u.get():!e.isFunction(u)&&e.isDefined(u)&&(r[o]=u)}return i},e.prototype._collectDefaults=function(t){var i=[];if(e.isDefined(t.defaults)&&(i=Object.keys(t.defaults)),e.isDefined(t._super))for(var n=this._collectDefaults(t._super),o=0;o<n.length;o++)-1===i.indexOf(n[o])&&i.push(n[o]);return i},e.defaults=function(t,i,n){var o={};if(1===t.length&&e.isObject(t[0]))o=t[0];else for(var s=0;s<i.length;s++)o[i[s]]=t[s];return e.isDefined(n.defaults)?e.defaultArg(o,n.defaults):e.isObject(n)?e.defaultArg(o,n):o},e.defaultArg=function(t,i){if(e.isObject(t)&&e.isObject(i)){var n={};for(var o in t)n[o]=e.defaultArg(i[o],t[o]);for(var s in i)n[s]=e.defaultArg(t[s],i[s]);return n}return e.isUndef(t)?i:t},e.prototype.log=function(){if(this.debug||this.toString()===e.global.TONE_DEBUG_CLASS){var t=Array.from(arguments);t.unshift(this.toString()+":"),console.log.apply(void 0,t)}},e.prototype.assert=function(t,e){if(!t)throw new Error(e)},e.connectSeries=function(){for(var t=arguments[0],i=1;i<arguments.length;i++){var n=arguments[i];t.connect(n),t=n}return e},e.isUndef=function(t){return void 0===t},e.isDefined=function(t){return!e.isUndef(t)},e.isFunction=function(t){return"function"==typeof t},e.isNumber=function(t){return"number"==typeof t},e.isObject=function(t){return"[object Object]"===Object.prototype.toString.call(t)&&t.constructor===Object},e.isBoolean=function(t){return"boolean"==typeof t},e.isArray=function(t){return Array.isArray(t)},e.isString=function(t){return"string"==typeof t},e.isNote=function(t){return e.isString(t)&&/^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i.test(t)},e.noOp=function(){},e.prototype._readOnly=function(t){if(Array.isArray(t))for(var e=0;e<t.length;e++)this._readOnly(t[e]);else Object.defineProperty(this,t,{writable:!1,enumerable:!0})},e.prototype._writable=function(t){if(Array.isArray(t))for(var e=0;e<t.length;e++)this._writable(t[e]);else Object.defineProperty(this,t,{writable:!0})},e.State={Started:"started",Stopped:"stopped",Paused:"paused"},e.global=e.isUndef(n)?window:n,e.equalPowerScale=function(t){var e=.5*Math.PI;return Math.sin(t*e)},e.dbToGain=function(t){return Math.pow(10,t/20)},e.gainToDb=function(t){return Math.log(t)/Math.LN10*20},e.intervalToFrequencyRatio=function(t){return Math.pow(2,t/12)},e.prototype.now=function(){return e.context.now()},e.now=function(){return e.context.now()},e.prototype.immediate=function(){return e.context.currentTime},e.immediate=function(){return e.context.currentTime},e.extend=function(t,i){function n(){}e.isUndef(i)&&(i=e),n.prototype=i.prototype,t.prototype=new n,t.prototype.constructor=t,t._super=i},e._audioContext=null,e.start=function(){return e.context.res
//# sourceMappingURL=Tone.js.map
/***/ }),
/***/ "./src/audio.ts":
/*!**********************!*\
!*** ./src/audio.ts ***!
\**********************/
/*! exports provided: getSampler, changeSampler */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getSampler", function() { return getSampler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "changeSampler", function() { return changeSampler; });
/* harmony import */ var tone__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tone */ "./node_modules/tone/build/Tone.js");
/* harmony import */ var tone__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tone__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _index__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./index */ "./src/index.ts");
/* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./data */ "./src/data.ts");
function setSamplerRelease(sampler, instrument) {
const instrumentDuration = _data__WEBPACK_IMPORTED_MODULE_2__["instrumentData"][instrument]["duration"];
switch (instrumentDuration) {
case "instant":
sampler.release = 0.05;
break;
case "mini":
sampler.release = 0.125;
break;
case "short":
sampler.release = 0.25;
break;
case "mid":
sampler.release = 0.4;
break;
case "long":
sampler.release = 1;
break;
case "extended":
sampler.release = 1.5;
break;
case "mega":
sampler.release = 5;
break;
case "constant":
sampler.release = 30;
break;
case "infinite":
sampler.release = 0.1;
break;
default:
Object(_index__WEBPACK_IMPORTED_MODULE_1__["assertNever"])(instrumentDuration);
}
}
function setSamplerCurve(sampler) {
sampler.curve = "linear";
}
function getSampler(instrument, extension = "ogg", baseUrl = "/bosca-ceoil-js/audio/") {
let samples = {};
for (const note of _index__WEBPACK_IMPORTED_MODULE_1__["notes"]) {
samples[note] = `${instrument}/${note.toLowerCase()}.${extension}`;
}
let sampler = new tone__WEBPACK_IMPORTED_MODULE_0__["Sampler"](samples, undefined, baseUrl);
setSamplerCurve(sampler);
setSamplerRelease(sampler, instrument);
return sampler;
}
function changeSampler(sampler, instrument, extension = "ogg") {
for (const note of _index__WEBPACK_IMPORTED_MODULE_1__["notes"]) {
sampler.add(note, `${instrument}/${note.toLowerCase()}.${extension}`);
}
setSamplerCurve(sampler);
setSamplerRelease(sampler, instrument);
return sampler;
}
/***/ }),
/***/ "./src/data.ts":
/*!*********************!*\
!*** ./src/data.ts ***!
\*********************/
/*! exports provided: instrumentData */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "instrumentData", function() { return instrumentData; });
const instrumentData = __webpack_require__(/*! ../instruments.yaml */ "./instruments.yaml");
/***/ }),
/***/ "./src/index.ts":
/*!**********************!*\
!*** ./src/index.ts ***!
\**********************/
/*! exports provided: assertNever, notes */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "assertNever", function() { return assertNever; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "notes", function() { return notes; });
function assertNever(x) {
throw new Error(`Unexhaustive condition leading to value: ${x}`);
}
const notes = ["C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9"];
/***/ }),
/***/ "./src/player.ts":
/*!***********************!*\
!*** ./src/player.ts ***!
\***********************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var tone__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tone */ "./node_modules/tone/build/Tone.js");
/* harmony import */ var tone__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tone__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _audio__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./audio */ "./src/audio.ts");
const dialogPolyfill = __webpack_require__(/*! dialog-polyfill */ "./node_modules/dialog-polyfill/dist/dialog-polyfill.esm.js");
let playing = false;
const letters = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
const chords = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const volume = new tone__WEBPACK_IMPORTED_MODULE_0__["Volume"](0);
const lowPass = new tone__WEBPACK_IMPORTED_MODULE_0__["LowpassCombFilter"](0, 0);
const delayEffect = new tone__WEBPACK_IMPORTED_MODULE_0__["FeedbackDelay"](0, 0);
const chorusEffect = new tone__WEBPACK_IMPORTED_MODULE_0__["Chorus"]();
chorusEffect.wet.value = 0;
const reverbEffect = new tone__WEBPACK_IMPORTED_MODULE_0__["Freeverb"](0, 3000);
reverbEffect.wet.value = 0;
const distortionEffect = new tone__WEBPACK_IMPORTED_MODULE_0__["BitCrusher"](4);
distortionEffect.wet.value = 0;
const lowBoostEffect = new tone__WEBPACK_IMPORTED_MODULE_0__["Filter"](0, "lowshelf");
const compressorEffect = new tone__WEBPACK_IMPORTED_MODULE_0__["Compressor"](0);
const highPassEffect = new tone__WEBPACK_IMPORTED_MODULE_0__["Filter"](0, "highpass");
let instrumentName = "midi.piano1";
let sampler = Object(_audio__WEBPACK_IMPORTED_MODULE_1__["getSampler"])("midi.piano1");
let patterns = {};
for (const chord of chords) {
patterns[chord] = {};
for (const letter of letters) {
patterns[chord][letter] = Array.from({ length: 16 }, () => { return { length: 0, scheduledEvent: null }; });
}
}
function toggleAudio() {
if (playing) {
tone__WEBPACK_IMPORTED_MODULE_0__["Transport"].stop();
tone__WEBPACK_IMPORTED_MODULE_0__["Transport"].position = "0";
}
else {
resumeAudioContext();
tone__WEBPACK_IMPORTED_MODULE_0__["Transport"].loopEnd = '1m';
tone__WEBPACK_IMPORTED_MODULE_0__["Transport"].loop = true;
}
tone__WEBPACK_IMPORTED_MODULE_0__["Transport"].toggle(0);
playing = !playing;
}
function resumeAudioContext() {
let ac = tone__WEBPACK_IMPORTED_MODULE_0__["context"];
if (ac.state !== "running") {
ac.resume();
}
}
// mdl-selectfield doesn't play nice with custom onchange event listeners,
// so we use this to handle instrument changes instead.
function setInstrumentLoop(instrumentField) {
setInstrument(instrumentField);
setTimeout(() => { setInstrumentLoop(instrumentField); }, 250);
}
function setInstrument(instrumentField) {
if (instrumentName !== instrumentField.value) {
instrumentName = instrumentField.value;
Object(_audio__WEBPACK_IMPORTED_MODULE_1__["changeSampler"])(sampler, instrumentField.value);
}
}
function setBpm() {
let bpmField = document.getElementById("bpm");
if (bpmField !== null && bpmField instanceof HTMLInputElement) {
tone__WEBPACK_IMPORTED_MODULE_0__["Transport"].bpm.value = parseInt(bpmField.value);
}
}
function setVolume() {
const field = document.getElementById("volume");
if (field !== null && field instanceof HTMLInputElement) {
let newValue = parseInt(field.value);
if (newValue === 0) {
volume.mute = true;
}
else {
volume.volume.value = (newValue - 100) / 5;
volume.mute = false;
}
}
}
function setSwing() {
const field = document.getElementById("swing");
if (field !== null && field instanceof HTMLInputElement) {
tone__WEBPACK_IMPORTED_MODULE_0__["Transport"].swing = parseFloat(field.value);
tone__WEBPACK_IMPORTED_MODULE_0__["Transport"].swingSubdivision = "16n";
}
}
function setResonance() {
const field = document.getElementById("resonance");
if (field !== null && field instanceof HTMLInputElement) {
lowPass.resonance.value = parseFloat(field.value);
}
}
function setDampening() {
const field = document.getElementById("dampening");
if (field !== null && field instanceof HTMLInputElement) {
lowPass.dampening.value = parseInt(field.value);
}
}
function togglePlayButton() {
let playButton = document.getElementById("playButton");
if (playButton !== null) {
if (playButton.textContent !== null && playButton.textContent.trim().toLowerCase() === "play") {
playButton.textContent = "Stop";
}
else {
playButton.textContent = "Play";
}
}
}
function setEffect(effect, value) {
switch (effect) {
case "delay":
delayEffect.delayTime.value = value === 0 ? 0 : tone__WEBPACK_IMPORTED_MODULE_0__["Time"]("8n") * 2 * value;
delayEffect.feedback.value = 0.15 * 2 * value;
break;
case "chorus":
chorusEffect.wet.value = value;
break;
case "reverb":
reverbEffect.roomSize.value = value * 0.9;
reverbEffect.wet.value = value;
break;
case "distortion":
distortionEffect.wet.value = value === 0 ? 0 : 1;
distortionEffect.bits = value;
break;
case "lowBoost":
lowBoostEffect.frequency.value = value;
lowBoostEffect.gain.value = value === 0 ? 0 : 20;
break;
case "compressor":
compressorEffect.threshold.value = value;
break;
case "highPass":
highPassEffect.frequency.value = value;
break;
}
}
function scheduleNote(chord, letter, index, length) {
unscheduleNote(chord, letter, index);
// console.log(`scheduleNote(chord=${chord}, letter=${letter}, index=${index}, length=${length})`);
patterns[chord][letter][index]["length"] = length;
patterns[chord][letter][index]["scheduledEvent"] = tone__WEBPACK_IMPORTED_MODULE_0__["Transport"].schedule(time => {
sampler.triggerAttackRelease(`${letter}${chord}`, tone__WEBPACK_IMPORTED_MODULE_0__["Time"]("16n") * length, time);
tone__WEBPACK_IMPORTED_MODULE_0__["Draw"].schedule(() => {
const noteElement = document.querySelector(`#${letter.replace("#", "\\#")}-${chord}-${index}`);
if (noteElement !== null) {
if (length <= 1) {
noteElement.classList.add("playing");
}
else {
noteElement.classList.add("playingLong");
}
setTimeout(() => {
noteElement.classList.remove("playing");
noteElement.classList.remove("playingLong");
}, 100 * length);
}
}, time);
}, `0:0:${index}`);
}
function unscheduleNote(chord, letter, index) {
patterns[chord][letter][index]["length"] = 0;
const schedulee = patterns[chord][letter][index]["scheduledEvent"];
if (schedulee !== null) {
tone__WEBPACK_IMPORTED_MODULE_0__["Transport"].clear(schedulee);
patterns[chord][letter][index]["scheduledEvent"] = null;
}
}
function onClickNoteCell(event, cell, chord, letter, index) {
let length = patterns[chord][letter][index]["length"];
// console.log(`onClickNoteCell(chord=${chord}, letter=${letter}, index=${index}) | length ${length}`);
if (event.shiftKey && event.ctrlKey) {
length = Math.max(length - 1, 0);
}
else if (event.shiftKey) {
length = Math.max(Math.min(length + 1, 16), 2);
}
else if (length > 0) {
length = 0;
}
else {
length = 1;
}
cell.innerHTML = length.toString();
if (length <= 1) {
cell.classList.remove("noteLong");
}
else {
cell.classList.add("noteLong");
}
if (length > 0 && length !== patterns[chord][letter][index]["length"]) {
cell.classList.add("active");
scheduleNote(chord, letter, index, length);
}
else if (length === 0) {
cell.classList.remove("active");
unscheduleNote(chord, letter, index);
}
}
function onLoad() {
sampler.chain(volume, lowPass, delayEffect, chorusEffect, reverbEffect, distortionEffect, lowBoostEffect, compressorEffect, highPassEffect, tone__WEBPACK_IMPORTED_MODULE_0__["Master"]);
document.onkeypress = event => {
if (event.keyCode === 32) {
toggleAudio();
togglePlayButton();
return false;
}
};
let playButton = document.getElementById("playButton");
if (playButton !== null) {
playButton.addEventListener("click", toggleAudio);
playButton.addEventListener("click", togglePlayButton);
}
let helpButton = document.getElementById("helpButton");
let helpModal = document.getElementById("helpModal");
if (helpButton !== null && helpModal !== null) {
if (!helpModal.showModal) {
dialogPolyfill.default.registerDialog(helpModal);
}
helpButton.addEventListener("click", () => { helpModal.showModal(); });
const helpModalClose = helpModal.querySelector(".close");
if (helpModalClose !== null) {
helpModalClose.addEventListener("click", () => {
helpModal.close();
});
}
}
let instrumentField = document.getElementById("instruments");
if (instrumentField !== null && instrumentField instanceof HTMLSelectElement) {
setInstrumentLoop(instrumentField);
}
let bpmField = document.getElementById("bpm");
if (bpmField !== null) {
bpmField.addEventListener("change", setBpm);
}
let effectsMenu = document.getElementById("effectsMenu");
if (effectsMenu !== null) {
effectsMenu.addEventListener("click", event => {
event.stopPropagation();
});
}
const effects = ["delay", "chorus", "reverb", "distortion", "lowBoost", "compressor", "highPass"];
for (const effect of effects) {
const effectField = document.getElementById(`${effect}Effect`);
if (effectField !== null && effectField instanceof HTMLInputElement) {
effectField.addEventListener("change", () => {
setEffect(effect, parseFloat(effectField.value));
});
}
}
let patternTable = document.getElementById("pattern");
if (patternTable !== null && patternTable instanceof HTMLTableElement) {
for (const chord of chords.slice().reverse()) {
let first = true;
for (const letter of letters.slice().reverse()) {
let row = patternTable.insertRow();
if (first) {
first = false;
let chordHeader = document.createElement("th");
chordHeader.rowSpan = letters.length;
chordHeader.innerHTML = chord.toString();
row.appendChild(chordHeader);
}
let letterHeader = document.createElement("th");
letterHeader.innerHTML = letter;
row.appendChild(letterHeader);
for (const i of Array(16).keys()) {
let cell = row.insertCell();
cell.id = `${letter}-${chord}-${i}`;
cell.classList.add(`note-${letter}`);
cell.onclick = event => { onClickNoteCell(event, cell, chord, letter, i); };
}
}
}
}
const centralRow = document.getElementById("F-5-0");
if (centralRow !== null) {
centralRow.scrollIntoView({ "behavior": "smooth", "block": "center" });
}
let volumeField = document.getElementById("volume");
if (volumeField !== null) {
volumeField.addEventListener("change", setVolume);
}
let swingField = document.getElementById("swing");
if (swingField !== null) {
swingField.addEventListener("change", setSwing);
}
let resonanceField = document.getElementById("resonance");
if (resonanceField !== null) {
resonanceField.addEventListener("change", setResonance);
}
let dampeningField = document.getElementById("dampening");
if (dampeningField !== null) {
dampeningField.addEventListener("change", setDampening);
}
}
window.onload = onLoad;
/***/ })
/******/ });
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vaW5zdHJ1bWVudHMueWFtbCIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvZGlhbG9nLXBvbHlmaWxsL2Rpc3QvZGlhbG9nLXBvbHlmaWxsLmVzbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvdG9uZS9idWlsZC9Ub25lLmpzIiwid2VicGFjazovLy8uL3NyYy9hdWRpby50cyIsIndlYnBhY2s6Ly8vLi9zcmMvZGF0YS50cyIsIndlYnBhY2s6Ly8vLi9zcmMvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3BsYXllci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrREFBMEMsZ0NBQWdDO0FBQzFFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0VBQXdELGtCQUFrQjtBQUMxRTtBQUNBLHlEQUFpRCxjQUFjO0FBQy9EOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBeUMsaUNBQWlDO0FBQzFFLHdIQUFnSCxtQkFBbUIsRUFBRTtBQUNySTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1DQUEyQiwwQkFBMEIsRUFBRTtBQUN2RCx5Q0FBaUMsZUFBZTtBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4REFBc0QsK0RBQStEOztBQUVySDtBQUNBOzs7QUFHQTtBQUNBOzs7Ozs7Ozs7Ozs7QUNsRkEsZUFBZSxnQkFBZ0IsMkVBQTJFLG1CQUFtQiwwRUFBMEUsbUJBQW1CLGdGQUFnRixvQkFBb0IsOEVBQThFLGtCQUFrQiwrRUFBK0UscUJBQXFCLHdFQUF3RSxzQkFBc0IsbUZBQW1GLG1CQUFtQix1RUFBdUUsa0JBQWtCLDBFQUEwRSxrQkFBa0Isc0VBQXNFLGtCQUFrQiwwRUFBMEUsaUJBQWlCLDBFQUEwRSxnQkFBZ0Isb0VBQW9FLG1CQUFtQiwwRUFBMEUsb0JBQW9CLDRFQUE0RSxnQkFBZ0IsNkVBQTZFLGNBQWMsMkVBQTJFLEVBQUU7QUFDamtELGdEOzs7Ozs7Ozs7Ozs7QUNEQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkIsWUFBWSxRQUFRO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsWUFBWSxrQkFBa0I7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0Isa0JBQWtCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFVBQVU7QUFDckIsV0FBVyxLQUFLO0FBQ2hCLFlBQVksUUFBUTtBQUNwQjtBQUNBO0FBQ0EsaUJBQWlCLHFCQUFxQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLGdCQUFnQjtBQUMzQixZQUFZLFFBQVE7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLG1CQUFtQjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esd0JBQXdCLDRDQUE0QztBQUNwRSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLGlDQUFpQyxRQUFRLEVBQUU7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0ZBQW9GLFFBQVE7QUFDNUY7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLFFBQVE7QUFDckM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLGtFQUFrRTtBQUNsRTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUN