MediaWiki:Common.js
From GxPlex
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.
/* site-wide JS — VoteNY toggle is handled in Vote.js */
/* GxPlex Search — dynamic filter UI */
( function () {
if ( mw.config.get( 'wgPageName' ) !== 'GxPlex_Search' ) {
return;
}
var TOPICS = [
'Medical Devices',
'In Vitro Diagnostics',
'EU Regulation',
'Clinical',
'Labelling',
'Post-Market Surveillance',
'Performance Evaluation',
'Traceability'
];
var allResults = [];
/* ---- helpers ---- */
function esc( str ) {
return String( str || '' )
.replace( /&/g, '&' )
.replace( /</g, '<' )
.replace( />/g, '>' )
.replace( /"/g, '"' );
}
function el( tag, attrs, children ) {
var node = document.createElement( tag );
Object.keys( attrs || {} ).forEach( function ( k ) {
node.setAttribute( k, attrs[ k ] );
} );
( children || [] ).forEach( function ( c ) {
node.appendChild( typeof c === 'string' ? document.createTextNode( c ) : c );
} );
return node;
}
function getProp( printouts, key ) {
var arr = printouts[ key ];
if ( !arr || !arr.length ) { return ''; }
return arr.map( function ( v ) {
if ( typeof v === 'string' ) { return v; }
return v.item !== undefined ? v.item : ( v.fulltext || '' );
} ).filter( Boolean ).join( ', ' );
}
/* ---- build UI ---- */
function buildUI( container ) {
/* filters row */
var topicSel = el( 'select', { id: 'gplx-filter-topic', class: 'gplx-filter-select' } );
[ [ '', 'All topics' ] ].concat( TOPICS.map( function ( t ) { return [ t, t ]; } ) )
.forEach( function ( pair ) {
topicSel.appendChild( el( 'option', { value: pair[ 0 ] }, [ pair[ 1 ] ] ) );
} );
var regionSel = el( 'select', { id: 'gplx-filter-region', class: 'gplx-filter-select' } );
regionSel.appendChild( el( 'option', { value: '' }, [ 'All regions' ] ) );
var textInput = el( 'input', {
type: 'search',
id: 'gplx-filter-text',
class: 'gplx-filter-input',
placeholder: 'Search…'
} );
var filters = el( 'div', { class: 'gplx-search-filters' }, [
el( 'div', { class: 'gplx-filter-group' }, [
el( 'label', { class: 'gplx-filter-label', for: 'gplx-filter-topic' }, [ 'Topic' ] ),
topicSel
] ),
el( 'div', { class: 'gplx-filter-group' }, [
el( 'label', { class: 'gplx-filter-label', for: 'gplx-filter-region' }, [ 'Region' ] ),
regionSel
] ),
el( 'div', { class: 'gplx-filter-group gplx-filter-group--grow' }, [
el( 'label', { class: 'gplx-filter-label', for: 'gplx-filter-text' }, [ 'Search' ] ),
textInput
] )
] );
var status = el( 'p', { id: 'gplx-search-status', class: 'gplx-search-status' } );
var results = el( 'div', { id: 'gplx-search-results' } );
container.innerHTML = '';
container.appendChild( filters );
container.appendChild( status );
container.appendChild( results );
return { topicSel: topicSel, regionSel: regionSel, textInput: textInput };
}
/* ---- data ---- */
function buildQuery( topic ) {
return ( topic ? '[[Category:' + topic + ']]' : '' )
+ '[[Status::+]]'
+ '|?Document name=Document'
+ '|?Area of validity=Region'
+ '|?Document type=Type'
+ '|?Scope'
+ '|?Language'
+ '|?Restricted access=Restricted'
+ '|?Category'
+ '|limit=500'
+ '|sort=Document name'
+ '|order=asc';
}
function parseResponse( data ) {
var raw = ( data.query && data.query.results ) || {};
return Object.keys( raw ).map( function ( key ) {
var page = raw[ key ];
var p = page.printouts || {};
var cats = ( p.Category || [] )
.map( function ( v ) {
return ( v.fulltext || '' ).replace( /^Category:/, '' );
} )
.filter( function ( v ) { return TOPICS.indexOf( v ) !== -1; } )
.join( ', ' );
return {
name: getProp( p, 'Document' ) || page.fulltext,
url: page.fullurl,
topic: cats,
region: getProp( p, 'Region' ),
type: getProp( p, 'Type' ),
scope: getProp( p, 'Scope' ),
language: getProp( p, 'Language' ),
restricted: getProp( p, 'Restricted' )
};
} );
}
/* ---- render ---- */
function updateRegionDropdown( results, sel ) {
var prev = sel.value;
var seen = {};
results.forEach( function ( r ) {
r.region.split( ',' ).forEach( function ( v ) {
v = v.trim();
if ( v ) { seen[ v ] = true; }
} );
} );
while ( sel.options.length > 1 ) { sel.remove( 1 ); }
Object.keys( seen ).sort().forEach( function ( v ) {
var opt = new Option( v, v, false, v === prev );
sel.add( opt );
} );
}
function applyFilters( results ) {
var region = ( document.getElementById( 'gplx-filter-region' ).value || '' ).trim().toLowerCase();
var text = ( document.getElementById( 'gplx-filter-text' ).value || '' ).trim().toLowerCase();
return results.filter( function ( r ) {
if ( region && r.region.toLowerCase().indexOf( region ) === -1 ) { return false; }
if ( text ) {
var haystack = [ r.name, r.scope, r.type, r.language, r.topic ].join( ' ' ).toLowerCase();
if ( haystack.indexOf( text ) === -1 ) { return false; }
}
return true;
} );
}
function renderTable( results ) {
var container = document.getElementById( 'gplx-search-results' );
if ( !results.length ) {
container.innerHTML = '<p class="gplx-no-results">No documents match the selected filters.</p>';
return;
}
var rows = results.map( function ( r ) {
var restricted = r.restricted && r.restricted.toLowerCase() === 'yes'
? ' <span class="gplx-badge-restricted">Restricted</span>'
: '';
return '<tr>'
+ '<td><a href="' + esc( r.url ) + '">' + esc( r.name ) + '</a>' + restricted + '</td>'
+ '<td>' + esc( r.topic ) + '</td>'
+ '<td>' + esc( r.scope ) + '</td>'
+ '<td>' + esc( r.language ) + '</td>'
+ '<td>' + esc( r.region ) + '</td>'
+ '<td>' + esc( r.type ) + '</td>'
+ '</tr>';
} );
container.innerHTML = '<table class="wikitable sortable gplx-results-table">'
+ '<thead><tr><th>Document</th><th>Topic</th><th>Scope</th><th>Language</th><th>Region</th><th>Type</th></tr></thead>'
+ '<tbody>' + rows.join( '' ) + '</tbody>'
+ '</table>';
}
function setStatus( msg, busy ) {
var el = document.getElementById( 'gplx-search-status' );
el.textContent = msg;
el.className = 'gplx-search-status' + ( busy ? ' gplx-search-busy' : '' );
}
function refresh() {
var visible = applyFilters( allResults );
setStatus( visible.length + ' of ' + allResults.length
+ ' document' + ( allResults.length !== 1 ? 's' : '' ), false );
renderTable( visible );
}
function load( topic, regionSel ) {
setStatus( 'Loading…', true );
document.getElementById( 'gplx-search-results' ).innerHTML = '';
( new mw.Api() ).get( {
action: 'ask',
query: buildQuery( topic ),
format: 'json'
} ).done( function ( data ) {
allResults = parseResponse( data );
updateRegionDropdown( allResults, regionSel );
refresh();
} ).fail( function () {
setStatus( 'Failed to load results. Please reload the page.', false );
} );
}
/* ---- init ---- */
mw.loader.using( [ 'mediawiki.api' ], function () {
$( function () {
var container = document.getElementById( 'gplx-search-app' );
if ( !container ) { return; }
var controls = buildUI( container );
var debounce;
controls.topicSel.addEventListener( 'change', function () {
load( controls.topicSel.value, controls.regionSel );
} );
controls.regionSel.addEventListener( 'change', refresh );
controls.textInput.addEventListener( 'input', function () {
clearTimeout( debounce );
debounce = setTimeout( refresh, 250 );
} );
load( '', controls.regionSel );
} );
} );
}() );