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

Firefox (sur GNU/Linux) / Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5.
/*
	ce script (pour firefox) rassemble bon nombre de « gadgets » des préférences
	et permet une navigation plus rapide en centralisant les appels de scripts
	less edit clutter pas encore terminé (85%)
*/

var Config = {

	NavigationTool : {

		addToolboxLinks : true,
		editFirstSection : true,
		addGotoTopLinks : true,
		changeModifyLinks : true,
		shortenRefBox : true,

	},

	NavigationToolOptions : {

		addToolboxLinks : {
			'Stats':'http://stats.grok.se/fr/',
			'Journal':'http://fr.wikipedia.org/w/index.php?title=Special:Journal&page=',
			'Sous pages':'http://fr.wikipedia.org/wiki/Special:Index/',
		},

		editFirstSection : '/w/index.php?title=articleName&action=edit&section=0',
		addGotoTopLinks : '⬆',
		changeModifyLinks : '✍',
		shortenRefBox : '300px',

	},

	EditingTool : {

		//edition options
		setAsMinorEdit : true,
		addPredefinedText : true,
		addRegexTool : true,
		addLessEditClutter : false,
	},

	EditingToolOptions : {
		setAsMinorEdit : 'wpMinoredit',
		addPredefinedText : {

			'main' : [
				'typo',
				'ortho',
				'wikif',
				'interwiki',
				'ajout cat',
			],

			'projets' : {
				'Projets':'',
				'----':'',
				'Liens rouges':'[[Projet:Restauration_lien_rouge]]',
				'Homonymie':'',
			},

			'bandeaux' : {
				'Bandeaux':'',
				'----':'',
				'Ébauche':'{{m|Ébauche}}',
				'Portail':'{{m|Portail}}',
				'Copyvio':	'{{m|Copyvio}}',
				'À recycler':'{{m|À recycler}}',
			},

			'blanchiment' : {
				'Blanchiment':'',
				'----':'',
				'Bac à sable':'blanchi (bac à sable)',
				'Canular':'blanchi (canular)',
				'HC':'blanchi ([[WP:HC]])',
			}
		}
	}
}

var Helpers = {

	createNewNode : function(type, attrDict, parentNode) {
		var node = document.createElement(type);
		for (key in attrDict) node[key] = attrDict[key];
		return parentNode ? parentNode.appendChild(node) : node;
	},

	getElement : function(str, parent) {
		parent = parent || document;
		return document.getElementById(str) || parent.getElementsByClassName(str)[0] || parent.getElementsByTagName(str)[0];
	},

	getElements : function(str, parent) {
		parent = parent || document;
		return parent.getElementsByClassName(str).length==0 ? parent.getElementsByTagName(str) : parent.getElementsByClassName(str);
	},

	getSibling : function(elm, dir) {
		while (elm[dir].data == '\n')
			elm = elm[dir];
		return elm[dir];
	},

	getNextSibling : function(elm) {
		return Helpers.getSibling(elm,'nextSibling');
	},

	getPreviousSibling : function(elm) {
		return Helpers.getSibling(elm,'previousSibling');
	},

	appendCustom : function ( elm, arr ) {
		for (var i=0;i<arr.length;i++) {
			if (typeof(arr[i]) == "string")
				arr[i] = document.createTextNode(arr[i]);
			elm.appendChild(arr[i]);
		}
	}
}

// shortcuts for Helpers
$new = Helpers.createNewNode;
$get = Helpers.getElement;
$$get = Helpers.getElements;
$next = Helpers.getNextSibling;
$previous = Helpers.getPreviousSibling;
$append = Helpers.appendCustom;

