<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
	<id>https://www.insurerbrain.com/w/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-wix-core.js</id>
	<title>MediaWiki:Gadget-wix-core.js - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.insurerbrain.com/w/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-wix-core.js"/>
	<link rel="alternate" type="text/html" href="https://www.insurerbrain.com/w/index.php?title=MediaWiki:Gadget-wix-core.js&amp;action=history"/>
	<updated>2026-04-22T07:09:44Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://www.insurerbrain.com/w/index.php?title=MediaWiki:Gadget-wix-core.js&amp;diff=22526&amp;oldid=prev</id>
		<title>Wikilah admin: Created page with &quot;/* ================================================================    WIX-CORE.JS — Wiki Interactive Experience: Shared Foundation    ================================================================    Loaded via ResourceLoader on every page (hidden gadget).    Provides DOM helpers, state management, event delegation, and    UI-building utilities used by all wix-* category gadgets.     Exposes:  window.wix  (single global namespace)     RULES:    - All public API live...&quot;</title>
		<link rel="alternate" type="text/html" href="https://www.insurerbrain.com/w/index.php?title=MediaWiki:Gadget-wix-core.js&amp;diff=22526&amp;oldid=prev"/>
		<updated>2026-03-31T05:40:49Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;/* ================================================================    WIX-CORE.JS — Wiki Interactive Experience: Shared Foundation    ================================================================    Loaded via ResourceLoader on every page (hidden gadget).    Provides DOM helpers, state management, event delegation, and    UI-building utilities used by all wix-* category gadgets.     Exposes:  window.wix  (single global namespace)     RULES:    - All public API live...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;/* ================================================================&lt;br /&gt;
   WIX-CORE.JS — Wiki Interactive Experience: Shared Foundation&lt;br /&gt;
   ================================================================&lt;br /&gt;
   Loaded via ResourceLoader on every page (hidden gadget).&lt;br /&gt;
   Provides DOM helpers, state management, event delegation, and&lt;br /&gt;
   UI-building utilities used by all wix-* category gadgets.&lt;br /&gt;
&lt;br /&gt;
   Exposes:  window.wix  (single global namespace)&lt;br /&gt;
&lt;br /&gt;
   RULES:&lt;br /&gt;
   - All public API lives under window.wix.&lt;br /&gt;
   - Never touch the DOM outside [data-wix-module] containers.&lt;br /&gt;
   - Guard every hook callback so it costs nothing on pages&lt;br /&gt;
     without WIX content.&lt;br /&gt;
   ================================================================ */&lt;br /&gt;
