Forum |  HardWare.fr | News | Articles | PC | Prix | S'identifier | S'inscrire | Aide | Shop Recherche
1693 connectés 

  FORUM HardWare.fr
  Programmation
  HTML/CSS

  Création d'un range personnalisé (fourchette)

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Création d'un range personnalisé (fourchette)

n°2330132
MaybeEijOr​Not
but someone at least
Posté le 07-03-2019 à 16:56:26  profilanswer
 

Bonjour,
 
J'ai attaqué la création d'un range permettant de définir graphiquement une fourchette :
 
https://codepen.io/anon/pen/gEmdYm
 
Néanmoins avez-vous une idée de comment je peux définir un évènement JS pour le déplacement de mes cercles ? Je partais sur du grab mais ça n'a pas l'air de coller, y a t-il un moyen de simuler ça avec un onClick ?
Avez-vous une autre idée ?


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
mood
Publicité
Posté le 07-03-2019 à 16:56:26  profilanswer
 

n°2330149
aliasdmc
Posté le 07-03-2019 à 19:12:44  profilanswer
 

Bonjour MaybeEijOrNot,
 
mousedown = j'écoute le mousemove
mousemove = dans l'event tu as la position du curseur  
voir https://developer.mozilla.org/fr/do [...] /mousemove
mouseup = je n'écoute plus mousemove

n°2330151
MaybeEijOr​Not
but someone at least
Posté le 07-03-2019 à 19:27:39  profilanswer
 

Merci, bon j'avais trouvé pour le mousedown. Par contre merci pour le mousedown, j'étais entrain d'un ajouter au document, si je comprends bien, je n'ai pas besoin de le faire et c'est tant mieux parce que là je n'arrivais pas à le supprimer. xD


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2330153
MaybeEijOr​Not
but someone at least
Posté le 07-03-2019 à 20:10:37  profilanswer
 

Bon j'ai pas mal buggé dessus mais ça y est ça bouge : https://codepen.io/anon/pen/rRybpX

 

J'ai plein de choses à faire (notamment retourner sur des %) mais les bases sont posées. :jap:


Message édité par MaybeEijOrNot le 07-03-2019 à 20:10:55

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2330215
aliasdmc
Posté le 08-03-2019 à 21:55:28  profilanswer
 

Bonjour MaybeEijOrNot,  
Je t'ai fait un exemple mais cela reste un proto, il y a surement des trucs a améliorer, je verais plus tard
https://codepen.io/Zonecss/pen/YgZBRR

n°2330223
MaybeEijOr​Not
but someone at least
Posté le 09-03-2019 à 14:34:10  profilanswer
 

Merci, je n'ai pas encore eu le temps de me repencher dessus.
Mais il faut déjà que je détermine ce que je veux exactement. Je pense que l'histoire des pourcentages par exemple ça va sauter parce que je trouve ça débile en fin de compte. Je vais surement fonctionner avec un "pas" de déplacement. Là encore faut savoir ce que je veux... Est-ce que je fais un pas qui respecte l'écart entre les données ? Est-ce que je fais une échelle log ? Est-ce que je fais un pas constant qui passe d'une donnée à la suivante, peu importe la différence entre les deux données ?


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2330273
aliasdmc
Posté le 10-03-2019 à 14:42:36  profilanswer
 

Bonjour MaybeEijOrNot,  
Dans le systeme proposé j'ai un pas de déplacement identique en fonction du tableau de données

n°2330274
MaybeEijOr​Not
but someone at least
Posté le 10-03-2019 à 14:54:11  profilanswer
 

Oui j'ai remarqué, et je pense que c'est vers quoi je vais me diriger.


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2331785
MaybeEijOr​Not
but someone at least
Posté le 11-04-2019 à 16:31:08  profilanswer
 

Bon, pas eu le temps de me pencher dessus à nouveau, j'ai donc terminé aujourd'hui sans faire de "pas" de déplacement du curseur :
https://codepen.io/anon/pen/XQRPQg
 
Ce ne doit pas être très compliqué d'ajouter un pas mais vu mon temps libre en ce moment ce sera sans. Au pire, aliasdmc a proposé une solution mais son code me semblait trop long, et mon but n'est pas non plus de récupérer une solution mais de faire par moi-même.


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2347281
MaybeEijOr​Not
but someone at least
Posté le 06-03-2020 à 19:44:34  profilanswer
 

