Modérateur
Bonjour,

Je souhaite définir un ordre d'affichage de données définies dans un backend (en l'occurrence c'est dans WordPress, mais ça pourrait être dans n'importe quelle partie administrative). Pour expliquer simplement, chaque élément sera nommé par une lettre : A, B, C, D.
Ces éléments seront affichés dans le frontend en respectant un ordre indiqué par le rédacteur dans l'admin. Par exemple, Toto, souhaiterait que A, B, C et D s'affichent dans le frontend dans l'ordre suivant : C, A, B, D.
Ma question : Quels sont les moyens à ma disposition pour demander et conserver l'ordre que le rédacteur défini (de préférence en php, mais le JS m'irait également). J'ai pensé à des <select> ou des <input> pour indiquer un nombre, mais je suis preneur d'autres idées déjà éprouvées.
C'est quelque chose que je n'ai jamais fait et je n'ai trouvé aucun exemple sur le Web (faut dire que les bons mots clés ne sont pas faciles à trouver s'agissant de mon interrogation).
Merci d'avance pour votre partage d'expérience. Smiley smile
Modifié par jojaba (23 Jul 2016 - 20:24)
Bonsoir !

Il y a sans doute de meilleurs solutions mais il y a quelques temps, j'avais fait un petit jeu qui tirait au hasard des phrases, et bien sûr, il était préférable que les solutions soient dans le même ordre.

Les phrases était dans un tableau $proposition et les indices étaient les id de la base de données et pour afficher les solutions dans une autre page, je ré-affichais les phrases en reprenant les indices avec array_keys...

Ce n'est ni malin ni économe... Smiley sweatdrop

Smiley smile
Encore un moyen "ni malin ni économe" : j'utiliserais des champs personalisés dont la valeur serait modifiable à partir du backend de chaque article.
jojaba a écrit :
Bonjour,
Je souhaite définir un ordre d'affichage de données définies dans un backend (en l'occurrence c'est dans WordPress, mais ça pourrait être dans n'importe quelle partie administrative). Pour expliquer simplement, chaque élément sera nommé par une lettre : A, B, C, D.
Ces éléments seront affichés dans le frontend en respectant un ordre indiqué par le rédacteur dans l'admin. Par exemple, Toto, souhaiterait que A, B, C et D s'affichent dans le frontend dans l'ordre suivant : C, A, B, D.
Ma question : Quels sont les moyens à ma disposition pour demander et conserver l'ordre que le rédacteur défini (de préférence en php, mais le JS m'irait également). J'ai pensé à des &lt;select&gt; ou des &lt;input&gt; pour indiquer un nombre, mais je suis preneur d'autres idées déjà éprouvées.
C'est quelque chose que je n'ai jamais fait et je n'ai trouvé aucun exemple sur le Web (faut dire que les bons mots clés ne sont pas faciles à trouver s'agissant de mon interrogation).
Merci d'avance pour votre partage d'expérience. Smiley smile

