Niveau
..........
En rapport...

Quoi

Prenons un span normal. Lorsqu'on clique dessus, il se transforme en zone de saisie de texte et lorsqu'on sort de cette zone de saisie, le <span> revient, avec son nouveau contenu.
Je vais décrire ici la méthode pour faire ceci.
Exemple fonctionnel : editinplace.htm

Ma méthode est adapté aux span mais peu s'adapter a n'importe quelle balise. Par exemple, pour les div faire juste un “Remplacer tout” de “span.” par “div.”

Principe

On va attacher un évènement “onclick” aux <span> qui on la classe CSS “editinplace”. Cet évènement va appeler une fonction qui va remplacer le contenu du span par un textarea auquel on va attacher l'évènement “onblur”. Ainsi, lorsqu'on quitte le textarea, un fonction va mettre la valeur du textarea dans le <span>. Le textarea va donc disparaitre et laisser place à la nouvelle valeur.

Code

javascript
addEvent(window,'load',EditInPlace);
function EditInPlace() {
	var v=getElementsBySelector("span.editinplace");
	var l=v.length;
	for(i=0;i<l;i++)
		addEvent(v[i],'click',ShowEditInPlace);
}
function ShowEditInPlace() {
	removeEvent(this,'click',ShowEditInPlace);
	this.id="editinplace_inprogress";
	var inner=replace(this.innerHTML,"<br>","\n");
	inner=replace(inner,"<BR>","\n");
	this.innerHTML='<textarea class="editinplace">'+inner+'</textarea>';
	var v=getElementsBySelector("textarea.editinplace");
	var l=v.length;
	for(i=0;i<l;i++) {
		v[i].focus();
		addEvent(v[i],'blur',HideEditInPlace);
	}
}
function HideEditInPlace() {
	var e=document.getElementById('editinplace_inprogress');
	e.innerHTML=replace(this.value,"\n","<br />");
	e.id='';
	addEvent(e,'click',ShowEditInPlace);
}
function addEvent( obj, type, fn ) {
//John Resig : http://ejohn.org/projects/flexible-javascript-events/
	if ( obj.attachEvent ) {
		obj['e'+type+fn] = fn;
		obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
		obj.attachEvent( 'on'+type, obj[type+fn] );
	} else
		obj.addEventListener( type, fn, false );
}
function removeEvent( obj, type, fn ) {
//John Resig : http://ejohn.org/projects/flexible-javascript-events/
	if ( obj.detachEvent ) {
		obj.detachEvent( 'on'+type, obj[type+fn] );
		obj[type+fn] = null;
	} else
		obj.removeEventListener( type, fn, false );
}
function getElementsBySelector(selector){
//Extracted from nifty.js
	var i,selid="",selclass="",tag=selector,f,s=[],objlist=[];
	if(selector.indexOf(" ")>0){  //descendant selector like "tag#id tag"
		s=selector.split(" ");
		var fs=s[0].split("#");
		if(fs.length==1) return(objlist);
		f=document.getElementById(fs[1]);
		if(f) return(f.getElementsByTagName(s[1]));
		return(objlist);
	}
	if(selector.indexOf("#")>0){ //id selector like "tag#id"
		s=selector.split("#");
		tag=s[0];
		selid=s[1];
    }
	if(selid!=""){
		f=document.getElementById(selid);
		if(f) objlist.push(f);
		return(objlist);
    }
	if(selector.indexOf(".")>0){  //class selector like "tag.class"
		s=selector.split(".");
		tag=s[0];
		selclass=s[1];
    }
	var v=document.getElementsByTagName(tag);  // tag selector like "tag"
	if(selclass=="")
		return(v);
	for(i=0;i<v.length;i++){
		if(v[i].className.indexOf(selclass)>=0)
			objlist.push(v[i]);
    }
	return(objlist);
}
function replace(string,text,by) {
	// Replaces text with by in string
    var strLength = string.length, txtLength = text.length;
    if ((strLength == 0) || (txtLength == 0)) return string;
    var i = string.indexOf(text);
    if ((!i) && (text != string.substring(0,txtLength))) return string;
    if (i == -1) return string;
    var newstr = string.substring(0,i) + by;
    if (i+txtLength < strLength)
        newstr += replace(string.substring(i+txtLength,strLength),text,by);
    return newstr;
}

