| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 | import loadScript from 'load-script';/** * @typedef {Object} InitParams * @property {WavesurferParams} [defaults={backend: 'MediaElement, * mediaControls: true}] The default wavesurfer initialisation parameters * @property {string|NodeList} containers='wavesurfer' Selector or NodeList of * elements to attach instances to * @property {string} * pluginCdnTemplate='//localhost:8080/dist/plugin/wavesurfer.[name].js' URL * template for the dynamic loading of plugins * @property {function} loadPlugin If set overwrites the default ajax function, * can be used to inject plugins differently. *//** * The HTML initialisation API is not part of the main library bundle file and * must be additionally included. * * The API attaches wavesurfer instances to all `<wavesurfer>` (can be * customised), parsing their `data-` attributes to construct an options object * for initialisation. Among other things it can dynamically load plugin code. * * The automatic initialisation can be prevented by setting the * `window.WS_StopAutoInit` flag to true. The `html-init[.min].js` file exports * the `Init` class, which can be called manually. * * Site-wide defaults can be added by setting `window.WS_InitOptions`. * * @example * <!-- with minimap and timeline plugin --> * <wavesurfer *   data-url="../media/demo.wav" *   data-plugins="minimap,timeline" *   data-minimap-height="30" *   data-minimap-wave-color="#ddd" *   data-minimap-progress-color="#999" *   data-timeline-font-size="13px" *   data-timeline-container="#timeline" * > * </wavesurfer> * <div id="timeline"></div> * * <!-- with regions plugin --> * <wavesurfer *   data-url="../media/demo.wav" *   data-plugins="regions" *   data-regions-regions='[{"start": 1,"end": 3,"color": "hsla(400, 100%, 30%, 0.5)"}]' * > * </wavesurfer> */class Init {    /**     * Instantiate Init class and initialise elements     *     * This is done automatically if `window` is defined and     * `window.WS_StopAutoInit` is not set to true     *     * @param {WaveSurfer} WaveSurfer The WaveSurfer library object     * @param {InitParams} params initialisation options     */    constructor(WaveSurfer, params = {}) {        if (!WaveSurfer) {            throw new Error('WaveSurfer is not available!');        }        /**         * cache WaveSurfer         * @private         */        this.WaveSurfer = WaveSurfer;        /**         * build parameters, cache them in _params so minified builds are smaller         * @private         */        const _params = this.params = WaveSurfer.util.extend({}, {            // wavesurfer parameter defaults so by default the audio player is            // usable with native media element controls            defaults: {                backend: 'MediaElement',                mediaControls: true            },            // containers to instantiate on, can be selector string or NodeList            containers: 'wavesurfer',            // @TODO insert plugin CDN URIs            pluginCdnTemplate: '//localhost:8080/dist/plugin/wavesurfer.[name].js',            // loadPlugin function can be overriden to inject plugin definition            // objects, this default function uses load-script to load a plugin            // and pass it to a callback            loadPlugin(name, cb) {                const src = _params.pluginCdnTemplate.replace('[name]', name);                loadScript(src, { async: false }, (err, plugin) => {                    if (err) {                        return console.error(`WaveSurfer plugin ${name} not found at ${src}`);                    }                    cb(window.WaveSurfer[name]);                });            }        }, params);        /**         * The nodes that should have instances attached to them         * @type {NodeList}         */        this.containers = typeof _params.containers == 'string'            ? document.querySelectorAll(_params.containers)            : _params.containers;        /** @private */        this.pluginCache = {};        /**         * An array of wavesurfer instances         * @type {Object[]}         */        this.instances = [];        this.initAllEls();    }    /**     * Initialise all container elements     */    initAllEls() {        // iterate over all the container elements        Array.prototype.forEach.call(this.containers, el => {            // load the plugins as an array of plugin names            const plugins = el.dataset.plugins                ? el.dataset.plugins.split(',')                : [];            // no plugins to be loaded, just render            if (!plugins.length) {                return this.initEl(el);            }            // … or: iterate over all the plugins            plugins.forEach((name, i) => {                // plugin is not cached already, load it                if (!this.pluginCache[name]) {                    this.params.loadPlugin(name, lib => {                        this.pluginCache[name] = lib;                        // plugins were all loaded, render the element                        if (i + 1 === plugins.length) {                            this.initEl(el, plugins);                        }                    });                } else if (i === plugins.length) {                    // plugin was cached and this plugin was the last                    this.initEl(el, plugins);                }            });        });    }    /**     * Initialise a single container element and add to `this.instances`     *     * @param  {HTMLElement} el The container to instantiate wavesurfer to     * @param  {PluginDefinition[]} plugins An Array of plugin names to initialise with     * @return {Object} Wavesurfer instance     */    initEl(el, plugins = []) {        const jsonRegex = /^[[|{]/;        // initialise plugins with the correct options        const initialisedPlugins = plugins.map(plugin => {            const options = {};            // the regex to find this plugin attributes            const attrNameRegex = new RegExp('^' + plugin);            let attrName;            // iterate over all the data attributes and find ones for this            // plugin            for (attrName in el.dataset) {                const regexResult = attrNameRegex.exec(attrName);                if (regexResult) {                    const attr = el.dataset[attrName];                    // if the string begins with a [ or a { parse it as JSON                    const prop = jsonRegex.test(attr) ? JSON.parse(attr) : attr;                    // this removes the plugin prefix and changes the first letter                    // of the resulting string to lower case to follow the naming                    // convention of ws params                    const unprefixedOptionName = attrName.slice(plugin.length, plugin.length + 1).toLowerCase()                        + attrName.slice(plugin.length + 1);                    options[unprefixedOptionName] = prop;                }            }            return this.pluginCache[plugin].create(options);        });        // build parameter object for this container        const params = this.WaveSurfer.util.extend(            { container: el },            this.params.defaults,            el.dataset,            { plugins: initialisedPlugins }        );        // @TODO make nicer        el.style.display = 'block';        // initialise wavesurfer, load audio (with peaks if provided)        const instance = this.WaveSurfer.create(params);        const peaks = params.peaks ? JSON.parse(params.peaks) : undefined;        instance.load(params.url, peaks);        // push this instance into the instances cache        this.instances.push(instance);        return instance;    }}// if window object exists and window.WS_StopAutoInit is not trueif (typeof window === 'object' && !window.WS_StopAutoInit) {    // call init when document is ready, apply any custom default settings    // in window.WS_InitOptions    if (document.readyState === 'complete') {        window.WaveSurferInit = new Init(window.WaveSurfer, window.WS_InitOptions);    } else {        window.addEventListener('load', () => {            window.WaveSurferInit = new Init(window.WaveSurfer, window.WS_InitOptions);        });    }}// export init for manual usageexport default Init;
 |