Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;

Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5.
mw.loader.using('mediawiki.util', function () {

/***********************************************************************
 * addViafData.js
 * 
 * A tool to make it easy to select and import authority control data
 * from VIAF (viaf.org) using a text query.
 * 
 * Adds a link to the toolbox which opens a frame at the top of the page
 * containing a search box which loads data directly from VIAF. Click
 * the icon to use the record, or the number to jump to the VIAF record
 * page.
 * 
 * Bugs and suggestions to [[User:Inductiveload]], or patch as needed
 * 
 * Version 0.1   - 2012-01-19 - Initial release  
 *               - 2012-01-25 - Allow suggested text to load even on 
 *                              non-existent pages
 *               - 2012-03-10 - Warn when VIAF AutoSuggest might not 
 *                              return all hits
 *               - 2012-04-23 - Add ability to save pages, update pages 
 * 	                            while editing, de-select VIAF entries
 * 
 **********************************************************************/
 
var VIAFDataGrabber = function(){ //constructor
 
	//list of parameters allowed in AC templates
	this.template_parameters_allowed = ['GND', 'BNF', 'LCCN', 'VIAF', 'SELIBR', 'NLA', 'ULAN', 'SUDOC', 'type', 'WORLDCATID', 'ISNI'];
 
	this.ac_template_re = /{{ *[Aa]utorité *\|[\s\S]*?}}/m; //regex to find AC templates
	this.footer_re = /((\=+ *Liens? externes? *\=+)\n(\n*\{\{[aA]utres projets[^\}]*\}\})?)/ ;//regex to find the footers which go under the AC template
 
	this.icons = {
		'add':'//upload.wikimedia.org/wikipedia/commons/thumb/4/41/Ambox_emblem_plus.svg/20px-Ambox_emblem_plus.svg.png',
		'remove':'//upload.wikimedia.org/wikipedia/commons/thumb/9/97/Dialog-error-round.svg/20px-Dialog-error-round.svg.png'
	}
 
 
	this.pageDataFound = false;
	this.acDataFound = false;
	this.acDataFoundIsBad = false;
 
	this.viafAutosuggestMaxResults= 10; //max results viaf returns
 
	this.add_VIAF_button();
	//this.add_VIAF_pane(); //uncomment when debugging to prevent having to click button each time
}
 
VIAFDataGrabber.prototype.construct_VIAF_search_URL = function(query){
 
	return 'http://viaf.org/viaf/search?query=local.personalNames="' + query + '"&stylesheet=/viaf/xsl/results.xsl&sortKeys=holdingscount&maximumRecords=100'
}
 
VIAFDataGrabber.prototype.close_VIAF_pane = function(){
	$('#add_viaf_data_pane').remove();
}
 
VIAFDataGrabber.prototype.add_VIAF_pane = function(){
 
	var myself = this;
	if ($('#add_viaf_data_pane').length > 0){
		return
	}
 
	mw.util.addCSS( '.selected .viaf-id-link { font-weight:bold; }' );
	mw.util.addCSS( '.viaf-entry-icon { float:left; width:20px; height:20px; background-image:url("' + this.icons['add'] + '"); }' );
	mw.util.addCSS( '.selected .viaf-entry-icon { background-image:url("' + this.icons['remove'] + '"); }' );
	mw.util.addCSS( '#viaf_raw_proposed_data {margin-left:1em; font-size:120%; background-color:white; }' );
	mw.util.addCSS( '.viaf-changes-list {margin-left:2em; font-size:80%;}' );
 
	this.viafDiv = $('<div id="add_viaf_data_pane" style="position:relative; background-color:#F9F9F9; border:1px solid #AAAAAA; padding:1em; margin-bottom:0.5em; margin-top:0.5em;"><h3>Ajouter des notices d’autorité</h3></div>')
 
	var closeDiv = $('<div style="position:absolute; right:1em; top:0.1em;"></div>');
 
	var closeLink = $('<a href="#">[Fermer]</a>');
 
	closeLink.click( function(){
		myself.close_VIAF_pane()
	});
 
	closeDiv.append(closeLink);
	this.viafDiv.append(closeDiv);
 
 
	var jump_to_viaf_link = $("<a> Aller à la page de recherche du VIAF.</a>");
 
	var viaf_query_input = $('<input type="text" name="viaf_query" id="viaf_query_input" value="' + mw.config.get( 'wgTitle' ) + '"/>');
 
	viaf_query_input.change( function(){
			// link to real VIAF search
			jump_to_viaf_link.attr('href', myself.construct_VIAF_search_URL( $('#viaf_query_input').val() ) );
		} );
 
 
	var submitVIAFquery = $('<input type="button" value="Rechercher dans le VIAF" id="submit_viaf_query" name="submit_viaf_query"/>')
 
	submitVIAFquery.click( function(){
 
			//using real search (but how to make the cross domain request?)
			//var url = 'http://viaf.org/viaf/search?query=local.personalNames = "' + $('#viaf_query_input').val() + '"&version=1.1&operation=searchRetrieve&recordSchema=http://viaf.org/VIAFCluster&maximumRecords=50&startRecord=1&resultSetTTL=300&recordPacking=xml&recordXPath=&sortKeys=&httpAccept=text/xml'
 
			//using autosuggest (clumsy, but we can use JSONP)
			$.ajax( {
				url: 'http://viaf.org/viaf/AutoSuggest',
				data: {
					query: $('#viaf_query_input').val()
				},
				dataType: 'jsonp',
				success: function( data ) {
					myself.display_query_results(data);
				}
			} );
		} );
 
	this.viafResultsDiv = $('<div id="viaf_results"></div>');
	this.viafCurrentDataDiv = $('<div></div>');
	this.viafProposedDataDiv = $('<div id="proposed_authority_control_data"></div>');
	this.viafSaveACDiv = $('<div id="viaf_save_authority_control" style="display:none;"><hr></div>');
 
	var saveACButton = $('<input type="button" value="Mettre à jour les notices d’autorité de la page" id="viaf_save_ac_template" name="viaf_save_ac_template"/>');
	this.viafSaveACDiv.append(saveACButton);
 
	saveACButton.click( function(){
		myself.save_ac_data();
	});
 
	this.viafDiv.append(viaf_query_input, submitVIAFquery, jump_to_viaf_link);
 
	this.viafDiv.append('<hr>', this.viafResultsDiv)
	this.viafDiv.append('<hr>', this.viafCurrentDataDiv);
	this.viafDiv.append('<hr>', this.viafProposedDataDiv);
	this.viafDiv.append(this.viafSaveACDiv);
 
	$('#bodyContent').prepend( this.viafDiv );
 
	viaf_query_input.change(); //trigger an update of the link
 
	if ( mw.config.get( 'wgAction' ) == 'view' ){ //get data from API
		this.get_raw_page( mw.config.get( 'wgPageName' ), this.show_current_authority_data)
	} else if ($.inArray( mw.config.get( 'wgAction' ), ['submit', 'edit'] ) > -1 ){ //or from the current edit box
		this.show_current_authority_data ($('#wpTextbox1').val() );
	}
 
	submitVIAFquery.click(); //preload the page name results
}
 
VIAFDataGrabber.prototype.show_current_authority_data = function(data){
 
	if (data == null){
		var current_ac_data = null
	} else {
		var current_ac_data = data.match(/{{ *[Aa]utorité *\|.*}}/g);
	}
 
	this.pageDataFound = true;
 
	if (current_ac_data == null ){
		this.viafCurrentDataDiv.html('Aucune notice d’autorité n’a été trouvée sur cette page.');
		this.acDataFound = false;
		this.acDataFoundIsBad = false;
	} else if (current_ac_data.length == 1){
		this.viafCurrentDataDiv.html('Des notices d’autorité ont été trouvées sur cette page. Les nouvelles notices vont leur être ajoutées.<br>');
		this.viafCurrentDataDiv.append('<tt style="margin-left:1em;" id="current_authority_control_data">' + current_ac_data[0] + '</tt>');
		this.acDataFound = this.parse_ac_template( current_ac_data[0] );
		this.acDataFoundIsBad = false;
	} else { 
		this.viafCurrentDataDiv.html('<span class="error">Plusieurs modèles {{Autorité}} figurent sur cette page :</span><br>')
		this.acDataFound = true;
		this.acDataFoundIsBad = true;
		for (i in current_ac_data){
			this.viafCurrentDataDiv.append('<tt style="margin-left:1em" id="current_authority_control_data">' + current_ac_data[i] + '</tt><br>');
		}
	}
}
 
VIAFDataGrabber.prototype.parse_ac_template = function(template){
//parse a string holding a AC template into the AC array
 
	var i = 0;
	var parameter = ''
	var array = {};
 
 
	while(template[i] != '|'){ //get past the {{template name|
		i = i+1;
	}
 
	while(1){
 
		if (i == template.length){ //somehow we have overstepped the end of the template - maybe it was incomplete
			break;
		}
 
		i = i + 1;
 
		if (template[i] != '|' && template[i] != '}'){
			parameter = parameter + template[i];
		} else { //we have completed a parameter
 
			var myRegexp = /([^=]+)\s*=\s*(.*)/g; //look for parameter = value
			var match = myRegexp.exec(parameter);
 
			if (match != null){
				array[match[1]] = match[2]
			}
 
			if (template[i] == '}'){ //end of the template
				break;
			}
 
			parameter = '';
		}
	}
 
	return array
}
 
VIAFDataGrabber.prototype.add_VIAF_button = function(){
	var btn_id = 'tb-viaf-authority-control'
	var portletLink = mw.util.addPortletLink('p-tb', '#', 'Ajouter des notices d’autorité', btn_id, 'Ajouter des notices d’autorité à partir du VIAF');
 
	// Bind click handler
	$( '#' + btn_id ).click( $.proxy( this.add_VIAF_pane, this ) );
}
 
VIAFDataGrabber.prototype.display_query_results = function(results){
 
	if (results['result'] == null){
		this.viafResultsDiv.html('Aucun résultat trouvé pour "'+results['query']+'"');
	} else {
 
		var viafids = []; //list of ids to prevent dupes
		var results_list = $('<ul id="viaf-results-list" style="list-style: none;"><ul>')
 
		var count = 0;
 
		for (i in results['result']){
 
			if ($.inArray(results['result'][i]['viafid'],  viafids) == -1 ){ //fliter out duplicate VIAF ids
				viafids.push(results['result'][i]['viafid']);
				results_list.append(this.build_list_entry(results['result'][i]));
			}
			count++;
		}		
 
		this.viafResultsDiv.html('').append(results_list);
 
		if (count >= this.viafAutosuggestMaxResults ){
			var warning = $("<span style='font-style:italic' id='viaf-warn-further-results'>D’autres résultats peuvent être présents dans le VIAF. Voir <a href='" +  this.construct_VIAF_search_URL( $('#viaf_query_input').val() ) + "'>la page de recherche du VIAF</a>.</span>");
 
			this.viafResultsDiv.append(warning);
		}
	}
}
 
VIAFDataGrabber.prototype.build_list_entry = function(result){
	var myself = this;
	var entry = $('<li></li>');
 
	var use_id = $('<div class="viaf-entry-icon"></div>');
 
	use_id.click( function(){
 
		if (entry.hasClass('selected')){
			entry.removeClass('selected');
			myself.remove_data();
		} else {
			$.ajax({
				url: 'http://creatorlinks.wmflabs.org/viafLinks.php',
				data: {
					format: 'json',
					id: result['viafid'],
				},
				dataType: 'jsonp',
				success: function( data ) {
					if( data.links ) {
						myself.add_viaf_data( data );
						myself.viafResultsDiv.find('li').removeClass('selected'); //remove other entries' bolding
						entry.addClass('selected'); //add it to this one
					} else {
						alert( 'Identifiant VIAF invalide.' );
					}
				},
				error: function( xhr ) {
					alert( 'Erreur de communication avec creatorlinks.wmflabs.org : la requête a échoué.' );
				}
			});
		}
	});
 
	entry.append(use_id, '&nbsp;VIAF ID: ', '<a class="viaf-id-link" href="http://viaf.org/viaf/' + result['viafid'] + '">' + result['viafid'] + '</a> ', result['term']);
 
	return entry;
}
 
VIAFDataGrabber.prototype.remove_data = function(){
//remove any result selected
 
	this.viafProposedDataDiv.empty();
	this.viafProposedDataDiv.empty();
	this.merge_authority_data(null);
 
}
 
VIAFDataGrabber.prototype.add_viaf_data = function( result ){
// adds data from a viaf json result to the AC data already present
 
	if (!this.pageDataFound){
		this.viafCurrentDataDiv.html('<span class="error">La syntaxe wiki de la page ne peut être chargée. Veuillez réessayer plus tard.</span>');
		return;
	}
 
	if (this.acDataFoundIsBad){
		this.viafCurrentDataDiv.append('<span class="error">Les notices d’autorité de la page ne peuvent être fusionnées avec les nouvelle. Veuillez supprimer les modèles en doublon et réessayer.</span>');
		return;
	}
 
	//page data is loaded, and it is OK, let's merge the data!
	this.merge_authority_data(result);
 
}
 
VIAFDataGrabber.prototype.construct_ac_template = function(data){
 
	var text = '{{Autorité'
 
	for (field in data){
 
		if ($.inArray(field, this.template_parameters_allowed) > -1 ){
			text += '|' + field + '=' + data[field];
		}
	}
 
	text = text + '}}';
 
	return text;
}
 
VIAFDataGrabber.prototype.merge_authority_data = function(result){
//Merge authority data from a VIAF result with any existing data
	//construct an array of new data
	new_data = {};
 
	if( result && result.links ) {
		for (field in result.links ) {
			var id = field.toUpperCase();
			if ( $.inArray( id, this.template_parameters_allowed ) > -1 ){ //if the parameter is allowed, get the WS template parameter and save it
				var value = result.links[field];
				var bnfRegex = /^cb(.*)$/;
				if( id == 'BNF' && bnfRegex.test( value ) ) {
					new_data[id] = bnfRegex.exec( value )[1];
				} else {
					new_data[id] = result.links[field];
				}
			}
		}
	}
 
	this.added_fields = {};      //fields add the existing data
	this.conflicted_fields = {}; //fields that conflict and need approval
	this.pending_fields = {};    //fields that don't conflict but won't be added
 
	for (field in new_data){
 
		if (this.acDataFound && field in this.acDataFound){
 
			if (this.acDataFound[field] == new_data[field]){ //duplicate field, ignore
				continue;
			}
 
			console.log('Conflit sur la notice : ' + field + '. Notices présentes : "' +  this.acDataFound[field] + '" Nouvelles notices : "' + new_data[field] + '"' );
			this.conflicted_fields[field] = new_data[field];
		} else {
			this.added_fields[field] = new_data[field];
		}
	}
 
	this.provisional_data = Object.assign({}, this.acDataFound); 
 
	for (field in this.added_fields){
		if (!(field in this.provisional_data)){ //add any new data by default
			this.provisional_data[field] = this.added_fields[field]
		}
	}
 
	this.show_suggestions();
}
 
VIAFDataGrabber.prototype.show_suggestions = function(){
 
	var myself = this;
	this.viafSaveACDiv.css('display','none');
 
	if (!('VIAF' in this.provisional_data)){ //we don't have a selected item, clear out and get out
		this.viafProposedDataDiv.empty();
		return;
	}
 
	if ($.isEmptyObject(this.added_fields) &&  $.isEmptyObject(this.pending_fields) && $.isEmptyObject(this.conflicted_fields)){
		this.viafProposedDataDiv.html('Aucune notice d’autorité à ajouter ' + this.provisional_data['VIAF'] + '.');
	} else {
		if ($.isEmptyObject(this.added_fields) && $.isEmptyObject(this.provisional_data) ){
			this.viafProposedDataDiv.html('Aucune notice d’autorité sélectionnée.<br>');
		} else {
			template = this.construct_ac_template(this.provisional_data)
 
			this.viafProposedDataDiv.html('Modèle proposé :<br><tt id="viaf_raw_proposed_data">' +template+ '</tt><br>');
 
			var renderedTemplateHTML = $('<div id="viaf-rendered-template"></div>');
			this.viafProposedDataDiv.append(renderedTemplateHTML);
 
			//render the template and display it
			$.ajax({
				url: mw.util.wikiScript( 'api' ),
				data: {
					format: 'json',
					action: 'parse',
					prop: 'text',
					title: mw.config.get( 'wgPageName' ),
					text: template
				},
				dataType: 'json',
				success: function( data ) {
					renderedTemplateHTML.append( $(data['parse']['text']['*']));
				},
				error: function( xhr ) {
					alert( 'Erreur de rendu.' );
				}
			});
		}
 
		var added_list = $('<ul class="viaf-changes-list"></ul>')
		var pending_list = $('<ul class="viaf-changes-list"></ul>')
		var conflict_list = $('<ul class="viaf-changes-list"></ul>')
 
		var list_item, link;
 
		for (field in this.added_fields){
			list_item = $( '<li>Notice ajoutée : ' + field + ': ' + this.added_fields[field] + '. </li>')
			link = $('<a href="#">Retirer cette notice.</a>');
 
			link.bind('click', {field: field}, function(e){
				myself.remove_added(e.data.field)
				return false;
			});
 
			added_list.append(list_item.append(link));
		}
 
		for (field in this.pending_fields){
			list_item = $( '<li>Pending field: ' + field + ': ' + this.pending_fields[field] + '. </li>')
			link = $('<a href="#">Add this value.</a>');
 
			link.bind('click', {field: field}, function(e){
				myself.add_removed(e.data.field)
				return false;
			});
 
			pending_list.append(list_item.append(link));
		}
 
 
		for (field in this.conflicted_fields){
			list_item = $( '<li>Conflit sur la notice : ' + field + '. Notice présente : ' + this.provisional_data[field] + '; Notice en conflit : ' + this.conflicted_fields[field] + '. </li>')
			link = $('<a href="#">Intervertir les valeurs.</a>');
 
			link.bind('click', {field: field}, function(e){
				myself.approve_conflict(e.data.field)
				return false;
			});
 
			conflict_list.append(list_item.append(link));
		}
 
		//show whichever list have items
		if (!$.isEmptyObject(this.added_fields)){ this.viafProposedDataDiv.append('Modifications effectuées :', added_list); }
		if (!$.isEmptyObject(this.pending_fields)){ this.viafProposedDataDiv.append('Notices disponibles :', pending_list);}
		if (!$.isEmptyObject(this.conflicted_fields)){this.viafProposedDataDiv.append('Conflits :', conflict_list);}
 
		if ($('#viaf_raw_proposed_data').length > 0 && $('#viaf_raw_proposed_data').text() != $('#current_authority_control_data').text()){ //if we changed anything
			this.viafSaveACDiv.css('display','');
		} else {
			this.viafSaveACDiv.css('display','none');
		}
	}
}
 
VIAFDataGrabber.prototype.approve_conflict = function(field){
 
	var temp = this.provisional_data[field];
 
	this.provisional_data[field] = this.conflicted_fields[field];
	this.conflicted_fields[field] = temp;
 
	this.show_suggestions(); //update the suggestions
}
 
VIAFDataGrabber.prototype.remove_added = function(field){
 
	this.pending_fields[field] = this.added_fields[field];
	delete this.added_fields[field];
	delete this.provisional_data[field];
	this.show_suggestions(); //update the suggestions
}
 
VIAFDataGrabber.prototype.add_removed = function(field){
 
	this.added_fields[field] = this.pending_fields[field];
	this.provisional_data[field] = this.pending_fields[field];
	delete this.pending_fields[field];
	this.show_suggestions(); //update the suggestions
}
 
VIAFDataGrabber.prototype.save_ac_data = function(){
 
 
	if ( mw.config.get( 'wgAction' ) == 'view' ){ //update in the background
		this.get_raw_page(mw.config.get('wgPageName'), this.update_page);
	} else if ($.inArray( mw.config.get(  'wgAction' ), ['submit', 'edit'] ) > -1 ){
		var text = $('#wpTextbox1').val();
		var text = this.add_ac_template_to_text(text);
 
		$('#wpTextbox1').val(text);
 
		$('#wpTextbox1').css({'outline':'2px solid green'});
		setTimeout(function() {
			$('#wpTextbox1').css({'outline':''});
		}, 2000);
	}
}
 
VIAFDataGrabber.prototype.add_ac_template_to_text = function(text){
	//splice the template into the text, overwriting any current template
	var raw_template = $('#viaf_raw_proposed_data').text();
 
	var match = this.ac_template_re.exec(text);
 
	if (match == null){ //there is no existing template
		var foot = this.footer_re.exec(text)
 
		if (foot != null){
			text = text.replace(this.footer_re, foot[1] + '\n' + raw_template + '\n')
		} else {
			text = text + '\n\n' + raw_template;
		}
 
	} else {
		text = text.replace(this.ac_template_re, raw_template); //update the text in the text box
	}
 
	return text;
}
 
VIAFDataGrabber.prototype.update_page = function(data){
	var text = this.add_ac_template_to_text(data);
 
	this.save_page( mw.config.get( 'wgPageName' ), text, 'Ajout/modification de [[Modèle:Autorité|notices d’autorité]] à partir du [[VIAF]].' );
 
}
 
VIAFDataGrabber.prototype.get_raw_page = function(pagetitle, callback){
	var myself = this;
 
	//get the current page text
	$.ajax({
		url: mw.util.wikiScript( 'index' ),
		data: {
			action: 'raw',
			title: pagetitle,
		},
		cache:false,
		success:function(data){
			$.proxy(callback, myself)(data);
		},
		error:function(jqXHR, textStatus, errorThrown){
			alert('Le texte de la page [[' + pagetitle + ']] ne peut être chargé');
		}
	});
}
 
VIAFDataGrabber.prototype.save_page = function(title, content, summary, go_to_diff){
	var myself = this;
 
	$.ajax({
		url: mw.util.wikiScript( 'api' ),
		data: {
			format: 'json',
			action: 'edit',
			title: title,
			summary: summary,
			text: content,
			token: mw.user.tokens.get( 'csrfToken' )
		},
		dataType: 'json',
		type: 'POST',
		success: function( data ) {
			if ( data && data.edit && data.edit.result == 'Success' ) {
				window.location = mw.util.wikiScript( 'index' ) + '?' + $.param({ title: mw.config.get( 'wgPageName' ), diff:data.edit.newrevid , oldid:data.edit.oldrevid  });
			} else if ( data && data.error ) {
				alert( 'Erreur : l’API a retourné un code d’erreur "' + data.error.code + '": ' + data.error.info );
			} else {
				alert( 'Erreur : l’API a retourné un résultat inconnu.' );
			}
		},
		error: function( xhr ) {
			alert( 'Erreur : la requête a échoué.' );
		}
	});
}
 
jQuery( document ).ready( function() {
 
	if ($.inArray( mw.config.get( 'wgNamespaceNumber' ), [0, 2] ) > -1 ){ //only trigger in sensible namespaces
		VIAFDataGrabberInstance = new VIAFDataGrabber();
	}
});

});