MediaWiki

Difference between revisions of "Common.js"

(nouvelle version pour l’interface de recherche de contributions, beaucoup plus frugale (moins d’appels à Blazegraph) et plus rapide, il y a aussi un essai d’UX à réduire les listes aux choix possibles, par ex quand on choisit un locuteur ça sélectionne automatiquement son genre et les langues qu’iel parle (ce fonctionnement entraîne certains effets de bord étranges quand on délélectionne, ce comportement reste du POC))
m (renamed LinguaZip)
 
(76 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=';
+
/* PAGE-SPECIFIC SCRIPTS LOADINGS ******************************** */
 
+
// Documentation: https://m.mediawiki.org/wiki/ResourceLoader/Architecture#Resource:_Scripts
function playButton( audioUrl ) {
+
// Documentation: https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader
var button = new OO.ui.ButtonWidget( {
+
//🎷🥁🎸🐣📔🗻🌏
framed: false,
+
// LastAudiosBoxes
icon: 'play',
+
if (/^LinguaLibre:Main/.test(mw.config.get('wgPageName'))) {
title: 'play'
+
  console.log('🎸 Last Audios');
} );
+
  mw.loader.load('/index.php?title=MediaWiki:LastAudios.js&action=raw&ctype=text/javascript');
button.on( 'click', function() {
 
var audio = new Audio( audioUrl );
 
audio.play();
 
} );
 
 
 
return button.$element;
 
 
}
 
}
 
+
// 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: 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');
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 ) );
 
}
 
 
 
function getLastRecords() {
 
    var api = new mw.Api();
 
api.get( {
 
        action: 'query',
 
        format: 'json',
 
        list: 'rwrecords',
 
        rwrlimit: '2',
 
rwrsort: 'pageid',
 
rwrdir: 'descending',
 
rwrformat: 'qid'
 
  } ).then( createAudioBoxes, displayError );
 
}
 
 
 
function displayError( code, error ) {
 
console.warn( code, error );
 
 
}
 
}
 +
// Minorities languages statistics page
  
if ( mw.config.get( 'wgPageName' ) === 'LinguaLibre:Main_Page' ) {
+
// Iframe gallery for Lingualibre:Apps
    mw.loader.using( [ 'mediawiki.api', 'ext.recordWizard.wikibase' ] ).then( getLastRecords );
+
// 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.
 
 
// 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' || mw.config.get( 'wgUserName' ) === 'Seb35' ) {
 
return;
 
}
 
const userLanguage = mw.config.get( 'wgUserLanguage' );
 
const messages = {
 
'msg-no-results': {
 
en: 'No results.',
 
de: 'Keine Ergebnisse.',
 
fr: 'Pas de résultat.',
 
//qqq: 'Message when there are no results.',
 
},
 
'button-gosearch': {
 
en: 'Search',
 
de: 'Suchen',
 
fr: 'Rechercher',
 
//qqq: 'Button where the user clicks to search.',
 
},
 
'button-resetsearch': {
 
en: 'Reset',
 
de: 'Löschen',
 
fr: 'Effacer',
 
//qqq: 'Button where the user clicks to reset the form.',
 
},
 
'placeholder-speaker': {
 
en: '👤 Speaker',
 
fr: '👤 Locuteur',
 
//qqq: 'Placeholder for the field Speaker.',
 
},
 
'placeholder-gender': {
 
en: '♀️ ♂️ Speaker\'s gender',
 
fr: '♀️ ♂️ Genre du locuteur',
 
//qqq: 'Placeholder for the field Gender.',
 
},
 
'placeholder-language': {
 
en: '🏳️ Language',
 
fr: '🏳️ Langue',
 
//qqq: 'Placeholder for the field Language.',
 
},
 
'placeholder-proficiency': {
 
en: '🥇 Level of proficiency',
 
fr: '🥇 Niveau de compétence',
 
//qqq: 'Placeholder for the field Proficiency.',
 
},
 
};
 