Correction d'un bug à la con, la largeur de la fourchette est définie en pourcentage et lorsque ça donne un nombre non entier en pixels ça merde au premier clic, je recalcule-donc en JS la valeur arrondie en pixels :

 
Code :
  1. function nogood(min, max) {
  2.   let myrange = document.getElementById('myrange');
  3.   myrange.style.width = Math.round(myrange.innerWidth) + 'px';
  4.   document.getElementById('min').value = min;
  5.   document.getElementById('max').value = max;
  6.   document.getElementById('circleleft').addEventListener('mousedown', function(e) {
  7.     smackmybitsup(e, 'left');
  8.   }, false);
  9.   document.getElementById('circleright').addEventListener('mousedown', function(e) {
  10.     smackmybitsup(e, 'right');
  11.   }, false);
  12. }
 

Bon faudrait faire ça à chaque fois que la fenêtre redimensionnée, penser à ajouter un évènement.


Message édité par MaybeEijOrNot le 06-03-2020 à 19:46:09

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
mood
Publicité
Posté le 06-03-2020 à 19:44:34  profilanswer
 

n°2347489
rufo
Pas me confondre avec Lycos!
Posté le 10-03-2020 à 16:35:29  profilanswer
 

Pour info, quand on travaille avec un min et max de forte amplitude (genre, des timestamp), quand on bouge les bornes et qu'on les remets à leur position initiale, on ne retrouve pas les valeurs min/max du début. Pareil, c'est à cause des arrondis.
 
Perso, j'ai corrigé comme ça dans la fonction resize :

Code :
  1. if (left < 0.003) {
  2.    filterMin = min;
  3. }
  4. if (right < 0.003) {
  5.    filterMax = max;
  6. }


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Cantine Calandreta : http://sourceforge.net/projects/canteen-calandreta
n°2347491
MaybeEijOr​Not
but someone at least
Posté le 10-03-2020 à 17:06:23  profilanswer
 

Ok merci je note, ça doit surement pouvoir se corriger lors de l'initialisation aussi.

 

De toute façon faut que je revois tout pour le passer en objet afin de faciliter une implémentation multiple. Mais j'ai du mal à voir comment faire le lien avec le DOM sans le générer dans le JS. Peut-être en attachant l'objet à un élément du DOM sinon.
Pour le bug précédent, je vais tenter de passer par une variable CSS qui fera la différence entre la valeur calculée initiale et la valeur arrondie, ça permettra de garder une valeur en pourcentage dans le CSS.


Message édité par MaybeEijOrNot le 10-03-2020 à 17:06:32

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2347507
rufo
Pas me confondre avec Lycos!
Posté le 10-03-2020 à 20:32:09  profilanswer
 

Je serais intéressé par les évolutions de ton implémentation. Je suis parti de ton code pour faire une variante pour filtrer des données basées sur des dates.
Ca marche bien pour l'instant. Seul bug trouvé : quand on resize la fenêtre, ça part en sucette (mais tu l'avais indiqué) ;)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Cantine Calandreta : http://sourceforge.net/projects/canteen-calandreta
n°2347514
MaybeEijOr​Not
but someone at least
Posté le 10-03-2020 à 21:22:20  profilanswer
 

Ok, ben ça va dépendre du temps que j'aurai, j'en avais la semaine dernière, mais insuffisant pour finir ce que je voulais faire. Du coup va falloir que je trouve de nouveau du temps, mais j'ai jamais beaucoup de visibilité. :(


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2347720
rufo
Pas me confondre avec Lycos!
Posté le 12-03-2020 à 18:24:38  profilanswer
 

