11528 sujets

JavaScript, DOM et API Web HTML5

Bonsoir à tous,

Dans la suite de ce topic. J'ai réussi à obtenir le comportement attendu grace à deux écouteurs d'événement. Le problème étant que je duplique mon code :
input[0].oninput = function() {
  valStop = Number(input[1].value)
  output.textContent = `${this.value}-${valStop}`
  input[1].value = (valStop > Number(this.value)) ? valStop : (Number(this.value) + step)
}

input[0].onchange = function() {
  valStop = Number(input[1].value)
  output.textContent = `${this.value}-${valStop}`
  input[1].value = (valStop > Number(this.value)) ? valStop : (Number(this.value) + step)
}

Comment factoriser ces deux appels à la même fonction que je duplique ici (J'ai tenté plusieurs solutions que je passe sous silence pour éviter de vous disperser).

Le code dans son contexte : CodePen
Modifié par Olivier C (07 Dec 2022 - 05:39)
Modérateur
Salut,

Je t'invite à lire ceci [^1]

const rangeMultithumb = (() => {
    let eventsSelect = ['input', 'change'];
    let eventsInputs = {
        change_min(e, params){
            let currentTargetValue = e.currentTarget.value;
            params.valStop = Number(params.inputMax.value)
            params.output.textContent = `${currentTargetValue}-${params.valStop}`
            params.inputMax.value = (params.valStop > Number(currentTargetValue)) ? params.valStop : (Number(currentTargetValue) + params.step)
        },
        change_max(e, params){
            let currentTargetValue = e.currentTarget.value;
            params.valStart = Number(params.inputMin.value)
            params.output.textContent = `${params.valStart}-${currentTargetValue}`
            params.inputMin.value = (params.valStart < Number(currentTargetValue)) ? params.valStart : (Number(currentTargetValue) - params.step)
        }
    };


    document.querySelectorAll('.range-multithumb').forEach(range => {
        const [inputMin, inputMax] = range.querySelectorAll('input') 
        const params = {
            inputMin,
            inputMax,
            output : range.querySelector('output'),
            step : Number(inputMin.step),
            valStart : Number(inputMin.value),
            valStop : Number(inputMax.value),
        }

        params.output.textContent = `${params.valStart}-${params.valStop}`;
        // @see  https://stackoverflow.com/questions/8796988/binding-multiple-events-to-a-listener-without-jquery
 
        eventsSelect.forEach(event_type =>{
            inputMin.addEventListener(event_type, e => eventsInputs.change_min(e, params))
            inputMax.addEventListener(event_type, e => eventsInputs.change_max(e, params))
        });
    })
})()


Tu as le codepen ici

[^1] peut être, on peut améliorer.
Modifié par niuxe (07 Dec 2022 - 00:19)
Ouf ! il va falloir que je décortique... (édit : ton code est nettement plus lisible pour moi si je commence par la deuxième partie)

Je te remercie.

Je vais récupérer tel et tel concept que je comprends et les intégrer petit à petit pour m'approprier le code. Parce que, hormis ma question d'origine, il y a des trucs qui m'intéressent et auxquels je n'avais pas pensé, par exemple :
const [inputMin, inputMax] = range.querySelectorAll('input')

Modifié par Olivier C (07 Dec 2022 - 07:12)
Modérateur
il n'y a rien de compliqué. La base de ton code est la même. Le code que je t'ai présenté, ce ne sont que des pirouettes syntaxiques.

ce code

const params = {
    inputMin,
    inputMax,
    // ....
}


est l'équivalent de :

const params = {
    inputMin: inputMin,
    inputMax: inputMax,
    // ....
}

et celui ci

let eventsInputs = {
    change_min(e, params){
        let currentTargetValue = e.currentTarget.value;
        params.valStop = Number(params.inputMax.value)
        params.output.textContent = `${currentTargetValue}-${params.valStop}`
        params.inputMax.value = (params.valStop > Number(currentTargetValue)) ? params.valStop : (Number(currentTargetValue) + params.step)
    },
    // ...
};

est l'équivalent de

let eventsInputs = {
    change_min: (e, params) =>{
        let currentTargetValue = e.currentTarget.value;
        params.valStop = Number(params.inputMax.value)
        params.output.textContent = `${currentTargetValue}-${params.valStop}`
        params.inputMax.value = (params.valStop > Number(currentTargetValue)) ? params.valStop : (Number(currentTargetValue) + params.step)
    },
    // ...
};

Modifié par niuxe (07 Dec 2022 - 11:49)
Salut,

En solution simple, au lieu de declarer des fonctions anonymes, je pense que tu peux déclarer des fonctions et les nommer puis les affecter aux events voulus, un truc dans le genre :

    function stopPlus(){
      valStop = Number(stop.value)
			output.textContent = `${this.value}-${valStop}`
      stop.value = (valStop > Number(this.value)) ? valStop : (Number(this.value) + step)
    }
    
    function stopMoins(){
      valStart = Number(start.value)
			output.textContent = `${valStart}-${this.value}`
      start.value = (valStart < Number(this.value)) ? valStart : (Number(this.value) - step)
    }
    
		start.oninput = stopPlus;

		stop.oninput = stopMoins;

		start.onchange = stopPlus;

		stop.onchange = stopMoins;
Meilleure solution
Mathieuu a écrit :
start.oninput = stopPlus;
stop.oninput = stopMoins;
start.onchange = stopPlus;
stop.onchange = stopMoins;

A ben volà ! il était là le hic : j'avais essayé cette solution mais j'avais mis des parenthèses aux fonctions, comme ceci :
start.oninput = stopPlus();

Et ensuite je me perdais sur de faustes pistes de déboguage...

Merci beaucoup. C'est encore plus important pour moi de comprendre mon erreur que de trouver une solution.
Pour la postérité (si le codepen est supprimé un jour), voici ce que peut donner le code (ton code fonctionne très bien niuxe, mais celui-ci sera plus simple à maintenir pour moi parce que je le comprend mieux d'emblée) :
const rangeMultithumb = (() => {
  document.querySelectorAll('.range-multithumb').forEach(range => {

    const [start, stop] = range.querySelectorAll('input')
    const output = range.querySelector('output')
    const step = Number(start.getAttribute('step'))
    let valStart = Number(start.value)
    let valStop = Number(stop.value)
    let scope = Number(stop.max) - Number(stop.min)
    let percentStart = (100 / Number(stop.max)) * valStart
    let percentStop = (100 / Number(stop.max)) * valStop
    
    range.style.setProperty('--start', `${percentStart}%`)
    range.style.setProperty('--stop', `${percentStop}%`)
    output.textContent = `${valStart}-${valStop}`
    display(valStart, valStop)
    
    function display(start, stop){
      output.textContent = `${start}-${stop}`
    }
    
    function startCursor(){
      valStop = Number(stop.value)
      display(this.value, valStop)
      stop.value = (valStop > Number(this.value)) ? valStop : (Number(this.value) + step)
      range.style.setProperty('--start', `${(100 / Number(stop.max)) * this.value}%`)
      range.style.setProperty('--stop', `${(100 / Number(stop.max)) * stop.value}%`)
    }

    function stopCursor(){
      valStart = Number(start.value)
      display(valStart, this.value)
      start.value = (valStart < Number(this.value)) ? valStart : (Number(this.value) - step)
      range.style.setProperty('--start', `${(100 / Number(stop.max)) * start.value}%`)
      range.style.setProperty('--stop', `${(100 / Number(stop.max)) * this.value}%`)
    }

    start.oninput = startCursor
    start.onchange = startCursor

    stop.oninput = stopCursor
    stop.onchange = stopCursor

  })
})()

Modifié par Olivier C (12 Dec 2022 - 02:55)