a) Moyen :
- 1 label / valeur
- 1 select en face de chaque valeur, avec la liste des positions possibles pour cette valeur (1, 2, 3, etc.)
- 1 function JS qui récupère les N couples label / valeur lors de la validation et s'assure que la série de positions est cohérente (toutes les positions représentées de façon séquentielle, c'est à dire sans doublon ni "trou")
b) Stockage :
Chaîne alphanumérique contenant la série de couples ID valeur / indice position, séparés par des délimiteurs (ex. "|")
c) Exemple :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<style type="text/css">
*
{
font-family:arial,sans-serif;
font-size:inherit;
}
body
{
font-size:1em;
}
select
{
margin:0.5rem 0;
}
textarea
{
width:90%;
margin:1rem auto;
font-size:3rem;
font-weight:bold;
}
</style>
<script>
const count = 4;
var values = [];
function initialize()
{
for (var index = 0 ; index < count ; index++)
{
var id = String.fromCharCode('A'.charCodeAt(0) + index);
var element = document.getElementById(id);
values[index] = element.value;
}
refresh();
}
function select(element)
{
var id = element.id;
var value = element.value;
var index = id.charCodeAt(0) - 'A'.charCodeAt(0);
values[index] = value;
refresh();
}
function pattern()
{
var result = '';
for (var index = 0 ; index < count ; index++)
{
result += (index == 0 ? '' : '|') + values[index];
}
return result;
}
function refresh()
{
var box = document.getElementById('pattern');
box.innerHTML = pattern();
}
</script>
</head>
<body onload="initialize()">
	<label for="A">Valeur A</label>
	<select id="A" onchange="select(this)">
		<option value="A1" selected>Position 1</option>
		<option value="A2">Position 2</option>
		<option value="A3">Position 3</option>
		<option value="A4">Position 4</option>
	</select>
	<br/>
	<label for="B">Valeur B</label>
	<select id="B" onchange="select(this)">
		<option value="B1">Position 1</option>
		<option value="B2" selected>Position 2</option>
		<option value="B3">Position 3</option>
		<option value="B4">Position 4</option>
	</select>
	<br/>
	<label for="C">Valeur C</label>
	<select id="C" onchange="select(this)">
		<option value="C1">Position 1</option>
		<option value="C2">Position 2</option>
		<option value="C3" selected>Position 3</option>
		<option value="C4">Position 4</option>
	</select>
	<br/>
	<label for="D">Valeur D</label>
	<select id="D" onchange="select(this)">
		<option value="D1">Position 1</option>
		<option value="D2">Position 2</option>
		<option value="D3">Position 3</option>
		<option value="D4" selected>Position 4</option>
	</select>
	<br/>
	<p>Clé base&nbsp;:</p>
	<textarea id="pattern">
	</textarea>
</body>
</html>

Pour finaliser cet exemple, il reste juste à s'assurer de la cohérence des positons comme indiqué supra.
Pour cela :
- calculer la somme des N positions (ex. 1 + 2 + 3 + 4)
- extraire chaque valeur (2ème caractère) des entrées du "pattern"
- les additionner et comparer avec la somme précédente (si = alors OK, si différente alors KO).
Code javascript ni optimisé ni testé sur tous navigateurs...
Modérateur
Merci beaucoup à tous pour vos propositions.
Donc liste déroulante (<select>) avec JS pour contrôle des valeurs (éviter les doublons) pour chaque élément à afficher. Pour le stockage, chaque option aurait comme valeur 1|A, 2|A, 3|A, ...,1|B, 2|B, ...
Exemple pour l'élément A (même structure pour les 3 autres éléments) :

<select id="A" name="element_position[]">
   <option value="">Pas affiché</option>
   <option value="1|A">Position 1</option>
   <option value="2|A" selected="selected">Position 2</option>
   <option value="3|A">Position 3</option>
   <option value="4|A">Position 4</option>
</select>

Je récupère donc après validation un tableau ($_POST['element_position']) contenant par exemple les éléments suivants :
array("2|A", "3|B", "1|C", "4|D");

