MediaWiki

Difference between revisions of "Common.js"

(+explicit dependency to 'ext.recordWizard' to hopefully make it work on Chrome 92 (although it works on Firefox and Chrome 90))
(Removed some hacks, since the source code was fixed and deployed (see https://github.com/lingua-libre/RecordWizard/commits/master))
 
(80 intermediate revisions by 3 users not shown)
Line 1: Line 1:
// Replace Wikidata IDs with their [label, description]
+
// Page-specific scripts modules and conditional loading
if ( $( '.wb-external-id' ).length > 0 ) {
+
// RecordWizard sugar
mw.loader.using( 'mediawiki.ForeignApi', function() {
 
$( '.wb-external-id' ).each( function() {
 
if ( $( this ).attr( 'href' ).lastIndexOf( 'https://www.wikidata.org', 0 ) === 0 ) {
 
var wikidataApi = new mw.ForeignApi( 'https://www.wikidata.org/w/api.php', {
 
anonymous: true,
 
parameters: { 'origin': '*' },
 
ajax: { timeout: 10000 }
 
} ),
 
lang = mw.config.get( 'wgUserLanguage' ),
 
node = $( this );
 
wikidataApi.get( {
 
'action': 'wbgetentities',
 
'format': 'json',
 
'ids': node.text(),
 
'props': 'labels|descriptions',
 
'languages': lang,
 
'languagefallback': 1,
 
'origin': '*'
 
} ).then( function( data ) {
 
                                       
 
var entity = data.entities[ node.text() ],
 
label = ( entity.labels[ lang ] !== undefined ? entity.labels[ lang ].value + ' <i>(' + node.text() + ')</i>' : node.text() ),
 
description = ( entity.descriptions[ lang ] !== undefined ? '<small>' + entity.descriptions[ lang ].value + '</small>' : '' );
 
 
node.html( label + '<br>' + description )
 
} );
 
}
 
} );
 
} );
 
}
 
 
 
//Add an audio player to the audio records links in the wikibase items
 
const BASE_FILE_URL = 'https://commons.wikimedia.org/wiki/Special:Redirect/file?wptype=file&wpvalue=';
 
 
 
function playButton( audioUrl ) {
 
var button = new OO.ui.ButtonWidget( {
 
framed: false,
 
icon: 'play',
 
title: 'play'
 
} );
 
button.on( 'click', function() {
 
var audio = new Audio( audioUrl );
 
audio.play();
 
} );
 
  
return button.$element;
+
/* *************************************************************** */
 +
/* PAGE-SPECIFIC SCRIPTS LOADINGS ******************************** */
 +
// Documentation: https://m.mediawiki.org/wiki/ResourceLoader/Architecture#Resource:_Scripts
 +
// Documentation: https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader
 +
//🎷🥁🎸🐣📔🗻🌏
 +
// LastAudiosBoxes
 +
if (/^LinguaLibre:Main/.test(mw.config.get('wgPageName'))) {
 +
  console.log('🎸 Last Audios');
 +
  mw.loader.load('/index.php?title=MediaWiki:LastAudios.js&action=raw&ctype=text/javascript');
 
}
 
}
 
+
// SoundLibrary
if ( $( '#P3 a.extiw' ).length > 0 ) {
+
if (/^LinguaLibre:Explore_the_sound_library(\/[a-z_-]+)?$/.test(mw.config.get('wgPageName'))) {
    mw.loader.using( [ 'oojs-ui-widgets', 'oojs-ui.styles.icons-media' ], function() {
+
  console.log('🥁 Sound library');
        $( '#P3 a.extiw' ).each( function() {
+
  mw.loader.load('/index.php?title=MediaWiki:SoundLibrary.js&action=raw&ctype=text/javascript');
            var $node = $( this );
 
            $node.before( playButton( BASE_FILE_URL + $node.text() ) );
 
        } );
 
    } );
 
 
}
 
}
 
+
// Item pages additional sugar
 
+
if (/^(Q|Property:P)[0-9]+$/.test(mw.config.get('wgPageName'))) {
/**
+
  console.log('🍭 ItemsSugar ');
* Display last records on main page
+
  mw.loader.load('/index.php?title=MediaWiki:ItemsSugar.js&action=raw&ctype=text/javascript');
**/
 
var ab1, ab2;
 
 
 
 
 
var AudioBox = function( recordQid, $node ) {
 
this.wbRecord = new mw.recordWizard.wikibase.Item( recordQid );
 
 
this.$node = $node;
 
this.audioNode = document.createElement( 'audio' );
 
this.audioNode.preload = 'auto';
 
 
 
    this.api = new mw.Api();
 
 
 
this.recordQid = recordQid;
 
this.langQid = null;
 
this.speakerQid = null;
 
 
this.label = '';
 
this.media = '';
 
this.lang = '';
 
this.speaker = '';
 
 
this.wbRecord.getFromApi( this.api ).then( this.processRecord.bind( this ), displayError );
 
 
}
 
}
 
+
// Lexeme Queries Generator (OOUI)
AudioBox.prototype.processRecord = function() {
+
if (/^Template:LexemeQueriesGenerator$/.test(mw.config.get('wgPageName')) || /^Help:SPARQL_/.test(mw.config.get('wgPageName'))) {
this.label = this.wbRecord.getLabel( 'en' );
+
  console.log('📔 Lexeme Queries Generator');
this.media = 'https://commons.wikimedia.org/wiki/Special:FilePath/' + this.wbRecord.getStatements( 'P3' )[ 0 ].getValue();
+
  mw.loader.load('/index.php?title=MediaWiki:LexemeQueriesGenerator.js&action=raw&ctype=text/javascript');
this.langQid = this.wbRecord.getStatements( 'P4' )[ 0 ].getValue();
 
this.speakerQid = this.wbRecord.getStatements( 'P5' )[ 0 ].getValue();
 
 
 
this.api.get( {
 
action: "wbgetentities",
 
format: "json",
 
ids: this.langQid + '|' + this.speakerQid,
 
props: "labels",
 
languages: mw.config.get( 'wgUserLanguage' ) + "|en",
 
languagefallback: 1,
 
} ).then( this.processLabels.bind( this ), displayError );
 
 
}
 
}
 
+
// SPARQL to data (OOUI)
AudioBox.prototype.processLabels = function( data ) {
+
if (/SPARQL/.test(mw.config.get('wgPageName')) || /parql/.test(mw.config.get('wgPageName'))) {
var langLabels;
+
  console.log('🚀 SPARQL to data');
 
+
  mw.loader.load('/index.php?title=MediaWiki:Sparql2data.js&action=raw&ctype=text/javascript');
if ( data.entities === undefined || data.entities[ this.langQid ] === undefined || data.entities[ this.speakerQid ] === undefined ) {
 
displayError( 'dataerror' );
 
return;
 
}
 
langLabels = data.entities[ this.langQid ].labels;
 
 
if ( langLabels[ mw.config.get( 'wgUserLanguage' ) ] !== undefined ) {
 
this.lang = langLabels[ mw.config.get( 'wgUserLanguage' ) ].value;
 
} else {
 
this.lang = langLabels[ 'en' ].value;
 
}
 
 
this.speaker = data.entities[ this.speakerQid ].labels[ 'en' ].value;
 
 
 
this.display();
 
 
}
 
}
 
+
// Click bug & browser
AudioBox.prototype.display = function() {
+
if (/browser/.test(mw.config.get('wgPageName')) || /bug/.test(mw.config.get('wgPageName'))) {
this.$node.find( '.ab-title' ).text( this.label );
+
  console.log('🎷 Click bug & browser');
this.$node.find( '.ab-metadata' ).text( this.lang + ' - ' + this.speaker );
+
  mw.loader.load('/index.php?title=MediaWiki:Browser.js&action=raw&ctype=text/javascript');
 
this.audioNode.src = this.media;
 
this.$node.find( '.ab-playbutton' ).click( this.audioNode.play.bind( this.audioNode ) );
 
 
}
 
}
 
+
/* *************************************************************** */
 
+
/* In development *************************************** */
 
+
// User:Yug: Language overview
 
+
if (/Languages/.test(mw.config.get('wgPageName'))) {
 
+
  console.log('🌏 Languages gallery');
 
+
  mw.loader.load('/index.php?title=MediaWiki:LanguagesGallery.js&action=raw&ctype=text/javascript');
function createAudioBoxes( data ) {
 
if ( data.query === undefined || data.query.rwrecords === undefined || data.query.rwrecords.length < 2 ) {
 
displayError( 'nodata' );
 
return;
 
}
 
 
 
ab1 = new AudioBox( data.query.rwrecords[ 0 ], $( '.audiobox' ).eq( 0 ) );
 
ab2 = new AudioBox( data.query.rwrecords[ 1 ], $( '.audiobox' ).eq( 1 ) );
 
 
}
 
}
 
+
// User:Yug: Search by words, see https://jsfiddle.net/hugolpz/ecpzy0fo/89/
function getLastRecords() {
+
if (/^LinguaLibre:Search_by(\/[a-z_-]+)?$/.test(mw.config.get('wgPageName'))) {
    var api = new mw.Api();
+
  console.log('🐣 Search by word');
api.get( {
+
  mw.loader.load('/index.php?title=MediaWiki:SearchBy.js&action=raw&ctype=text/javascript');
        action: 'query',
 
        format: 'json',
 
        list: 'rwrecords',
 
        rwrlimit: '2',
 
rwrsort: 'pageid',
 
rwrdir: 'descending',
 
rwrformat: 'qid'
 
  } ).then( createAudioBoxes, displayError );
 
 
}
 
}
 +
// Minorities languages statistics page
  
function displayError( code, error ) {
+
// Iframe gallery for Lingualibre:Apps
console.warn( code, error );
+
// Prototype https://jsfiddle.net/hugolpz/meygpo6t/
}
+
// Problem: iframe are not accepted into wikicode. Solution: hide key values in html tag, generate iframe via JS injection.
 
 
if ( mw.config.get( 'wgPageName' ) === 'LinguaLibre:Main_Page' ) {
 
    mw.loader.using( [ 'mediawiki.api', 'ext.recordWizard.wikibase' ] ).then( getLastRecords );
 
}
 
 
 
// T206801 - Links to Wikipedia contain "+" (instead of "_")
 
if ( $( 'div#P19 .wb-external-id' ).length ) {
 
$( 'div#P19 .wb-external-id' ).attr( 'href', $( 'div#P19 .wb-external-id' ).attr( 'href' ).replace( /\+/g, '_' ) );
 
}
 
 
 
// Development in final phase of the interface for displaying contributions
 
$( function (){
 
if( mw.config.get( 'wgPageName' ) !== 'User:Nicolas_NALLET' ) {
 
return;
 
}
 
var userLanguage = mw.config.get( 'wgUserLanguage' );
 
var messages = {
 
'no-results': {
 
en: 'No results.',
 
de: 'Keine Ergebnisse.',
 
fr: 'Pas de résultat.',
 
}
 
};
 
mw.loader.using( ['oojs', 'oojs-ui', 'ext.recordWizard'], function () {
 
 
 
var oouiSelectors = {
 
'speaker': null,
 
'gender': null,
 
'language': null,
 
'proficiency': null,
 
};
 
var sparqlGlobal = {
 
'speaker': 'SELECT DISTINCT ?speaker ?speakerLabel WHERE { ?speaker prop:P2 entity:Q3 . ?speaker rdfs:label ?speakerLabel . FILTER( LANG(?speakerLabel) = "en" ) } ORDER BY ?speakerLabel',
 
'gender': 'SELECT DISTINCT ?gender ?genderLabel WHERE { ?gender prop:P2 entity:Q7 . SERVICE wikibase:label { bd:serviceParam wikibase:language "' + userLanguage + ',fr,en" } } ORDER BY ?gender',
 
'language': 'SELECT DISTINCT ?language ?languageLabel WHERE { ?language prop:P2 entity:Q4 . SERVICE wikibase:label { bd:serviceParam wikibase:language "' + userLanguage + ',fr,en" } } ORDER BY ?languageLabel',
 
'proficiency': 'SELECT DISTINCT ?proficiency ?proficiencyLabel WHERE { ?proficiency prop:P2 entity:Q5 . SERVICE wikibase:label { bd:serviceParam wikibase:language "' + userLanguage + ',fr,en" } } ORDER BY ?proficiency',
 
};
 
var placeholders = {
 
'speaker': '👤 Speaker',
 
'gender': '♀️ ♂️ Speaker\'s gender',
 
'language': '🏳️ Language',
 
'proficiency': '🥇 Level of proficiency',
 
};
 
var htmlElements = {
 
'speaker': '#filteruser',
 
'gender': '#filtergender',
 
'language': '#filterlanguage',
 
'proficiency': '#filterlevelofproficiency',
 
};
 
var lastRequest = {
 
'speaker': '',
 
'gender': '',
 
'language': '',
 
'proficiency': '',
 
};
 
 
 
function updateSelector( type ) {
 
return function( values ) {
 
if( ( oouiSelectors['speaker'] && oouiSelectors['speaker'].getValue() != lastRequest['speaker'] ) ||
 
    ( oouiSelectors['gender'] && oouiSelectors['gender'].getValue() != lastRequest['gender'] ) ||
 
    ( oouiSelectors['language'] && oouiSelectors['language'].getValue() != lastRequest['language'] ) ||
 
    ( oouiSelectors['proficiency'] && oouiSelectors['proficiency'].getValue() != lastRequest['proficiency'] ) ) {
 
return;
 
}
 
 
 
oouiSelectors[type] = new OO.ui.ComboBoxInputWidget( {
 
placeholder: placeholders[type],
 
menu: {
 
filterFromInput: true,
 
items: values.results.bindings.map( function( x ) {
 
return new OO.ui.MenuOptionWidget( {
 
data: x[ type + 'Label' ].value + " (" + x[type].value.substr( 31 ) + ")",
 
label: x[ type + 'Label' ].value
 
} );
 
} )
 
}
 
} );
 
 
 
$( htmlElements[type] ).html('').append(
 
oouiSelectors[type].$element
 
);
 
 
 
oouiSelectors[type].on( 'change', function() { doQuery(); doQuery( 'speaker' ); doQuery( 'gender' ); doQuery( 'language' ); doQuery( 'proficiency' ); } );
 
 
 
};
 
}
 
 
 
$.getJSON(
 
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
 
{
 
query: sparqlGlobal['speaker']
 
}
 
).done( updateSelector( 'speaker' ) );
 
 
 
$.getJSON(
 
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
 
{
 
query: sparqlGlobal['gender']
 
}
 
).done( updateSelector( 'gender' ) );
 
 
 
$.getJSON(
 
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
 
{
 
query: sparqlGlobal['language']
 
}
 
).done( updateSelector( 'language' ) );
 
 
 
$.getJSON(
 
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
 
{
 
query: sparqlGlobal['proficiency']
 
}
 
).done( updateSelector( 'proficiency' ) );
 
 
 
// Display results
 
function createAudioBoxesForSearch( data ) {
 
if ( data.results === undefined || data.results.bindings === undefined ) {
 
displayError( 'error: no result from SPARQL' );
 
return;
 
}
 
if ( data.results.bindings.length < 1 ) {
 
$( '#audioresults' ).html( messages['no-results'][userLanguage] ? messages['no-results'][userLanguage] : messages['no-results']['en'] );
 
return;
 
}
 
var length = data.results.bindings.length < 100 ? data.results.bindings.length : 100;
 
$( '#audioresults' ).html( '' );
 
for (var i = 0; i < length; i++) {
 
var box = $( '<div class="audiobox"> <div class="ab-playbutton"><i></i></div> <div> <div class="ab-title">...</div> <div class="ab-metadata">...</div> </div> </div>' );
 
var audiobox = new AudioBox( data.results.bindings[ i ].record.value.substr( 31 ), box );
 
$( '#audioresults' ).append( box );
 
//ab1 = new AudioBox( data.query.rwrecords[ i ], $( '.audiobox' ).eq( i ) );
 
//$("body").append('<div class="audiobox"> <div class="ab-playbutton"><i></i></div> <div> <div class="ab-title">...</div> <div class="ab-metadata">...</div> </div> </div>');
 
}
 
}
 
 
 
// Do SPARQL request from filters
 
function doQuery( variable ){
 
 
 
// Do not modify a selector where there is a value
 
if( variable && oouiSelectors[variable] && oouiSelectors[variable].getValue() ) {
 
return;
 
}
 
 
 
function getQ( type ) {
 
if( variable === type ) {
 
return '?' + type;
 
}
 
var text = oouiSelectors[type] ? oouiSelectors[type].getValue() : '';
 
if( !text ) {
 
return '';
 
}
 
text = text.trim();
 
if( /^Q[0-9]+$/.test( text ) ) {
 
return 'entity:' + text;
 
} else if( /\((Q[0-9]+)\)$/.test( text ) ) {
 
return 'entity:' + text.replace( /.*\((Q[0-9]+)\)$/, '$1' );
 
} else {
 
console.warn( 'Bad input “' + text + '”' );
 
return '';
 
}
 
}
 
 
 
var speaker = getQ( 'speaker' ),
 
    gender = getQ( 'gender' ),
 
    language = getQ( 'language' ),
 
    proficiency = getQ( 'proficiency' ),
 
    somevalue = false;
 
if( ! variable ) {
 
lastRequest = {
 
'speaker': oouiSelectors['speaker'] ? oouiSelectors['speaker'].getValue() : '',
 
'gender': oouiSelectors['gender'] ? oouiSelectors['gender'].getValue() : '',
 
'language': oouiSelectors['language'] ? oouiSelectors['language'].getValue() : '',
 
'proficiency': oouiSelectors['proficiency'] ? oouiSelectors['proficiency'].getValue() : '',
 
};
 
}
 
 
 
var query = "SELECT " + ( variable ? 'DISTINCT ?' + variable + ' ?' + variable + 'Label' : "?record" ) + " WHERE { ?record prop:P2 entity:Q2 ; prop:P4 ?language ; prop:P5 ?speaker . ";
 
if( speaker ) {
 
query += "?record prop:P5 " + speaker + " . ";
 
somevalue = true;
 
}
 
if( gender ) {
 
query += "?record prop:P5 [ prop:P8 " + gender + " ] . ";
 
somevalue = true;
 
}
 
if( language ) {
 
query += "?record prop:P4 " + language + " . ";
 
somevalue = true;
 
}
 
if( proficiency ) {
 
query += "?speaker llp:P4 [ llv:P4 ?language ; llq:P16 " + proficiency + " ] . ";
 
somevalue = true;
 
}
 
query += "SERVICE wikibase:label { bd:serviceParam wikibase:language '" + userLanguage + ",en,fr' } } LIMIT 100";
 
 
 
if( variable ) {
 
if( !somevalue ) {
 
query = sparqlGlobal[variable];
 
}
 
} else {
 
if( !variable && !somevalue ) {
 
return;
 
}
 
$( '#audioresults' ).html( '' ); // TODO replace by a spinner
 
}
 
 
 
// Execute the request
 
var result = $.getJSON(
 
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
 
{
 
query: query,
 
//Accept: 'application/sparql-results+json'
 
}
 
);
 
 
 
// Depending if we want the whole results or update on selector
 
if( variable ) {
 
result.then( updateSelector( variable ), displayError );
 
} else {
 
result.then( createAudioBoxesForSearch, displayError );
 
}
 
}
 
  
} );
 
  
} );
+
/*Query visualisation: Replace loading text by a spinner gif***********************************************************/
 +
$( '.queryviz-loading' ).html( '<center><img src="https://upload.wikimedia.org/wikipedia/commons/7/7a/Balls.gif" width="50" /></center>' );

Latest revision as of 08:51, 20 April 2023

// Page-specific scripts modules and conditional loading
// RecordWizard sugar

/* *************************************************************** */
/* PAGE-SPECIFIC SCRIPTS LOADINGS ******************************** */
// Documentation: https://m.mediawiki.org/wiki/ResourceLoader/Architecture#Resource:_Scripts
// Documentation: https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader
//🎷🥁🎸🐣📔🗻🌏
// LastAudiosBoxes
if (/^LinguaLibre:Main/.test(mw.config.get('wgPageName'))) {
  console.log('🎸 Last Audios');
  mw.loader.load('/index.php?title=MediaWiki:LastAudios.js&action=raw&ctype=text/javascript');
}
// SoundLibrary
if (/^LinguaLibre:Explore_the_sound_library(\/[a-z_-]+)?$/.test(mw.config.get('wgPageName'))) {
  console.log('🥁 Sound library');
  mw.loader.load('/index.php?title=MediaWiki:SoundLibrary.js&action=raw&ctype=text/javascript');
}
// Item pages additional sugar
if (/^(Q|Property:P)[0-9]+$/.test(mw.config.get('wgPageName'))) {
  console.log('🍭 ItemsSugar ');
  mw.loader.load('/index.php?title=MediaWiki:ItemsSugar.js&action=raw&ctype=text/javascript');
}
// Lexeme Queries Generator (OOUI)
if (/^Template:LexemeQueriesGenerator$/.test(mw.config.get('wgPageName')) || /^Help:SPARQL_/.test(mw.config.get('wgPageName'))) {
  console.log('📔 Lexeme Queries Generator');
  mw.loader.load('/index.php?title=MediaWiki:LexemeQueriesGenerator.js&action=raw&ctype=text/javascript');
}
// SPARQL to data (OOUI)
if (/SPARQL/.test(mw.config.get('wgPageName')) || /parql/.test(mw.config.get('wgPageName'))) {
  console.log('🚀 SPARQL to data');
  mw.loader.load('/index.php?title=MediaWiki:Sparql2data.js&action=raw&ctype=text/javascript');
}
// Click bug & browser
if (/browser/.test(mw.config.get('wgPageName')) || /bug/.test(mw.config.get('wgPageName'))) {
  console.log('🎷 Click bug & browser');
  mw.loader.load('/index.php?title=MediaWiki:Browser.js&action=raw&ctype=text/javascript');
}
/* *************************************************************** */
/* In development *************************************** */
// User:Yug: Language overview
if (/Languages/.test(mw.config.get('wgPageName'))) {
  console.log('🌏 Languages gallery');
  mw.loader.load('/index.php?title=MediaWiki:LanguagesGallery.js&action=raw&ctype=text/javascript');
}
// User:Yug: Search by words, see https://jsfiddle.net/hugolpz/ecpzy0fo/89/
if (/^LinguaLibre:Search_by(\/[a-z_-]+)?$/.test(mw.config.get('wgPageName'))) {
  console.log('🐣 Search by word');
  mw.loader.load('/index.php?title=MediaWiki:SearchBy.js&action=raw&ctype=text/javascript');
}
// Minorities languages statistics page

// Iframe gallery for Lingualibre:Apps
// Prototype https://jsfiddle.net/hugolpz/meygpo6t/
// Problem: iframe are not accepted into wikicode. Solution: hide key values in html tag, generate iframe via JS injection.


/*Query visualisation: Replace loading text by a spinner gif***********************************************************/
$( '.queryviz-loading' ).html( '<center><img src="https://upload.wikimedia.org/wikipedia/commons/7/7a/Balls.gif" width="50" /></center>' );