Une fois la slidebar affichée avec une valeur min et max, je dois pouvoir positionner les 2 curseurs automatiquement sur 2 valeurs fournies par un objet sur lequel j'ai cliqué. J'arrive bien à faire le filtrage mais impossible de trouver comment faire bouger les 2 curseurs :( Une idée, svp ?
Merci :jap:


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Cantine Calandreta : http://sourceforge.net/projects/canteen-calandreta
n°2347778
mathieuu
Posté le 13-03-2020 à 09:35:10  profilanswer
 

Salut,  
A priori vous devriez pouvoir faire le job avec ça : https://github.com/leongersen/noUiSlider

n°2347788
MaybeEijOr​Not
but someone at least
Posté le 13-03-2020 à 11:19:24  profilanswer
 

Oui, s'il te faut un truc dans l'immédiat il doit exister plein de solutions complètes. Moi je voulais ma propre version, et surtout légère.

 

Ce que tu veux faire rufo, j'ai prévu aussi de l'ajouter, tu veux agir dans le sens inverse, tu sélectionnes une valeur et les curseurs se mettent à jour tout seul. De même, j'ajouterai l'option pour ne pouvoir déplacer les curseurs que de valeurs existantes en valeurs existantes.
Ces deux choses ne me semblent pas très compliquées. Une histoire de temps... :D

 

Pour ce que tu veux faire, faut récupérer la largeur totale de la barre, calculer par règle de trois la largeur relative des trois éléments avec un offset de quelques pixels (qui doivent correspondre de souvenir au rayon des curseurs) puis leur fixer les largeurs calculées.

 

Mais vu comment on est parti avec le Coronavirus, il y a quand même de bonnes chances que je finisse par trouver du temps dans les semaines à venir. :o


Message édité par MaybeEijOrNot le 13-03-2020 à 11:20:00

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2347835
rufo
Pas me confondre avec Lycos!
Posté le 13-03-2020 à 15:32:30  profilanswer
 

Oui, c'est ce que j'ai fait la règle de 3. L'ennui, c'est que sur une plage étendue (grand écart entre la date min et max), avec les arrondis, une fois que j'ai positionné les 2 curseurs sur des dates définies, quand je bouge un des curseurs, ça décale un peu les 2 valeurs et du coup, ça filtre des objets qui ne devraient pas être impacté. J'ai joué avec floor() pour le min et ceil() pour le max, mais bon, ça marche pas à tous les coups.
 
Edit : en mettant de floor() partout, ça va, ça empêche le filtrage erroné de certains objets. Par contre, ces arrondis font que les dates dans les inputs peuvent légèrement changer quand on bouge l'un des curseurs (de 2-3j). Je précise que je travaille sur une amplitude de 9 ans avec un range qui fait moins de 800px de large.

Message cité 1 fois
Message édité par rufo le 13-03-2020 à 15:42:48

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Cantine Calandreta : http://sourceforge.net/projects/canteen-calandreta
n°2348138
MaybeEijOr​Not
but someone at least
Posté le 15-03-2020 à 20:26:46  profilanswer
 

rufo a écrit :

Par contre, ces arrondis font que les dates dans les inputs peuvent légèrement changer quand on bouge l'un des curseurs (de 2-3j). Je précise que je travaille sur une amplitude de 9 ans avec un range qui fait moins de 800px de large.


Ah oui. xD
 
Peut-être que là par contre il te faudrait une fonction en plus pour affiner, utilisation du clavier ou de boutons pour avancer de jour en jour par exemple.


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2348179
rufo
Pas me confondre avec Lycos!
Posté le 16-03-2020 à 08:59:46  profilanswer
 

Non, ça marchera pas : 9 ans, ça fait plus de 800j (i.e. 800 px). Donc, dans mon cas, 1px = plusieurs jours. C'est normal que ça "bagotte". Toutefois, je pense que ce cas arrivera peu.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Cantine Calandreta : http://sourceforge.net/projects/canteen-calandreta
n°2348189
MaybeEijOr​Not
but someone at least
Posté le 16-03-2020 à 09:22:18  profilanswer
 

Cela n'est pas problématique, la fonction inverse met à jour les valeurs et corrige la position, la correction peut très bien être nulle. Cela permet de découpler partiellement.


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2349060
MaybeEijOr​Not
but someone at least
Posté le 22-03-2020 à 19:30:22  profilanswer
 

Bon comme prévu, j'ai du temps en ce moment et j'ai passé mon code en objet (un peu à l'arrache) afin de faciliter l'implémentation de plusieurs instances : https://codepen.io/Perrier_ChouFleur/pen/qBdMVaP
 
code : [màj plus bas]
 
Je vais ajouter les fonctionnalités de magnétisme de la barre (déplacer de valeur en valeur) et l'utilisation inverse (saisie manuelle par l'utilisateur puis ajustement automatique de la barre).
Si tu as des bugs particuliers, je veux bien un jeu de données.


Message édité par MaybeEijOrNot le 24-03-2020 à 17:51:11

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2349190
MaybeEijOr​Not
but someone at least
Posté le 23-03-2020 à 18:17:45  profilanswer
 

Bon j'avance, ça commence à grossir un peu trop, mais tant pis. (codepen updated)
 
Pour l'utilisation inverse il faudrait que j'ajoute un listener d'évènement onChange sur les inputs, seulement quand on utilise la barre de la fourchette ces champs sont mis à jour par le JS, est-ce que cela déclenche l'évènement onChange ?
 
Le mode magnétique pour l'instant va coller automatiquement la barre sur la valeur la plus proche une fois que l'utilisateur relâche le curseur, je ne trouve pas ça terrible car il faut faire au moins 50% du chemin, limiter à 1/3 de parcours me semble plus approprié, tout comme le placement de la barre devrait se faire en direct sans attendre de relâcher le curseur (ne pas proposer un déplacement progressif de la barre). Vous en pensez quoi ? Sachant que ces deux choses vont bien alourdir le code.
 
Code : (comment le mettre en spoiler ?) [màj plus bas]


Message édité par MaybeEijOrNot le 24-03-2020 à 17:50:40

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2349232
rufo
Pas me confondre avec Lycos!
Posté le 23-03-2020 à 22:11:32  profilanswer
 

Merci pour ton boulot :jap:


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Cantine Calandreta : http://sourceforge.net/projects/canteen-calandreta
n°2349240
MaybeEijOr​Not
but someone at least
Posté le 23-03-2020 à 23:23:18  profilanswer
 

Ahah, j'avais des problèmes avec les évènements que j'ai trouvé en debuggant autre chose, j'ai passé 2 heures à les retourner dans tous les sens. :fou:  
Je posterai le code corrigé quand j'aurai ajouté le magnétisme.


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2349351
MaybeEijOr​Not
but someone at least
Posté le 24-03-2020 à 18:03:41  profilanswer
 

Bon j'ai quelque chose qui me plaît, ce n'est pas exactement ce que j'ai dit précédemment car je ne trouve pas ça si pertinent le replacement de la barre avant d'avoir relâcher la souris. Et l'histoire de magnétiser à partir de 1/3 du chemin et non 50 % ne me semble pas si importante dans cette utilisation, voire même trompeuse. De plus, cela redemande pas mal de travail je pense même si ça peut paraître simple, je suis déjà à environ une centaine de lignes de JS.
 
Et je viens de me rappeler que je voulais aussi utiliser ce genre de fourchette pour filtrer des tailles de fichiers d'ordres de grandeur différents (ko, Mo, Go). :pt1cable:  
 
Rufo, pour ce qui est de ton histoire de floor au lieu de round je ne comprends pas trop ce que ça va changer (en dehors des valeurs aux extrémités), le floor va sélectionner la valeur entre ]1;2] là où le round va sélectionner entre [1,5;2,5[ mais au final l'espace de sélection fait la même taille.
 
codepen.io : https://codepen.io/Perrier_ChouFleur/pen/qBdMVaP
 
code page de test :

Code :
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.  <meta charset="UTF-8">
  5.  <title>Custom range</title>
  6.  <style type="text/css">
  7.   body {
  8.    width: 100%;
  9.   }
  10.   div#main {
  11.    width: 100%;
  12.   }
  13.   input.scale {
  14.    width: 40px;
  15.    text-align: center;
  16.   }
  17.   div.rangecontainer {
  18.    height: 18px;
  19.    padding: 0px 4px 4px 4px;
  20.    border-style: solid;
  21.    border-width: 1px 1px 1px 1px;
  22.    border-color: #000000;
  23.   }
  24.   div#my1_range {
  25.    width: 20%;
  26.   }
  27.   div#my2_range {
  28.    width: 30%;
  29.   }
  30.   div.inrange {
  31.    background-color: #00CC00;
  32.   }
  33.   div.outrange {
  34.    padding: 0px 0px 0px 0px;
  35.    margin: 0px 0px 0px 0px;
  36.    background-color: #BBBBBB;
  37.   }
  38.   div.range {
  39.    height: 8px;
  40.   }
  41.   div.middle {
  42.    display: inline-block;
  43.    position: relative;
  44.    left: 0px;
  45.    height: 10px;
  46.    width: calc(100% - 38px);
  47.    box-sizing: border-box;
  48.    border-style: solid;
  49.    border-width: 1px 1px 1px 1px;
  50.    border-color: #666666;
  51.   }
  52.   div.left {
  53.    display: inline-block;
  54.    position: relative;
  55.    left: 16px;
  56.    height: 10px;
  57.    width: 2px;
  58.    box-sizing: border-box;
  59.    border-style: solid;
  60.    border-width: 1px 1px 1px 1px;
  61.    border-color: #666666;
  62.   }
  63.   div.right {
  64.    display: inline-block;
  65.    position: relative;
  66.    left: -16px;
  67.    height: 10px;
  68.    width: 2px;
  69.    box-sizing: border-box;
  70.    border-style: solid;
  71.    border-width: 1px 1px 1px 1px;
  72.    border-color: #666666;
  73.   }
  74.   div.circleleft {
  75.    display: inline-block;
  76.    position: relative;
  77.    top: 3px;
  78.    left: 8px;
  79.    width: 16px;
  80.    height: 16px;
  81.    box-sizing: border-box;
  82.    border-style: solid;
  83.    border-width: 1px 1px 1px 1px;
  84.    border-color: #666666;
  85.    border-radius: 8px;
  86.    z-index: 1;
  87.    cursor: pointer;
  88.   }
  89.   div.circleright {
  90.    display: inline-block;
  91.    position: relative;
  92.    top: 3px;
  93.    left: -8px;
  94.    width: 16px;
  95.    height: 16px;
  96.    box-sizing: border-box;
  97.    border-style: solid;
  98.    border-width: 1px 1px 1px 1px;
  99.    border-color: #666666;
  100.    border-radius: 8px;
  101.    z-index: 1;
  102.    cursor: pointer;
  103.   }
  104.  </style>
  105.  <script type="text/javascript">
  106.   class CustomRange {
  107.    constructor(name, magnetic = false) { //name has to match with the HTML IDs so replace each "my" in HTML by this name; magnetic (optionnal) --> false: disabled, true: automaticly adjust the range and the value selected to the closest existing value
  108.     this.name = name;
  109.     this.magnetic = magnetic; //set the magnetic option
  110.     this.filteredDatas = []; //no datas are already filtered
  111.     this.tempWidth = Math.round(document.getElementById(this.name + '_range').clientWidth - 8); //we will work in pixels so we round the value to get an integer (if css in percentages)
  112.     this.setWidth('_range', this.tempWidth); //we will work in pixels so we round the value to get an integer (if css in percentages)
  113.     this.setWidth('_middle', this.tempWidth - 38); //we will work in pixels so we round the value to get an integer (if css in percentages)
  114.    }
  115.    setDatas(datas) { //datas have to be an unidimensional array sorted in ascending order
  116.     this.datas = datas; //to sort your array, replace by: this.datas = datas.sort(function(a, b) { return a - b; });
  117.     this.min = this.datas[0]; //initiate the minimal value of your datas
  118.     this.max = this.datas[this.datas.length - 1]; //initiate the maximal value of your datas
  119.     this.maxWidth = this.getWidth('_middle') + 4; //calculate the max width of our range
  120.     this.filterMin = this.min; //initiate the minimal value filtered
  121.     this.filterMax = this.max; //initiate the maximal value filtered
  122.    }
  123.    rangeInit() {
  124.     //you could initiate with filters: this.filter();
  125.     document.getElementById(this.name + '_min').value = this.filterMin; //display the minimal value in the input
  126.     document.getElementById(this.name + '_max').value = this.filterMax; //display the maximal value in the input
  127.     eventManager('createMouseDownListener', this); //add events on the circles to capture when and which the client is clicking on
  128.     eventManager('createChangeListener', this); //add events on the inputs to capture when the client is changing the inputs values
  129.    }
  130.    filter() {
  131.     this.filteredDatas = this.datas.filter(a => a >= this.filterMin && a <= this.filterMax); //apply the filter limits :o
  132.    }
  133.    setWidth(el, width) { //set the width of an element
  134.     document.getElementById(this.name + el).style.width = width + 'px';
  135.    }
  136.    getWidth(el) { //set the width of an element
  137.     return document.getElementById(this.name + el).offsetWidth;
  138.    }
  139.    setInputsValues() {
  140.     document.getElementById(this.name + '_min').value = this.filterMin; //correct the displayed minimal value
  141.     document.getElementById(this.name + '_max').value = this.filterMax; //correct the displayed maximal value
  142.    }
  143.    rangeListener(e, sign) {
  144.     this.sign = sign; //define which circle (left or right) is moving and so which widthes we will adjust (left and mid or right and mid)
  145.     this.posX0 = e.clientX; //capturing from which position the cursor started
  146.    }
  147.    calculateWidthes(e) { //calculate widthes of elements while user is moving the range
  148.     this.deltaX = e.clientX - this.posX0; //how far we move the cursor
  149.     this.posX0 = e.clientX; //adjust the new position for the next iterations
  150.     this.elOutWidth = this.getWidth(this.rangeOut) + this.sign * this.deltaX; //the new outside width
  151.     this.elInWidth = this.getWidth('_middle') - this.sign * this.deltaX; //the new inside width
  152.     this.elOtherWidth = 2; //default other outside width
  153.     if(this.sign === 1) { //get the other outside width
  154.      this.elOtherWidth = this.getWidth('_right');
  155.     } else {
  156.      this.elOtherWidth = this.getWidth('_left');
  157.     }
  158.    }
  159.    straightProcess() {  //calculate the limits when user is moving the range and then updating inputs
  160.     this.left = this.getWidth('_left') / this.maxWidth; //how much represents the left outside with comparing to the total width
  161.     this.right = this.getWidth('_right') / this.maxWidth; //how much represents the right outside with comparing to the total width
  162.     this.filterMin = Math.round(this.min + this.left * (this.max - this.min)); //the minimal value filtered (minimum + value * maximal_delta)
  163.     this.filterMax = Math.round(this.max - this.right * (this.max - this.min)); //the maximal value filtered (maximum - value * maximal_delta)
  164.    }
  165.    reverseProcess(sign) { //adjust the positionning and widthes of elements when user is manually entering values
  166.     if(sign === 1) {
  167.      this.filterMin = document.getElementById(this.name + '_min').value; //find the minimal value filtered
  168.      this.left = (this.filterMin - this.min) / (this.max - this.min); //calculate how much represents the minimal value from the minimum compared to the total range
  169.      this.left = Math.round(this.left * (this.maxWidth - 4)); //calculate the width of the left element
  170.      if(this.left <= 2) { //minimal width is 2px
  171.       this.left = 2;
  172.      }
  173.      this.right = this.getWidth('_right'); //get the width of right side
  174.     } else {
  175.      this.filterMax = document.getElementById(this.name + '_max').value; //find the maximal value filtered
  176.      this.right = (this.max - this.filterMax) / (this.max - this.min); //calculate how much represents the maximal value from the maximum compared to the total range
  177.      this.right = Math.round(this.right * (this.maxWidth - 4)); //calculate the width of the right element
  178.      if(this.right <= 2) { //minimal width is 2px
  179.       this.right = 2;
  180.      }
  181.      this.left = this.getWidth('_left'); //get the width of left side
  182.     }
  183.     this.setWidth('_middle', this.maxWidth - this.left - this.right); //calculate and set the width of inside element
  184.     this.setWidth('_left', this.left); //set width of left element
  185.     this.setWidth('_right', this.right); //set width of right element
  186.    }
  187.    calculateMagneticValue() {
  188.     if(this.sign === 1) {
  189.      this.tempDatas = this.datas.map(a => a - this.filterMin); //calculate distances from the minimal user value to the existing datas values
  190.      this.magneticValue = calcMinAbsoluteNeg(this.tempDatas); //find the lower distance between the minimal user value and the existing datas values, priority to the left values
  191.      this.magneticValue = this.tempDatas.indexOf(this.magneticValue); //find the near minimal value corresponding to the lower distance, priority to the left values
  192.      this.magneticValue = this.datas[this.magneticValue]; //update the minimal filtered value
  193.      if(this.filterMin !== this.magneticValue) { //test if the magnetic value is different or not of the previous filtered value
  194.       this.filterMin = this.magneticValue; //update the minimal value to filter
  195.       return true;
  196.      } else {
  197.       return false;
  198.      }
  199.     } else {
  200.      this.tempDatas = this.datas.map(a => a - this.filterMax); //calculate distances from the maximal user value to the existing datas values
  201.      this.magneticValue = calcMinAbsolutePos(this.tempDatas); //find the lower distance between the maximal user value and the existing datas values, priority to the right values
  202.      this.magneticValue = this.tempDatas.indexOf(this.magneticValue); //find the near maximal value corresponding to the lower distance, priority to the right values
  203.      this.magneticValue = this.datas[this.magneticValue]; //update the maximal filtered value
  204.      if(this.filterMax !== this.magneticValue) { //test if the magnetic value is different or not of the previous filtered value
  205.       this.filterMax = this.magneticValue; //update the maximal value to filter
  206.       return true;
  207.      } else {
  208.       return false;
  209.      }
  210.     }
  211.    }
  212.    resizeOnMove() { //adjust the positionning and widthes of elements while user is moving the range, depending of widthes calculates in calculateWidthes(e)
  213.     if(this.elOutWidth > 2 && this.elInWidth >= 2 && this.elOtherWidth >= 2 && (this.elOutWidth + this.elInWidth + this.elOtherWidth) == this.maxWidth) { //if we are not over the range
  214.      this.setWidth(this.rangeOut, this.elOutWidth); //define the outside width
  215.      this.setWidth('_middle', this.elInWidth); //define the inside width
  216.     } else if(this.elOutWidth <= 2) { //if we reach the min or max limit
  217.      this.setWidth(this.rangeOut, 2); //define the outside width to the minimal width
  218.      this.setWidth('_middle', this.maxWidth - this.elOtherWidth - 2); //define the inside width depending on the previous minimal width and the other outside width
  219.     } else { //if we reach the other limit
  220.      this.setWidth(this.rangeOut, this.maxWidth - this.elOtherWidth - 2); //define the outside width depending on the next minimal width and the other outside width
  221.      this.setWidth('_middle', 2); //define the inside width to the minimal width
  222.     }
  223.    }
  224.    adjustOnMove(e) {
  225.     if(this.sign === 1) { //the sign define if we move the left or the right circle
  226.      this.rangeOut = '_left';
  227.     } else {
  228.      this.rangeOut = '_right';
  229.     }
  230.     this.calculateWidthes(e);
  231.     this.straightProcess();
  232.     if(this.magnetic === false) {
  233.      this.setInputsValues();
  234.      this.resizeOnMove();
  235.     } else {
  236.      this.resizeOnMagnetic = this.calculateMagneticValue();
  237.      this.setInputsValues();
  238.      this.resizeOnMove();
  239.     }
  240.    }
  241.    validateOnMouseUp() { //correct values, positionning and widthes when the user is releasing the mouse click, depending on options selected
  242.     if(this.magnetic === true && this.resizeOnMagnetic === true) {
  243.      this.reverseProcess(this.sign); //correct the range position to the magnetic value on release
  244.     }
  245.     this.filter(); //apply the filter
  246.    }
  247.   }
  248.   function calcMinAbsoluteNeg(a) { //calculate the minimum of absolute values of an array, priority to negative values
  249.    let min = a[0];
  250.    for(let i = 1; i < a.length; i++) {
  251.     if(Math.abs(a[i]) < Math.abs(min)) {
  252.      min = a[i];
  253.     } else if(Math.abs(a[i]) == Math.abs(min) && a[i] < min) {
  254.      min = a[i];
  255.     }
  256.    }
  257.    return min;
  258.   }
  259.   function calcMinAbsolutePos(a) { //calculate the minimum of absolute values of an array, priority to positive values
  260.    let min = a[0];
  261.    for(let i = 1; i < a.length; i++) {
  262.     if(Math.abs(a[i]) < Math.abs(min)) {
  263.      min = a[i];
  264.     } else if(Math.abs(a[i]) == Math.abs(min) && a[i] > min) {
  265.      min = a[i];
  266.     }
  267.    }
  268.    return min;
  269.   }
  270.   function eventManager(fct, myObj) {
  271.    function magic1(e) {
  272.     myObj.adjustOnMove(e); //resizing and repositionning the different elements when the user is adjusting the range
  273.    }
  274.    function magic2(evt) {
  275.     document.removeEventListener('mousemove', magic1, false); //removing the MouseMove event listener when we release the circle
  276.     myObj.validateOnMouseUp(); //validate filter
  277.     document.removeEventListener('mouseup', magic2, false);
  278.    }
  279.    function createMouseDownListener() {
  280.     document.getElementById(myObj.name + '_circleright').addEventListener('mousedown', function(e) {
  281.      document.addEventListener('mousemove', magic1, false);
  282.      document.addEventListener('mouseup', magic2, false);
  283.      myObj.rangeListener(e, -1); //send -1 to define the right circle is selected
  284.     }, false);
  285.     document.getElementById(myObj.name + '_circleleft').addEventListener('mousedown', function(e) {
  286.      document.addEventListener('mousemove', magic1, false);
  287.      document.addEventListener('mouseup', magic2, false);
  288.      myObj.rangeListener(e, 1); //send 1 to define the left circle is selected
  289.     }, false);
  290.    }
  291.    function createChangeListener() {
  292.     document.getElementById(myObj.name + '_min').addEventListener('change', function(e) {
  293.      myObj.reverseProcess(1); //resizing and repositionning the different elements when the user is changing the value
  294.      myObj.validateOnMouseUp();
  295.     }, false);
  296.     document.getElementById(myObj.name + '_max').addEventListener('change', function(e) {
  297.      myObj.reverseProcess(-1); //resizing and repositionning the different elements when the user is changing the value
  298.      myObj.validateOnMouseUp();
  299.     }, false);
  300.    }
  301.    switch(fct) {
  302.     case 'createMouseDownListener':
  303.      createMouseDownListener();
  304.      break;
  305.     case 'createChangeListener':
  306.      createChangeListener();
  307.      break;
  308.    }
  309.   }
  310.   function init() {
  311.    const test1 = new CustomRange('my1');
  312.    test1.setDatas([1964, 1998, 1999, 2001, 2003, 2008, 2012, 2016, 2017, 2018, 2019]);
  313.    test1.rangeInit();
  314.    const test2 = new CustomRange('my2', true);
  315.    test2.setDatas([1964, 1998, 1999, 2001, 2003, 2008, 2012, 2016, 2017, 2018, 2019]);
  316.    test2.rangeInit();
  317.   }
  318.  </script>
  319. </head>
  320. <body onLoad="init();">
  321.  <div id="main">
  322.   <div id="my1_scale">
  323.    <form>
  324.     <span>min - max : </span><input class="scale" type="text" pattern="[0-9]{4}" id="my1_min"><span> - </span><input class="scale" type="text" pattern="[0-9]{4}" id="my1_max">
  325.    </form>
  326.   </div>
  327.   <div class="rangecontainer" id="my1_range">
  328.    <div class="range outrange left" id="my1_left"></div><div class="inrange circleleft" data-sign="1" id="my1_circleleft"></div><div class="range inrange middle" id="my1_middle"></div><div class="inrange circleright" data-sign="-1" id="my1_circleright"></div><div class="range outrange right" id="my1_right"></div>
  329.   </div>
  330.   <div id="my2_scale">
  331.    <form>
  332.     <span>min - max : </span><input class="scale" type="text" pattern="[0-9]{4}" id="my2_min"><span> - </span><input class="scale" type="text" pattern="[0-9]{4}" id="my2_max">
  333.    </form>
  334.   </div>
  335.   <div class="rangecontainer" id="my2_range">
  336.    <div class="range outrange left" id="my2_left"></div><div class="inrange circleleft" data-sign="1" id="my2_circleleft"></div><div class="range inrange middle" id="my2_middle"></div><div class="inrange circleright" data-sign="-1" id="my2_circleright"></div><div class="range outrange right" id="my2_right"></div>
  337.   </div>
  338.  </div>
  339. </body>
  340. </html>


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2349372
rufo
Pas me confondre avec Lycos!
Posté le 24-03-2020 à 20:10:44  profilanswer
 

