11488 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

Dans une interface d'admin, je cherche à faire pour plusieurs partie un uploader d'image. Mais sans succès, je veux éviter le classique upload input file que je sais faire en php.

J'ai 2 sections nécessitant l'upload d'image (localisation et acces). Pour localisation, je peux mettre 3 fichiers maximum qui seront nommé "loc_" + code + "_" + numImage +".jpg" stocké dans un répertoire img\localisation

dans le même principe pour Acces mais 1 seul image.

Pour ce faire dans l'interface, on voit les images de chaque section, si non présente, j'ai une image indiquant "pas d'image, cliquez ici pour ajouter", et je voudrais donc lorsque l'on clique sur l'image que l'on ai la "pop up" pour parcourir sont explorateur et sélectionner le fichier à envoyer (avec restriction sur les tailles d'image), upload se fait directement en ajax (pas de jQuery) et elle s'affiche à la place de l'ancienne.

Je bute donc à partir de la partie "onClick" sur l'image. Voici le code que j'ai fait, généré via Php comme exemple de départ.


<div>Localisation</div>
<img id="loc_53_1" onclick="upload();" src="http://serveur/img/localisation/nolocalisation.png"  />
<img id="loc_53_2" onclick="upload();" src="http://serveur/img/localisation/nolocalisation.png"  />
<img id="loc_53_3" onclick="upload();" src="http://serveur/img/localisation/nolocalisation.png"  />
<div>Accès</div>
<img id="acces_53_1" src="serveur/img/acces/noacces.png"  />	


Merci de votre aide, j'en ai bien besoin.
Je ne suis pas persuadé qu'il soit possible d'ouvrir la page d'upload de cette manière (question sécurité).

En général on retrouve 2 solutions.

1. flash ...
2. mettre un élément au dessus d'un "input file" (qui le cache) et en cliquant sur l'élément au dessus, on clic indirectement sur le "input file" qui ouvre le "pop up" dont tu parles.

Il y a peut-être d'autres solutions depuis mes dernières recherches (html5 etc ?)
Ce sont les utilisateurs de la société des différentes agences qui seront amené à mettre à jour leur site).

- Flash : non, ce sera refusé.
- Pour l'image par dessus, je viens de tenté avec un collègue, on a des clics possibles en dehors de la zone d'image, même en fixant la même taille au input file que l'image (donc vu que les images vont être côte à côte ça risque d'être "folklorique" l'utilisateur qui clic sur l'image 2 mais ça ouvre le input de l'image 1 Smiley cligne

J'ai regardé du côté du drag & drop car là il n'y a pas vraiment de parcours, mais je risque d'avoir des incompatibilités navigateur. (je veux m'éviter d'avoir des appels pour cette appli, c'est pour libérer du temps aux développeurs (nous) que l'on veut que les utilisateurs gère eux même leur site)

Ne peux t'on pas via un javascript "onclick" sur l'image faire comme ci un clic avait été fait sur le input file (qui serait en display:hidden) ?

après ceci c'est toute la partie javascript "ajax" qui va me bloquer, mais une étape à la fois Smiley cligne
Je viens de tomber sur un exemple sur le net qui semble marcher pour dériver l'appel du clic, je vais tenter de l'inclure dans mon code général pour voir en ne conservant que le strict nécessaire, il restera la partie la plus dur, l'ajax pour indiquer à l'utilisateur que l'image va vers le serveur (l'image habituel ajax qui tourne au centre de l'ancienne image) et le chargement de la nouvelle image une fois l'upload fait (avec le move et renommage du fichier)
en gros le click sur l'image devrais passer son "id" car il correspond au nom du fichier à créer Smiley cligne et utile aussi pour retrouver l'image à reloader via le getElementById.


<HTML>
<HEAD>
<TITLE></TITLE>
<script type="text/javascript">
function choix()
{	frm.res.click();
frm.fic.click();
alert ( frm.fic.value ) ; }
</script>
</HEAD>
<BODY>
<form	name="frm"
style="display:'none'">
<input	type="file"
name="fic">
<input	type="reset"
name="res">
</form>
<img	src="exemple.gif"
onclick="choix();">
</BODY></HTML>
je viens d'arriver à faire ceci, j'ai du mettre un style pour cacher l'input file via le visibility et non le display qui le rendait inaccessible. bon j'ai un décalage quand même du fait que la place et toujours "présente" avec le visibility...

à suivre...


<HTML>
<HEAD>
<TITLE></TITLE>
<script type="text/javascript">
function choix(a)
{	
frm.fic.click();
alert(a);
}
</script>
</HEAD>
<BODY>
<form name="frm">
<input type="file"name="fic" style="margin:-1000px;border:solid red 1px;">
</form>
<img id="toto" src="http://server/img/localisation/nolocalisation.png" onclick="choix(this.id);">
</BODY></HTML>
Bonjour,