Pour stocker ça dans la bdd de WordPress je vais devoir linéariser le tableau (j'utilise pour ça implode(",", $_POST['element_position'] )) et j'obtiendrai une liste des éléments séparés par des virgules (2|A, 3|B, 1|C, 4|D).
Dans le frontend, je pourrai retransformer cette liste en tableau (explode()), la trier par ordre alphabétique (pour avoir l'ordre chronologique) , récupérer l'ID pour chaque élément (en ne prenant en compte que ce qui se trouve après le "|") et les afficher dans une boucle foreach{}.
Pour le tri du tableau, il serait d'ailleurs plus judicieux de faire ça dans l'admin avant de stocker les valeurs linéarisées...
En revanche, pour le contrôle js, je ne suis pas sûr que cela soit possible en l'état...
Commentaires supplémentaires ?
Modifié par jojaba (23 Jul 2016 - 08:02)
Modérateur
Bon ben, je crois avoir obtenu quelque chose de correct. En tout cas, ça fonctionne bien sur mon installation locale...
Les select ressemblent à ça (je vous donne juste le premier, les autres ressemblent, il faut juste remplacer "buttons" par l'id des autres éléments :

<select id="buttons_order" name="sidebar_menu_items_order[]">
	<option value=""><?php _e('Pas affiché', 'mon_domaine') ?></option>
	<option value="1|buttons"<?php if(in_array('1|buttons',$sidebar_menu_items_order)) echo ' selected="selected"'; ?>><?php _e('Position 1', 'mon_domaine') ?></option>
	<option value="2|buttons"<?php if(in_array('2|buttons',$sidebar_menu_items_order)) echo ' selected="selected"'; ?>><?php _e('Position 2', 'mon_domaine') ?></option>
	<option value="3|buttons"<?php if(in_array('3|buttons',$sidebar_menu_items_order)) echo ' selected="selected"'; ?>><?php _e('Position 3', 'mon_domaine') ?></option>
	<option value="4|buttons"<?php if(in_array('4|buttons',$sidebar_menu_items_order)) echo ' selected="selected"'; ?>><?php _e('Position 4', 'mon_domaine') ?></option>
</select>

Pour le JS, je profite d'être sur WordPress pour utiliser jQuery (beaucoup plus à l'aise avec jQuery qu'avec JS, je sais, c'est pas bien !) :

<script>
	jQuery(document).ready(function () {
		// The array of the different sidebar elements
		var orderSect = ["buttons_order", "contact_box_order", "highlight_box_order", "diary_order"];
			var oslen = orderSect.length;
		// controlling if same value for items order
		jQuery("#buttons_order, #contact_box_order, #highlight_box_order, #diary_order, #video_order, #rel_blog_order, #feedbacks_order").on("change", function() {
			for(var i = 0; i < oslen; i++) {
				if(jQuery(this).attr("id") != orderSect[i] && jQuery(this).val().substring(0, 1) == jQuery("#" + orderSect[i] ).val().substring(0, 1)) {
					jQuery("#" + orderSect[i] ).val("");
					jQuery("#" + orderSect[i] ).parent().parent("div").css("opacity", "0.5");
				}
			}
		});
		// Change display of element if not displayed on frontend
		for(var i = 0; i < oslen; i++) {
			if(jQuery("#" + orderSect[i] ).val() == "") {
				jQuery("#" + orderSect[i] ).parent().parent("div").css("opacity", "0.5");
			}
		}
		jQuery("#buttons_order, #contact_box_order, #highlight_box_order, #diary_order, #video_order, #rel_blog_order, #feedbacks_order").on("change", function() {
			if (jQuery(this).val() == "") {
				jQuery(this).parent().parent("div").css("opacity", "0.5");
			} else {
				jQuery(this).parent().parent("div").css("opacity", "1");
			}
		});
		// toggle element
		jQuery(".toggle_element").on("click", function(e) {
			e.preventDefault();
			if(jQuery(this).parent().parent().find(".toggled_div").css("display") == "none") {
				jQuery(this).parent().parent().find(".toggled_div").slideDown();
				jQuery(this).html("&and;")
			} else {
				jQuery(this).parent().parent().find(".toggled_div").slideUp();
				jQuery(this).html("&or;")
			}
		});
	});
	</script>

J'ai donc choisi de faire de la manière suivante pour éviter les doublons : si une valeur est sélectionnée et qu'elle est déjà prise par un autre élément, on demande à ce que ce dernier élément ne soit pas affiché (valeur "" pour le select). Vous constaterez dans ce script que j'ajoute un effet d'opacité sur l'élément qui n'est pas affiché en frontend. La parie "toggle element" sert à masquer afficher les éléments, ceci afin de faciliter le changement de l'ordre des éléments.
Une copie d'écran du résultat Smiley cligne
upload/3069-select-pour.jpg [/i][/i][/i][/i][/i][/i]
Modifié par jojaba (23 Jul 2016 - 20:23)