User:Inthar/common.js: Difference between revisions

Inthar (talk | contribs)
Created page with "** BEGIN WIKIBREAK ENFORCER **: $(document).ready(function() { ** Start editing here **: // When you want to end your break? // no leading zeroes. (example: 9 - co..."
 
Inthar (talk | contribs)
No edit summary
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
/*** BEGIN WIKIBREAK ENFORCER ***/
(function () {
$(document).ready(function()  
    'use strict';
{


/*** Start editing here ***/
    var ctx = null;
    var activeNodes = [];
    var activeBtn = null;
    var STORAGE_KEY = 'edoChordPlayTimbre';
    var TIMBRES = ['triangle', 'sawtooth', 'square', 'sine'];
    var TIMBRE_LABELS = { triangle: 'Triangle', sawtooth: 'Sawtooth', square: 'Square', sine: 'Sine' };
    var LOOK_AHEAD = 0.00;    // 50ms buffer so the audio thread can schedule
    var BASE_FREQ = 261.63;  // middle C; pitch is set via detune (cents) on top


// When you want to end your break?
    var timbre = (function () {
// no leading zeroes. (example: 9 - correct, 09 - incorrect)
        try {
            var saved = localStorage.getItem(STORAGE_KEY);
            return TIMBRES.indexOf(saved) >= 0 ? saved : 'triangle';
        } catch (e) { return 'triangle'; }
    })();


var date = { year: 2100, month: 2, day: 11};
    function setTimbre(t) {
var time = { hours: 20, minutes: 22, seconds: 0 };
        if (TIMBRES.indexOf(t) < 0) return;
        timbre = t;
        try { localStorage.setItem(STORAGE_KEY, t); } catch (e) {}
        document.querySelectorAll('.edo-chord-timbre').forEach(function (sel) {
            sel.value = t;
        });
    }


/*** Stop editing here ***/
    function getCtx() {
        if (!ctx) ctx = new (window.AudioContext || window.webkitAudioContext)();
var currentDate = new Date();
        return ctx;
var enforcedBreakEnd = new Date(
    }
date.year,date.month-1,date.day,time.hours,time.minutes,time.seconds);
 
if (currentDate <= enforcedBreakEnd)  
    function disposeNode(node) {
{
        try { node.osc.disconnect(); } catch (e) {}
alert("Enforced wikibreak until "+enforcedBreakEnd.toLocaleString()
        try { node.gain.disconnect(); } catch (e) {}
+ "\n(now is "+currentDate.toLocaleString()+")\n\nBye!");
        var idx = activeNodes.indexOf(node);
mw.loader.using(["mediawiki.api", "mediawiki.user"]).then(function ()
        if (idx >= 0) activeNodes.splice(idx, 1);
{
    }
new mw.Api().post(
 
{
    function stopAll() {
action: 'logout',
        if (!ctx) return;
token: mw.user.tokens.get('csrfToken')
        var now = ctx.currentTime + LOOK_AHEAD;
}).done(function (data)
        // Snapshot and clear before stopping, so onended handlers find no matches and just dispose
{
        var toStop = activeNodes;
location = "//" + location.host + "/w/index.php?title="
        activeNodes = [];
+ "Special:Userlogin&returnto=Main_Page";
        toStop.forEach(function (n) {
}).fail(function ()
            try {
{
                n.gain.gain.cancelScheduledValues(now);
console.log("logout failed")
                n.gain.gain.setValueAtTime(n.gain.gain.value, now);
});
                n.gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.05);
});
                n.osc.stop(now + 0.06);
}
            } catch (e) {}
});
        });
/*** END WIKIBREAK ENFORCER ***/
        if (activeBtn) { activeBtn.classList.remove('playing'); activeBtn = null; }
    }
 
    function playChord(centsArr, btn) {
        stopAll();
        var c = getCtx();
        if (c.state === 'suspended') c.resume();
        var now = c.currentTime + LOOK_AHEAD;
        var attack = 0.02, sustain = 0.2, release = 5;
        var totalDur = attack + sustain + release;
        var peak = 0.18 / Math.sqrt(centsArr.length);
 
        centsArr.forEach(function (cents) {
            var osc = c.createOscillator();
            var gain = c.createGain();
            osc.type = timbre;
            osc.frequency.value = BASE_FREQ;
            osc.detune.value = cents;
            gain.gain.setValueAtTime(0, now);
            gain.gain.linearRampToValueAtTime(peak, now + attack);
            gain.gain.setValueAtTime(peak, now + attack + sustain);
            gain.gain.exponentialRampToValueAtTime(0.0001, now + totalDur);
            osc.connect(gain).connect(c.destination);
            osc.start(now);
            osc.stop(now + totalDur + 0.1);
 
            var node = { osc: osc, gain: gain };
            activeNodes.push(node);
            osc.onended = function () { disposeNode(node); };
        });
 
        if (btn) {
            btn.classList.add('playing');
            activeBtn = btn;
            setTimeout(function () {
                if (activeBtn === btn) { btn.classList.remove('playing'); activeBtn = null; }
            }, totalDur * 1000);
        }
    }
 
    function injectSelectors() {
        var tables = new Set();
        document.querySelectorAll('.edo-chord-play').forEach(function (btn) {
            var table = btn.closest('table');
            if (table) tables.add(table);
        });
        tables.forEach(function (table) {
            var firstTh = table.querySelector('th');
            if (!firstTh || firstTh.querySelector('.edo-chord-timbre')) return;
            var sel = document.createElement('select');
            sel.className = 'edo-chord-timbre';
            sel.title = 'Synth timbre';
            TIMBRES.forEach(function (t) {
                var opt = document.createElement('option');
                opt.value = t;
                opt.textContent = TIMBRE_LABELS[t];
                if (t === timbre) opt.selected = true;
                sel.appendChild(opt);
            });
            sel.addEventListener('change', function () { setTimbre(sel.value); });
            sel.addEventListener('click', function (e) { e.stopPropagation(); });
            firstTh.innerHTML = '';
            firstTh.appendChild(sel);
        });
    }
 
    function handle(e) {
        var btn = e.target.closest && e.target.closest('.edo-chord-play');
        if (!btn) return;
        e.preventDefault();
        if (btn === activeBtn) { stopAll(); return; }
 
        var cents;
        if (btn.dataset.cents) {
            cents = btn.dataset.cents.split(',').map(Number);
        } else {
            var edo = parseInt(btn.dataset.edo, 10);
            var steps = (btn.dataset.steps || '').split(',').map(Number);
            if (!edo || !steps.length) return;
            var stepSize = 1200 / edo;
            cents = steps.map(function (s) { return s * stepSize; });
        }
        if (!cents.length || cents.some(isNaN)) return;
        playChord(cents, btn);
    }
 
    document.addEventListener('click', handle);
    document.addEventListener('keydown', function (e) {
        if ((e.key === 'Enter' || e.key === ' ') && e.target.classList && e.target.classList.contains('edo-chord-play')) {
            handle(e);
        }
    });
 
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', injectSelectors);
    } else {
        injectSelectors();
    }
}());