J'avance un peu, je retourne sur ce projet pour cette après midi (.Net au matin, Php/js l’après midi) mais je n'ai pu n’empêcher de travailler hier soir chez moi. J'ai avancé, j'avance étape par étape pour comprendre sans recopier bêtement. J'ai donc dût utiliser la technique de l'iframe, je voit pas ce qu'il y a d'ajax dedans... il me semblait que l'ajax comporté "XMLHttpRequest".
Ou alors je suis mal parti, mais je ne vois/trouve pas comment faire autrement.

ci dessous le code actuel (je sais j'ai des appels intermédiaires, mais l'optimisation c'est en dernier, ce sont des restes)



<html>
<head>
</head>
<body>
<script>
function envoi(id)
{
	//alert(id);
	frm.elements['sender'].value=id;
	frm.upload.click();
	//a=frm.elements['sender'].value;
	//alert(a)
}

function startUpload(idSender)
{
alert('sender value : '+ sender);
//frm.submit();
ajaxUpload(idSender);
}

function loadiframe()
{
	alert('iframe chargée');
}

<!-- Code pour ajax -->
function isWebKit(){
	return RegExp(" AppleWebKit/").test(navigator.userAgent);
}

function ajaxUpload(idSender)
{
	//alert('ajax upload');
	var detectWebKit = isWebKit();
	//alert('Retour var : '+ detectWebKit);
	
	var elSenderClic = document.getElementById(idSender);
	var frm_elSenderClic = elSenderClic.parentNode; // Form incluant l'image cliqué (il ne faut pas de balise intermediaire)
	alert(frm_elSenderClic);
	
	var iframe = document.createElement("iframe");
	iframe.setAttribute("id","ajax-temp");
	iframe.setAttribute("name","ajax-temp");
	iframe.setAttribute("width","0");
	iframe.setAttribute("height","0");
	iframe.setAttribute("border","0");
	iframe.setAttribute("style","width: 0; height: 0; border: none;");
	iframe.setAttribute("onload","loadiframe();");
	//form.parentNode.appendChild(iframe);
	frm_elSenderClic.parentNode.appendChild(iframe)
	window.frames['ajax-temp'].name="ajax-temp";
	alert('pause');
}


</script>
<form name="frm" action="upload.php"  method="post" enctype="multipart/form-data" onsubmit="startUpload();" >
<input id="upload" type="file" onChange="startUpload(frm.elements['sender'].value);" />
<input id="sender" type="hidden" value="14" />
<br>
<img id="monimage" src="pun1.png" onclick="envoi(this.id);"/>
<img id="monimage2" src="pun0.png" onclick="envoi(this.id);"/>
</form>
</body>
</html>

Toujours pour des questions de sécurité, il n'est pas possible de faire un upload en Ajax. D'où l'utilisation d'une iframe pour envoyer le formulaire d'upload vers une page qui chargera l'image puis dira à la page de départ que l'upload c'est bien passé.
Bonjour,

Je souhaite moi aussi me libérer de l'affreux bouton parcourir. Je cache l'input type file (display : none; ce qui ne semble pas le "désactiver" après essais) et au clique du label à l'aide d'un trigger jquery, je simule le clic sur le bouton parcourir. Mais j'ai un problème avec ie. Tu peux retrouver mon sujet via cette recherche "simuler clic sur input type file"

Je pense que si tu trouves la solution ou si je la trouve, ça résoudra notre problème.

Bon courage
- gemcod, je viens de lire ton post avant de revenir dans le mien, je n'ai pas d'ie 9 pour tester, sinon mon précédent post ouvre le parcours à partir d'une image cliquer puis envoi le formulaire (j'ai juste un input qui contient qui a émis l'action du clic, car j'en ai besoin), base toi sur mon code.

Sinon pour mon problème, j'ai avancé mais là je suis bloqué au niveau des "retours". je m'explique :
- Lors que je clic sur l'image, celle-ci doit être remplacer (voir superposer) par un cercle qui tourne (chargement) j'ai réussi à le faire mais l'image n'étant pas de la même taille que celle sur laquelle on clic elle apparaît plus bas, le mieux serai qu'elle s'affiche par au dessus).
- Je voulais juste retourner l'url de l'image une fois l'upload fait, mais voilà que faire en cas d'erreur, il faudrait mettre un message (il me faudrait donc 2 zones à mettre à jour, l'une l'image elle même, l'autre pour les message d'erreur)

Voici le code actuel :


<html>
<head>
</head>
<body>
<script>
function envoi(id)
{
	//alert(id);
	frm.elements['sender'].value=id;
	frm.upload.click();
	//a=frm.elements['sender'].value;
	//alert(a)
}
function $m(theVar){
	return document.getElementById(theVar)
}

