Bonjour à tous,

J'ai tenté d'incruster 3 double-range-sliders par un include dans ma page d'index contenant déjà un form servant de filtre.

1er Problème :

Pour que le formulaire de filtres fonctionne je mets le script en mode defer mais à ce moment là, l'autre form contenant les sliders lui ne répond plus, je dois retirer le defer du script antérieur et le mettre sur celui des sliders pour que celui-ci fonctionne, à n'y rien comprendre !

2ème problème :

Bien que j'ai écrit une fonction par délégation sensée écouter les 3 sliders, seul le premier d'entre-eux s'active, me tromperai-je de sélecteur ?

3ème problème :

Une fois transformé en Html Twig le code css des sliders ne fonctionne pas bien : les sliders se chevauchent et ignorent le css (-webkit) alors qu'en html pur tout est bon (voir capture jointe)...

Nom : Capture d’écran 2023-06-08 185922.jpg
Affichages : 564
Taille : 11,1 Ko

Merci d'avance pour vos réponses et expertise


index.html.twig :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
{% extends "base.html.twig" %}
{% block title %}Liste des véhicules
{% endblock %}
{% block body %}
 
	<div class="main">
 
		<h1 class="titre-principal">Liste des véhicules</h1>
 
		{% if is_granted(['ROLE_ADMIN']) %}
		<a href="{{path('app_vehicules_creer_vehicule')}}" class="btn btn-primary">Créer un nouveau véhicule</a>			
		{% endif %}
 
		<p>Total véhicules dans la base =
			{{totalVehicules}}</p>
		<p>Résultats filtre actif =
			{{totalVehiculesFiltered}}</p>
 
		{# Sliders double range #}
		{{ include('_partials/_sliders.html.twig') }}
 
		<div
			class="wrapper">
			{# Filtre multicritère : #}
			<div class="filtres">
 
				<form
					id="filters" class="filtersForm">
 
					{# Filtre sur type de véhicule #}
					<fieldset>
						<legend>Type :</legend>
						{% for  type in typesVehicules %}
 
							<input type="checkbox" name="types[]" id="types{{type.id}}" value="{{type.id}}" class="filtreTypes">
							<label for="types{{type.id}}">{{type.nomtype}}</label>
 
						{% endfor %}
					</fieldset>
 
					{# Filtre sur marques de véhicules #}
					<fieldset>
						<legend>Marque :</legend>
						{% for  marque in marquesVehicules %}
 
							<input type="checkbox" name="marques[]" id="marques{{marque.id}}" value="{{marque.id}}" class="filtreMarques">
							<label for="marques{{marque.id}}">{{marque.marque}}</label>
 
						{% endfor %}
					</fieldset>
 
					<input type="hidden" name="page" value="{{page}}">
				</form>
			</div>
 
			<div
				class="cards-container" id="content">
 
				{# Contenu généré en Ajax #}
				{{ include('vehicules/_content.html.twig') }}
			</div>
		</div>
	</div>
{% endblock %}
 
{% block javascripts %}
	<script src="{{asset('assets/js/filters.js')}}" type="text/javascript"></script>
{% endblock %}
_sliders.html.twig :
Code html : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<div class="wrapper-sliders">
	<form id="slidersForm">
 
		<div class="range_container">
			<p>Intervalle de prix en €</p>
			<div class="sliders_control">
				<input id="fromSlider" type="range" value="10" min="0" max="100"/>
				<input id="toSlider" type="range" value="30" min="0" max="100"/>
			</div>
			<div class="form_control">
				<div class="form_control_container">
					<div class="form_control_container__time">Min</div>
					<input class="form_control_container__time__input" type="number" id="fromInput" value="10" min="0" max="100"/>
				</div>
				<div class="form_control_container">
					<div class="form_control_container__time">Max</div>
					<input class="form_control_container__time__input" type="number" id="toInput" value="30" min="0" max="100"/>
				</div>
			</div>
		</div>
		<div class="range_container">
			<p>Ancienneté</p>
			<div class="sliders_control">
				<input id="fromSlider" type="range" value="10" min="0" max="100"/>
				<input id="toSlider" type="range" value="30" min="0" max="100"/>
			</div>
			<div class="form_control">
				<div class="form_control_container">
					<div class="form_control_container__time">Min</div>
					<input class="form_control_container__time__input" type="number" id="fromInput" value="10" min="0" max="100"/>
				</div>
				<div class="form_control_container">
					<div class="form_control_container__time">Max</div>
					<input class="form_control_container__time__input" type="number" id="toInput" value="30" min="0" max="100"/>
				</div>
			</div>
		</div>
		<div class="range_container">
			<p>Kilométrage</p>
			<div class="sliders_control">
				<input id="fromSlider" type="range" value="10" min="0" max="100"/>
				<input id="toSlider" type="range" value="30" min="0" max="100"/>
			</div>
			<div class="form_control">
				<div class="form_control_container">
					<div class="form_control_container__time">Min</div>
					<input class="form_control_container__time__input" type="number" id="fromInput" value="10" min="0" max="100"/>
				</div>
				<div class="form_control_container">
					<div class="form_control_container__time">Max</div>
					<input class="form_control_container__time__input" type="number" id="toInput" value="30" min="0" max="100"/>
				</div>
			</div>
		</div>
 
	</form>
</div>
{% block javascripts %}
<script src="{{asset('assets/js/sliders.js')}}" type="text/javascript" defer></script>
{% endblock %}

sliders.js :
Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
window.onload = () => {
  const container = document.querySelectorAll(".range_container input");
  container.forEach(input => {
    input.addEventListener("change", () => {
 
      function controlFromInput(fromSlider, fromInput, toInput, controlSlider) {
        const [from, to] = getParsed(fromInput, toInput);
        fillSlider(fromInput, toInput, "#C6C6C6", "#25daa5", controlSlider);
        if (from > to) {
          fromSlider.value = to;
          fromInput.value = to;
        } else {
          fromSlider.value = from;
        }
      }
 
      function controlToInput(toSlider, fromInput, toInput, controlSlider) {
        const [from, to] = getParsed(fromInput, toInput);
        fillSlider(fromInput, toInput, "#C6C6C6", "#25daa5", controlSlider);
        setToggleAccessible(toInput);
        if (from <= to) {
          toSlider.value = to;
          toInput.value = to;
        } else {
          toInput.value = from;
        }
      }
 
      function controlFromSlider(fromSlider, toSlider, fromInput) {
        const [from, to] = getParsed(fromSlider, toSlider);
        fillSlider(fromSlider, toSlider, "#C6C6C6", "#25daa5", toSlider);
        if (from > to) {
          fromSlider.value = to;
          fromInput.value = to;
        } else {
          fromInput.value = from;
        }
      }
 
      function controlToSlider(fromSlider, toSlider, toInput) {
        const [from, to] = getParsed(fromSlider, toSlider);
        fillSlider(fromSlider, toSlider, "#C6C6C6", "#25daa5", toSlider);
        setToggleAccessible(toSlider);
        if (from <= to) {
          toSlider.value = to;
          toInput.value = to;
        } else {
          toInput.value = from;
          toSlider.value = from;
        }
      }
 
      function getParsed(currentFrom, currentTo) {
        const from = parseInt(currentFrom.value, 10);
        const to = parseInt(currentTo.value, 10);
        return [from, to];
      }
 
      function fillSlider(from, to, sliderColor, rangeColor, controlSlider) {
        const rangeDistance = to.max - to.min;
        const fromPosition = from.value - to.min;
        const toPosition = to.value - to.min;
        controlSlider.style.background = `linear-gradient(
    to right,
    ${sliderColor} 0%,
    ${sliderColor} ${(fromPosition / rangeDistance) * 100}%,
    ${rangeColor} ${(fromPosition / rangeDistance) * 100}%,
    ${rangeColor} ${(toPosition / rangeDistance) * 100}%, 
    ${sliderColor} ${(toPosition / rangeDistance) * 100}%, 
    ${sliderColor} 100%)`;
      }
 
      function setToggleAccessible(currentTarget) {
        const toSlider = document.querySelector("#toSlider");
        if (Number(currentTarget.value) <= 0) {
          toSlider.style.zIndex = 2;
        } else {
          toSlider.style.zIndex = 0;
        }
      }
 
      const fromSlider = document.querySelector("#fromSlider");
      const toSlider = document.querySelector("#toSlider");
      const fromInput = document.querySelector("#fromInput");
      const toInput = document.querySelector("#toInput");
      fillSlider(fromSlider, toSlider, "#C6C6C6", "#25daa5", toSlider);
      setToggleAccessible(toSlider);
 
      fromSlider.oninput = () =>
        controlFromSlider(fromSlider, toSlider, fromInput);
      toSlider.oninput = () => controlToSlider(fromSlider, toSlider, toInput);
      fromInput.oninput = () =>
        controlFromInput(fromSlider, fromInput, toInput, toSlider);
      toInput.oninput = () =>
        controlToInput(toSlider, fromInput, toInput, toSlider);
    });
  });
};
filters.js :
Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
window.onload = () => {
  const filtersForm = document.querySelector("#filters");
 
  document.querySelectorAll("#filters input").forEach((input) => {
    input.addEventListener("change", () => {
      //Récupération des données du formulaire
      const Form = new FormData(filtersForm);
      console.log(Form);
      //Création de la queryString
      const Params = new URLSearchParams();
 
      Form.forEach((value, key) => {
        Params.append(key, value);
      });
 
      //Récupération de l'url active
      const Url = new URL(window.location.href);
 
      //Lancement requête Ajax
 
      fetch(Url.pathname + "?" + Params.toString() + "&ajax=1", {
        headers: {
          "X-Requested-With": "XMLHttpRequest",
        },
      })
        .then((response) => response.json())
        .then((data) => {
          //Recherche de la zone de contenu
          const content = document.querySelector("#content");
 
          //Remplacement du contenu
          content.innerHTML = data.content;
 
          //Mise à jour de l'url
          history.pushState({}, null, Url.pathname + "?" + Params.toString());
        })
        .catch((e) => alert(e));
    });
  });
};

sliders.css :
Code css : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
.wrapper-sliders {
  display: flex;
  width: 100%;
 
}
 
#slidersForm {
  background-color: #fff;
  width: auto;
  height: auto;
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  padding: 5px;
}
 
.range_container {
  display: flex;
  flex-direction: column;
  width: 200px;
  margin: 10px 40px;
  padding: 5px;
}
 
.sliders_control {
  position: relative;
  min-height: 35px;
}
 
.form_control {
  position: relative;
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: #635a5a;
}
 
input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  pointer-events: all;
  width: 24px;
  height: 24px;
  background-color: #fff;
  border-radius: 50%;
  box-shadow: 0 0 0 1px #c6c6c6;
  cursor: pointer;
}
 
input[type="range"]::-moz-range-thumb {
  appearance: none;
  -webkit-appearance: none;
  pointer-events: all;
  width: 24px;
  height: 24px;
  background-color: #fff;
  border-radius: 50%;
  box-shadow: 0 0 0 1px #c6c6c6;
  cursor: pointer;
}
 
input[type="range"]::-webkit-slider-thumb:hover {
  background: #f7f7f7;
}
 
input[type="range"]::-webkit-slider-thumb:active {
  box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;
  -webkit-box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;
}
 
input[type="number"] {
  color: #8a8383;
  width: 50px;
  height: 30px;
  font-size: 20px;
  border: none;
}
 
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  font-size: 12px;
  opacity: 1;
}
 
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  height: 2px;
  width: 100%;
  position: absolute;
  background-color: #c6c6c6;
  pointer-events: none;
}
 
#fromSlider {
  height: 0;
  z-index: 1;
}
.form_control_container__time__input {
  font-size: 12px;
}