|
|
(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();
| |
− | }
| |
− | | |
− | AudioBox.prototype.display = function() {
| |
− | this.$node.find( '.ab-title' ).text( this.label );
| |
− | this.$node.find( '.ab-metadata' ).text( this.lang + ' - ' + this.speaker );
| |
− |
| |
− | this.audioNode.src = this.media;
| |
− | this.$node.find( '.ab-playbutton' ).click( this.audioNode.play.bind( this.audioNode ) );
| |
| } | | } |
− | | + | // 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'); |
− | | |
− | | |
− | 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() {
| + | /* In development *************************************** */ |
− | var api = new mw.Api();
| + | // User:Yug: Search by words, see https://jsfiddle.net/hugolpz/ecpzy0fo/89/ |
− | api.get( {
| + | if (/^LinguaLibre:Search_by(\/[a-z_-]+)?$/.test(mw.config.get('wgPageName'))) { |
− | action: 'query',
| + | console.log('🐣 Search by word'); |
− | format: 'json',
| + | mw.loader.load('/index.php?title=MediaWiki:SearchBy.js&action=raw&ctype=text/javascript'); |
− | 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' || mw.config.get( 'wgUserName' ) === 'Seb35' ) {
| |
− | 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'], 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>' ); |
| | | |
− | } );
| + | // 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'); |