function remove(theVar){
	var theParent = theVar.parentNode;
	theParent.removeChild(theVar);
}

function addEvent(obj, evType, fn){
	if(obj.addEventListener)
	    obj.addEventListener(evType, fn, true)
	if(obj.attachEvent)
	    obj.attachEvent("on"+evType, fn)
}
function removeEvent(obj, type, fn){
	if(obj.detachEvent){
		obj.detachEvent('on'+type, fn);
	}else{
		obj.removeEventListener(type, fn, false);
	}
}

function startUpload(idSender)
{
alert('sender value : '+ sender);
//frm.submit();
ajaxUpload(idSender);
}

function loadiframe()
{
	alert('iframe chargée');
}

<!-- Code pour ajax -->
function isWebKit(){
	return RegExp(" AppleWebKit/").test(navigator.userAgent);
}

function ajaxUpload(idSender)
{
	//alert('ajax upload');
	var detectWebKit = isWebKit();
	//alert('Retour var : '+ detectWebKit);
	
	var elSenderClic = document.getElementById(idSender);
	var elSuivi = document.getElementById('upload_area');
	var frm_elSenderClic = elSenderClic.parentNode; // Form incluant l'image cliquer (il ne faut pas de balise intermediaire)
	alert(frm_elSenderClic);
	
	var iframe = document.createElement("iframe");
	iframe.setAttribute("id","ajax-temp");
	iframe.setAttribute("name","ajax-temp");
	iframe.setAttribute("width","0");
	iframe.setAttribute("height","0");
	iframe.setAttribute("border","0");
	iframe.setAttribute("style","width: 0; height: 0; border: none;");
	//iframe.setAttribute("onload","loadiframe();");
	
	//form.parentNode.appendChild(iframe);
	frm_elSenderClic.parentNode.appendChild(iframe)
	window.frames['ajax-temp'].name="ajax-temp";
	alert('pause');
	var doUpload = function()
	{
		removeEvent($m('ajax-temp'),"load", doUpload);
		var cross = "javascript: ";
		cross += "window.parent.$m('"+idSender+"').src = 'spinner.gif'; void(0);";
		//cross += "window.parent.$m('upload_area').innerHTML = document.body.innerHTML; void(0);";
		//$m('upload_area').innerHTML = html_error_http;
		$m('ajax-temp').src = cross;
		
		alert(cross);
		
		if(detectWebKit){
        	remove($m('ajax-temp'));
        }else{
        	setTimeout(function(){ remove($m('ajax-temp'))}, 250);
        }
		
	}
	//iframe.setAttribute("onload","doUpload");
	addEvent($m('ajax-temp'),"load", doUpload);
	frm_elSenderClic.setAttribute("target","ajax-temp");
	frm_elSenderClic.submit();
}


</script>
<form name="frm" action="upload.php"  method="post" enctype="multipart/form-data" >
<input id="upload" type="file" onChange="ajaxUpload(frm.elements['sender'].value);return false;" />
<input id="sender" type="hidden" value="14" />
<br>
<img id="monimage" src="nolocalisation.png" onclick="envoi(this.id);"/>
<img id="monimage2" src="nolocalisation.png" onclick="envoi(this.id);"/>
</form>
<div id="upload_area">
ICI
</div>
</body>
</html>
note : Dans ma réponse, j'utilise Jquery

Puisque tu cliques sur une image, tu connais forcément sa hauteur. Tu peux donc remplacer l'élément img par un élément en "display: inline-block" avec une image de fond positionnée en css via javascript.
Autre solution, tu remplaces l'image par ton image de loader elle même placée dans une balise en inline-block avec hauteur spécifiée. Ensuite tu peux mettre l'image en vertical-align :middle
Enfin, une fois ton retour terminé, tu peux écrire le message à la place de ton image ou à côté (au dessus, en dessous, etc) en récupérant les coordonnées de positionnement de celle-ci. Par exemple, si ton image est position.left : 100 et position.top : 200, ton message d'erreur sera placé dans un élément en position absolute mobilisant ces coordonnées modifiées de la hauteur du message d'erreur (il est possible de récupérer la hauteur avec Element.height)

Sinon, je n'arrive pas à voir en quoi ton chargement d'image pourrait m'aider (peut être que je ne le comprends pas bien). En fait dans mon cas, lorsque je clique sur l'envoi du formulaire, mon champ file se vide et il ne se passe plus rien.
Modifié par gemcod (21 Nov 2011 - 13:40)
Bon j'avance... encore un peu de travail, je viens de remettre en forme une partie, en supprimant certains tests et modifier (à ma sauce Smiley cligne ), j'ai maintenant 3 fichiers, pour les tests je modifie le retour du php et j'ai mis une tempo pour avoir le temps du retour php pour voir le code généré.


