11543 sujets

JavaScript, DOM et API Web HTML5

Bonjour,
je débute en HTML5 et je recherche des pistes qui m'aideraient à résoudre ce problème :

j'ai deux zones : à gauche, la zone dédiée aux articles disponibles comprenant des div drag-and-droppables dans la zone de droite (mon panier).
J'aimerais que chaque div comporte une valeur invisible qui s'ajoute au "total courses" quand droppé dans "mon panier" et retranchée si article remis dans "articles disponibles".

Mes questions sont : existe t'il un moyen en html5 (via set/getData - localStorage ?)
- d'allouer une valeur numérique invisible à chaque div ?
- de faire en sorte que les additions/soustractions se fassent automatiquement ?
- et que le résultat soit affiché à la suite de "total courses"


En théorie ça me paraissait plutôt simple, sauf qu'en pratique je rame Smiley sweatdrop

Le truc est ici : http://fluosaure.com/test/dragtest2.html

Voila le code actuel de la page :

	<script>
		function dragDefine(ev) {
			ev.dataTransfer.effectAllowed = 'move';
			ev.dataTransfer.setData("text/plain", ev.target.getAttribute('id'));
			ev.dataTransfer.setDragImage(ev.target, 0, 0);
			return true;
		}
		function dragOver(ev) {
			ev.preventDefault();
		}
		
		function dragEnd(ev) {
			return true;
		}
		function dragDrop(ev) {
			var idDrag = ev.dataTransfer.getData("Text");
			ev.target.appendChild(document.getElementById(idDrag));
			ev.preventDefault();
		}		
	</script>
</head>
<body>
	<article>
		<header>
			<h1>Ma liste de courses</h1>
		</header>
		<section>
			<div id="boxA" ondragover="dragOver(event)" ondrop="dragDrop(event)">articles disponibles
				<div id="word1" class="word" draggable="true" ondragstart="return dragDefine(event)" ondragend="dragEnd(event)">Yaourts aux fruits</div>
				<div id="word2" class="word" draggable="true" ondragstart="return dragDefine(event)" ondragend="dragEnd(event)">Quiche lorraine</div>
				<div id="word3" class="word" draggable="true" ondragstart="return dragDefine(event)" ondragend="dragEnd(event)">Sauce tomate</div>
				<div id="word4" class="word" draggable="true" ondragstart="return dragDefine(event)" ondragend="dragEnd(event)">Côte de boeuf</div>
				<div id="word5" class="word" draggable="true" ondragstart="return dragDefine(event)" ondragend="dragEnd(event)">Bon pinard</div>
			</div>			
			<div id="boxB" ondragover="return dragOver(event)" ondrop="dragDrop(event)">Mon panier</div>	
		</section>
        <section>
			<header>
				<h3>Total courses : 0€</h3>
			</header>
		</section>
	</article>
</body>	
</html>


Je serai infiniment reconnaissant à toute personne qui pourrait m'aiguiller, un peu, beaucoup...
D'avance merci Smiley biggrin

Guillaume
Modifié par GSI (18 Mar 2012 - 13:21)
Bonsoir,
Pour stocker les prix de tes articles tu peux utiliser une petite nouveauté HTML5, les attributs personnalisés : <div data-prix="50"></div> .
Et les récupérer en Javascript avec getAttribute("data-prix").
Pour faire la somme du prix de tes articles il te faut écouter un évènement qui est déclenché à la fin de ton drag & drop. L'événement ondrop ou ondragend peut être, je ne suis pas sûr. Une fois déclenché tu as deux solutions je pense :
- Avoir une variable qui au départ vaut zéro que tu augmente à chaque fois de la valeur du nouvel élément ajouté.
- Parcourir tous les enfants de ton conteneur et faire la somme de chaque à chaque fois.

En espérant avoir pu t'aider.
Prince-Leto
Modifié par Prince-Leto (18 Mar 2012 - 21:48)
Hello !
merci pour ta réponse.
Je vais essayer dès demain.
Avec un penchant pour la première solution, la deuxième dépasse mes compétences je pense et je me demande ce que ça pourrait donner avec une vingtaine d'items...

A chaque jour suffit sa peine et déjà je vais essayer de trouver la différence entre getData et getAttribute... d'ailleurs vu que tu préconises un getAttribute alors qu'on déclare un "data-prix" ne serait-ce pas un getData plutôt ?

Muchas gracias anyways
Modifié par GSI (18 Mar 2012 - 23:08)
Bon,
je cherche, je cherche mais je butte encore sur des trucs qui paraîtront être du "B-A BA" pour la majorité d'entre vous (je m'en excuse), je le répète, je suis un noob.

A ce stade, je comprends que je dois définir une valeur variable : totalPrice d'une valeur initiale = 0

pour l'instant, la partie script de ma page est


	<script>
		function dragDefine(ev) {
			ev.dataTransfer.effectAllowed = 'move';
			ev.dataTransfer.setData("text/plain", ev.target.getAttribute('id'));
			ev.dataTransfer.setDragImage(ev.target, 0, 0);
			return true;
		}
		function dragOver(ev) {
			ev.preventDefault();
		}
		
		function dragEnd(ev) {
			return true;
		}
		function dragDrop(ev) {
			var idDrag = ev.dataTransfer.getData("Text");
			ev.target.appendChild(document.getElementById(idDrag));
			ev.preventDefault();
		}		
	</script>