Pour mon histoire de date, le floor a son importance dans le cas où on a 1px du range qui représente plusieurs valeurs. Je travaille avec des dates sous la forme de timestamp (pour travailler avec des int). Avec le round, je peux me retrouver sur le pixel qui correspond à une valeur > à celle que je veux imposer pour la borne min. Pareil pour la borne max. Du coup, ça filtre plus et mes objets qui ont les dates correspondant exactement aux dates min et max positionnées ne sont pas sélectionnées mais hors de la plage de sélection.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Cantine Calandreta : http://sourceforge.net/projects/canteen-calandreta
n°2349381
MaybeEijOr​Not
but someone at least
Posté le 24-03-2020 à 20:53:12  profilanswer
 

Un calendrier pouvant faire défiler les mois et années, affichant les jours du mois, comme le calendrier Windows n'aurait-il pas été plus approprié dans ton cas ?
L'utilisateur sélectionne alors la date minimale sur le calendrier puis la date maximale, de la même manière que les applis de réservation.
 
Sinon en intégrant mon code à mon projet, j'ai eu un petit problème, les données que je passais n'étaient pas de vrais integer mais des string. -_-'
Il suffit alors de faire une conversion :
datas = datas.map(a => +a);


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2349388
rufo
Pas me confondre avec Lycos!
Posté le 24-03-2020 à 22:40:15  profilanswer
 

