diff --git a/gsuiChannel/gsuiChannel.js b/gsuiChannel/gsuiChannel.js
index af66574e..711da9be 100644
--- a/gsuiChannel/gsuiChannel.js
+++ b/gsuiChannel/gsuiChannel.js
@@ -1,116 +1,110 @@
-"use strict";
-
-class gsuiChannel extends HTMLElement {
- #dispatch = GSUdispatchEvent.bind( null, this, "gsuiChannel" );
- #children = GSUgetTemplate( "gsui-channel" );
- #elements = GSUfindElements( this.#children, {
- toggle: "gsui-toggle",
- nameWrap: ".gsuiChannel-nameWrap",
- name: ".gsuiChannel-name",
- analyser: "gsui-analyser",
- effects: ".gsuiChannel-effects",
- pan: ".gsuiChannel-pan gsui-slider",
- gain: ".gsuiChannel-gain gsui-slider",
- connecta: ".gsuiChannel-connectA",
- connectb: ".gsuiChannel-connectB",
- } );
- analyser = this.#elements.analyser;
-
- constructor() {
- super();
- Object.seal( this );
-
- this.#elements.nameWrap.onclick =
- this.#elements.analyser.onclick = () => {
- this.#dispatch( "selectChannel" );
- };
- this.#elements.effects.onclick = e => {
- if ( e.target.dataset.id ) {
- this.#dispatch( "selectChannel" );
- this.#dispatch( "selectEffect", e.target.dataset.id );
- }
- };
- GSUlistenEvents( this, {
- gsuiToggle: {
- toggle: d => {
- GSUsetAttribute( this, "muted", !d.args[ 0 ] );
- this.#dispatch( "toggle", d.args[ 0 ] );
- },
- toggleSolo: () => {
- GSUsetAttribute( this, "muted", false );
- this.#dispatch( "toggleSolo" );
- },
- },
- gsuiSlider: {
- inputStart: GSUnoop,
- inputEnd: GSUnoop,
- input: ( d, sli ) => {
- this.#dispatch( "liveChange", sli.dataset.prop, d.args[ 0 ] );
- },
- change: ( d, sli ) => {
- this.#dispatch( "change", sli.dataset.prop, d.args[ 0 ] );
- },
- },
- } );
- }
-
- // .........................................................................
- connectedCallback() {
- if ( !this.firstChild ) {
- this.append( ...this.#children );
- this.#children = null;
- GSUsetAttribute( this, "draggable", "true" );
- GSUrecallAttributes( this, {
- name: "chan",
- pan: 0,
- gain: 1,
- connecta: "down",
- } );
- }
- }
- static get observedAttributes() {
- return [ "name", "muted", "pan", "gain", "connecta", "connectb" ];
- }
- attributeChangedCallback( prop, prev, val ) {
- if ( !this.#children && prev !== val ) {
- switch ( prop ) {
- case "name":
- this.#elements.name.textContent = val;
- break;
- case "muted":
- GSUsetAttribute( this.#elements.toggle, "off", val !== null );
- break;
- case "pan":
- case "gain":
- this.#elements[ prop ].setValue( val );
- break;
- case "connecta":
- case "connectb":
- this.#elements[ prop ].dataset.icon = val ? `caret-${ val }` : "";
- break;
- }
- }
- }
-
- // .........................................................................
- $addEffect( id, obj ) {
- this.#elements.effects.append( GSUgetTemplate( "gsui-channel-effect", id, obj.type ) );
- }
- $removeEffect( id ) {
- this.#getEffect( id ).remove();
- }
- $updateEffect( id, obj ) {
- if ( "order" in obj ) {
- this.#getEffect( id ).style.order = obj.order;
- }
- if ( "toggle" in obj ) {
- this.#getEffect( id ).classList.toggle( "gsuiChannel-effect-enable", obj.toggle );
- }
- }
- #getEffect( id ) {
- return this.#elements.effects.querySelector( `[data-id="${ id }"]` );
- }
-}
-
-Object.freeze( gsuiChannel );
-customElements.define( "gsui-channel", gsuiChannel );
+"use strict";
+
+class gsuiChannel extends gsui0ne {
+ $analyser = null;
+
+ constructor() {
+ super( {
+ $cmpName: "gsuiChannel",
+ $tagName: "gsui-channel",
+ $elements: {
+ toggle: "gsui-toggle",
+ nameWrap: ".gsuiChannel-nameWrap",
+ name: ".gsuiChannel-name",
+ analyser: "gsui-analyser",
+ effects: ".gsuiChannel-effects",
+ pan: ".gsuiChannel-pan gsui-slider",
+ gain: ".gsuiChannel-gain gsui-slider",
+ connecta: ".gsuiChannel-connectA",
+ connectb: ".gsuiChannel-connectB",
+ },
+ $attributes: {
+ draggable: "true",
+ name: "chan",
+ pan: 0,
+ gain: 1,
+ connecta: "down",
+ },
+ } );
+ Object.seal( this );
+
+ this.$analyser = this.$elements.analyser;
+ this.$analyser.onclick =
+ this.$elements.nameWrap.onclick = () => {
+ this.$dispatch( "selectChannel" );
+ };
+ this.$elements.effects.onclick = e => {
+ if ( e.target.dataset.id ) {
+ this.$dispatch( "selectChannel" );
+ this.$dispatch( "selectEffect", e.target.dataset.id );
+ }
+ };
+ GSUlistenEvents( this, {
+ gsuiToggle: {
+ toggle: d => {
+ GSUsetAttribute( this, "muted", !d.args[ 0 ] );
+ this.$dispatch( "toggle", d.args[ 0 ] );
+ },
+ toggleSolo: () => {
+ GSUsetAttribute( this, "muted", false );
+ this.$dispatch( "toggleSolo" );
+ },
+ },
+ gsuiSlider: {
+ inputStart: GSUnoop,
+ inputEnd: GSUnoop,
+ input: ( d, sli ) => {
+ this.$dispatch( "liveChange", sli.dataset.prop, d.args[ 0 ] );
+ },
+ change: ( d, sli ) => {
+ this.$dispatch( "change", sli.dataset.prop, d.args[ 0 ] );
+ },
+ },
+ } );
+ }
+
+ // .........................................................................
+ static get observedAttributes() {
+ return [ "name", "muted", "pan", "gain", "connecta", "connectb" ];
+ }
+ $attributeChanged( prop, val ) {
+ switch ( prop ) {
+ case "name":
+ this.$elements.name.textContent = val;
+ break;
+ case "muted":
+ GSUsetAttribute( this.$elements.toggle, "off", val !== null );
+ break;
+ case "pan":
+ case "gain":
+ this.$elements[ prop ].setValue( val );
+ break;
+ case "connecta":
+ case "connectb":
+ this.$elements[ prop ].dataset.icon = val ? `caret-${ val }` : "";
+ break;
+ }
+ }
+
+ // .........................................................................
+ $addEffect( id, obj ) {
+ this.$elements.effects.append( GSUgetTemplate( "gsui-channel-effect", id, obj.type ) );
+ }
+ $removeEffect( id ) {
+ this.#getEffect( id ).remove();
+ }
+ $updateEffect( id, obj ) {
+ if ( "order" in obj ) {
+ this.#getEffect( id ).style.order = obj.order;
+ }
+ if ( "toggle" in obj ) {
+ this.#getEffect( id ).classList.toggle( "gsuiChannel-effect-enable", obj.toggle );
+ }
+ }
+ #getEffect( id ) {
+ return this.$elements.effects.querySelector( `[data-id="${ id }"]` );
+ }
+}
+
+Object.freeze( gsuiChannel );
+customElements.define( "gsui-channel", gsuiChannel );
diff --git a/gsuiChannel/index.html b/gsuiChannel/index.html
index 7b7e5284..87340d8a 100644
--- a/gsuiChannel/index.html
+++ b/gsuiChannel/index.html
@@ -1,62 +1,63 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gsuiChannels/gsuiChannels.js b/gsuiChannels/gsuiChannels.js
index e81de7c7..2c0138c2 100644
--- a/gsuiChannels/gsuiChannels.js
+++ b/gsuiChannels/gsuiChannels.js
@@ -1,196 +1,194 @@
-"use strict";
-
-class gsuiChannels extends HTMLElement {
- oninput = null;
- onchange = null;
- onselectChan = null;
- onselectEffect = null;
- #chans = {};
- #chanSelected = null;
- #analyserW = 10;
- #analyserH = 50;
- #onresizeBind = this.#onresize.bind( this );
- #children = GSUgetTemplate( "gsui-channels" );
- #elements = GSUfindElements( this.#children, {
- pmain: ".gsuiChannels-panMain",
- pchans: ".gsuiChannels-panChannels",
- addBtn: ".gsuiChannels-addChan",
- } );
- static #selectChanPopup = GSUgetTemplate( "gsui-channels-selectPopup" );
- static #selectChanInput = gsuiChannels.#selectChanPopup.querySelector( "select" );
-
- constructor() {
- super();
- Object.seal( this );
-
- this.#elements.addBtn.onclick = () => this.onchange( "addChannel" );
- GSUlistenEvents( this, {
- gsuiChannel: {
- selectChannel: ( d, chan ) => this.selectChannel( chan.dataset.id ),
- selectEffect: ( d, chan ) => this.onselectEffect( chan.dataset.id, d.args[ 0 ] ),
- liveChange: ( d, chan ) => this.oninput( chan.dataset.id, ...d.args ),
- change: ( d, chan ) => this.onchange( "changeChannel", chan.dataset.id, ...d.args ),
- toggle: ( d, chan ) => this.onchange( "toggleChannel", chan.dataset.id ),
- },
- } );
- new gsuiReorder( {
- rootElement: this,
- direction: "row",
- dataTransferType: "channel",
- itemSelector: "gsui-channel",
- handleSelector: ".gsuiChannel-grip",
- parentSelector: ".gsuiChannels-panChannels",
- onchange: elChan => {
- this.onchange( "reorderChannel", elChan.dataset.id,
- gsuiReorder.listComputeOrderChange( this.#elements.pchans, {} ) );
- },
- } );
- }
-
- // .........................................................................
- connectedCallback() {
- if ( !this.firstChild ) {
- this.append( ...this.#children );
- this.#children = null;
- }
- GSUobserveSizeOf( this, this.#onresizeBind );
- }
- disconnectedCallback() {
- GSUunobserveSizeOf( this, this.#onresizeBind );
- }
-
- // .........................................................................
- #onresize() {
- const chans = Object.values( this.#chans );
-
- if ( chans.length ) {
- const { width, height } = chans[ 0 ].analyser.getBoundingClientRect();
-
- this.#analyserW = width;
- this.#analyserH = height;
- chans.forEach( chan => chan.analyser.setResolution( width, height ) );
- }
- }
- updateAudioData( id, ldata, rdata ) {
- this.#chans[ id ].analyser.draw( ldata, rdata );
- }
- selectChannel( id ) {
- const chan = this.#chans[ id ];
- const pchan = this.#chans[ this.#chanSelected ];
-
- pchan && GSUsetAttribute( pchan, "selected", false );
- GSUsetAttribute( chan, "selected", true );
- this.#chanSelected = id;
- this.#updateChanConnections();
- this.onselectChan?.( id );
- }
- static openSelectChannelPopup( chans, currChanId ) {
- return new Promise( res => {
- gsuiChannels.#selectChanInput.append(
- ...Object.entries( chans ).map(
- kv => GSUcreateOption( { value: kv[ 0 ] }, kv[ 1 ].name ) )
- );
- gsuiChannels.#selectChanInput.value = currChanId;
- GSUpopup.custom( {
- title: "Channels",
- element: gsuiChannels.#selectChanPopup,
- submit( data ) {
- res( data.channel !== currChanId ? data.channel : null );
- }
- } ).then(() => GSUemptyElement( gsuiChannels.#selectChanInput ) );
- } );
- }
-
- // .........................................................................
- $getChannel( id ) {
- return this.#chans[ id ];
- }
- addChannel( id ) {
- const chan = GSUcreateElement( "gsui-channel", { "data-id": id } );
- const qs = n => chan.querySelector( `.gsuiChannel-${ n }` );
-
- ( id === "main" ? this.#elements.pmain : this.#elements.pchans ).append( chan );
- this.#chans[ id ] = chan;
- qs( "delete" ).onclick = () => this.onchange( "removeChannel", id );
- qs( "connect" ).onclick = () => this.onchange( "redirectChannel", this.#chanSelected, id );
- qs( "rename" ).onclick = () => {
- GSUpopup.prompt( "Rename channel", "", GSUgetAttribute( this.#chans[ id ], "name" ) )
- .then( name => this.onchange( "renameChannel", id, name ) );
- };
- chan.analyser.setResolution( this.#analyserW, this.#analyserH );
- if ( this.#chanSelected ) {
- this.#updateChanConnections();
- } else if ( id === "main" ) {
- this.selectChannel( id );
- }
- }
- removeChannel( id ) {
- const chan = this.#chans[ id ];
-
- if ( id === this.#chanSelected ) {
- const next = this.#getNextChan( chan, "nextElementSibling" );
-
- if ( next ) {
- this.selectChannel( next.dataset.id );
- } else {
- const prev = this.#getNextChan( chan, "previousElementSibling" );
-
- this.selectChannel( prev ? prev.dataset.id : "main" );
- }
- }
- delete this.#chans[ id ];
- chan.remove();
- }
- toggleChannel( id, b ) {
- GSUsetAttribute( this.#chans[ id ], "muted", !b );
- }
- changePanChannel( id, val ) {
- GSUsetAttribute( this.#chans[ id ], "pan", val );
- }
- changeGainChannel( id, val ) {
- GSUsetAttribute( this.#chans[ id ], "gain", val );
- }
- renameChannel( id, name ) {
- GSUsetAttribute( this.#chans[ id ], "name", name );
- }
- reorderChannel( id, n ) {
- this.#chans[ id ].dataset.order = n;
- }
- reorderChannels( channels ) {
- gsuiReorder.listReorder( this.#elements.pchans, channels );
- }
- redirectChannel( id, dest ) {
- this.#chans[ id ].dataset.dest = dest;
- this.#updateChanConnections();
- }
-
- // .........................................................................
- #getNextChan( el, dir ) {
- const sibling = el[ dir ];
-
- return sibling && "id" in sibling.dataset ? sibling : null;
- }
- #updateChanConnections() {
- const selId = this.#chanSelected;
-
- if ( selId ) {
- const chan = this.#chans[ selId ];
- const chanDest = chan.dataset.dest;
- let bOnce = false;
-
- Object.entries( this.#chans ).forEach( ( [ id, chan ] ) => {
- const a = id === chanDest;
- const b = chan.dataset.dest === selId;
-
- GSUsetAttribute( chan, "connecta", a ? "up" : "" );
- GSUsetAttribute( chan, "connectb", b ? "down" : "" );
- bOnce = bOnce || b;
- } );
- GSUsetAttribute( chan, "connecta", selId !== "main" ? "down" : "" );
- GSUsetAttribute( chan, "connectb", bOnce ? "up" : "" );
- }
- }
-}
-
-Object.freeze( gsuiChannels );
-customElements.define( "gsui-channels", gsuiChannels );
+"use strict";
+
+class gsuiChannels extends gsui0ne {
+ $oninput = null;
+ $onchange = null;
+ $onselectChan = null;
+ $onselectEffect = null;
+ #chans = {};
+ #chanSelected = null;
+ #analyserW = 10;
+ #analyserH = 50;
+ #onresizeBind = this.#onresize.bind( this );
+ static #selectChanPopup = GSUgetTemplate( "gsui-channels-selectPopup" );
+ static #selectChanInput = gsuiChannels.#selectChanPopup.querySelector( "select" );
+
+ constructor() {
+ super( {
+ $cmpName: "gsuiChannels",
+ $tagName: "gsui-channels",
+ $elements: {
+ pmain: ".gsuiChannels-panMain",
+ pchans: ".gsuiChannels-panChannels",
+ addBtn: ".gsuiChannels-addChan",
+ },
+ } );
+ Object.seal( this );
+
+ this.$elements.addBtn.onclick = () => this.$onchange( "addChannel" );
+ GSUlistenEvents( this, {
+ gsuiChannel: {
+ selectChannel: ( d, chan ) => this.$selectChannel( chan.dataset.id ),
+ selectEffect: ( d, chan ) => this.$onselectEffect( chan.dataset.id, d.args[ 0 ] ),
+ liveChange: ( d, chan ) => this.$oninput( chan.dataset.id, ...d.args ),
+ change: ( d, chan ) => this.$onchange( "changeChannel", chan.dataset.id, ...d.args ),
+ toggle: ( d, chan ) => this.$onchange( "toggleChannel", chan.dataset.id ),
+ },
+ } );
+ new gsuiReorder( {
+ rootElement: this,
+ direction: "row",
+ dataTransferType: "channel",
+ itemSelector: "gsui-channel",
+ handleSelector: ".gsuiChannel-grip",
+ parentSelector: ".gsuiChannels-panChannels",
+ onchange: elChan => {
+ this.$onchange( "reorderChannel", elChan.dataset.id,
+ gsuiReorder.listComputeOrderChange( this.$elements.pchans, {} ) );
+ },
+ } );
+ }
+
+ // .........................................................................
+ $connected() {
+ GSUobserveSizeOf( this, this.#onresizeBind );
+ }
+ $disconnected() {
+ GSUunobserveSizeOf( this, this.#onresizeBind );
+ }
+
+ // .........................................................................
+ #onresize() {
+ const chans = Object.values( this.#chans );
+
+ if ( chans.length ) {
+ const { width, height } = chans[ 0 ].$analyser.getBoundingClientRect();
+
+ this.#analyserW = width;
+ this.#analyserH = height;
+ chans.forEach( chan => chan.$analyser.setResolution( width, height ) );
+ }
+ }
+ $updateAudioData( id, ldata, rdata ) {
+ this.#chans[ id ].$analyser.draw( ldata, rdata );
+ }
+ $selectChannel( id ) {
+ const chan = this.#chans[ id ];
+ const pchan = this.#chans[ this.#chanSelected ];
+
+ pchan && GSUsetAttribute( pchan, "selected", false );
+ GSUsetAttribute( chan, "selected", true );
+ this.#chanSelected = id;
+ this.#updateChanConnections();
+ this.$onselectChan?.( id );
+ }
+ static $openSelectChannelPopup( chans, currChanId ) {
+ return new Promise( res => {
+ gsuiChannels.#selectChanInput.append(
+ ...Object.entries( chans ).map(
+ kv => GSUcreateOption( { value: kv[ 0 ] }, kv[ 1 ].name ) )
+ );
+ gsuiChannels.#selectChanInput.value = currChanId;
+ GSUpopup.custom( {
+ title: "Channels",
+ element: gsuiChannels.#selectChanPopup,
+ submit( data ) {
+ res( data.channel !== currChanId ? data.channel : null );
+ }
+ } ).then(() => GSUemptyElement( gsuiChannels.#selectChanInput ) );
+ } );
+ }
+
+ // .........................................................................
+ $getChannel( id ) {
+ return this.#chans[ id ];
+ }
+ $addChannel( id ) {
+ const chan = GSUcreateElement( "gsui-channel", { "data-id": id } );
+ const qs = n => chan.querySelector( `.gsuiChannel-${ n }` );
+
+ ( id === "main" ? this.$elements.pmain : this.$elements.pchans ).append( chan );
+ this.#chans[ id ] = chan;
+ qs( "delete" ).onclick = () => this.$onchange( "removeChannel", id );
+ qs( "connect" ).onclick = () => this.$onchange( "redirectChannel", this.#chanSelected, id );
+ qs( "rename" ).onclick = () => {
+ GSUpopup.prompt( "Rename channel", "", GSUgetAttribute( this.#chans[ id ], "name" ) )
+ .then( name => this.$onchange( "renameChannel", id, name ) );
+ };
+ chan.$analyser.setResolution( this.#analyserW, this.#analyserH );
+ if ( this.#chanSelected ) {
+ this.#updateChanConnections();
+ } else if ( id === "main" ) {
+ this.$selectChannel( id );
+ }
+ }
+ $removeChannel( id ) {
+ const chan = this.#chans[ id ];
+
+ if ( id === this.#chanSelected ) {
+ const next = this.#getNextChan( chan, "nextElementSibling" );
+
+ if ( next ) {
+ this.$selectChannel( next.dataset.id );
+ } else {
+ const prev = this.#getNextChan( chan, "previousElementSibling" );
+
+ this.$selectChannel( prev ? prev.dataset.id : "main" );
+ }
+ }
+ delete this.#chans[ id ];
+ chan.remove();
+ }
+ $toggleChannel( id, b ) {
+ GSUsetAttribute( this.#chans[ id ], "muted", !b );
+ }
+ $changePanChannel( id, val ) {
+ GSUsetAttribute( this.#chans[ id ], "pan", val );
+ }
+ $changeGainChannel( id, val ) {
+ GSUsetAttribute( this.#chans[ id ], "gain", val );
+ }
+ $renameChannel( id, name ) {
+ GSUsetAttribute( this.#chans[ id ], "name", name );
+ }
+ $reorderChannel( id, n ) {
+ this.#chans[ id ].dataset.order = n;
+ }
+ $reorderChannels( channels ) {
+ gsuiReorder.listReorder( this.$elements.pchans, channels );
+ }
+ $redirectChannel( id, dest ) {
+ this.#chans[ id ].dataset.dest = dest;
+ this.#updateChanConnections();
+ }
+
+ // .........................................................................
+ #getNextChan( el, dir ) {
+ const sibling = el[ dir ];
+
+ return sibling && "id" in sibling.dataset ? sibling : null;
+ }
+ #updateChanConnections() {
+ const selId = this.#chanSelected;
+
+ if ( selId ) {
+ const chan = this.#chans[ selId ];
+ const chanDest = chan.dataset.dest;
+ let bOnce = false;
+
+ Object.entries( this.#chans ).forEach( ( [ id, chan ] ) => {
+ const a = id === chanDest;
+ const b = chan.dataset.dest === selId;
+
+ GSUsetAttribute( chan, "connecta", a ? "up" : "" );
+ GSUsetAttribute( chan, "connectb", b ? "down" : "" );
+ bOnce = bOnce || b;
+ } );
+ GSUsetAttribute( chan, "connecta", selId !== "main" ? "down" : "" );
+ GSUsetAttribute( chan, "connectb", bOnce ? "up" : "" );
+ }
+ }
+}
+
+Object.freeze( gsuiChannels );
+customElements.define( "gsui-channels", gsuiChannels );
diff --git a/gsuiMixer/index.html b/gsuiMixer/index.html
index 56dd6a13..6bc34b21 100644
--- a/gsuiMixer/index.html
+++ b/gsuiMixer/index.html
@@ -1,89 +1,90 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gsuiPatterns/gsuiPatterns.js b/gsuiPatterns/gsuiPatterns.js
index 9913e02f..17ef0274 100644
--- a/gsuiPatterns/gsuiPatterns.js
+++ b/gsuiPatterns/gsuiPatterns.js
@@ -1,311 +1,311 @@
-"use strict";
-
-class gsuiPatterns extends HTMLElement {
- $getChannels = () => [];
- #dispatch = GSUdispatchEvent.bind( null, this, "gsuiPatterns" );
- #fnsPattern = Object.freeze( {
- clone: id => this.onchange( "clonePattern", id ),
- remove: id => this.onchange( "removePattern", id ),
- editInfo: ( id, el ) => this.#openInfoPopup( id, el ),
- undefined: id => this.onchange( "openPattern", id ),
- redirect: ( id, el, e ) => this.#openChannelsPopup( "redirectPatternBuffer", id, e.target.dataset.id ),
- } );
- #fnsSynth = Object.freeze( {
- expand: id => this.expandSynth( id ),
- undefined: id => this.onchange( "openSynth", id ),
- redirect: ( id, e ) => this.#openChannelsPopup( "redirectSynth", id, e.target.dataset.id ),
- newPattern: id => {
- this.onchange( "addPatternKeys", id );
- this.expandSynth( id, true );
- },
- delete: id => {
- this.#elements.lists.synth.children.length > 1
- ? this.onchange( "removeSynth", id )
- : GSUpopup.alert( "Error", "You have to keep at least one synthesizer" );
- },
- } );
- #children = GSUgetTemplate( "gsui-patterns" );
- #elements = GSUfindElements( this.#children, {
- lists: {
- slices: ".gsuiPatterns-panelSlices .gsuiPatterns-panel-list",
- drums: ".gsuiPatterns-panelDrums .gsuiPatterns-panel-list",
- synth: ".gsuiPatterns-panelKeys .gsuiPatterns-panel-list",
- buffer: ".gsuiPatterns-panelBuffers .gsuiPatterns-panel-list",
- },
- newSlices: "[data-action='newSlices']",
- newDrums: "[data-action='newDrums']",
- newSynth: "[data-action='newSynth']",
- } );
- #nlKeysLists = this.#elements.lists.synth.getElementsByClassName( "gsuiPatterns-synth-patterns" );
- static infoPopupContent = GSUgetTemplate( "gsui-patterns-infoPopup" );
-
- constructor() {
- super();
- this.onchange =
- this.onpatternDataTransfer = null;
- Object.seal( this );
-
- new gsuiReorder( {
- rootElement: this.#elements.lists.buffer,
- direction: "column",
- dataTransfer: ( ...args ) => this.onpatternDataTransfer( ...args ),
- dataTransferType: "pattern-buffer",
- itemSelector: ".gsuiPatterns-pattern",
- handleSelector: ".gsuiPatterns-pattern-grip",
- parentSelector: ".gsuiPatterns-panel-list",
- onchange: this.#onreorderPatterns.bind( this, this.#elements.lists.buffer ),
- } );
- new gsuiReorder( {
- rootElement: this.#elements.lists.slices,
- direction: "column",
- dataTransfer: ( ...args ) => this.onpatternDataTransfer( ...args ),
- dataTransferType: "pattern-slices",
- itemSelector: ".gsuiPatterns-pattern",
- handleSelector: ".gsuiPatterns-pattern-grip",
- parentSelector: ".gsuiPatterns-panel-list",
- onchange: this.#onreorderPatterns.bind( this, this.#elements.lists.slices ),
- } );
- new gsuiReorder( {
- rootElement: this.#elements.lists.drums,
- direction: "column",
- dataTransfer: ( ...args ) => this.onpatternDataTransfer( ...args ),
- dataTransferType: "pattern-drums",
- itemSelector: ".gsuiPatterns-pattern",
- handleSelector: ".gsuiPatterns-pattern-grip",
- parentSelector: ".gsuiPatterns-panel-list",
- onchange: this.#onreorderPatterns.bind( this, this.#elements.lists.drums ),
- } );
- new gsuiReorder( {
- rootElement: this.#elements.lists.synth,
- direction: "column",
- dataTransfer: ( ...args ) => this.onpatternDataTransfer( ...args ),
- dataTransferType: "pattern-keys",
- itemSelector: ".gsuiPatterns-pattern",
- handleSelector: ".gsuiPatterns-pattern-grip",
- parentSelector: ".gsuiPatterns-synth-patterns",
- onchange: this.#onreorderPatternsKeys.bind( this ),
- } );
- this.#elements.lists.buffer.ondrop = e => {
- const defBufId = e.dataTransfer.getData( "library-buffer:default" );
- const locBufId = e.dataTransfer.getData( "library-buffer:local" );
-
- if ( defBufId ) {
- this.#dispatch( "libraryBufferDropped", "default", defBufId );
- } else if ( locBufId ) {
- this.#dispatch( "libraryBufferDropped", "local", locBufId );
- }
- };
- this.#elements.lists.synth.ondragover = e => {
- const syn = e.target.closest( ".gsuiPatterns-synth" );
-
- if ( syn ) {
- this.expandSynth( syn.dataset.id, true );
- }
- };
- this.#elements.lists.synth.ondblclick = e => {
- if ( e.target.classList.contains( "gsuiPatterns-synth-info" ) ) {
- this.expandSynth( e.target.closest( ".gsuiPatterns-synth" ).dataset.id );
- }
- };
- this.#elements.lists.buffer.onclick =
- this.#elements.lists.slices.onclick =
- this.#elements.lists.drums.onclick = this.#onclickListPatterns.bind( this );
- this.#elements.lists.synth.onclick = this.#onclickSynths.bind( this );
- this.#elements.newSlices.onclick = () => this.onchange( "addPatternSlices" );
- this.#elements.newDrums.onclick = () => this.onchange( "addPatternDrums" );
- this.#elements.newSynth.onclick = () => this.onchange( "addSynth" );
- }
-
- // .........................................................................
- connectedCallback() {
- if ( !this.firstChild ) {
- this.append( this.#children );
- this.#children = null;
- }
- }
-
- // .........................................................................
- expandSynth( id, b ) {
- const elSyn = this.#getSynth( id );
- const show = elSyn.classList.toggle( "gsuiPatterns-synth-expanded", b );
-
- elSyn.querySelector( ".gsuiPatterns-synth-expand" ).dataset.icon = `caret-${ show ? "down" : "right" }`;
- }
- reorderPatterns( patterns ) {
- gsuiReorder.listReorder( this.#elements.lists.buffer, patterns );
- gsuiReorder.listReorder( this.#elements.lists.slices, patterns );
- gsuiReorder.listReorder( this.#elements.lists.drums, patterns );
- Array.prototype.forEach.call( this.#nlKeysLists, list => {
- gsuiReorder.listReorder( list, patterns );
- } );
- }
- #openChannelsPopup( action, objId, currChanId ) {
- gsuiChannels.openSelectChannelPopup( this.$getChannels(), currChanId )
- .then( chanId => chanId && this.onchange( action, objId, chanId ) );
- }
- #openInfoPopup( id, el ) {
- const radio = gsuiPatterns.infoPopupContent.querySelector( `[value="${ el.dataset.bufferType }"]` );
-
- if ( radio ) {
- radio.checked = true;
- } else {
- const radio = gsuiPatterns.infoPopupContent.querySelector( "input:checked" );
-
- if ( radio ) {
- radio.checked = false;
- }
- }
- gsuiPatterns.infoPopupContent.querySelector( "[name='bpm']" ).value = el.dataset.bufferBpm;
- gsuiPatterns.infoPopupContent.querySelector( "[name='name']" ).value = el.dataset.name;
- GSUpopup.custom( {
- title: "Buffer's info",
- element: gsuiPatterns.infoPopupContent,
- submit: data => {
- data.bpm = data.bpm || null;
- this.onchange( "changePatternBufferInfo", id, data );
- }
- } );
- }
-
- // .........................................................................
- updateChannel( id, name ) {
- this.querySelectorAll( `.gsuiPatterns-btnSolid[data-id="${ id }"] .gsuiPatterns-btnText` )
- .forEach( el => el.textContent = name );
- }
-
- // .........................................................................
- addSynth( id ) {
- const elSyn = GSUgetTemplate( "gsui-patterns-synth" );
-
- elSyn.dataset.id = id;
- this.#elements.lists.synth.prepend( elSyn );
- }
- changeSynth( id, prop, val ) {
- const elSyn = this.#getSynth( id );
-
- switch ( prop ) {
- case "name": elSyn.querySelector( ".gsuiPatterns-synth-name" ).textContent = val; break;
- case "dest": elSyn.querySelector( ".gsuiPatterns-synth-dest" ).dataset.id = val; break;
- case "destName": elSyn.querySelector( ".gsuiPatterns-synth-dest .gsuiPatterns-btnText" ).textContent = val; break;
- }
- }
- deleteSynth( id ) {
- this.#getSynth( id ).remove();
- }
-
- // .........................................................................
- addPattern( id, { type, synth } ) {
- const elPat = GSUgetTemplate( "gsui-patterns-pattern" );
-
- elPat.dataset.id = id;
- if ( type !== "buffer" ) {
- elPat.querySelector( ".gsuiPatterns-pattern-btnInfo" ).remove();
- elPat.querySelector( ".gsuiPatterns-destArrow" ).remove();
- elPat.querySelector( ".gsuiPatterns-pattern-dest" ).remove();
- } else {
- elPat.querySelector( "[data-action='clone']" ).remove(); // 1.
- }
- this.#getPatternParent( type, synth ).append( elPat );
- }
- changePattern( id, prop, val ) {
- const elPat = this.getPattern( id );
-
- switch ( prop ) {
- case "data-missing": GSUsetAttribute( elPat, "data-missing", val ); break;
- case "order": elPat.dataset.order = val; break;
- case "name":
- elPat.dataset.name = val;
- elPat.querySelector( ".gsuiPatterns-pattern-name" ).textContent = val;
- break;
- case "dest": elPat.querySelector( ".gsuiPatterns-pattern-dest" ).dataset.id = val; break;
- case "destName": elPat.querySelector( ".gsuiPatterns-pattern-dest .gsuiPatterns-btnText" ).textContent = val; break;
- case "synth": this.#getPatternParent( "keys", val ).append( elPat ); break;
- case "bufferType":
- GSUsetAttribute( elPat, "data-buffer-type", val );
- elPat.querySelector( ".gsuiPatterns-pattern-btnInfo" ).dataset.icon = `buf-${ val || "undefined" }`;
- break;
- case "bufferBpm":
- GSUsetAttribute( elPat, "data-buffer-bpm", val );
- break;
- }
- }
- appendPatternSVG( id, svg ) {
- svg.classList.add( "gsuiPatterns-pattern-svg" );
- this.getPattern( id ).querySelector( ".gsuiPatterns-pattern-content" ).append( svg );
- }
- deletePattern( id ) {
- this.getPattern( id )?.remove(); // 2.
- }
-
- // .........................................................................
- selectPattern( type, id ) {
- const elList = this.#elements.lists[ type === "keys" ? "synth" : type ];
-
- elList.querySelector( ".gsuiPatterns-pattern-selected" )?.classList?.remove( "gsuiPatterns-pattern-selected" );
- this.getPattern( id )?.classList?.add( "gsuiPatterns-pattern-selected" );
- }
- selectSynth( id ) {
- this.#elements.lists.synth.querySelector( ".gsuiPatterns-synth-selected" )?.classList?.remove( "gsuiPatterns-synth-selected" );
- this.#getSynth( id ).classList.add( "gsuiPatterns-synth-selected" );
- }
-
- // .........................................................................
- getPattern( id ) {
- return this.querySelector( `.gsuiPatterns-pattern[data-id="${ id }"]` );
- }
- #getSynth( id ) {
- return this.#elements.lists.synth.querySelector( `.gsuiPatterns-synth[data-id="${ id }"]` );
- }
- #getPatternParent( type, synthId ) {
- switch ( type ) {
- case "slices":
- case "buffer":
- case "drums": return this.#elements.lists[ type ];
- case "keys": return this.#elements.lists.synth.querySelector( `.gsuiPatterns-synth[data-id="${ synthId }"] .gsuiPatterns-synth-patterns` );
- }
- }
-
- // .........................................................................
- #onreorderPatterns( list, elPat ) {
- this.onchange( "reorderPattern", elPat.dataset.id,
- gsuiReorder.listComputeOrderChange( list, {} ) );
- }
- #onreorderPatternsKeys( elPat, indA, indB, parA, parB ) {
- if ( parA === parB ) {
- this.#onreorderPatterns( parA, elPat );
- } else {
- const patId = elPat.dataset.id;
- const synth = parB.parentNode.dataset.id;
- const patterns = { [ patId ]: { synth } };
-
- gsuiReorder.listComputeOrderChange( parA, patterns );
- gsuiReorder.listComputeOrderChange( parB, patterns );
- this.onchange( "redirectPatternKeys", patId, synth, patterns );
- }
- }
- #onclickListPatterns( e ) {
- const pat = e.target.closest( ".gsuiPatterns-pattern" );
-
- if ( pat ) {
- this.#fnsPattern[ e.target.dataset.action ]( pat.dataset.id, pat, e );
- return false;
- }
- }
- #onclickSynths( e ) {
- if ( this.#onclickListPatterns( e ) !== false ) {
- const syn = e.target.closest( ".gsuiPatterns-synth" );
-
- if ( syn ) {
- this.#fnsSynth[ e.target.dataset.action ]( syn.dataset.id, e );
- }
- }
- }
-}
-
-Object.freeze( gsuiPatterns );
-customElements.define( "gsui-patterns", gsuiPatterns );
-
-/*
-1. The cloning feature for the patterns of type buffer is removed because it's for the moment useless.
-2. We are checking if the pattern exists because the entire synth could have been removed before.
-*/
+"use strict";
+
+class gsuiPatterns extends HTMLElement {
+ $getChannels = () => [];
+ #dispatch = GSUdispatchEvent.bind( null, this, "gsuiPatterns" );
+ #fnsPattern = Object.freeze( {
+ clone: id => this.onchange( "clonePattern", id ),
+ remove: id => this.onchange( "removePattern", id ),
+ editInfo: ( id, el ) => this.#openInfoPopup( id, el ),
+ undefined: id => this.onchange( "openPattern", id ),
+ redirect: ( id, el, e ) => this.#openChannelsPopup( "redirectPatternBuffer", id, e.target.dataset.id ),
+ } );
+ #fnsSynth = Object.freeze( {
+ expand: id => this.expandSynth( id ),
+ undefined: id => this.onchange( "openSynth", id ),
+ redirect: ( id, e ) => this.#openChannelsPopup( "redirectSynth", id, e.target.dataset.id ),
+ newPattern: id => {
+ this.onchange( "addPatternKeys", id );
+ this.expandSynth( id, true );
+ },
+ delete: id => {
+ this.#elements.lists.synth.children.length > 1
+ ? this.onchange( "removeSynth", id )
+ : GSUpopup.alert( "Error", "You have to keep at least one synthesizer" );
+ },
+ } );
+ #children = GSUgetTemplate( "gsui-patterns" );
+ #elements = GSUfindElements( this.#children, {
+ lists: {
+ slices: ".gsuiPatterns-panelSlices .gsuiPatterns-panel-list",
+ drums: ".gsuiPatterns-panelDrums .gsuiPatterns-panel-list",
+ synth: ".gsuiPatterns-panelKeys .gsuiPatterns-panel-list",
+ buffer: ".gsuiPatterns-panelBuffers .gsuiPatterns-panel-list",
+ },
+ newSlices: "[data-action='newSlices']",
+ newDrums: "[data-action='newDrums']",
+ newSynth: "[data-action='newSynth']",
+ } );
+ #nlKeysLists = this.#elements.lists.synth.getElementsByClassName( "gsuiPatterns-synth-patterns" );
+ static infoPopupContent = GSUgetTemplate( "gsui-patterns-infoPopup" );
+
+ constructor() {
+ super();
+ this.onchange =
+ this.onpatternDataTransfer = null;
+ Object.seal( this );
+
+ new gsuiReorder( {
+ rootElement: this.#elements.lists.buffer,
+ direction: "column",
+ dataTransfer: ( ...args ) => this.onpatternDataTransfer( ...args ),
+ dataTransferType: "pattern-buffer",
+ itemSelector: ".gsuiPatterns-pattern",
+ handleSelector: ".gsuiPatterns-pattern-grip",
+ parentSelector: ".gsuiPatterns-panel-list",
+ onchange: this.#onreorderPatterns.bind( this, this.#elements.lists.buffer ),
+ } );
+ new gsuiReorder( {
+ rootElement: this.#elements.lists.slices,
+ direction: "column",
+ dataTransfer: ( ...args ) => this.onpatternDataTransfer( ...args ),
+ dataTransferType: "pattern-slices",
+ itemSelector: ".gsuiPatterns-pattern",
+ handleSelector: ".gsuiPatterns-pattern-grip",
+ parentSelector: ".gsuiPatterns-panel-list",
+ onchange: this.#onreorderPatterns.bind( this, this.#elements.lists.slices ),
+ } );
+ new gsuiReorder( {
+ rootElement: this.#elements.lists.drums,
+ direction: "column",
+ dataTransfer: ( ...args ) => this.onpatternDataTransfer( ...args ),
+ dataTransferType: "pattern-drums",
+ itemSelector: ".gsuiPatterns-pattern",
+ handleSelector: ".gsuiPatterns-pattern-grip",
+ parentSelector: ".gsuiPatterns-panel-list",
+ onchange: this.#onreorderPatterns.bind( this, this.#elements.lists.drums ),
+ } );
+ new gsuiReorder( {
+ rootElement: this.#elements.lists.synth,
+ direction: "column",
+ dataTransfer: ( ...args ) => this.onpatternDataTransfer( ...args ),
+ dataTransferType: "pattern-keys",
+ itemSelector: ".gsuiPatterns-pattern",
+ handleSelector: ".gsuiPatterns-pattern-grip",
+ parentSelector: ".gsuiPatterns-synth-patterns",
+ onchange: this.#onreorderPatternsKeys.bind( this ),
+ } );
+ this.#elements.lists.buffer.ondrop = e => {
+ const defBufId = e.dataTransfer.getData( "library-buffer:default" );
+ const locBufId = e.dataTransfer.getData( "library-buffer:local" );
+
+ if ( defBufId ) {
+ this.#dispatch( "libraryBufferDropped", "default", defBufId );
+ } else if ( locBufId ) {
+ this.#dispatch( "libraryBufferDropped", "local", locBufId );
+ }
+ };
+ this.#elements.lists.synth.ondragover = e => {
+ const syn = e.target.closest( ".gsuiPatterns-synth" );
+
+ if ( syn ) {
+ this.expandSynth( syn.dataset.id, true );
+ }
+ };
+ this.#elements.lists.synth.ondblclick = e => {
+ if ( e.target.classList.contains( "gsuiPatterns-synth-info" ) ) {
+ this.expandSynth( e.target.closest( ".gsuiPatterns-synth" ).dataset.id );
+ }
+ };
+ this.#elements.lists.buffer.onclick =
+ this.#elements.lists.slices.onclick =
+ this.#elements.lists.drums.onclick = this.#onclickListPatterns.bind( this );
+ this.#elements.lists.synth.onclick = this.#onclickSynths.bind( this );
+ this.#elements.newSlices.onclick = () => this.onchange( "addPatternSlices" );
+ this.#elements.newDrums.onclick = () => this.onchange( "addPatternDrums" );
+ this.#elements.newSynth.onclick = () => this.onchange( "addSynth" );
+ }
+
+ // .........................................................................
+ connectedCallback() {
+ if ( !this.firstChild ) {
+ this.append( this.#children );
+ this.#children = null;
+ }
+ }
+
+ // .........................................................................
+ expandSynth( id, b ) {
+ const elSyn = this.#getSynth( id );
+ const show = elSyn.classList.toggle( "gsuiPatterns-synth-expanded", b );
+
+ elSyn.querySelector( ".gsuiPatterns-synth-expand" ).dataset.icon = `caret-${ show ? "down" : "right" }`;
+ }
+ reorderPatterns( patterns ) {
+ gsuiReorder.listReorder( this.#elements.lists.buffer, patterns );
+ gsuiReorder.listReorder( this.#elements.lists.slices, patterns );
+ gsuiReorder.listReorder( this.#elements.lists.drums, patterns );
+ Array.prototype.forEach.call( this.#nlKeysLists, list => {
+ gsuiReorder.listReorder( list, patterns );
+ } );
+ }
+ #openChannelsPopup( action, objId, currChanId ) {
+ gsuiChannels.$openSelectChannelPopup( this.$getChannels(), currChanId )
+ .then( chanId => chanId && this.onchange( action, objId, chanId ) );
+ }
+ #openInfoPopup( id, el ) {
+ const radio = gsuiPatterns.infoPopupContent.querySelector( `[value="${ el.dataset.bufferType }"]` );
+
+ if ( radio ) {
+ radio.checked = true;
+ } else {
+ const radio = gsuiPatterns.infoPopupContent.querySelector( "input:checked" );
+
+ if ( radio ) {
+ radio.checked = false;
+ }
+ }
+ gsuiPatterns.infoPopupContent.querySelector( "[name='bpm']" ).value = el.dataset.bufferBpm;
+ gsuiPatterns.infoPopupContent.querySelector( "[name='name']" ).value = el.dataset.name;
+ GSUpopup.custom( {
+ title: "Buffer's info",
+ element: gsuiPatterns.infoPopupContent,
+ submit: data => {
+ data.bpm = data.bpm || null;
+ this.onchange( "changePatternBufferInfo", id, data );
+ }
+ } );
+ }
+
+ // .........................................................................
+ updateChannel( id, name ) {
+ this.querySelectorAll( `.gsuiPatterns-btnSolid[data-id="${ id }"] .gsuiPatterns-btnText` )
+ .forEach( el => el.textContent = name );
+ }
+
+ // .........................................................................
+ addSynth( id ) {
+ const elSyn = GSUgetTemplate( "gsui-patterns-synth" );
+
+ elSyn.dataset.id = id;
+ this.#elements.lists.synth.prepend( elSyn );
+ }
+ changeSynth( id, prop, val ) {
+ const elSyn = this.#getSynth( id );
+
+ switch ( prop ) {
+ case "name": elSyn.querySelector( ".gsuiPatterns-synth-name" ).textContent = val; break;
+ case "dest": elSyn.querySelector( ".gsuiPatterns-synth-dest" ).dataset.id = val; break;
+ case "destName": elSyn.querySelector( ".gsuiPatterns-synth-dest .gsuiPatterns-btnText" ).textContent = val; break;
+ }
+ }
+ deleteSynth( id ) {
+ this.#getSynth( id ).remove();
+ }
+
+ // .........................................................................
+ addPattern( id, { type, synth } ) {
+ const elPat = GSUgetTemplate( "gsui-patterns-pattern" );
+
+ elPat.dataset.id = id;
+ if ( type !== "buffer" ) {
+ elPat.querySelector( ".gsuiPatterns-pattern-btnInfo" ).remove();
+ elPat.querySelector( ".gsuiPatterns-destArrow" ).remove();
+ elPat.querySelector( ".gsuiPatterns-pattern-dest" ).remove();
+ } else {
+ elPat.querySelector( "[data-action='clone']" ).remove(); // 1.
+ }
+ this.#getPatternParent( type, synth ).append( elPat );
+ }
+ changePattern( id, prop, val ) {
+ const elPat = this.getPattern( id );
+
+ switch ( prop ) {
+ case "data-missing": GSUsetAttribute( elPat, "data-missing", val ); break;
+ case "order": elPat.dataset.order = val; break;
+ case "name":
+ elPat.dataset.name = val;
+ elPat.querySelector( ".gsuiPatterns-pattern-name" ).textContent = val;
+ break;
+ case "dest": elPat.querySelector( ".gsuiPatterns-pattern-dest" ).dataset.id = val; break;
+ case "destName": elPat.querySelector( ".gsuiPatterns-pattern-dest .gsuiPatterns-btnText" ).textContent = val; break;
+ case "synth": this.#getPatternParent( "keys", val ).append( elPat ); break;
+ case "bufferType":
+ GSUsetAttribute( elPat, "data-buffer-type", val );
+ elPat.querySelector( ".gsuiPatterns-pattern-btnInfo" ).dataset.icon = `buf-${ val || "undefined" }`;
+ break;
+ case "bufferBpm":
+ GSUsetAttribute( elPat, "data-buffer-bpm", val );
+ break;
+ }
+ }
+ appendPatternSVG( id, svg ) {
+ svg.classList.add( "gsuiPatterns-pattern-svg" );
+ this.getPattern( id ).querySelector( ".gsuiPatterns-pattern-content" ).append( svg );
+ }
+ deletePattern( id ) {
+ this.getPattern( id )?.remove(); // 2.
+ }
+
+ // .........................................................................
+ selectPattern( type, id ) {
+ const elList = this.#elements.lists[ type === "keys" ? "synth" : type ];
+
+ elList.querySelector( ".gsuiPatterns-pattern-selected" )?.classList?.remove( "gsuiPatterns-pattern-selected" );
+ this.getPattern( id )?.classList?.add( "gsuiPatterns-pattern-selected" );
+ }
+ selectSynth( id ) {
+ this.#elements.lists.synth.querySelector( ".gsuiPatterns-synth-selected" )?.classList?.remove( "gsuiPatterns-synth-selected" );
+ this.#getSynth( id ).classList.add( "gsuiPatterns-synth-selected" );
+ }
+
+ // .........................................................................
+ getPattern( id ) {
+ return this.querySelector( `.gsuiPatterns-pattern[data-id="${ id }"]` );
+ }
+ #getSynth( id ) {
+ return this.#elements.lists.synth.querySelector( `.gsuiPatterns-synth[data-id="${ id }"]` );
+ }
+ #getPatternParent( type, synthId ) {
+ switch ( type ) {
+ case "slices":
+ case "buffer":
+ case "drums": return this.#elements.lists[ type ];
+ case "keys": return this.#elements.lists.synth.querySelector( `.gsuiPatterns-synth[data-id="${ synthId }"] .gsuiPatterns-synth-patterns` );
+ }
+ }
+
+ // .........................................................................
+ #onreorderPatterns( list, elPat ) {
+ this.onchange( "reorderPattern", elPat.dataset.id,
+ gsuiReorder.listComputeOrderChange( list, {} ) );
+ }
+ #onreorderPatternsKeys( elPat, indA, indB, parA, parB ) {
+ if ( parA === parB ) {
+ this.#onreorderPatterns( parA, elPat );
+ } else {
+ const patId = elPat.dataset.id;
+ const synth = parB.parentNode.dataset.id;
+ const patterns = { [ patId ]: { synth } };
+
+ gsuiReorder.listComputeOrderChange( parA, patterns );
+ gsuiReorder.listComputeOrderChange( parB, patterns );
+ this.onchange( "redirectPatternKeys", patId, synth, patterns );
+ }
+ }
+ #onclickListPatterns( e ) {
+ const pat = e.target.closest( ".gsuiPatterns-pattern" );
+
+ if ( pat ) {
+ this.#fnsPattern[ e.target.dataset.action ]( pat.dataset.id, pat, e );
+ return false;
+ }
+ }
+ #onclickSynths( e ) {
+ if ( this.#onclickListPatterns( e ) !== false ) {
+ const syn = e.target.closest( ".gsuiPatterns-synth" );
+
+ if ( syn ) {
+ this.#fnsSynth[ e.target.dataset.action ]( syn.dataset.id, e );
+ }
+ }
+ }
+}
+
+Object.freeze( gsuiPatterns );
+customElements.define( "gsui-patterns", gsuiPatterns );
+
+/*
+1. The cloning feature for the patterns of type buffer is removed because it's for the moment useless.
+2. We are checking if the pattern exists because the entire synth could have been removed before.
+*/