mw.loader.using( ['oojs', 'oojs-ui', 'mediawiki.api', 'ext.recordWizard.wikibase'], function () {
 
 
 
oouiSelectors = {
 
'speaker': null,
 
'gender': null,
 
'language': null,
 
'proficiency': null,
 
};
 
var sparqlGlobal = {
 
'speaker': 'SELECT ?speaker ?speakerLabel ?gender ?language ?proficiency WHERE { ?speaker prop:P2 entity:Q3 . OPTIONAL { ?speaker prop:P8 ?gender } . OPTIONAL { ?speaker llp:P4 ?statement . ?statement llv:P4 ?language . OPTIONAL { ?statement llq:P16 ?proficiency } } . SERVICE wikibase:label { bd:serviceParam wikibase:language "' + userLanguage + ',fr,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',
 
};
 
const htmlElements = {
 
'speaker': '#filteruser',
 
'gender': '#filtergender',
 
'language': '#filterlanguage',
 
'proficiency': '#filterlevelofproficiency',
 
};
 
const unknown = {};
 
 
 
request = {
 
'speaker': '',
 
'gender': '',
 
'language': '',
 
'proficiency': '',
 
};
 
lastRequest = {
 
'speaker': '',
 
'gender': '',
 
'language': '',
 
'proficiency': '',
 
};
 
speakersCriteria = [];
 
list = {
 
'speaker': null,
 
'gender': null,
 
'language': null,
 
'proficiency': null,
 
};
 
mapping = {
 
'speaker': null,
 
'gender': null,
 
'language': null,
 
'proficiency': null,
 
};
 
 
 
// Helper function to obtain the Qvalue of some selector
 
function getQValue( type ) {
 
var rawValue;
 
if( type === 'speaker' || type === 'language' ) {
 
rawValue = oouiSelectors[type].getValue();
 
} else {
 
rawValue = oouiSelectors[type].getMenu().findSelectedItem() ? oouiSelectors[type].getMenu().findSelectedItem().getData() : '';
 
}
 
rawValue = rawValue.trim();
 
if( !rawValue ) {
 
return '';
 
} else if( /^Q[0-9]+$/.test( rawValue ) ) {
 
return rawValue;
 
} else if( /\((Q[0-9]+)\)$/.test( rawValue ) ) {
 
return rawValue.replace( /.*\((Q[0-9]+)\)$/, '$1' );
 
} else {
 
return '';
 
}
 
}
 
 
 
// Helper function to dedupe a sorted list
 
function dedupe( arr, fn ) {
 
if( fn ) {
 
return arr.filter( function( x, i, a ) {
 
return !i || fn( x ) !== fn( a[i-1] );
 
} );
 
}
 
return arr.filter( function( x, i, a ) {
 
return !i || x !== a[i-1];
 
} );
 
}
 
 
 
// Returns the list of items of a given type for a restricted list of Qids
 
function getListSelectorFromQids( type, qids ) {
 
const indexes = dedupe( qids.map( function( x ) {
 
return mapping[type][x];
 
} ).sort( function( a, b ) { return a-b; } ) );
 
const r = indexes.map( function( x ) {
 
return list[type][x];
 
} );
 
console.log( 'getListSelectorFromQids', type, qids, indexes, r );
 
return r;
 
}
 
 
 
// Initialise a selector and keep the list in memory the result for later reuse
 
function updateSelector( type, force ) {
 
return function( values ) {
 
 
 
const widgetType = type === 'speaker' || type === 'language' ? 'ComboBoxInputWidget' : 'DropdownWidget';
 
 
 
if( !list[type] ) {
 
 
 
// Save the list in a global variable to quickly filter then
 
// We dedupe because the 'speaker' (only) has duplicate (ordered) values
 
const v = values.results.bindings;
 
list[type] = dedupe( v, function( x ) { return x[type].value; } );
 
if( widgetType === 'DropdownWidget' ) {
 
var emptyItem = [ {} ];
 
emptyItem[0][type] = { value: '' };
 
emptyItem[0][type+'Label'] = { value: ' ' };
 
list[type] = emptyItem.concat( list[type] );
 
}
 
values = list[type];
 
 
 
// Save the mapping Qxx → index to update the list from a list of Qxx (see doQuery)
 
console.log( type, list[type] );
 
mapping[type] = list[type].reduce( function( o, x, i ) {
 
o[ x[type].value.substr( 31 ) ] = i;
 
return o;
 
}, {} );
 
 
 
// Save the global matrix: speaker x gender x language x proficiency
 
if( type === 'speaker' ) {
 
speakersCriteria = v.map( function( x ) {
 
return [
 
x.speaker.value.substr( 31 ),
 
!x.gender || x.gender.type === 'bnode' ? unknown : x.gender.value.substr( 31 ),
 
!x.language || x.language.type === 'bnode' ? unknown : x.language.value.substr( 31 ),
 
!x.proficiency || x.proficiency.type === 'bnode' ? unknown : x.proficiency.value.substr( 31 ),
 
];
 
} );
 
}
 
}
 
 
 
if( !force && getQValue( type ) ) {
 
return;
 
}
 
 
 
if( widgetType === 'DropdownWidget' && values.length && values[0][type].value ) {
 
var emptyItem = [ {} ];
 
emptyItem[0][type] = { value: '' };
 
emptyItem[0][type+'Label'] = { value: ' ' };
 
values = emptyItem.concat( values );
 
}
 
 
 
// Create the OOUI selector
 
oouiSelectors[type] = new OO.ui[widgetType]( {
 
placeholder: messages['placeholder-'+type][userLanguage] ? messages['placeholder-'+type][userLanguage] : messages['placeholder-'+type].en,
 
menu: {
 
filterFromInput: true,
 
items: values.map( function( x ) {
 
return new OO.ui.MenuOptionWidget( {
 
data: widgetType === 'ComboBoxInputWidget' ? x[ type + 'Label' ].value + " (" + x[type].value.substr( 31 ) + ")" : x[type].value.substr( 31 ),
 
label: x[ type + 'Label' ].value
 
} );
 
} )
 
}
 
} );
 
if( widgetType === 'DropdownWidget' && values.length > 2 ) {
 
oouiSelectors[type].getMenu().items[0].toggle( false );
 
}
 
 
 
if( widgetType === 'ComboBoxInputWidget' && values.length === 1 ) {
 
oouiSelectors[type].setValue( values[0][ type + 'Label' ].value + " (" + values[0][type].value.substr( 31 ) + ")" );
 
// For dropdown, when there is one real value, there is also the empty value as first option
 
} else if( widgetType === 'DropdownWidget' && values.length === 2 ) {
 
oouiSelectors[type].getMenu().selectItemByData( values[1][type].value.substr( 31 ) );
 
}
 
 
 
$( htmlElements[type] ).html('').append(
 
oouiSelectors[type].$element
 
);
 
 
 
if( widgetType === 'ComboBoxInputWidget' ) {
 
oouiSelectors[type].on( 'change', function() {
 
if( !getQValue( type ) ) {
 
return;
 
}
 
onChange();
 
} );
 
} else {
 
oouiSelectors[type].getMenu().on( 'select', function( item ) {
 
if( item.getData() === '' ) {
 
item.toggle( false );
 
} else {
 
oouiSelectors[type].getMenu().items[0].toggle( true );
 
}
 
onChange();
 
} );
 
}
 
 
 
};
 
}
 
 
 
function onChange() {
 
 
 
request = {
 
speaker: getQValue( 'speaker' ),
 
gender: getQValue( 'gender' ),
 
language: getQValue( 'language' ),
 
proficiency: getQValue( 'proficiency' ),
 
};
 
if( JSON.stringify( request ) === JSON.stringify( lastRequest ) ) {
 
return;
 
}
 
 
 
var potentialSpeakers = speakersCriteria;
 
 
 
if( request.language ) {
 
potentialSpeakers = reduceSpeakers( 2, request.language, potentialSpeakers );
 
}
 
if( request.speaker ) {
 
potentialSpeakers = reduceSpeakers( 0, request.speaker, potentialSpeakers );
 
}
 
if( request.gender ) {
 
potentialSpeakers = reduceSpeakers( 1, request.gender, potentialSpeakers );
 
}
 
if( request.proficiency ) {
 
potentialSpeakers = reduceSpeakers( 3, request.proficiency, potentialSpeakers );
 
}
 
 
 
console.log( potentialSpeakers );
 
 
 
// Update the selectors with the restricted values
 
updateSelector( 'speaker' )( getListSelectorFromQids( 'speaker', dedupe( potentialSpeakers.map( function( x ) { return x[0]; } ) ) ) );
 
updateSelector( 'gender' )( getListSelectorFromQids( 'gender', dedupe( potentialSpeakers.map( function( x ) { return x[1]; } ) ) ) );
 
updateSelector( 'language' )( getListSelectorFromQids( 'language', dedupe( potentialSpeakers.map( function( x ) { return x[2]; } ) ) ) );
 
updateSelector( 'proficiency' )( getListSelectorFromQids( 'proficiency', dedupe( potentialSpeakers.map( function( x ) { return x[3]; } ) ) ) );
 
 
 
}
 
 
 
function initSelectors() {
 
 
 
$.getJSON(
 
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
 
{
 
query: sparqlGlobal['speaker']
 
}
 
).done( updateSelector( 'speaker', true ) );
 
 
 
$.getJSON(
 
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
 
{
 
query: sparqlGlobal['gender']
 
}
 
).done( updateSelector( 'gender', true ) );
 
 
 
$.getJSON(
 
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
 
{
 
query: sparqlGlobal['language']
 
}
 
).done( updateSelector( 'language', true ) );
 
 
 
$.getJSON(
 
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
 
{
 
query: sparqlGlobal['proficiency']
 
}
 
).done( updateSelector( 'proficiency', true ) );
 
}
 
 
 
function reset() {
 
lastRequest = {
 
speaker: '',
 
gender: '',
 
language: '',
 
proficiency: '',
 
};
 
updateSelector( 'speaker', true )( list.speaker );
 
updateSelector( 'gender', true )( list.gender );
 
updateSelector( 'language', true )( list.language );
 
updateSelector( 'proficiency', true )( list.proficiency );
 
$( '#audioresults' ).html( '' );
 
}
 
 
 
function reduceSpeakers( index, value, arr ) {
 
return arr.filter( function( x ) {
 
return x[index] === value;
 
} );
 
}
 
 
 
// Add button 'Search'
 
$( '#gosearch' ).html('').append(
 
( new OO.ui.ButtonInputWidget( {
 
label: messages['button-gosearch'][userLanguage] ? messages['button-gosearch'][userLanguage] : messages['button-gosearch'].en
 
} ) ).on( 'click', doQuery ).$element
 
);
 
 
 
// Add button 'Reset'
 
$( '#resetsearch' ).html('').append(
 
( new OO.ui.ButtonInputWidget( {
 
label: messages['button-resetsearch'][userLanguage] ? messages['button-resetsearch'][userLanguage] : messages['button-resetsearch'].en
 
} ) ).on( 'click', reset ).$element
 
);
 
 
 
// 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['msg-no-results'][userLanguage] ? messages['msg-no-results'][userLanguage] : messages['msg-no-results'].en );
 
return;
 
}
 
var length = data.results.bindings.length;
 
console.log( data.results.bindings );
 
function displayAudioBoxes( index ) {
 
$( '#audioresults' ).html( '' );
 
console.log( 'index', index );
 
for( var i = 0; i < 10 && i+index*10 < length; i++ ) {
 
console.log( 'i effectif', i+index*10 );
 
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+index*10 ].record.value.substr( 31 ), box );
 
$( '#audioresults' ).append( box );
 
}
 