var NavigationTool = {

	menu : null,
	articleName : null,

	init : function() {

		NavigationTool.articleName = $get('h1').innerHTML;

		var _this = 'NavigationTool';
		for(option in Config[_this])
			if (Config[_this][option])
				NavigationTool[option](Config[_this+'Options'][option]);

	},

	addToolboxLinks : function(dict) {

		NavigationTool.menu = $get('ul', $get('p-tb'));

		for (key in dict) {
			if (key=='Stats') {
				var url = dict['Stats']+NavigationTool.generateDateLink()+'/';
				NavigationTool.addToolboxLink('Stats',url);
			} else
				NavigationTool.addToolboxLink(key,dict[key]);
		}
	},

	generateDateLink : function() {
		var date = new Date();
		date.setMonth(date.getMonth()-1);
		return date.getFullYear()+''+(date.getMonth()+1<10?'0'+(date.getMonth()+1):date.getMonth()+1);
	},

	addToolboxLink : function(name, loc) {
		var link = $new('li',{},NavigationTool.menu);
		$new('a',{innerHTML:name,href:loc+NavigationTool.articleName},link);
	},

	editFirstSection : function(text) {
		var head = $get('h1');
		var link = text.split('articleName').join(NavigationTool.articleName);
		var linkContent = '[<a href="'+link+'">modifier</a>]';
		$new('span',{innerHTML:linkContent,className:'editsection'},head);
	},

	changeModifyLinks : function(text) {
		var links = $$get('editsection');
		for (var i=0;i<links.length;i++) {
			var link = $get('a',links[i]).href;
			links[i].innerHTML = '';
			$new('a',{href:link,innerHTML:text},links[i]);
		}
	},

	addGotoTopLinks : function(text) {

		var bodyContent = $get('bodyContent');
		var titles = [];

		for (var i=2;i<=6;i++)
			titles = titles.concat(NavigationTool.extractTags('h'+i, bodyContent));

		for(var i=0;i<titles.length;i++)
			$new('a',{innerHTML:text,href:'#top'},titles[i]);

	},

	extractTags : function(tag, parent) {
		var collection = $$get(tag, parent);
		var tempArr = [];
		for(var i=0;i<collection.length;i++)
			tempArr.push(collection[i]);
		return tempArr;
	},

	shortenRefBox : function(height) {
		var refs = $$get('references-small');
		if (refs.length>0) {
			for (var i=0;i<refs.length;i++) {
				refs[i].style.maxHeight = height;
				refs[i].style.overflowY = 'auto';
				refs[i].style.overflowX = 'hidden';
			}
		}
	},

}

var RegexTool = {
	template : '<input type="text" id="regexToolFind" value=""/><input type="text" id="regexToolReplace" value=""/><input type="checkbox" id="regexToolDoReplace" /><label for="regexToolDoReplace">Replace</label>',
	textarea : null,
	results : null,
	msgType : null,
	flag : null,
	find : null,
	replace : null,
	matchValues : null,

	init : function () {
		RegexTool.textarea = $get('textarea');
		var link = $new('a',{innerHTML:"[Regex]",id:"regexToolLink",href:"#",onclick:RegexTool.showRegexTool});
		$get('bodyContent').insertBefore(link, $get('editform'));
		$new('style',{innerHTML:'#bodyContent, #regexTool {position:relative;} #RegexToolMatchValues, #regexToolResults, #regexToolLink, #regexToolButton {position:absolute;right:0;top:0px;} #regexToolButton {cursor:pointer;} #regexToolResults {right:0;top:-28px;} #regexToolDoReplace {margin:3px 0 0 5px;} #RegexToolMatchValues {display:none;border:1px solid black;background:#FFFFEF;top:30px !important;}'},$get('head'));
	},

	showRegexTool : function () {
		var bodyContent = $get('bodyContent');
		var regexMain = $new('div',{id:'regexTool',innerHTML:RegexTool.template});
		$new('div',{id:'regexToolButton',onclick:RegexTool.parseFields,innerHTML:'Go!'},regexMain);
		RegexTool.results = $new('div',{id:'regexToolResults'},regexMain);
		bodyContent.insertBefore(regexMain, $get('editform'));
		bodyContent.removeChild(this);
		return false;
	},

	arrayCount : function(arr) {
		arr = arr.sort();
		var tempKey = '';
		var tempCount = '';
		var dict = {};
		for (i in arr) {
			if (arr[i]==tempKey) dict[arr[i]]++
			else {dict[arr[i]] = 1;	tempKey=arr[i];};
		}
		return dict;
	},

	makeMatchList : function(dict) {
		var str = '';
		for (key in dict) str+=key+': '+dict[key]+'<br />';
		return str;
	},

	showInfo : function(type, addInfo) {
		messages = [
			'Empty Field',
			'Found None',
			'Found: ',
			'Replaced: '
		]
		addInfo = addInfo || '';
		RegexTool.results.innerHTML = messages[type]+addInfo;
	},

	parseFields : function() {
		var find = $get('regexToolFind').value;
		RegexTool.flag = $get('regexToolDoReplace').checked;
		RegexTool.replace = $get('regexToolReplace').value;
		if (find=='' || (RegexTool.flag && RegexTool.replace==''))
			RegexTool.showInfo(0)
		else {
			RegexTool.find=new RegExp(find,'g');
			RegexTool.parseContent();
		}
	},

	parseContent : function () {

		var text = RegexTool.textarea.value;

		try {
			var str = text.match(RegexTool.find);
			var matchCounter = str.length;
		} catch (e) {
			RegexTool.showInfo(1);
			return;
		}

		if (RegexTool.flag) {
			msgType = 3
			RegexTool.textarea.value = text.replace(RegexTool.find, RegexTool.replace);
		} else msgType = 2;

		// display number of matches and a popup with different ones
		RegexTool.showInfo(msgType,matchCounter);
		RegexTool.displayMatches(str);
	},

	displayMatches : function (str) {
		var content = '<b>Matches:</b><br />'+RegexTool.makeMatchList(RegexTool.arrayCount(str));
		RegexTool.matchValues = $new('div',{id:'RegexToolMatchValues',innerHTML:content},RegexTool.results);
		var link = $new('a',{id:'RegexToolMatchLink',innerHTML:'<sup>[info]</sup>',href:'#'},RegexTool.results);
		link.onmouseover = function() {RegexTool.matchValues.style.display = 'block';}
		link.onmouseout = function() {RegexTool.matchValues.style.display = 'none';}
	}
}


