// Copyright (C) 2008 SpinkBB
// Entire code by Julien VAUBOURG
// julien__AT__vaubourg__DOT__com

// Author  : http://julien.vaubourg.com
// SpinkBB : http://spinkbb.jsand.net
// Forums  : http://CtrlAltSuppr.com


/******************/
/** Constructeur **/
/******************/

function EditStyle(flotteur) {
	// Base du modulo pour la CSS
	this.iLine = 0;

	// Définitions du flotteur
	this.flotteur = flotteur;
	this.flotteurStyle = window.getComputedStyle ? window.getComputedStyle(this.flotteur, null) : this.flotteur.currentStyle;
	this.flotteur.flotteurStyle = this.flotteurStyle;
}	

// Propriétés redéfinissables pour les inlines
EditStyle.propInline = {
	Format: ['font-weight', 'font-style'],
	Taille: 'font-size',
	'Soulign\351' : 'text-decoration',
	Police: ['font-variant', 'font-family'],
	Couleur: 'color'
};

// Propriétés redéfinissables pour les blocks			
EditStyle.propBlock = {
	'Bordures': ['border-4c-style', 'border-4c-color', 'border-4c-width'],
	'Marges int.': 'padding-4c',
	'Marges ext.': 'margin-4c',
	'Largeur': 'width',
	'Alignement': 'text-align',
	'Couleur de fond': 'background-color'
};

// Ajout des éléments inline parmis les blocks
for(var element in EditStyle.propInline)
	if(!Outils.isFunction(EditStyle.propInline[element]))
		EditStyle.propBlock[element] = EditStyle.propInline[element];


/*************************/
/** Méthodes d'instance **/
/*************************/