&lt;br /&gt;
( function () {&lt;br /&gt;
  &amp;#039;use strict&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
  // Prevent double-load&lt;br /&gt;
  if ( window.wix ) {&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* ── Namespace ────────────────────────────────────────────────── */&lt;br /&gt;
&lt;br /&gt;
  var wix = {};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* ── 1. DOM Helpers ───────────────────────────────────────────── */&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Shorthand for querySelector scoped to a parent.&lt;br /&gt;
   * @param {string} selector&lt;br /&gt;
   * @param {Element} [parent=document]&lt;br /&gt;
   * @returns {Element|null}&lt;br /&gt;
   */&lt;br /&gt;
  wix.qs = function ( selector, parent ) {&lt;br /&gt;
    return ( parent || document ).querySelector( selector );&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Shorthand for querySelectorAll, returns a real Array.&lt;br /&gt;
   * @param {string} selector&lt;br /&gt;
   * @param {Element} [parent=document]&lt;br /&gt;
   * @returns {Element[]}&lt;br /&gt;
   */&lt;br /&gt;
  wix.qsa = function ( selector, parent ) {&lt;br /&gt;
    return Array.prototype.slice.call(&lt;br /&gt;
      ( parent || document ).querySelectorAll( selector )&lt;br /&gt;
    );&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Create an element with optional attributes, classes, and children.&lt;br /&gt;
   *&lt;br /&gt;
   *   wix.el(&amp;#039;div&amp;#039;, { className: &amp;#039;wix-card&amp;#039;, &amp;#039;data-idx&amp;#039;: &amp;#039;3&amp;#039; }, [&lt;br /&gt;
   *     wix.el(&amp;#039;span&amp;#039;, { className: &amp;#039;wix-badge&amp;#039;, textContent: &amp;#039;1&amp;#039; }),&lt;br /&gt;
   *     &amp;#039;Plain text node&amp;#039;&lt;br /&gt;
   *   ]);&lt;br /&gt;
   *&lt;br /&gt;
   * @param {string} tag&lt;br /&gt;
   * @param {Object} [attrs]  - Applied via setAttribute, except:&lt;br /&gt;
   *        className  -&amp;gt; el.className&lt;br /&gt;
   *        textContent -&amp;gt; el.textContent&lt;br /&gt;
   *        innerHTML  -&amp;gt; el.innerHTML&lt;br /&gt;
   *        style (object) -&amp;gt; Object.assign(el.style, ...)&lt;br /&gt;
   * @param {Array&amp;lt;Element|string&amp;gt;} [children]&lt;br /&gt;
   * @returns {Element}&lt;br /&gt;
   */&lt;br /&gt;
  wix.el = function ( tag, attrs, children ) {&lt;br /&gt;
    var el = document.createElement( tag );&lt;br /&gt;
    var directProps = { className: 1, textContent: 1, innerHTML: 1 };&lt;br /&gt;
&lt;br /&gt;
    if ( attrs ) {&lt;br /&gt;
      Object.keys( attrs ).forEach( function ( key ) {&lt;br /&gt;
        if ( directProps[ key ] ) {&lt;br /&gt;
          el[ key ] = attrs[ key ];&lt;br /&gt;
        } else if ( key === &amp;#039;style&amp;#039; &amp;amp;&amp;amp; typeof attrs[ key ] === &amp;#039;object&amp;#039; ) {&lt;br /&gt;
          Object.keys( attrs[ key ] ).forEach( function ( prop ) {&lt;br /&gt;
            el.style[ prop ] = attrs[ key ][ prop ];&lt;br /&gt;
          } );&lt;br /&gt;
        } else {&lt;br /&gt;
          el.setAttribute( key, attrs[ key ] );&lt;br /&gt;
        }&lt;br /&gt;
      } );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ( children ) {&lt;br /&gt;
      children.forEach( function ( child ) {&lt;br /&gt;
        if ( child == null ) {&lt;br /&gt;
          return;&lt;br /&gt;
        }&lt;br /&gt;
        if ( typeof child === &amp;#039;string&amp;#039; || typeof child === &amp;#039;number&amp;#039; ) {&lt;br /&gt;
          el.appendChild( document.createTextNode( String( child ) ) );&lt;br /&gt;
        } else {&lt;br /&gt;
          el.appendChild( child );&lt;br /&gt;
        }&lt;br /&gt;
      } );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return el;&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Remove all child nodes from an element.&lt;br /&gt;
   * @param {Element} el&lt;br /&gt;
   */&lt;br /&gt;
  wix.empty = function ( el ) {&lt;br /&gt;
    while ( el.firstChild ) {&lt;br /&gt;
      el.removeChild( el.firstChild );&lt;br /&gt;
    }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Toggle a CSS class on an element.&lt;br /&gt;
   * @param {Element} el&lt;br /&gt;
   * @param {string} cls&lt;br /&gt;
   * @param {boolean} [force]&lt;br /&gt;
   */&lt;br /&gt;
  wix.toggle = function ( el, cls, force ) {&lt;br /&gt;
    if ( typeof force === &amp;#039;boolean&amp;#039; ) {&lt;br /&gt;
      el.classList.toggle( cls, force );&lt;br /&gt;
    } else {&lt;br /&gt;
      el.classList.toggle( cls );&lt;br /&gt;
    }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* ── 2. Event Delegation ──────────────────────────────────────── */&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Attach a delegated event listener to a container.&lt;br /&gt;
   * Clicks (or other events) on descendants matching `selector`&lt;br /&gt;
   * trigger the callback with the matched element.&lt;br /&gt;
   *&lt;br /&gt;
   *   wix.on(container, &amp;#039;click&amp;#039;, &amp;#039;.wix-option&amp;#039;, function (target, e) {&lt;br /&gt;
   *     // target is the .wix-option element&lt;br /&gt;
   *   });&lt;br /&gt;
   *&lt;br /&gt;
   * @param {Element} root&lt;br /&gt;
   * @param {string} eventType&lt;br /&gt;
   * @param {string} selector&lt;br /&gt;
   * @param {function(Element, Event)} callback&lt;br /&gt;
   */&lt;br /&gt;
  wix.on = function ( root, eventType, selector, callback ) {&lt;br /&gt;
    root.addEventListener( eventType, function ( e ) {&lt;br /&gt;
      var target = e.target.closest( selector );&lt;br /&gt;
      if ( target &amp;amp;&amp;amp; root.contains( target ) ) {&lt;br /&gt;
        callback( target, e );&lt;br /&gt;
      }&lt;br /&gt;
    } );&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* ── 3. Data Attribute Helpers ────────────────────────────────── */&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Read a data attribute, with an optional fallback.&lt;br /&gt;
   * @param {Element} el&lt;br /&gt;
   * @param {string} key   - Attribute name without &amp;quot;data-&amp;quot; prefix.&lt;br /&gt;
   * @param {*} [fallback]&lt;br /&gt;
   * @returns {string|*}&lt;br /&gt;
   */&lt;br /&gt;
  wix.data = function ( el, key, fallback ) {&lt;br /&gt;
    var val = el.getAttribute( &amp;#039;data-&amp;#039; + key );&lt;br /&gt;
    return val !== null ? val : ( fallback !== undefined ? fallback : null );&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Write a data attribute.&lt;br /&gt;
   * @param {Element} el&lt;br /&gt;
   * @param {string} key&lt;br /&gt;
   * @param {string|number} value&lt;br /&gt;
   */&lt;br /&gt;
  wix.setData = function ( el, key, value ) {&lt;br /&gt;
    el.setAttribute( &amp;#039;data-&amp;#039; + key, String( value ) );&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* ── 4. Module Init Guard ─────────────────────────────────────── */&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Find all containers for a given module type that have not yet&lt;br /&gt;
   * been initialized, mark them, and return the list.&lt;br /&gt;
   *&lt;br /&gt;
   *   var quizzes = wix.initModules(&amp;#039;quiz&amp;#039;);&lt;br /&gt;
   *   quizzes.forEach(function (el) { ... });&lt;br /&gt;
   *&lt;br /&gt;
   * @param {string} moduleType  - Value of data-wix-module.&lt;br /&gt;
   * @returns {Element[]}&lt;br /&gt;
   */&lt;br /&gt;
  wix.initModules = function ( moduleType ) {&lt;br /&gt;
    var selector = &amp;#039;[data-wix-module=&amp;quot;&amp;#039; + moduleType + &amp;#039;&amp;quot;]&amp;#039;;&lt;br /&gt;
    var all = wix.qsa( selector );&lt;br /&gt;
    var fresh = [];&lt;br /&gt;
    all.forEach( function ( el ) {&lt;br /&gt;
      if ( !el.getAttribute( &amp;#039;data-wix-init&amp;#039; ) ) {&lt;br /&gt;
        el.setAttribute( &amp;#039;data-wix-init&amp;#039;, &amp;#039;1&amp;#039; );&lt;br /&gt;
        fresh.push( el );&lt;br /&gt;
      }&lt;br /&gt;
    } );&lt;br /&gt;
    return fresh;&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* ── 5. Simple State Manager ──────────────────────────────────── */&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Create a minimal reactive state object for a single widget instance.&lt;br /&gt;
   * State changes trigger a render callback.&lt;br /&gt;
   *&lt;br /&gt;
   *   var state = wix.createState({ step: 0, score: 0 }, render);&lt;br /&gt;
   *   state.set({ step: 1 });      // triggers render(newState)&lt;br /&gt;
   *   state.get().step;             // 1&lt;br /&gt;
   *&lt;br /&gt;
   * @param {Object} initial&lt;br /&gt;
   * @param {function(Object)} onChange&lt;br /&gt;
   * @returns {{ get: function():Object, set: function(Object) }}&lt;br /&gt;
   */&lt;br /&gt;
  wix.createState = function ( initial, onChange ) {&lt;br /&gt;
    var state = {};&lt;br /&gt;
    Object.keys( initial ).forEach( function ( k ) {&lt;br /&gt;
      state[ k ] = initial[ k ];&lt;br /&gt;
    } );&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
      get: function () {&lt;br /&gt;
        return state;&lt;br /&gt;
      },&lt;br /&gt;
      set: function ( patch ) {&lt;br /&gt;
        Object.keys( patch ).forEach( function ( k ) {&lt;br /&gt;
          state[ k ] = patch[ k ];&lt;br /&gt;
        } );&lt;br /&gt;
        if ( typeof onChange === &amp;#039;function&amp;#039; ) {&lt;br /&gt;
          onChange( state );&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* ── 6. UI Builders ───────────────────────────────────────────── */&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Build a progress bar and return an object with an update method.&lt;br /&gt;
   *&lt;br /&gt;
   *   var bar = wix.buildProgressBar(container);&lt;br /&gt;
   *   bar.update(3, 10);  // &amp;quot;Question 3 of 10&amp;quot;, fill 30%&lt;br /&gt;
   *&lt;br /&gt;
   * @param {Element} parent - Element to append the bar into.&lt;br /&gt;
   * @returns {{ el: Element, update: function(number, number) }}&lt;br /&gt;
   */&lt;br /&gt;
  wix.buildProgressBar = function ( parent ) {&lt;br /&gt;
    var label = wix.el( &amp;#039;span&amp;#039;, { className: &amp;#039;wix-progress-label&amp;#039; } );&lt;br /&gt;
    var fill = wix.el( &amp;#039;div&amp;#039;, { className: &amp;#039;wix-progress-fill&amp;#039; } );&lt;br /&gt;
    var track = wix.el( &amp;#039;div&amp;#039;, { className: &amp;#039;wix-progress-track&amp;#039; }, [ fill ] );&lt;br /&gt;
    var wrap = wix.el( &amp;#039;div&amp;#039;, { className: &amp;#039;wix-progress-wrap&amp;#039; }, [ label, track ] );&lt;br /&gt;
&lt;br /&gt;
    parent.appendChild( wrap );&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
      el: wrap,&lt;br /&gt;
      update: function ( current, total ) {&lt;br /&gt;
        label.textContent = &amp;#039;Question &amp;#039; + current + &amp;#039; of &amp;#039; + total;&lt;br /&gt;
        fill.style.width = ( ( current / total ) * 100 ).toFixed( 1 ) + &amp;#039;%&amp;#039;;&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Build a score ring (SVG circle) and return an object with a set method.&lt;br /&gt;
   *&lt;br /&gt;
   *   var ring = wix.buildScoreRing(container);&lt;br /&gt;
   *   ring.set(7, 10);  // 70 %, animates the ring fill&lt;br /&gt;
   *&lt;br /&gt;
   * @param {Element} parent&lt;br /&gt;
   * @returns {{ el: Element, set: function(number, number) }}&lt;br /&gt;
   */&lt;br /&gt;
  wix.buildScoreRing = function ( parent ) {&lt;br /&gt;
    var CIRCUMFERENCE = 264;&lt;br /&gt;
    var ns = &amp;#039;http://www.w3.org/2000/svg&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
    var bgCircle = document.createElementNS( ns, &amp;#039;circle&amp;#039; );&lt;br /&gt;
    bgCircle.setAttribute( &amp;#039;cx&amp;#039;, &amp;#039;48&amp;#039; );&lt;br /&gt;
    bgCircle.setAttribute( &amp;#039;cy&amp;#039;, &amp;#039;48&amp;#039; );&lt;br /&gt;
    bgCircle.setAttribute( &amp;#039;r&amp;#039;, &amp;#039;42&amp;#039; );&lt;br /&gt;
    bgCircle.setAttribute( &amp;#039;class&amp;#039;, &amp;#039;wix-ring-bg&amp;#039; );&lt;br /&gt;
&lt;br /&gt;
    var fillCircle = document.createElementNS( ns, &amp;#039;circle&amp;#039; );&lt;br /&gt;
    fillCircle.setAttribute( &amp;#039;cx&amp;#039;, &amp;#039;48&amp;#039; );&lt;br /&gt;
    fillCircle.setAttribute( &amp;#039;cy&amp;#039;, &amp;#039;48&amp;#039; );&lt;br /&gt;
    fillCircle.setAttribute( &amp;#039;r&amp;#039;, &amp;#039;42&amp;#039; );&lt;br /&gt;
    fillCircle.setAttribute( &amp;#039;class&amp;#039;, &amp;#039;wix-ring-fill&amp;#039; );&lt;br /&gt;
&lt;br /&gt;
    var svg = document.createElementNS( ns, &amp;#039;svg&amp;#039; );&lt;br /&gt;
    svg.setAttribute( &amp;#039;viewBox&amp;#039;, &amp;#039;0 0 96 96&amp;#039; );&lt;br /&gt;
    svg.appendChild( bgCircle );&lt;br /&gt;
    svg.appendChild( fillCircle );&lt;br /&gt;
&lt;br /&gt;
    var pct = wix.el( &amp;#039;span&amp;#039;, { className: &amp;#039;wix-score-pct&amp;#039; } );&lt;br /&gt;
    var sub = wix.el( &amp;#039;span&amp;#039;, { className: &amp;#039;wix-score-sub&amp;#039; } );&lt;br /&gt;
    var label = wix.el( &amp;#039;div&amp;#039;, { className: &amp;#039;wix-score-label&amp;#039; }, [ pct, sub ] );&lt;br /&gt;
&lt;br /&gt;
    var wrap = wix.el( &amp;#039;div&amp;#039;, { className: &amp;#039;wix-score-ring&amp;#039; }, [ svg, label ] );&lt;br /&gt;
    parent.appendChild( wrap );&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
      el: wrap,&lt;br /&gt;
      set: function ( correct, total ) {&lt;br /&gt;
        var ratio = total &amp;gt; 0 ? correct / total : 0;&lt;br /&gt;
        var offset = CIRCUMFERENCE - ( ratio * CIRCUMFERENCE );&lt;br /&gt;
        pct.textContent = Math.round( ratio * 100 ) + &amp;#039;%&amp;#039;;&lt;br /&gt;
        sub.textContent = correct + &amp;#039; / &amp;#039; + total + &amp;#039; correct&amp;#039;;&lt;br /&gt;
        // Delay to let the browser paint the initial state first&lt;br /&gt;
        requestAnimationFrame( function () {&lt;br /&gt;
          fillCircle.style.strokeDashoffset = offset;&lt;br /&gt;
        } );&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Build a feedback panel (correct / wrong) and return control methods.&lt;br /&gt;
   *&lt;br /&gt;
   *   var fb = wix.buildFeedback(card);&lt;br /&gt;
   *   fb.show(&amp;#039;correct&amp;#039;, &amp;#039;Well done!&amp;#039;, &amp;#039;Because...&amp;#039;);&lt;br /&gt;
   *   fb.hide();&lt;br /&gt;
   *&lt;br /&gt;
   * @param {Element} parent&lt;br /&gt;
   * @returns {{ el: Element, show: function(string, string, string), hide: function() }}&lt;br /&gt;
   */&lt;br /&gt;
  wix.buildFeedback = function ( parent ) {&lt;br /&gt;
    var strong = wix.el( &amp;#039;strong&amp;#039; );&lt;br /&gt;
    var explanation = wix.el( &amp;#039;span&amp;#039;, { className: &amp;#039;wix-explanation&amp;#039; } );&lt;br /&gt;
    var panel = wix.el( &amp;#039;div&amp;#039;, { className: &amp;#039;wix-feedback&amp;#039; }, [ strong, explanation ] );&lt;br /&gt;
&lt;br /&gt;
    parent.appendChild( panel );&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
      el: panel,&lt;br /&gt;
      show: function ( type, heading, detail ) {&lt;br /&gt;
        panel.className = &amp;#039;wix-feedback wix-feedback--&amp;#039; + type + &amp;#039; wix-feedback--show&amp;#039;;&lt;br /&gt;
        strong.textContent = heading;&lt;br /&gt;
        explanation.textContent = detail || &amp;#039;&amp;#039;;&lt;br /&gt;
      },&lt;br /&gt;
      hide: function () {&lt;br /&gt;
        panel.className = &amp;#039;wix-feedback&amp;#039;;&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Build a navigation bar with named buttons.&lt;br /&gt;
   *&lt;br /&gt;
   *   var nav = wix.buildNav(container, {&lt;br /&gt;
   *     next:    { label: &amp;#039;Next&amp;#039;, primary: true },&lt;br /&gt;
   *     restart: { label: &amp;#039;Restart&amp;#039;, outline: true }&lt;br /&gt;
   *   });&lt;br /&gt;
   *   nav.disable(&amp;#039;next&amp;#039;);&lt;br /&gt;
   *   nav.enable(&amp;#039;next&amp;#039;);&lt;br /&gt;
   *   nav.on(&amp;#039;next&amp;#039;, function () { ... });&lt;br /&gt;
   *   nav.show(&amp;#039;restart&amp;#039;);&lt;br /&gt;
   *   nav.hide(&amp;#039;restart&amp;#039;);&lt;br /&gt;
   *&lt;br /&gt;
   * @param {Element} parent&lt;br /&gt;
   * @param {Object} buttons  - { key: { label, primary?, outline?, hidden? } }&lt;br /&gt;
   * @returns {Object}&lt;br /&gt;
   */&lt;br /&gt;
  wix.buildNav = function ( parent, buttons ) {&lt;br /&gt;
    var bar = wix.el( &amp;#039;div&amp;#039;, { className: &amp;#039;wix-nav&amp;#039; } );&lt;br /&gt;
    var map = {};&lt;br /&gt;
    var handlers = {};&lt;br /&gt;
&lt;br /&gt;
    Object.keys( buttons ).forEach( function ( key ) {&lt;br /&gt;
      var cfg = buttons[ key ];&lt;br /&gt;
      var cls = &amp;#039;wix-btn&amp;#039;;&lt;br /&gt;
      if ( cfg.outline ) {&lt;br /&gt;
        cls += &amp;#039; wix-btn--outline&amp;#039;;&lt;br /&gt;
      }&lt;br /&gt;
      if ( cfg.hidden ) {&lt;br /&gt;
        cls += &amp;#039; wix-hidden&amp;#039;;&lt;br /&gt;
      }&lt;br /&gt;
      var btn = wix.el( &amp;#039;button&amp;#039;, { className: cls, textContent: cfg.label } );&lt;br /&gt;
      btn.addEventListener( &amp;#039;click&amp;#039;, function () {&lt;br /&gt;
        if ( handlers[ key ] ) {&lt;br /&gt;
          handlers[ key ]();&lt;br /&gt;
        }&lt;br /&gt;
      } );&lt;br /&gt;
      map[ key ] = btn;&lt;br /&gt;
      bar.appendChild( btn );&lt;br /&gt;
    } );&lt;br /&gt;
&lt;br /&gt;
    parent.appendChild( bar );&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
      el: bar,&lt;br /&gt;
      disable: function ( key ) {&lt;br /&gt;
        if ( map[ key ] ) {&lt;br /&gt;
          map[ key ].disabled = true;&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      enable: function ( key ) {&lt;br /&gt;
        if ( map[ key ] ) {&lt;br /&gt;
          map[ key ].disabled = false;&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      show: function ( key ) {&lt;br /&gt;
        if ( map[ key ] ) {&lt;br /&gt;
          map[ key ].classList.remove( &amp;#039;wix-hidden&amp;#039; );&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      hide: function ( key ) {&lt;br /&gt;
        if ( map[ key ] ) {&lt;br /&gt;
          map[ key ].classList.add( &amp;#039;wix-hidden&amp;#039; );&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      on: function ( key, fn ) {&lt;br /&gt;
        handlers[ key ] = fn;&lt;br /&gt;
      },&lt;br /&gt;
      btn: function ( key ) {&lt;br /&gt;
        return map[ key ] || null;&lt;br /&gt;
      }&lt;br /&gt;
    };&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* ── 7. Utility Functions ─────────────────────────────────────── */&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Shuffle an array in place (Fisher-Yates).&lt;br /&gt;
   * @param {Array} arr&lt;br /&gt;
   * @returns {Array} The same array, shuffled.&lt;br /&gt;
   */&lt;br /&gt;
  wix.shuffle = function ( arr ) {&lt;br /&gt;
    for ( var i = arr.length - 1; i &amp;gt; 0; i-- ) {&lt;br /&gt;
      var j = Math.floor( Math.random() * ( i + 1 ) );&lt;br /&gt;
      var tmp = arr[ i ];&lt;br /&gt;
      arr[ i ] = arr[ j ];&lt;br /&gt;
      arr[ j ] = tmp;&lt;br /&gt;
    }&lt;br /&gt;
    return arr;&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Clamp a number between min and max.&lt;br /&gt;
   * @param {number} val&lt;br /&gt;
   * @param {number} min&lt;br /&gt;
   * @param {number} max&lt;br /&gt;
   * @returns {number}&lt;br /&gt;
   */&lt;br /&gt;
  wix.clamp = function ( val, min, max ) {&lt;br /&gt;
    return Math.max( min, Math.min( max, val ) );&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  /**&lt;br /&gt;
   * Format a number with locale-appropriate thousand separators.&lt;br /&gt;
   * @param {number} n&lt;br /&gt;
   * @returns {string}&lt;br /&gt;
   */&lt;br /&gt;
  wix.formatNumber = function ( n ) {&lt;br /&gt;
    if ( typeof n !== &amp;#039;number&amp;#039; ) {&lt;br /&gt;
      return String( n );&lt;br /&gt;
    }&lt;br /&gt;
    return n.toLocaleString();&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* ── 8. Expose Namespace ──────────────────────────────────────── */&lt;br /&gt;
&lt;br /&gt;
  window.wix = wix;&lt;br /&gt;
&lt;br /&gt;
}() );&lt;/div&gt;</summary>
		<author><name>Wikilah admin</name></author>
	</entry>
</feed>