MediaWiki

Difference between revisions of "Common.js"

(exception pour mon utilisateur dans la page de l’interface de contributions)
(new version of the UI for displaying contributions)
Line 173: Line 173:
 
// Development in final phase of the interface for displaying contributions
 
// Development in final phase of the interface for displaying contributions
 
$( function (){
 
$( function (){
if( mw.config.get( 'wgPageName' ) !== 'User:Nicolas_NALLET' || mw.config.get( 'wgUserName' ) === 'Seb35' ) {
+
if( mw.config.get( 'wgPageName' ) !== 'User:Nicolas_NALLET' ) {
 
return;
 
return;
 
}
 
}
Line 186: Line 186:
 
mw.loader.using( ['oojs', 'oojs-ui'], function () {
 
mw.loader.using( ['oojs', 'oojs-ui'], function () {
  
var oouiSelectors = {
+
oouiSelectors = {
 
'speaker': null,
 
'speaker': null,
 
'gender': null,
 
'gender': null,
Line 199: Line 199:
 
};
 
};
 
var placeholders = {
 
var placeholders = {
'speaker': '👤 Speaker',
+
'en': {
'gender': '♀️ ♂️ Speaker\'s gender',
+
'speaker': '👤 Speaker',
'language': '🏳️ Language',
+
'gender': '♀️ ♂️ Speaker\'s gender',
'proficiency': '🥇 Level of proficiency',
+
'language': '🏳️ Language',
 +
'proficiency': '🥇 Level of proficiency',
 +
},
 +
'fr': {
 +
'speaker': '👤 Locuteur',
 +
'gender': '♀️ ♂️ Genre du locuteur',
 +
'language': '🏳️ Langue',
 +
'proficiency': '🥇 Niveau de compétence',
 +
},
 
};
 
};
 
var htmlElements = {
 
var htmlElements = {
Line 216: Line 224:
 
'proficiency': '',
 
'proficiency': '',
 
};
 
};
 +
var resetSelectors = false;
 +
 +
function getValueWidget( type ) {
 +
if( !oouiSelectors[type] ) {
 +
return '';
 +
}
 +
var widgetCombobox = type === 'speaker' || type === 'language';
 +
if( widgetCombobox ) {
 +
return oouiSelectors[type].getValue();
 +
} else {
 +
return oouiSelectors[type].getMenu().findSelectedItem() ? oouiSelectors[type].getMenu().findSelectedItem().getData() : '';
 +
}
 +
 +
}
  
 
function updateSelector( type ) {
 
function updateSelector( type ) {
 
return function( values ) {
 
return function( values ) {
if( ( oouiSelectors['speaker'] && oouiSelectors['speaker'].getValue() != lastRequest['speaker'] ) ||
+
/*if( ( getValueWidget( 'speaker' ) != lastRequest['speaker'] ) ||
    ( oouiSelectors['gender'] && oouiSelectors['gender'].getValue() != lastRequest['gender'] ) ||
+
    ( getValueWidget( 'gender' ) != lastRequest['gender'] ) ||
    ( oouiSelectors['language'] && oouiSelectors['language'].getValue() != lastRequest['language'] ) ||
+
    ( getValueWidget( 'language' ) != lastRequest['language'] ) ||
    ( oouiSelectors['proficiency'] && oouiSelectors['proficiency'].getValue() != lastRequest['proficiency'] ) ) {
+
    ( getValueWidget( 'proficiency' ) != lastRequest['proficiency'] ) ) {
 
return;
 
return;
}
+
}*/
  
oouiSelectors[type] = new OO.ui.ComboBoxInputWidget( {
+
var widgetType = type === 'speaker' || type === 'language' ? 'ComboBoxInputWidget' : 'DropdownWidget';
placeholder: placeholders[type],
+
var v = values.results.bindings;
 +
console.log( type );
 +
console.log( v );
 +
console.log( v.length === 1 ? v[0][ type + 'Label' ].value + " (" + v[0][type].value.substr( 31 ) + ")" : null );
 +
oouiSelectors[type] = new OO.ui[widgetType]( {
 +
placeholder: placeholders[userLanguage][type] ? placeholders[userLanguage][type] : placeholders['en'][type],
 +
disabled: v.length === 1,
 
menu: {
 
menu: {
 
filterFromInput: true,
 
filterFromInput: true,
items: values.results.bindings.map( function( x ) {
+
items: v.map( function( x ) {
 
return new OO.ui.MenuOptionWidget( {
 
return new OO.ui.MenuOptionWidget( {
 
data: x[ type + 'Label' ].value + " (" + x[type].value.substr( 31 ) + ")",
 
data: x[ type + 'Label' ].value + " (" + x[type].value.substr( 31 ) + ")",
Line 238: Line 266:
 
}
 
}
 
} );
 
} );
 +
if( v.length === 1 ) {
 +
if( widgetType === 'ComboBoxInputWidget' ) {
 +
oouiSelectors[type].setValue( v[0][ type + 'Label' ].value + " (" + v[0][type].value.substr( 31 ) + ")" );
 +
} else {
 +
oouiSelectors[type].getMenu().selectItemByData( v[0][ type + 'Label' ].value + " (" + v[0][type].value.substr( 31 ) + ")" );
 +
}
 +
}
  
 
$( htmlElements[type] ).html('').append(
 
$( htmlElements[type] ).html('').append(
Line 243: Line 278:
 
);
 
);
  
oouiSelectors[type].on( 'change', function() { doQuery(); doQuery( 'speaker' ); doQuery( 'gender' ); doQuery( 'language' ); doQuery( 'proficiency' ); } );
+
function onChange() {
 +
console.log( 'event onChange ' + type );
 +
if( resetSelectors ) { return; }
 +
doQuery();
 +
doQuery( 'speaker' );
 +
doQuery( 'gender' );
 +
doQuery( 'language' );
 +
doQuery( 'proficiency' );
 +
}
 +
if( widgetType === 'ComboBoxInputWidget' ) {
 +
oouiSelectors[type].on( 'change', onChange );
 +
} else {
 +
oouiSelectors[type].getMenu().on( 'change', onChange );
 +
}
  
 
};
 
};
 
}
 
}
  
$.getJSON(
+
function initSelectors() {
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
+
 
{
+
$.getJSON(
query: sparqlGlobal['speaker']
+
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
}
+
{
).done( updateSelector( 'speaker' ) );
+
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(
+
$.getJSON(
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
+
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
{
+
{
query: sparqlGlobal['gender']
+
query: sparqlGlobal['proficiency']
}
+
}
).done( updateSelector( 'gender' ) );
+
).done( updateSelector( 'proficiency' ) );
 +
resetSelectors = false;
 +
}
  
$.getJSON(
+
function reset() {
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
+
resetSelectors = true;
{
+
initSelectors();
query: sparqlGlobal['language']
+
$( '#audioresults' ).html( '' );
}
+
}
).done( updateSelector( 'language' ) );
 
  
$.getJSON(
+
$( '#resetsearch' ).html('').append(
'https://lingualibre.org/bigdata/namespace/wdq/sparql',
+
( new OO.ui.ButtonInputWidget( {
{
+
label: 'Reset'
query: sparqlGlobal['proficiency']
+
} ) ).on( 'click', reset ).$element
}
+
);
).done( updateSelector( 'proficiency' ) );
 
  
 
// Display results
 
// Display results
Line 286: Line 350:
 
return;
 
return;
 
}
 
}
var length = data.results.bindings.length < 100 ? data.results.bindings.length : 100;
+
var length = data.results.bindings.length;
$( '#audioresults' ).html( '' );
+
console.log( data.results.bindings );
for (var i = 0; i < length; i++) {
+
function displayAudioBoxes( index ) {
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>' );
+
$( '#audioresults' ).html( '' );
var audiobox = new AudioBox( data.results.bindings[ i ].record.value.substr( 31 ), box );
+
console.log( 'index', index );
$( '#audioresults' ).append( box );
+
for( var i = 0; i < 10 && i+index*10 < length; i++ ) {
//ab1 = new AudioBox( data.query.rwrecords[ i ], $( '.audiobox' ).eq( i ) );
+
console.log( 'i effectif', i+index*10 );
//$("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>');
+
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 );
 +
//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>');
 +
}
 +
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
 
// Do SPARQL request from filters
function doQuery( variable ){
+
function doQuery( variable ) {
  
 
// Do not modify a selector where there is a value
 
// Do not modify a selector where there is a value
if( variable && oouiSelectors[variable] && oouiSelectors[variable].getValue() ) {
+
if( variable && getValueWidget( variable ) ) {
 
return;
 
return;
 
}
 
}
Line 309: Line 390:
 
return '?' + type;
 
return '?' + type;
 
}
 
}
var text = oouiSelectors[type] ? oouiSelectors[type].getValue() : '';
+
var text = getValueWidget( type );
 
if( !text ) {
 
if( !text ) {
 
return '';
 
return '';
Line 319: Line 400:
 
return 'entity:' + text.replace( /.*\((Q[0-9]+)\)$/, '$1' );
 
return 'entity:' + text.replace( /.*\((Q[0-9]+)\)$/, '$1' );
 
} else {
 
} else {
console.warn( 'Bad input “' + text + '”' );
 
 
return '';
 
return '';
 
}
 
}
Line 331: Line 411:
 
if( ! variable ) {
 
if( ! variable ) {
 
lastRequest = {
 
lastRequest = {
'speaker': oouiSelectors['speaker'] ? oouiSelectors['speaker'].getValue() : '',
+
'speaker': getValueWidget( 'speaker' ),
'gender': oouiSelectors['gender'] ? oouiSelectors['gender'].getValue() : '',
+
'gender': getValueWidget( 'gender' ),
'language': oouiSelectors['language'] ? oouiSelectors['language'].getValue() : '',
+
'language': getValueWidget( 'language' ),
'proficiency': oouiSelectors['proficiency'] ? oouiSelectors['proficiency'].getValue() : '',
+
'proficiency': getValueWidget( 'proficiency' ),
 
};
 
};
 +
}
 +
console.log( 'doQuery( "' + variable + '" );' );
 +
console.log( speaker, gender, language, proficiency, lastRequest );
 +
 +
// When all fields are empty, do not query
 +
if( !speaker && !gender && !language && !proficiency ) {
 +
return;
 
}
 
}
  
Line 365: Line 452:
 
return;
 
return;
 
}
 
}
$( '#audioresults' ).html( '' ); // TODO replace by a spinner
+
// 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" />' );
 
}
 
}
  
Line 384: Line 472:
 
}
 
}
 
}
 
}
 +
 +
initSelectors();
  
 
} );
 
} );
  
 
} );
 
} );

Revision as of 07:57, 3 September 2021

// Replace Wikidata IDs with their [label, description]
if ( $( '.wb-external-id' ).length > 0 ) {
	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;
}

if ( $( '#P3 a.extiw' ).length > 0 ) {
    mw.loader.using( [ 'oojs-ui-widgets', 'oojs-ui.styles.icons-media' ], function() {
        $( '#P3 a.extiw' ).each( function() {
            var $node = $( this );
            $node.before( playButton( BASE_FILE_URL + $node.text() ) );
        } );
    } );
}


/**
 * Display last records on main page
 **/
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 );
}