function applyFn( i ) {
 
return function() {
 
console.log( i );
 
displayAudioBoxes( i );
 
return false;
 
}
 
}
 
for( var i = 0; i < Math.ceil( length/10 ); i++ ) {
 
var link = $( '<a href="#">' + (i+1) + '</a>' ).on( 'click', applyFn( i ) );
 
$( '#audioresults' ).append( link ).append( ' ' );
 
}
 
}
 
displayAudioBoxes( 0 );
 
}
 
 
 
// Do SPARQL request from filters
 
function doQuery() {
 
 
 
request = {
 
speaker: getQValue( 'speaker' ),
 
gender: getQValue( 'gender' ),
 
language: getQValue( 'language' ),
 
proficiency: getQValue( 'proficiency' ),
 
};
 
if( JSON.stringify( request ) === JSON.stringify( lastRequest ) ) {
 
return;
 
}
 
 
 
lastRequest = request;
 
 
 
console.log( request );
 
 
 
// When all fields are empty, do not query
 
if( !request.speaker && !request.gender && !request.language && !request.proficiency ) {
 
return;
 
}
 
 
 
var potentialSpeakers = speakersCriteria;
 
 
 
var query = "SELECT ?record WHERE { ?record prop:P2 entity:Q2 ; prop:P4 ?language ; prop:P5 ?speaker . ";
 
if( request.language ) {
 
query += "?record prop:P4 entity:" + request.language + " . ";
 
potentialSpeakers = reduceSpeakers( 2, request.language, potentialSpeakers );
 
}
 
if( request.speaker ) {
 
query += "?record prop:P5 entity:" + request.speaker + " . ";
 
potentialSpeakers = reduceSpeakers( 0, request.speaker, potentialSpeakers );
 
}
 
if( request.gender ) {
 
potentialSpeakers = reduceSpeakers( 1, request.gender, potentialSpeakers );
 
}
 
if( request.proficiency ) {
 
potentialSpeakers = reduceSpeakers( 3, request.proficiency, potentialSpeakers );
 
query += "?speaker llp:P4 [ llv:P4 ?language ; llq:P16 entity:" + request.proficiency + " ] . ";
 
}
 
if( potentialSpeakers.length < speakersCriteria.length ) {
 
var listSpeakers = dedupe( potentialSpeakers.map( function( x ) {
 
return 'entity:' + x[0];
 
} ) ).join();
 
query += 'FILTER( ?speaker IN (' + listSpeakers + ') )';
 
}
 
query += "} LIMIT 100";
 
 
 
// Voir https://commons.wikimedia.org/wiki/Category:Throbbers - il faut que le fond soit transparent
 
$( '#audioresults' ).html( '' ).append( '<img src="https://upload.wikimedia.org/wikipedia/commons/7/7a/Balls.gif" width="50" />' );
 
 
 
console.log( potentialSpeakers );
 
console.log( listSpeakers );
 
 
 
// Execute the request
 
var result = $.getJSON(
 
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
 
{
 
query: query,
 
//Accept: 'application/sparql-results+json'
 
}
 
);
 
 
 
result.then( createAudioBoxesForSearch, displayError );
 
}
 
  
initSelectors();
 
  
} );
+
/*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>' );
  
} );
+
// Load LiLiZip.js gadget (full script only loaded when user visits the dedicated page)
 +
mw.loader.load('/index.php?title=MediaWiki:LiLiZip.js/load.js&action=raw&ctype=text/javascript');

Latest revision as of 10:32, 3 September 2024

// 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: 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>' );

// Load LiLiZip.js gadget (full script only loaded when user visits the dedicated page)
mw.loader.load('/index.php?title=MediaWiki:LiLiZip.js/load.js&action=raw&ctype=text/javascript');