EditStyle.prototype = {

	// Matérialisation du flotteur en cours de modification
	setVisible: function() {
		this.flotteur.backgroundColor = this.flotteurStyle.backgroundColor;
		this.flotteur.style.backgroundColor = 'red';
	},
	
	/** Création du navigateur de noeuds (remonte le flotteur dans l'arborescence) */
	addBrowser: function() {
		var ligne = document.createElement('tr');
		var colonneL = document.createElement('td');
		var colonneM = document.createElement('td');
		var colonneR = document.createElement('td');

		var browser = document.createElement('select');
		var parents = this.menu.declencheur.paths['arrayPath'];
		var flotteurName = this.flotteur.paths['arrayPath'].copieLast();
		var parentNodes = new Array();
		var unLien = false;

		// Déplacement de la fenêtre
		colonneL.onmousedown = function() {
			document.body.style.cursor = 'move';
			Affichage.opacity.call(document.getElementById('spinkbb'), false);
			document.body.onmousemove = Outils.deplacer;
		};

		colonneL.onmouseup = function() {
			document.body.style.cursor = 'auto';
			document.body.onmousemove = function() {};
			Affichage.opacity.call(document.getElementById('spinkbb'), true);
		};

		colonneL.title = Langues.get('D\351placer');
		colonneL.id = 'spkMove';
		
		// Petit cache purement esthétique
		colonneL.appendChild(document.createElement('div'));

		// Fermer la fenêtre
		var imgR = document.createElement('img');
		var lienR = document.createElement('a');

		imgR.src = Parametres.root + 'img/spkClose.png';
		imgR.alt = Langues.get('Fermer');

		lienR.title = imgR.alt;
		lienR.href = 'javascript:;';
		lienR.menu = this.menu;
		lienR.onclick = function() {
			EditStyle.removeMenu.apply(this.menu);
			return false;
		};

		lienR.appendChild(imgR);
		colonneR.appendChild(lienR);
		colonneR.id = 'spkClose';
	
		if(Outils.isArray(flotteurName))
			flotteurName = flotteurName.join('/');

		parentNodes[0] = this.flotteur;
		browser.menu = this.menu;
		browser.onchange = Outils.changeFlotteur;
		browser.id = 'spkNodeBrowser'
		colonneM.className = 'largeur';

		// Attribut les références vers les vrais éléments de la hiérarchie
		for(var i = 1; i < parents.length; i++)
			parentNodes[i] = parentNodes[i-1].parentNode;

		// Crée le menu de navigation dans les éléments parents (si cliquables)
		for(var i = 0; i < parents.length; i++)
			if(parentNodes[parents.length-i-1].onmousedown) {
				var element = parentNodes[parents.length-i-1];
				var option = document.createElement('option');
				var courant = Outils.isArray(parents[i]) ? parents[i].join('/') : parents[i];
				var display = window.getComputedStyle ? window.getComputedStyle(element, null).display : element.currentStyle.display;
				var libelleOption = document.createTextNode(courant + ' (' + (display == 'inline' ? 'I' : 'B') + ')');

				// Y'a-il un lien dans l'arborescence ?
				if(element.nodeName == 'A' && i != parents.length-1)
					unLien = option;

				// Sélection du flotteur courant
				if(courant == flotteurName)
					option.selected = true;

				option.value = parents.length - i;
				option.appendChild(libelleOption);

				browser.appendChild(option);
			}

		colonneM.appendChild(browser);

		ligne.appendChild(colonneL);
		ligne.appendChild(colonneM);
		ligne.appendChild(colonneR);
		ligne.id = 'spkBrowser';

		// Ajout du browser		
		this.menu.firstChild.appendChild(ligne);

		// Ajout dans la liste des selects du menu
		this.menu.selects.push(browser);

		// Accès direct au lien
		if(unLien)
			this.addEditLink(unLien);

		this.menu.browser = browser;
	},
	
	/** Ajout de la ligne d'accès direct au lien de l'arborescence */
	addEditLink: function(unLien) {
		ligne = document.createElement('tr');
		colonne = document.createElement('td');
		lien = document.createElement('a');
		lien.href = 'javascript:;';
		lien.onclick = function() { return false };

		colonne.colSpan = 3;
		colonne.className = 'largeur';
		colonne.leLien = unLien;
		colonne.onmousedown = function() {
			this.leLien.selected = true;
			this.leLien.parentNode.onchange();
		};

		var libelle = document.createTextNode(Langues.get('Editer le lien'));
		lien.appendChild(libelle);
		colonne.appendChild(lien);

		ligne.className = 'spkEditLink';
		ligne.appendChild(colonne);

		// Ajout de l'accès direct
		this.menu.firstChild.appendChild(ligne);
	},

	/** Ajoute un couple libellé / champ  */
	addPropriete: function(libelle, proprietes) {
		// Création des éléments pour une ligne de propriété du menu
		var ligne = document.createElement('tr');
		var colonne1 = document.createElement('th');
		var colonne2 = document.createElement('td');
		var champ, preChamp, postChamp;

		var choix = {
			'font-weight': { Gras: 'bold', Non: 'normal' },
			'font-style': { Italique: 'italic', Non: 'normal' },
			'text-decoration': { Oui: 'underline', Non: 'none' },
			'border-style': { Aucun: 'none', Plein: 'solid', Tirets: 'dashed' },
			'font-variant': { Majuscules: 'small-caps', 'Casse initiale': 'normal' },
			'text-align': { Gauche: 'left', Centre: 'center', Droite: 'right', 'Justifié': 'justify' },
			unites: ['px', 'em', '%']
		};
		
		// Un seul champ sur la ligne
		if(!Outils.isArray(proprietes))
			proprietes = [proprietes];


		/* LIBELLE */

		// Libellé dynamique (choix différent pour chacun des 4 côtés)
		if(/4c/i.test(proprietes[0])) {
			var libelleText = libelle;

			libelle = document.createElement('select');
			libelle.name = libelleText.replace(/[- ]+/g, '');
			libelle.onchange = Outils.changeLibelle;
			libelle.declencheur = this.flotteur;
			colonne2.id = libelle.name;

			var optionLibelle = document.createTextNode(libelleText);
			var option = document.createElement('option');
			option.value = '4c';
			option.appendChild(optionLibelle);
			libelle.appendChild(option);
			
			var card = ['top', 'right', 'bottom', 'left'];

			for(var i = 0; i < card.length; i++) {
				var optionLibelle = document.createTextNode(libelleText + ' (' + card[i] + ')');

				option = document.createElement('option');
				option.value = card[i];
				option.appendChild(optionLibelle);

				libelle.appendChild(option);
			}

			colonne1.appendChild(libelle);
			
			// Ajout dans la liste des selects du menu
			this.menu.selects.push(libelle);

		// Libellé simple
		} else {
			libelle = document.createTextNode(libelle);

			var label = document.createElement('label');
			label.htmlFor = 'spkChp' + Outils.propCSS2JS(proprietes[0]);
			label.appendChild(libelle);
			colonne1.appendChild(label);
		}

		ligne.appendChild(colonne1);


		/* PROPRIETES */

		// Parcours des/de la propriété(s)
		for(var i = 0; i < proprietes.length; i++) {
			preChamp = new Array();
			postChamp = new Array();

			// Elimination des indicateurs de côté (pr border, padding, margin, etc)
			laPropriete = proprietes[i].replace(/-(top|right|bottom|left|4c)/i, '');

			// La propriété se défini par des choix précis
			if(Outils.isset(choix[laPropriete])) {
				champ = document.createElement('select');
			
				// Paramétres
				champ.name = proprietes[i];
				champ.jsName = Outils.propCSS2JS(champ.name);
				champ.declencheur = this.menu.declencheur;
				champ.onchange = EditStyle.applyCSS;

				// Menu des choix
				for(var v in choix[laPropriete])
					if(!Outils.isFunction(choix[laPropriete][v])) {
						var option = document.createElement('option');
						var optionLibelle = document.createTextNode(Langues.get(typeof v == 'number' ? choix[laPropriete][v] : v));

						option.appendChild(optionLibelle);
						option.value = choix[laPropriete][v];

						champ.appendChild(option);
					}

				// Ajout dans la liste des selects du menu
				this.menu.selects.push(champ);

			// Choix libre (champ de texte)
			} else {
				champ = document.createElement('input');

				// Propriétés
				champ.type = 'text';
				champ.size = 10;
				champ.name = proprietes[i];
				champ.jsName = Outils.propCSS2JS(champ.name);
				champ.declencheur = this.menu.declencheur;
				champ.onfocus = function() { this.select() };
				champ.onchange = EditStyle.applyCSS;
			}
			
			// Par défaut, champ classique
			champ.spkFormat = 'classic';

			// Champ vers lequel pointera le label du libelle
			(i == 0 && Outils.isset(label)) ? champ.id = label.htmlFor : null;

			// Ajout du choix des unités & de la valeur auto
			if(/(width|height|size|margin|padding)/i.test(champ.jsName)) {
				var unites = document.createElement('select');
				unites.onchange = function() { this.previousSibling.onchange() }
				unites.className = 'spkUnite';
			
				// Menu des unités
				for(var u = 0; u < choix['unites'].length; u++) {
					var option = document.createElement('option');
					var optionLibelle = document.createTextNode(choix['unites'][u]);

					option.appendChild(optionLibelle);
					option.value = choix['unites'][u];

					unites.appendChild(option);
				}
			
				// Suppression de l'unité dans le champ
				champ.className = 'spkNombre';
				champ.size = 3;
				champ.spkFormat = 'number';
				
				// Ajout dans les postChamps
				postChamp.push(unites);
				
				// Ajout dans la liste du menu
				this.menu.champs.push(unites);
				
				// Ajout dans la liste des selects du menu
				this.menu.selects.push(unites);

				// Exclusion des champs qui ne peuvent pas avoir de taille auto
				champ.valeurAuto = !/(padding|border|font)/i.test(champ.name);

				// Ajout de la valeur auto
				if(champ.valeurAuto) {
					var checkbox = document.createElement('input');
					var labelAuto = document.createElement('label');
					var libelleAuto = document.createTextNode('auto');
				
					checkbox.className = 'spkCheckbox';
					checkbox.type = 'checkbox';
					checkbox.onclick = function() {
						var champ = this.parentNode.nextSibling;

						if(this.checked) {
							champ.style.display = 'none';
							champ.nextSibling.style.display = 'none';
							
							if(champ.nextSibling.nextSibling)
								champ.nextSibling.nextSibling.style.display = 'none';

							champ.value = 'auto';
							this.id = champ.id;
							champ.id = '';
							this.parentNode.style.display = 'inline';
						} else {
							champ.style.display = 'block';
							champ.nextSibling.nextSibling.style.display = 'block';
							champ.focus();
							champ.select();
							champ.id = this.id;
							this.id = '';
							this.parentNode.style.display = 'none';
						}
					};

					labelAuto.style.display = 'none';
					labelAuto.className = 'spkAuto';
					labelAuto.appendChild(checkbox);
					labelAuto.appendChild(libelleAuto);

					// Cas où on décoche Auto sans changer par la suite
					champ.onblur = function() {
						if(/auto/i.test(this.value)) {
							this.previousSibling.firstChild.checked = true;
							this.previousSibling.firstChild.onclick();
						}
					};
				
					// Ajout dans les preChamps
					preChamp.push(labelAuto);
					
					champ.title = Langues.get('Saisir un nombre ou la valeur auto');
				} else
					champ.title = Langues.get('Saisir un nombre');

			// Si c'est une couleur
			} else if(/color/i.test(champ.name)) {
				champ.onfocus = Outils.colorPicker;
				champ.className = 'spkColor';
				champ.readonly = true;
				champ.size = 7;
				champ.spkFormat = 'color';

				var colorPreview = document.createElement('input');
				colorPreview.onfocus = function() { this.previousSibling.onfocus() };
				colorPreview.className = 'spkColorPreview';
				colorPreview.readonly = true;
				
				// Ajout dans les postChamps
				postChamp.push(colorPreview);
			} else
				champ.spkFormat = 'string';

			// Ajout des preChamps (ex: valeur auto)
			if(!Outils.empty(preChamp))
				for(var j = 0; j < preChamp.length; colonne2.appendChild(preChamp[j++]));

			// Ajout du champ dans le td
			colonne2.appendChild(champ);
			colonne2.colSpan = 2;
				
			// Ajout des postChamps (ex: carré couleur, unités)
			if(!Outils.empty(postChamp))
				for(var j = 0; j < postChamp.length; colonne2.appendChild(postChamp[j++]));

			// Ajout du td dans le tr
			ligne.appendChild(colonne2);

			// Initialisation du champ
			EditStyle.loadInit.apply(champ);

			// Ajout dans la liste du menu
			this.menu.champs.push(champ);
		}

		// Style de la première ligne
		if(this.iLine == 0)
			ligne.id = 'spkFirst';

		// Affichage CSS
		if(++this.iLine%2)
			ligne.className = 'spkPropriete';

		// Ajout au menu
		this.menu.firstChild.appendChild(ligne);
	},
	
	/** Ajout d'une ligne de bréve explication */
	addNodeBrowserExplanation: function() {
		var ligne = document.createElement('tr');
		var colonne = document.createElement('td');
		var libelle = document.createTextNode(Langues.get('S\351lectionnez ci-dessus la port\351e de vos modifications'));

		colonne.colSpan = 3;
		colonne.className = 'largeur';
		
		// Ajout de la possibilité de retourner au noeud précédent
		if(Outils.historiquePointer > 0) {
			var lien = document.createElement('a');
			var libelleLien = document.createTextNode('\253 ' + Langues.get('Pr\351c.') + ' | ');

			lien.href = 'javascript:;';
			lien.title = Langues.get('Noeud pr\351c\351demment s\351lectionn\351');
			lien.menu = this.menu;
			lien.onclick = function() {
				Outils.history.call(this, -1);
				return false;
			};

			lien.appendChild(libelleLien);
			colonne.appendChild(lien);
		}
		
		colonne.appendChild(libelle);

		// Ajout de la possibilité de retourner au noeud suivant
		if(Outils.historiquePointer < Outils.historique.length-1) {
			var lien = document.createElement('a');
			var libelleLien = document.createTextNode(' | ' + Langues.get('Suiv.') + ' »');

			lien.href = 'javascript:;';
			lien.title = Langues.get('Noeud suivant s\351lectionn\351');
			lien.menu = this.menu;
			lien.onclick = function() {
				Outils.history.call(this, 1);
				return false;
			};

			lien.appendChild(libelleLien);
			colonne.appendChild(lien);
		}

		ligne.appendChild(colonne);
		ligne.className = 'spkOption';

		this.menu.firstChild.appendChild(ligne);
	},
	
	/** Création du menu de base */
	creerMenu: function() {

		// Création du menu de modification
		var menu = document.createElement('table');
		
		// Pour IE (ajout dans firstChild par la suite)
		var tbody = document.createElement('tbody');
		menu.appendChild(tbody);

		// Composition du menu
		menu.id = 'spinkbb';
		menu.declencheur = this.flotteur;
		menu.declencheur.paths = Outils.cheminAbsolu(this.flotteur);
		menu.style.left = menu.declencheur.coordonnees[0] + 'px';
		menu.style.top = menu.declencheur.coordonnees[1] + 'px';
		menu.champs = new Array();
		menu.selects = new Array();
		Affichage.opacity.call(menu, true);

		// Titre de la page
		var flotteurName = menu.declencheur.paths['arrayPath'].copieLast();
		document.title = 'SpinkBB[' + (Outils.isArray(flotteurName) ? flotteurName.join('/') : flotteurName) + '] - ' + Outils.documentTitle;

		this.menu = menu;
		
		// Ajout du navigateur de noeuds
		this.addBrowser();

		// Spécialisation du menu
		(this.flotteur.nodeName == 'A') ? this.menuLinks() : this.menuEdit();
	},

	/** Menu pour l'édition */
	menuEdit: function() {

		// Demande de rafraichissement des valeurs par défaut lorsque le flotteur n'est plus survolé
		if(/ A[.#]?[^ ]* /i.test(this.flotteur.paths['stringPaths'][0])) {
			this.flotteur.onmouseout = function() {
				if(Outils.flotteur == this)
					setTimeout('EditStyle.refreshMenu()', 200);
			};
		}
		
		// Ligne d'explication concernant le navigateur de noeuds
		this.addNodeBrowserExplanation();

		// Détermination du type de l'élément
		var proprietes = (this.flotteurStyle.display == 'inline') ? EditStyle.propInline : EditStyle.propBlock;
		this.isBlock = (this.flotteurStyle.display != 'inline');

		// Création du menu d'édition
		for(var element in proprietes)
			if(!Outils.isFunction(proprietes[element]))
				this.addPropriete(Langues.get(element), proprietes[element]);

		// Ajout du menu dans la page (si menuLinks ne l'a pas déjà ajouté)
		if(!Outils.isset(this.menu.parentNode) || /^#/.test(this.menu.parentNode.nodeName))
			document.body.appendChild(this.menu);

		// Remplacement des selects
		Affichage.replaceSelect.apply(this.menu);

		// Repositionnement
		if(Outils.repositionnement.apply(this.menu))
			this.menu.declencheur.coordonnees = [parseInt(this.menu.style.left), parseInt(this.menu.style.top)];
			
		// Fixage de la largeur du menu (pour la propriété border qui se coupe)
		if(this.isBlock && Outils.isset(this.menu.firstChild.lastChild.childNodes[1]) && this.menu.firstChild.lastChild.childNodes[1].offsetWidth < 222)
			this.menu.firstChild.lastChild.childNodes[1].style.width = '222px';

		// Style de la dernière ligne
		this.menu.firstChild.lastChild.id = 'spkLast';
	},

	/** Menu pour les liens */
	menuLinks: function() {
		var lienSuivre = document.createElement('a');
		var lienEditerF = document.createElement('a');
		var lienEditerS = document.createElement('a');

		lienSuivre.id = 'spkSuivre';
		lienEditerF.editStyle = this;
		lienEditerS.editStyle = this;
		
		lienSuivre.href = 'javascript:;';
		lienEditerF.href = 'javascript:;';
		lienEditerS.href = 'javascript:;';

		// Suivre le lien
		lienSuivre.onclick = function() {
			if(Outils.change) {
				ImportExport.httpr = 'window.location.href = Outils.flotteur.link;';
				ImportExport.saveInSession();
			} else
				window.location.href = Outils.flotteur.link;

			return false;
		};
	
		// Editer le style du lien à l'état fixe
		lienEditerF.onmousedown = function() {
			this.editStyle.viderMenu();
			this.editStyle.addEditLink(this.editStyle.menu.browser.options[this.editStyle.menu.browser.selectedIndex]);
			this.editStyle.menuEdit();
			return false;
		};

		// Editer le style du lien à l'état survolé			
		lienEditerS.onmousedown = function() {
			this.editStyle.viderMenu();
			this.editStyle.addEditLink(this.editStyle.menu.browser.options[this.editStyle.menu.browser.selectedIndex]);
			var courant = this.editStyle.menu.declencheur.paths['arrayPath'].copieLast();
		
			for(var p = 0; p < this.editStyle.menu.declencheur.paths['stringPaths'].length; p++)
				this.editStyle.menu.declencheur.paths['stringPaths'][p] += ':hover';
			
			if(Outils.isArray(courant))
				for(var p = 0; p < courant.length; p++)
					courant[p] = courant[p] += ':hover';
			
			this.editStyle.menuEdit();
			return false;
		};

		var libelleSuivre = document.createTextNode(Langues.get('Suivre le lien'));
		var libelleEditerF = document.createTextNode(Langues.get('Editer le style (\351tat fixe)'));
		var libelleEditerS = document.createTextNode(Langues.get('Editer le style (\351tat survol\351)'));
	
		var ligne = document.createElement('tr');
		var colonne = document.createElement('td');
		colonne.colSpan = 3;

		lienSuivre.appendChild(libelleSuivre);
		lienEditerF.appendChild(libelleEditerF);
		lienEditerS.appendChild(libelleEditerS);
		
		colonne.appendChild(lienSuivre);
		colonne.appendChild(lienEditerF);
		colonne.appendChild(lienEditerS);
	
		ligne.appendChild(colonne);
		this.menu.firstChild.appendChild(ligne);
		document.body.appendChild(this.menu);
		
		// Remplacement des selects
		Affichage.replaceSelect.apply(this.menu);

		// Repositionnement
		if(Outils.repositionnement.apply(this.menu))
			this.menu.declencheur.coordonnees = [parseInt(this.menu.style.left), parseInt(this.menu.style.top)];
	},

	/** Remise à vierge du menu */
	viderMenu: function() {
		var root = this.menu.firstChild; // '> 1' pour ne pas virer le navigateur de noeuds
		for(var i = root.childNodes.length; i > 1; root.removeChild(root.childNodes[--i]));
	}
};


/************************/
/** Méthodes de classe **/
/************************/

/** Enregistrement et application du changement de style (onchange) */
EditStyle.applyCSS = function() {
	if(this.value != '?' || !/4c/i.test(this.name)) {

		// Modification de 4 côtés à la fois
		if(/4c/i.test(this.jsName)) {
			var card = ['top', 'right', 'bottom', 'left'];
			this.is4c = true;

			if(this.value == '')
				this.delValue = true;

			// Changement de style pour chaque cardinalité			
			for(var i = 0; i < card.length; i++) {
				Outils.changeCard(this, card[i]);
				EditStyle.applyCSS.apply(this);
			}

			Outils.changeCard(this, '4c');
			this.delValue = false;
			this.is4c = false;

			return;

		// Changement de style
		} else {
			var declencheur = this.declencheur;
			this.value = Outils.setGeneric(this.value);
			var valeurAuto = (this.valeurAuto && this.value == 'auto');
			var delValue = Outils.isset(this.delValue) ? this.delValue : false;
			var is4c = Outils.isset(this.is4c) ? this.is4c : false;

			// Si aucune valeur n'est précisée : suppression de la régle
			if(this.value == '') {
				var valeur = this.value;
				delValue = true;

			// Sinon si c'est un nombre, mise au format
			} else if(this.spkFormat == 'number' && !valeurAuto) {
				this.value = isNaN(Outils.parseFloatFr(this.value)) ? 0 : Outils.parseFloatFr(this.value);

				if(this.nextSibling.value == '?') {
					this.nextSibling.value = 'px';
					Affichage.updateOption.apply(this.nextSibling);
				}

				var valeur = this.value + this.nextSibling.value;

			// Sinon aucun changement
			} else
				var valeur = this.value;

			// Regexp
			var regValeur = new RegExp('^' +  valeur + '$', 'i');

			// Parcours des sélecteurs
			for(var p = 0; p < declencheur.paths['stringPaths'].length; p++) {
				var selecteur = declencheur.paths['stringPaths'][p];

				// La régle existe déjà
				if(Outils.isset(EditStyle.GArrayStyles[selecteur])) {

					// Modification de la valeur (bien que onchange : casse) ?
					if(!Outils.isset(EditStyle.GArrayStyles[selecteur][this.name]) || !regValeur.test(EditStyle.GArrayStyles[selecteur][this.name])) {

						// Demande de suppression
						if(delValue) {
							EditStyle.delRule(selecteur, this.name);

							// Mise à jour avec les nouvelles valeurs attribuées
							if(!is4c || /-left/i.test(this.name))
								EditStyle.loadInit.apply(this);

							valeur = this.value;
						} else
							EditStyle.updateRule(selecteur, this.name, valeur);

						// Au moins une modification
						Outils.change = true;
					}
				} else {
					EditStyle.createRule(selecteur);
					EditStyle.updateRule(selecteur, this.name, valeur);

					// Au moins une modification
					Outils.change = true;
				}
			}

			// Couleur (mise à jour du petit carré)
			if(this.spkFormat == 'color')
				this.nextSibling.style.backgroundColor = this.value;

			// Mise à jour de la liste graphique
			if(/select/i.test(this.nodeName))
				Affichage.updateOption.apply(this);

			// Débugueur			
			/* alert(this.jsName + '\nvaleur:' + valeur + '\ndelValue: ' + delValue); */

			// Mises à jour mutuelles : modification d'un paramétre de bordure (uniquement pour left si c'est un enchainement 4c)
			if(/border/i.test(this.name) && (!this.is4c || /left/i.test(this.name))) {

				// Modification d'un style
				if(/style/i.test(this.name)) {
					var borderWidth = this;

					while(!/width/i.test(borderWidth.name))
						borderWidth = borderWidth.nextSibling;

					// Si on demande un style none XOR que la largeur est à 0
					if(/none/i.test(valeur) ? borderWidth.value != '0' : borderWidth.value == '0') {

						// Demande d'un style none : suppression de la régle pour la largeur
						if(/none/i.test(valeur)) {
							borderWidth.value = '';
							borderWidth.nextSibling.value = '';
							borderWidth.onchange();

						// Sinon réglage à 2px si on ne vient pas de supprimer la régle
						} else if(!delValue) {
							borderWidth.value = 2;
							borderWidth.nextSibling.value = 'px';
							borderWidth.onchange();
						}
					}

				// Modification d'une largeur
				} else if(/width/i.test(this.name)) {
					var borderStyle = this;

					while(!borderStyle.name || !/style/i.test(borderStyle.name))
						borderStyle = borderStyle.previousSibling;

					// Si on demande 0 (donc une largeur nulle) XOR que le style n'est pas none
					if((parseInt(valeur) == 0) ? borderStyle.value != 'none' : borderStyle.value == 'none') {

						// Demande d'une largeur nulle : suppression de la régle pour le style
						if(parseInt(valeur) == 0) {
							borderStyle.value = '';
							borderStyle.onchange();

						// Sinon ajout d'un style solid si on ne vient pas de supprimer la régle
						} else if(!delValue) {
							borderStyle.value = 'solid';
							borderStyle.onchange();
						}
					}
				}

				// Demande d'un style none ou d'une largeur nulle : suppression de la régle pour la couleur (si on ne vient pas de supprimer la régle)
				if((/none/i.test(valeur) || parseInt(valeur) == 0) && !delValue) {
					var borderColor = this;

					while(!borderColor.name || !/color/i.test(borderColor.name))
						borderColor = /width/i.test(this.name) ? borderColor.previousSibling : borderColor.nextSibling;

					// Si une régle a déjà été créé pour cette propriété
					borderColor.value = '';
					borderColor.nextSibling.style.backgroundColor = '#CCC';
					borderColor.onchange();
				}
			}

			// Affichage de la case Auto
			if(valeurAuto && this.previousSibling)
				this.onblur();
		}
	}
};

/** Destruction du menu en cours et libération du flotteur */
EditStyle.removeMenu = function() {
	document.title = Outils.documentTitle;
	document.body.removeChild(this);
	this.declencheur.style.backgroundColor = '';
	delete Outils.flotteur;
};

/** Matérialisation des potentiels flotteurs */
EditStyle.setVisible = function(visible) {
	if(Outils.potentialFlotteur)
		if(visible)
			Outils.potentialFlotteur.style.backgroundColor = 'green';
		else {
			Outils.potentialFlotteur.style.backgroundColor = '';
			Outils.potentialFlotteur = false;
		}
};

/** Initialisation des valeurs par défaut du champ */
EditStyle.loadInit = function() {

	// Prise en compte des styles HOVER du lien si on est dans ce cas
	var flotteurStyle = / A[.#]?[^:]*:HOVER$/i.test(this.declencheur.paths['stringPaths'][0]) ? this.declencheur.stylesHover : this.declencheur.flotteurStyle;

	/* Gestion des 4c */

	// Champ de modification des 4 côtés à la fois
	if(/4c/i.test(this.name)) {
		var c = 0;
		var card = ['top', 'left', 'bottom', 'right'];
		var reg = new RegExp('-(top|right|bottom|left|4c)', 'i');

		do { // Valeur de la propriété communes à tous les côtés ?
			oldValeur = valeur;
			valeur = eval('flotteurStyle.' + Outils.propCSS2JS(this.name.replace(reg, '-' + card[c++])));
			(c == 1) ? oldValeur = valeur : null;
		} while(c < card.length && valeur == oldValeur);

		// La valeur de cette propriété n'est actuellement pas commune à tous les côtés
		if(c != card.length || valeur != oldValeur) {

			// Liste de choix ou Nombre
			if(/select/i.test(this.nodeName) || this.spkFormat == 'number') {
				var option = document.createElement('option');
				var libelleOption = document.createTextNode('?');

				option.value = '?';
				option.className = 'spkIndefini';
				option.appendChild(libelleOption);

				// Liste de choix
				if(/select/i.test(this.nodeName))
					var select = this;

				// Nombre
				if(this.spkFormat == 'number') {
					var select = this.nextSibling;
					this.value = '?';
				}

				select.insertBefore(option, select.firstChild);
				select.firstChild.selected = true;
				
				// Mise à jour de la liste graphique
				Affichage.updateOption.apply(select);
			} else
				this.value = '?';
			
			// Couleur
			if(this.spkFormat == 'color')
				this.nextSibling.style.backgroundColor = '#CCC';
				
			// Avortement de la fonction
			return;
			
		// Propriété commune : on initiale avec les valeurs de top (par exemple)
		} else
			var valeur = Outils.setGeneric(flotteurStyle[this.jsName.replace(/4c/i, 'Top')]);

	} else
		// Valeur actuelle de la propriété gérée par le champ
		var valeur = Outils.setGeneric(this.jsName == 'backgroundColor' ? this.declencheur.backgroundColor : flotteurStyle[this.jsName]);


	/* Initialisations */

	// Liste de choix
	if(/select/i.test(this.nodeName)) {

		// Suppression du choix indéfini éventuellement ajouté par un 4c
		if(this.firstChild.value == '?')
			this.removeChild(this.firstChild);

		// Sélection du choix actuel
		for(var i = 0; i < this.childNodes.length; i++)
			this.childNodes[i].selected = (this.childNodes[i].value == valeur);

		// Mise à jour de la liste graphique
		Affichage.updateOption.apply(this);
		
	// Nombre (séparation de l'unité)
	} else if(this.spkFormat == 'number') {

		// Suppression du choix indéfini éventuellement ajouté par un 4c
		if(this.nextSibling.firstChild.value == '?')
			this.nextSibling.removeChild(this.nextSibling.firstChild);

		if(valeur != 'auto') {
			var nombre = Outils.parseFloatFr(valeur);
			var unite = valeur.replace(nombre, '');
			var unites = this.nextSibling.childNodes;

			// Sélection de l'unité actuelle
			for(var i = 0; i < unites.length; i++)
				unites[i].selected = (unites[i].value == unite);

			// Valeur auto
			if(Outils.isset(this.previousSibling) && this.previousSibling.className == 'spkAuto' && this.previousSibling.firstChild.checked) {
				this.previousSibling.firstChild.checked = false;
				this.previousSibling.firstChild.onclick();
			}
				
			// Mise à jour de la liste graphique
			Affichage.updateOption.apply(this.nextSibling);

			this.value = nombre;
		} else {
			this.value = 'auto';
			this.nextSibling.firstChild.selected = true;
			this.onblur();
		}

	// Champ simple
	} else
		this.value = valeur;

	// Couleur (mise à jour du petit carré)
	if(this.spkFormat == 'color') {
		this.value = (typeof this.value != 'number' && this.value != 'transparent') ? this.value.toUpperCase() : this.value;
		this.nextSibling.style.backgroundColor = this.value;
	}
};

/** Création d'une régle CSS */
EditStyle.createRule = function(selecteur) {
	var sheet = document.styleSheets[Parametres.stylesheet];

	if(sheet.insertRule)
		sheet.insertRule(selecteur + '{}\n', sheet.cssRules.length);
	else if(sheet.addRule)
		sheet.addRule(selecteur, ' ');
	
	if(!Outils.isset(EditStyle.GArrayStyles[selecteur]))
		EditStyle.GArrayStyles[selecteur] = new Array();
		
	EditStyle.GArrayStyles[selecteur]['cssRule'] = EditStyle.lastRule();
};

/** Modification d'une régle CSS */
EditStyle.updateRule = function(selecteur, nom, valeur) {
	var sheet = document.styleSheets[Parametres.stylesheet];
	var regle = sheet.rules ? sheet.rules[EditStyle.GArrayStyles[selecteur]['cssRule']] : sheet.cssRules[EditStyle.GArrayStyles[selecteur]['cssRule']];

	regle.style[Outils.propCSS2JS(nom)] = valeur;
	EditStyle.GArrayStyles[selecteur][nom] = valeur; // Inutile en cas d'import
};

/** Suppression d'une régle CSS (sans décaler les index) */
EditStyle.delRule = function(selecteur, nom) {
	var sheet = document.styleSheets[Parametres.stylesheet];
	var regle = sheet.rules ? sheet.rules[EditStyle.GArrayStyles[selecteur]['cssRule']] : sheet.cssRules[EditStyle.GArrayStyles[selecteur]['cssRule']];

	regle.style[Outils.propCSS2JS(nom)] = '';
	delete EditStyle.GArrayStyles[selecteur][nom];
};

/** Dernière régle créée */
EditStyle.lastRule = function() {
	var sheet = document.styleSheets[Parametres.stylesheet];
	return (sheet.rules ? sheet.rules.length : sheet.cssRules.length) - 1;
};

/** Rafraichissement des valeurs par défaut quand le flotteur n'est plus survolé */
EditStyle.refreshMenu = function() {
	var champs = document.getElementById('spinkbb').champs;
	for(var c = 0; c < champs.length; Outils.isset(champs[c++].spkFormat) ? EditStyle.loadInit.apply(champs[c-1]) : null);
	
	// Rétablissement de l'événement onmouseout pour la localisation du flotteur
	Outils.flotteur.onmouseout = function() {
		if(!Outils.isset(Outils.flotteur) && typeof Outils.isset(Outils.potentialFlotteur) && Outils.potentialFlotteur != false)
			EditStyle.setVisible(false);
	};
};

