MediaWiki:Common.js

From Tuflow
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* Any JavaScript here will be loaded for all users on every page load. */

/* Add live search to hardware benchmark tables */
mw.hook('wikipage.content').add(function ($content) {
    'use strict';

    var action = mw.config.get('wgAction');

    /* Do not run inside edit or preview screens */
    if (action === 'edit' || action === 'submit') {
        return;
    }

    $content.find('.benchmark-results-table').each(function () {
        var table = this;

        if (table.dataset.searchInitialised === 'true') {
            return;
        }

        table.dataset.searchInitialised = 'true';

        /* Create a wrapper that follows the table's natural width */
        var tableBlock = document.createElement('div');
        tableBlock.className = 'benchmark-table-block';

        table.parentNode.insertBefore(tableBlock, table);
        tableBlock.appendChild(table);

        var controls = document.createElement('div');
        controls.className = 'benchmark-table-controls';

        var searchWrapper = document.createElement('div');
        searchWrapper.className = 'benchmark-table-search';

        var input = document.createElement('input');
        input.type = 'search';
        input.className = 'benchmark-search-input';
        input.placeholder =
            'Search processor, system name, RAM, or benchmark result';
        input.setAttribute(
            'aria-label',
            'Search benchmark results'
        );

        var clearButton = document.createElement('button');
        clearButton.type = 'button';
        clearButton.className = 'benchmark-search-clear';
        clearButton.textContent = 'Clear';

        var resultCount = document.createElement('div');
        resultCount.className = 'benchmark-result-count';
        resultCount.setAttribute('aria-live', 'polite');

        searchWrapper.appendChild(input);
        searchWrapper.appendChild(clearButton);

        controls.appendChild(searchWrapper);
        controls.appendChild(resultCount);

        tableBlock.insertBefore(controls, table);

        var rows = Array.from(
            table.querySelectorAll('tr')
        ).filter(function (row) {
            return row.querySelectorAll('td').length > 0;
        });

        function normaliseText(value) {
            return value
                .toLocaleLowerCase()
                .replace(/\s+/g, ' ')
                .trim();
        }

        function filterRows() {
            var query = normaliseText(input.value);
            var visibleCount = 0;

            rows.forEach(function (row) {
                var matches =
                    query === '' ||
                    normaliseText(row.textContent).includes(query);

                row.hidden = !matches;

                if (matches) {
                    visibleCount += 1;
                }
            });

            resultCount.textContent = query
                ? visibleCount +
                  ' matching result' +
                  (visibleCount === 1 ? '' : 's')
                : rows.length + ' benchmark results';

            clearButton.hidden = query === '';
        }

        input.addEventListener('input', filterRows);

        clearButton.addEventListener('click', function () {
            input.value = '';
            filterRows();
            input.focus();
        });

        filterRows();
    });
});

/* Add live search to Example Model Catalogue tables */
mw.hook('wikipage.content').add(function ($content) {
    'use strict';

    var action = mw.config.get('wgAction');

    /* Do not run inside edit or preview screens */
    if (action === 'edit' || action === 'submit') {
        return;
    }

    $content.find('.example-model-results-table').each(function () {
        var table = this;

        if (table.dataset.exampleSearchInitialised === 'true') {
            return;
        }

        table.dataset.exampleSearchInitialised = 'true';

        /*
         * Reuse the hardware-search classes for the same appearance,
         * while retaining separate Example Model filtering behaviour.
         */
        var tableBlock = document.createElement('div');
        tableBlock.className = 'benchmark-table-block';

        table.parentNode.insertBefore(tableBlock, table);
        tableBlock.appendChild(table);

        var controls = document.createElement('div');
        controls.className = 'benchmark-table-controls';

        var searchWrapper = document.createElement('div');
        searchWrapper.className = 'benchmark-table-search';

        var input = document.createElement('input');
        input.type = 'search';
        input.className = 'benchmark-search-input';
        input.placeholder =
            'Search model category, description, or model name';
        input.setAttribute(
            'aria-label',
            'Search Example Model Catalogue'
        );

        var clearButton = document.createElement('button');
        clearButton.type = 'button';
        clearButton.className = 'benchmark-search-clear';
        clearButton.textContent = 'Clear';

        var resultCount = document.createElement('div');
        resultCount.className = 'benchmark-result-count';
        resultCount.setAttribute('aria-live', 'polite');

        searchWrapper.appendChild(input);
        searchWrapper.appendChild(clearButton);

        controls.appendChild(searchWrapper);
        controls.appendChild(resultCount);

        tableBlock.insertBefore(controls, table);

        var rows = Array.from(
            table.querySelectorAll('tr')
        ).filter(function (row) {
            return row.querySelectorAll('td').length > 0;
        });

        function normaliseText(value) {
            return value
                .toLocaleLowerCase()
                .replace(/\s+/g, ' ')
                .trim();
        }

        function filterRows() {
            var query = normaliseText(input.value);
            var visibleCount = 0;

            rows.forEach(function (row) {
                var matches =
                    query === '' ||
                    normaliseText(row.textContent).includes(query);

                row.hidden = !matches;

                if (matches) {
                    visibleCount += 1;
                }
            });

            resultCount.textContent = query
                ? visibleCount +
                  ' matching model' +
                  (visibleCount === 1 ? '' : 's')
                : rows.length + ' example models';

            clearButton.hidden = query === '';
        }

        input.addEventListener('input', filterRows);

        clearButton.addEventListener('click', function () {
            input.value = '';
            filterRows();
            input.focus();
        });

        filterRows();
    });
});