j'ai deux boites :
une à gauche qui contient tous les articles disponibles (je n'en mets que deux)

<div id="boxA" ondragover="dragOver(event)" ondrop="dragDrop(event)">articles disponibles
<div id="word1" class="word" draggable="true" ondragstart="return dragDefine(event)" ondragend="dragEnd(event)" data-value="200">Yaourts aux fruits</div>
<div id="word2" class="word" draggable="true" ondragstart="return dragDefine(event)" ondragend="dragEnd(event)" data-value="300">Quiche lorraine</div>
</div>	


une autre à droite qui ne contient rien mais qui si un élément draggé depuis gauche est droppé dedans, ajoutera la valeur data-value à la variable totalPrice (et retranchera cette même valeur si draggé de droite et droppé dans gauche.

<div id="boxB" ondragover="return dragOver(event)" ondrop="dragDrop(event)">Mon panier</div>	


Je comprends que totalPrice est une donnée composite et qu'à ce stade, j'ai plusieurs façons de la définir/calculer (j'aimerais que ce soit le plus simple/léger possible).
Je ne sais pas si je dois la définir en tant qu'object (
var totalPrice = new Object();
ou en tant qu'array (
var totalPrice = [ 200, 300, ...]


Ca serait plus simple d'écouter juste l'array de gauche qui aurait une valeur initiale en l'occurrence de (-)500, le total négatif de tous les data-value), totalPrice intial n'est alors pas = 0 mais à 0+a. SI c'était possible, ça résoudrait pas mal de probèmes

SVP, j'ai besoin de vos lumières car je n'ai ni le vocabulaire, ni la grammaire pour transformer ces idées en code (propre). Smiley rolleyes
Modifié par GSI (19 Mar 2012 - 09:09)
Tu as choisi la première solution qui pour moi n'était la plus simple. Bon je ne l'avais pas précisé, c'est juste un avis personnel, en fait tout dépend de comment tu voyais ton code.

Tu fais erreur, je pense que totalprice doit plutôt être un simple integer - un entier. A chaque ondragend de tes éléments tu incrémente ta variable de la valeur de son data-value.
D'ailleurs tu me demandais comme récupérer sa valeur, les éléments du DOM tels que div ne possèdent pas de méthode nommée getData, mais une méthode getAttribute qui marche à merveille.
Pour faire simple tu peux ajouter à chaque ondragend="dragEnd(event, this)" et récupérer le this, nouveau paramètre sur lequel tu ira chercher ton getAttribute("data-value") et l'ajouter à totalprice. Avec un petit appel à la fonction parseInt pour que l'addition se fasse sans souci. Puis ajouter la valeur de totalprice dans ton DOM.
Il reste néanmoins un hic : tu ne sais pas si l'élément est ajouté ou retiré, il y a sûrement un moyen de le faire mais là je ne sais pas comment.
D'où la première solution qui paraissait plus simple pour moi, je te balance du code tout fais qui marche, tu as juste à ajouter tes data-value dans ton HTML, les explications suivent :


function Update()
{
	var Enfants = document.getElementById("boxB").childNodes;
	var Totalprice = 0;
	for(var k = 0; k < Enfants.length; k++)
	{
		if(Enfants[k].nodeType == 1)
		{
			Totalprice += parseInt(Enfants[k].getAttribute("data-value"));
		}
	}
	document.getElementsByTagName("section")[1].getElementsByTagName("header")[0].getElementsByTagName("h3")[0].innerHTML = "Total courses : " + String(Totalprice) + " €";
}
window.onload = function()
{
	document.getElementById("boxA").addEventListener("drop", Update, false);
	document.getElementById("boxB").addEventListener("drop", Update, false);
}


Je t'explique son fonctionnement. Il faut d'abord écouter quand est-ce qu'un élément est déposé sur un de tes conteneurs, d'où la fonction qui est dans window.onload où l'on écoute l'évènement ondrop de tes deux conteneurs. La fonction est appellé, elle liste tous les enfants de ton conteneur de droite - trop d'enfants en fait même comme je vais te l'expliquer - et qui pour chaque enfant ajoute la valeur de son data-value si l'enfant est de type 1. En fait quand Javascript vas chercher les enfants il récupère tout, y compris les espaces entre tes balises qu'il considère comme des enfants de type texte. Ceux là n'ont pas d'attribut get-value, et les seuls enfants qui t'intéresse sont ceux de type 1. D'où la condition. Et pour finir tu ajoute la valeur - j'ai fait un truc bien long pour récupérer l'élément... o_O
Voilà voilà.

Prince-Leto

Edit : Pas la variable i usuelle dans la boucle mais un k, sinon le site m'affiche un truc en italique.
Modifié par Prince-Leto (19 Mar 2012 - 19:38)
Bon, je n'ai pas encore testé ton truc mais déjà vraiment merci d'avoir passé ce temps à m'aider et m'expliquer (j'étais loin d'imaginer que ce serait finalement aussi alambiqué). Ton code + son explication me fait comprendre et c'est probablement ce qui me plait le plus. Malheureusement, je n'aurai jamais pu pondre ça tout seul... Bref, merci encore