Utilisation

Il suffit de placer ce code dans vos page et de mettre la classe “editinplace” aux <span> a rendre éditable. ex:

html4strict
<span class="editinplace">J'édite</span>

Un peu de style

Vois pouvez définir un style pour les span éditable ainsi que pour les textarea.
Pour ce faire définissez les style suivants : span.editinplace et textarea.editinplace.
Ex :

css
span.editinplace {
	border-bottom:1px dashed #000
}
textarea.editinplace {
	border:1px dashed #000;
	border-bottom:0
}

Aller plus loin

Éditer sans sauvegarder n'est pas fort utile. On pourrais imaginer un système de sauvegarde par cookie ou par AJAX.
Si quelqu'un le développe, ça serais sympa de nous en faire profiter :)


iDo 27/12/2005 13:32

Discussion

ChoiZ, 28/01/2007 21:35:

Dans la fonction HideEditInPlace()

J’ai ajouter :

javascript
	var datasend=replace(this.value,"\n","<br />");
	insert(datasend);

Puis j’ai fait ma fonction insert :

javascript
function insert(datasend) {
	sendData('data='+datasend, 'update.php', 'GET')
}

Et j’ai utilisé une fonction toute faite du site (http://qwix.media-box.net/index.php/2005/01/21/45-XmlhttprequestEtPhp) :

javascript
/**
* Permet d'envoyer des données en GET ou POST en utilisant les XmlHttpRequest
*/
function sendData(data, page, method)
{
    if(document.all)
    {
        //Internet Explorer
        var XhrObj = new ActiveXObject("Microsoft.XMLHTTP") ;
    }//fin if
    else
    {
        //Mozilla
        var XhrObj = new XMLHttpRequest();
    }//fin else
    
    //définition de l'endroit d'affichage:
    var content = document.getElementById("contenu");
    
    //si on envoie par la méthode GET:
    if(method == "GET")
    {
        if(data == 'null')
        {
            //Ouverture du fichier sélectionné:
            XhrObj.open("GET", page);
        }//fin if
        else
        {
            //Ouverture du fichier en methode GET
            XhrObj.open("GET", page+"?"+data);
        }//fin else
    }//fin if
    else if(method == "POST")
    {
        //Ouverture du fichier en methode POST
        XhrObj.open("POST", page);
    }//fin elseif
 
    //Ok pour la page cible
    XhrObj.onreadystatechange = function()
    {
        if (XhrObj.readyState == 4 && XhrObj.status == 200)
            content.innerHTML = XhrObj.responseText ;
    }    
 
    if(method == "GET")
    {
        XhrObj.send(null);
    }//fin if
    else if(method == "POST")
    {
        XhrObj.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        XhrObj.send(data);
    }//fin elseif
}//fin fonction SendData

Maintenant vous devez faire votre page php (update.php) qui enregistrera data soit dans une base sql un fichier texte ou autre... :)

php
<?
echo $_GET['data'];
?>
 
IWK, 10/04/2007 19:37:

Bonjour,

le débug me donne ceci qd c’est sensé enregistrer la saisie dans la bdd

content has no properties onreadystatechange()ajax.js (line 44) sendData(”data=bonjourr”, “update.php”, “GET”)ajax.js (line 49) insert(”bonjourr”)edit.js (line 105) HideEditInPlace()edit.js (line 36) [Break on this error] content.innerHTML = XhrObj.responseText ;

Ajax.js etant la fonction plus haut :)

 
iDo, 12/04/2007 09:45:

la fonction sendData prend le contenu du champs qui a pour id “contenu” et l’envois a ton php.
A mon avis, tu n’a pas de champs avec l’id “contenu”.

 
Si vous ne pouvez pas lire les lettres, tlchargez ce fichier WEV et coutez les.