var EditingTool = {

	wpSummary : null,

	init : function() {
		var _this = 'EditingTool';
		for(option in Config[_this])
			if (Config[_this][option])
				EditingTool[option](Config[_this+'Options'][option]);
	},

	setAsMinorEdit : function(id) {
		$get(id).checked="checked";
	},

	addPredefinedText : function() {

		// get config for keywords
		var keyDict = Config.EditingToolOptions.addPredefinedText;
		EditingTool.wpSummary = $get('wpSummary');

		// create div container
		var container = $get('editOptions');
		var firstSibling = $get('wpSummaryLabel');
		var keyDiv = $new('div',{id:'EditingToolMainDiv'});
		container.insertBefore(keyDiv,firstSibling);

		for (key in keyDict) {
			if (key=='main')
				for (key2 in keyDict['main'])
					$new('a',{href:'#',onclick:EditingTool.insertWord,innerHTML:keyDict['main'][key2]},keyDiv);
			else
				EditingTool.createSelectBox(keyDict[key],keyDiv);
		}
	},

	insertWord : function() {
		var text = this.tagName == 'A' ? this.innerHTML : this.value;
		EditingTool.wpSummary.value += text+' ';
		return false;
	},

	createSelectBox : function(dict, parent) {
		var select = $new('select',{onchange:EditingTool.insertWord},parent)
		for (key in dict)
			$new('option',{value:dict[key],innerHTML:key},select);
	},

	addRegexTool : function() {
		RegexTool.init();
	},

	addLessEditClutter : function() {
		LessEditClutter.init();
	}
}