Moi, j'ai utilisé parseInt().
Pour le coup du calendrier, oui, ça aurait été plus simple mais on m'a demandé une timeline.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Cantine Calandreta : http://sourceforge.net/projects/canteen-calandreta
n°2349392
MaybeEijOr​Not
but someone at least
Posté le 24-03-2020 à 23:35:34  profilanswer
 

Je ne sais plus pourquoi exactement mais le parseInt n'est pas formidable de souvenir, le +variable est ce qui fonctionne le mieux au niveau de la conversion (ça convertit certains exemple qui ne passent pas avec le parseInt).


Message édité par MaybeEijOrNot le 24-03-2020 à 23:36:58

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2349420
rufo
Pas me confondre avec Lycos!
Posté le 25-03-2020 à 10:55:43  profilanswer
 

Ca pose peut-être des pbs avec des nombres écrits en hexa ?


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Cantine Calandreta : http://sourceforge.net/projects/canteen-calandreta
n°2349484
MaybeEijOr​Not
but someone at least
Posté le 25-03-2020 à 13:47:47  profilanswer
 

C'est moi qui ne suit plus vraiment à jour et qui confond en plus.

 

Depuis ECMA15 il n'y a plus besoin de spécifier la base avec parseInt, avant certains cas ne passaient pas sans spécifier la base, notamment les nombres commençant par un 0 (genre les heures : 3h08).
Mais j'ai pris l'habitude d'utiliser le +var parce que ça fonctionne sur des entiers comme des décimaux, dans ce cas là il existe Nombre(var)...


Message édité par MaybeEijOrNot le 25-03-2020 à 13:48:11

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  HTML/CSS

  Création d'un range personnalisé (fourchette)

 

Sujets relatifs
Création d'un "select" personnalisé[Aide] Création jeu textuel
Création site web gestion serveurs minecraftCréation site web gestion serveurs minecraft
création d'u petit gestionnaire de contactscréation d'u petit gestionnaire de contacts
Création d'une alarme et gestion du mode veille d'un téléphoneCréation d'une liste en SQL
Création base de données avec Entity code first 
Plus de sujets relatifs à : Création d'un range personnalisé (fourchette)


Copyright © 1997-2018 Hardware.fr SARL (Signaler un contenu illicite) / Groupe LDLC / Shop HFR