AudioBox.prototype.processRecord = function() {
	this.label = this.wbRecord.getLabel( 'en' );
	this.media = 'https://commons.wikimedia.org/wiki/Special:FilePath/' + this.wbRecord.getStatements( 'P3' )[ 0 ].getValue();
	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 );
}

AudioBox.prototype.processLabels = function( data ) {
	var langLabels;

	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 ) );
}






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 );
}

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'], function () {

		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 = {
			'en': {
				'speaker': '👤 Speaker',
				'gender': '♀️ ♂️ Speaker\'s gender',
				'language': '🏳️ Language',
				'proficiency': '🥇 Level of proficiency',
			},
			'fr': {
				'speaker': '👤 Locuteur',
				'gender': '♀️ ♂️ Genre du locuteur',
				'language': '🏳️ Langue',
				'proficiency': '🥇 Niveau de compétence',
			},
		};
		var htmlElements = {
			'speaker': '#filteruser',
			'gender': '#filtergender',
			'language': '#filterlanguage',
			'proficiency': '#filterlevelofproficiency',
		};
		var lastRequest = {
			'speaker': '',
			'gender': '',
			'language': '',
			'proficiency': '',
		};
		var resetSelectors = false;

		function getValueWidget( type ) {
			if( !oouiSelectors[type] ) {
				return '';
			}
			var widgetCombobox = type === 'speaker' || type === 'language';
			if( widgetCombobox ) {
				return oouiSelectors[type].getValue();
			} else {
				return oouiSelectors[type].getMenu().findSelectedItem() ? oouiSelectors[type].getMenu().findSelectedItem().getData() : '';
			}
			
		}

		function updateSelector( type ) {
			return function( values ) {
				/*if( ( getValueWidget( 'speaker' ) != lastRequest['speaker'] ) ||
				    ( getValueWidget( 'gender' ) != lastRequest['gender'] ) ||
				    ( getValueWidget( 'language' ) != lastRequest['language'] ) ||
				    ( getValueWidget( 'proficiency' ) != lastRequest['proficiency'] ) ) {
					return;
				}*/

				var widgetType = type === 'speaker' || type === 'language' ? 'ComboBoxInputWidget' : 'DropdownWidget';
				var v = values.results.bindings;
				console.log( type );
				console.log( v );
				console.log( v.length === 1 ? v[0][ type + 'Label' ].value + " (" + v[0][type].value.substr( 31 ) + ")" : null );
				oouiSelectors[type] = new OO.ui[widgetType]( {
					placeholder: placeholders[userLanguage][type] ? placeholders[userLanguage][type] : placeholders['en'][type],
					disabled: v.length === 1,
					menu: {
						filterFromInput: true,				
						items: v.map( function( x ) {
							return new OO.ui.MenuOptionWidget( {
								data: x[ type + 'Label' ].value + " (" + x[type].value.substr( 31 ) + ")",
								label: x[ type + 'Label' ].value
							} );
						} )
					}
				} );
				if( v.length === 1 ) {
					if( widgetType === 'ComboBoxInputWidget' ) {
						oouiSelectors[type].setValue( v[0][ type + 'Label' ].value + " (" + v[0][type].value.substr( 31 ) + ")" );
					} else {
						oouiSelectors[type].getMenu().selectItemByData( v[0][ type + 'Label' ].value + " (" + v[0][type].value.substr( 31 ) + ")" );
					}
				}

				$( htmlElements[type] ).html('').append(
					oouiSelectors[type].$element
				);

				function onChange() {
					console.log( 'event onChange ' + type );
					if( resetSelectors ) { return; }
					doQuery();
					doQuery( 'speaker' );
					doQuery( 'gender' );
					doQuery( 'language' );
					doQuery( 'proficiency' );
				}
				if( widgetType === 'ComboBoxInputWidget' ) {
					oouiSelectors[type].on( 'change', onChange );
				} else {
					oouiSelectors[type].getMenu().on( 'change', onChange );
				}

			};
		}

		function initSelectors() {

			$.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' ) );
			resetSelectors = false;
		}

		function reset() {
			resetSelectors = true;
			initSelectors();
			$( '#audioresults' ).html( '' );
		}

		$( '#resetsearch' ).html('').append(
			( new OO.ui.ButtonInputWidget( {
				label: 'Reset'
			} ) ).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['no-results'][userLanguage] ? messages['no-results'][userLanguage] : messages['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 );
					//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>');	
				}
				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( variable ) {

			// Do not modify a selector where there is a value
			if( variable && getValueWidget( variable ) ) {
				return;
			}

			function getQ( type ) {
				if( variable === type ) {
					return '?' + type;
				}
				var text = getValueWidget( type );
				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 {
					return '';
				}
			}

			var speaker = getQ( 'speaker' ),
			    gender = getQ( 'gender' ),
			    language = getQ( 'language' ),
			    proficiency = getQ( 'proficiency' ),
			    somevalue = false;
			if( ! variable ) {
				lastRequest = {
					'speaker': getValueWidget( 'speaker' ),
					'gender': getValueWidget( 'gender' ),
					'language': getValueWidget( 'language' ),
					'proficiency': getValueWidget( 'proficiency' ),
				};
			}
			console.log( 'doQuery( "' + variable + '" );' );
			console.log( speaker, gender, language, proficiency, lastRequest );

			// When all fields are empty, do not query
			if( !speaker && !gender && !language && !proficiency ) {
				return;
			}

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

			// 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 );
			}
		}

		initSelectors();

	} );

} );