var LessEditClutter = {

	lec_sort_category : false,
	lec_parse_references : 1,

	lec_tb1 : null,
	lec_active : null,
	lec_last_edited : null,
	lec_current_view : null,
	head_foot : null,
	main_data : {
		'general' : {},
		'header' : {},
		'footer' : {},
	},

	init : function  () {
		lec_active = 1 ;
		LessEditClutter.create_elements () ;
		LessEditClutter.hook_button ( 'wpSave' ) ;
		LessEditClutter.hook_button ( 'wpPreview' ) ;
		LessEditClutter.hook_button ( 'wpDiff' ) ;
		LessEditClutter.parse_main_textbox () ;
		LessEditClutter.fill_data_box();
		//LessEditClutter.rejoin();
	},

	hook_button : function  ( id ) {
		var b = $get(id) ;
		b.onclick = function () { LessEditClutter.rejoin() ; return true ; } ;
	},

	rejoin : function  () {

		//Reconstruct document
		var header = LessEditClutter.head_foot[0];
		var footer = LessEditClutter.head_foot[1];
		function join_extra(part) {
			var text = '';
			for (key in LessEditClutter.main_data[part]) {
				var dict = LessEditClutter.main_data[part][key];
				text += dict.join('\n')+('\n');
			}
			return text;
		}

		header = join_extra('header') + header;
		footer = footer + join_extra('footer');
		var text = header + '\n\n' + LessEditClutter.lec_tb1.value + '\n\n' + footer;

		var regex = /<<([^\d]*)(\d?)>>/;
		var dict = LessEditClutter.main_data['general'];
		while ((result = text.match(regex)) != null) {
			var keyword = result[1];
			var index = result[2]-1;
			text = text.replace(result[0], dict[keyword][index]);
		}

		LessEditClutter.lec_tb1.value = text;

	},

	create_elements : function  () {
		var main = $get('wpTextbox1');
		LessEditClutter.lec_tb1 = main;
		main.onfocus = function() {LessEditClutter.lec_last_edited = true};
		main.onblur = function() {LessEditClutter.lec_last_edited = false};

		var top = $new('div');
		main.parentNode.insertBefore(top, LessEditClutter.lec_tb1);
		top.style.height = '180px';
		top.style.marginBottom = '10px';
		LessEditClutter.append_show_hide(top);

		// list
		var objects = $new('div', {id:'lec_objects'}, top);
		with (objects.style) {
			width = '30%';
			cssFloat = 'left';
			border = '2px solid #a99';
			height = '100%';
			overflow = 'auto';
			padding = '5px';
		}

		// data
		var lec_tb2 = $new('textarea', {
			id : 'lec_tb2',
			onblur : update_current,
			onfocus : function() {LessEditClutter.lec_last_edited = true}
		}, top);
		enable_add_ref(lec_tb2);
		with (lec_tb2.style) {
			cssFloat = 'left';
			width = '67%';
			height = '100%';
		}

		function update_current() {
			var elm = LessEditClutter.current_view;
			if (elm[1] == 'general')
				LessEditClutter.main_data[elm[1]][elm[2]][parseInt(elm[3])] = this.value;
			else
				LessEditClutter.main_data[elm[1]][elm[2]] = this.value.split('\n');
			LessEditClutter.lec_last_edited = false;
		}
	},

	toggle_show_hide : function  ( x , a ) {
		if ( x.style.display == 'none' ) {
			x.style.display = '' ;
			a.innerHTML = 'masquer';
		} else {
			x.style.display = 'none' ;
			a.innerHTML = 'voir';
		}
	},

	append_show_hide : function  ( elm ) {
		var n = $new ( 'span' ) ;
		function addHideLink () {
			LessEditClutter.toggle_show_hide ( elm, a ) ;
			return false ;
		}
		var a = $new ( 'a', {
			href : '#',
			onclick : addHideLink,
			innerHTML : 'masquer'
		}) ;

		$append(n, ['(', a, ')',$new('br')]);
		elm.parentNode.insertBefore ( n , elm ) ;
		//  x.style.display = 'none' ;
	},

	parse_main_textbox : function  () {
		var text = LessEditClutter.lec_tb1.value;
		var main_array = {
			general : {
				'REF' :  [/<ref(?:\sname="(.*)")?(?:(?:\s?\/>)|(?:>([\w\W]*?)<\/ref>))/, 'Références'],
				'COMM' : [/<!--\s([\w\W]*?)\s-->/, 'Commentaires'],
				'FILE' : [/\[\[((image|file|fichier):(.*?))\]\]/i, 'Fichiers']
			},

			header : {
				'HEAD' : [/\{\{([^\n]*?)\}\}/, 'Bandeaux'],
				'INFO' : [/\{\{((?:[^<>\}]*?)\n(?:[\w\W]*?))\}\}/i, 'Infoboxes'],
			},

			footer : {
				'FOOT' : [/\{\{([\w\W]*?)\}\}/, 'Modèles de pied de page'],
				'CAT' : [/\[\[catégorie:(.*?)\]\]/i, 'Catégories'],
				'WIKI' : [/\[\[(.*?):(.*?)\]\]/, 'Liens Interwiki']
			}
		}

		for (key in main_array.general) {
			var data = main_array.general[key];
			text = LessEditClutter.parse_and_replace(text, data[0], data[1], 'general', key, true);
		}

		// Separate head/body/foot of article
		function parse_extra(text, part) {
			for (key in main_array[part]) {
				var data = main_array[part][key];
				text = LessEditClutter.parse_and_replace(text, data[0], data[1], part, key, false);
			}
			return text;
		}

		var regex = /^('|\w)+/m;
		var result = text.match(regex);
		var header = text.split(result[0]).shift();
		text = text.replace(header, '');
		header = parse_extra(header, 'header');
		header = header.replace(/\s/, '');

		regex = /\w+\.?$/mg;
		result = text.match(regex);
		var footer = text.split(result[result.length-1]).pop();
		text = text.replace(footer, '');
		footer = parse_extra(footer, 'footer');
		footer = footer.replace(/\s/g, '');

		LessEditClutter.head_foot = [header, footer];
		LessEditClutter.lec_tb1.value = text;

	},

	parse_and_replace : function(text, regex, key, part, dictName, replace) {
		var main_array = [];
		var key_dict = {};
		var results = [];
		var index = 0;

		// used only to group refs
		function store_groups() {
			var name = results[1];
			var ref = results[2];
			if (!name) {
				main_array[index] = [];
				if (!ref || ref == '') main_array[index].error = true;
				main_array[index].hasChild = false;
				main_array[index].name = 'Ref anonyme';
				main_array[index].push([index, ref]);
			} else if (key_dict[name]==undefined) {
				// stores index for grouped refs
				key_dict[name] = index;
				main_array[index] = [];
				main_array[index].name = name;
				if (!ref) {
					main_array[index].error = true;
					main_array[index].ref = '';
				} else main_array[index].ref = ref;
				main_array[index].push([index, name, ref]);
				main_array[index].hasChild = false;
				groupIndex = (index+1) + 'a';
			} else {
				groupIndex = key_dict[name];
				if (main_array[groupIndex].ref == '' && ref) {
					main_array[groupIndex].error = false;
					main_array[groupIndex].ref = ref;
				} else if (main_array[groupIndex].ref != ref && ref)
					main_array[groupIndex].error = true;
				main_array[groupIndex].push([index, name, ref]);
				main_array[groupIndex].hasChild = true;
				groupIndex = (key_dict[name]+1) + String.fromCharCode(96+main_array[groupIndex].length);
				index--;
			}
		}

		while ((results = text.match(regex)) != null)	{
			var groupIndex = null;
			if (dictName=='REF') store_groups()
			else main_array.push(results[0]);
			if (replace) text = text.replace(results[0], '<<'+dictName+(groupIndex!=null?groupIndex:(index+1))+'>>')
			else text = text.replace(results[0], '');
			index++;
		}
		if (main_array.length !=0) {
			LessEditClutter.main_data[part][dictName] = [];
			LessEditClutter.main_data[part][dictName] = main_array;
			LessEditClutter.main_data[part][dictName]['name'] = key;
		}
		return text;
	},

	fill_data_box : function() {
		var div = $get('lec_objects');
		for (section in LessEditClutter.main_data) {
			var dict = LessEditClutter.main_data[section];
			for (key2 in dict) {
				var array = dict[key2];
				if (array.length == 0) continue;
				if (section == 'general') {
					append_div('▸ ' + array.name, show_list, '');
					var ul = $new('ul', {}, div);
					ul.style.display = 'none';
					if (key2 == 'REF')
						make_ref_tree()
					else
						create_sublist()
				} else
					append_div(array.name, show_data, ['lec', section, key2].join('_'));
			}
		}

		function make_ref_tree() {
			for (var i=0; i<array.length;i++) {
				if (!array[i].hasChild) {
					append_li(array[i].name, null, null, array[i].error);
				} else {
					var li = $new('li', {}, ul);
					li.style.listStyleType = 'none';
					var div2 = $new('div', {
						innerHTML : '▸ ' + array[i].name + ' (' + array[i].length + ')',
						onclick : show_list
					},li);
					div2.style.cursor = 'pointer';
					div2.style.marginLeft = '-15px';
					if (array[i].error) div2.style.color = 'red';
					var ul2 = $new('ul', {}, li);
					ul2.style.display='none';
					for (var j=0; j<array[i].length; j++) {
						$new('li', {
							innerHTML : 'test'
						}, ul2);
					}
				}
			}
		}

		function create_sublist () {
			for (var i=0; i<array.length;i++) {
				if (key2 == 'COMM')
					var title = array[i].substring(5, 20)+'...'
				else {
					var title = array[i].split('|').shift();
					title = title.split(':').pop();
				}
				append_li((i+1) + ' - ' + title, show_data, ['lec',section,key2,i].join('_'));
			}
		}

		function append_div(text, callback, id) {
			var div2 = $new('div', {
				innerHTML : text,
				onclick : callback,
				id : id
			}, div);
			div2.style.cursor = 'pointer';
		}

		function append_li(text, callback, id, error) {
			var li = $new('li', {
				innerHTML : text,
				id : id,
				onclick : callback
			}, ul);
			li.style.cursor = 'pointer';
			if (error) li.style.color = 'red';
		}

		function show_list() {
			var ul = $next(this);
			text = this.innerHTML;
			if (ul.style.display == 'none') {
				ul.style.display = 'block';
				this.innerHTML = text.replace('▸','▾');
			} else {
				ul.style.display = 'none';
				this.innerHTML = text.replace('▾','▸');
			}
		}

		function show_data() {
			var elm = this.id.split('_');
			LessEditClutter.current_view = elm;
			if (elm[1] == 'general')
				$get('lec_tb2').value = LessEditClutter.main_data[elm[1]][elm[2]][parseInt(elm[3])];
			else
				$get('lec_tb2').value = LessEditClutter.main_data[elm[1]][elm[2]].join('\n');
		}
	}
}
window.addEventListener('DOMContentLoaded',loadFuncs,true);
function loadFuncs() {
	NavigationTool.init();
	if ($get('editform')!=null) {
		EditingTool.init();
	}
}