<html>
<head>

<style> 
.AjxLoading { 
background:url('spinner.gif')50% 50% no-repeat;
}
.Err{background-color:#FFD5D5;color:red;}

</style> 
<script language="javascript" src="upload.js"></script>
</head>
<body>
<form id="frm" name="frm" action="upload.php"  method="post" enctype="multipart/form-data" >
<input id="upload" type="file" onChange="ajaxUpload(frm.elements['sender'].value);return false;" />
<input id="sender" type="hidden" value="14" />
<br>
<img id="monimage" src="nolocalisation.png" onclick="uploadNewImg(this.id);"/>
<img id="monimage2" src="nolocalisation.png" onclick="uploadNewImg(this.id);"/>
</form>
</body>
</html>



var ofrm = null;
var oSender = null;

function $m(id){return document.getElementById(id)}
function remove(obj){obj.parentNode.removeChild(obj)}
function isWebKit(){return RegExp(" AppleWebKit/").test(navigator.userAgent);}

function defondu(obj,ysnRemove){
	var i=1;
    var f = function()
		{
		obj.style.opacity = i;
		i = i-0.02;
		if(i>=0)
			setTimeout(f,20);
		else
			remove(obj);
  };
  f();
}

function addEvent(obj, evType, fn){
	if(obj.addEventListener)
	    obj.addEventListener(evType, fn, true)
	if(obj.attachEvent)
	    obj.attachEvent("on"+evType, fn)
}
function removeEvent(obj, type, fn){
	if(obj.detachEvent){
		obj.detachEvent('on'+type, fn);
	}else{
		obj.removeEventListener(type, fn, false);
	}
}

function uploadOk(id,src)
{
	remove($m('ajxWait'));
	$m(id).src=src;
}

function errorUpload(txt)
{
	remove($m('ajxWait'));
	
	divTmp=document.createElement("div");
	divTmp.setAttribute("id","uploadErr");
	divTmp.className="Err";
	divTmp.innerHTML=txt;
	ofrm.insertBefore(divTmp,ofrm.firstElementChild);
	setTimeout(function(){ defondu(divTmp,1);}, 4000)	
}

function uploadNewImg(id)
{
	frm.elements['sender'].value=id;
	frm.upload.click();
}


function ajaxUpload(idSender)
{
	var detectWebKit = isWebKit();
	// Recuperation des tags
	oSender = document.getElementById(idSender);
	//var elSuivi = document.getElementById('upload_area');
	ofrm = oSender.parentNode; // Form incluant l'image cliquer (il ne faut pas de balise intermediaire)
	
	// Creation du div d'attente
	divTmp=document.createElement("div");
	divTmp.setAttribute("id","ajxWait");
	divTmp.style.position="absolute";
	divTmp.style.width=oSender.width;
	divTmp.style.height=oSender.height;
	divTmp.style.top=oSender.y;
	divTmp.style.left=oSender.x;
	divTmp.className="AjxLoading";  	
	ofrm.appendChild(divTmp);
	
	// Creation de l'iframe pour l'envoi du fichier
	var iframe = document.createElement("iframe");
	iframe.setAttribute("id","ajax-temp");
	iframe.setAttribute("name","ajax-temp");
	iframe.setAttribute("width","0");
	iframe.setAttribute("height","0");
	iframe.setAttribute("border","0");
	iframe.setAttribute("style","width: 0; height: 0; border: none;");
	ofrm.parentNode.appendChild(iframe);
	
	
	var doUpload = function()
	{
		removeEvent($m('ajax-temp'),"load", doUpload);
		var cross = "javascript: ";
		//cross += "window.parent.$m('"+idSender+"').src = 'spinner.gif'; void(0);";
		cross += "window.parent.$m('upload_area').innerHTML = document.body.innerHTML; void(0);";
		//$m('upload_area').innerHTML = html_error_http;
		//$m('ajax-temp').src = cross;
		
		//alert(cross);
		//alert('tmp');
		
		if(detectWebKit){
        	remove($m('ajax-temp'));
        }else{
        	setTimeout(function(){ remove($m('ajax-temp'))}, 250);
        }
		
	}
	
	addEvent($m('ajax-temp'),"load", doUpload);
	ofrm.setAttribute("target","ajax-temp");
	ofrm.submit();
	
}



<?php
sleep(10);
//Retourne src image
echo '<Script>';
//echo 'window.top.window.uploadOk("monimage","retour.png");';
//echo 'window.top.window.errorUpload(\'Erreur lors de l\'upload\');';
echo 'window.top.window.errorUpload(\'test\');';
echo '</Script>';