Function Optimization (probably with for loop)

Asked

Viewed 85 times

4

I’m having trouble developing when we talk about for... The basics I can understand now in practice... People have developed this code and I believe it can be reduced to a few lines with for.

Notice that when changing the input range, it appears different buttons (the determined ones) and closes the open button Ivs. When we press these buttons he opens his div and closes the rest.

If necessary I have made available the simplified code below!

Here begins the Js

        /* Dinâmica do Input Range */
        function updateTextInput(val) {

            /* Para controlar os Botões */
            if(val == 1){ 
                document.getElementById('um').style.display = "block";
                document.getElementById('dois').style.display = "block";
                document.getElementById('tres').style.display = "none";
                document.getElementById('quatro').style.display = "none";
                document.getElementById('cinco').style.display = "none";

            }
            if(val == 2){ 
                document.getElementById('um').style.display = "block";
                document.getElementById('dois').style.display = "block"; 
                document.getElementById('tres').style.display = "block";
                document.getElementById('quatro').style.display = "none";
                document.getElementById('cinco').style.display = "none";
            }
            if(val == 3){ 
                document.getElementById('um').style.display = "block";
                document.getElementById('dois').style.display = "block"; 
                document.getElementById('tres').style.display = "block";
                document.getElementById('quatro').style.display = "block";
                document.getElementById('cinco').style.display = "none";
            }
            if(val == 4){ 
                document.getElementById('um').style.display = "block";
                document.getElementById('dois').style.display = "block"; 
                document.getElementById('tres').style.display = "block";
                document.getElementById('quatro').style.display = "block";
                document.getElementById('cinco').style.display = "block";
            }

            /* Para controlar as Slide's Div */
            document.getElementById('slideum').style.display = "none";
            document.getElementById('slidedois').style.display = "none"; 
            document.getElementById('slidetres').style.display = "none";
            document.getElementById('slidequatro').style.display = "none";
            document.getElementById('slidecinco').style.display = "none";
        }

        /* Dinâmica do Input Button */
        function slideumf(){
            document.getElementById('slideum').style.display = "block";
            document.getElementById('slidedois').style.display = "none"; 
            document.getElementById('slidetres').style.display = "none";
            document.getElementById('slidequatro').style.display = "none";
            document.getElementById('slidecinco').style.display = "none";
        }
        function slidedoisf(){
            document.getElementById('slideum').style.display = "none";
            document.getElementById('slidedois').style.display = "block"; 
            document.getElementById('slidetres').style.display = "none";
            document.getElementById('slidequatro').style.display = "none";
            document.getElementById('slidecinco').style.display = "none";
        }
        function slidetresf(){
            document.getElementById('slideum').style.display = "none";
            document.getElementById('slidedois').style.display = "none"; 
            document.getElementById('slidetres').style.display = "block";
            document.getElementById('slidequatro').style.display = "none";
            document.getElementById('slidecinco').style.display = "none";
        }
        function slidequatrof(){
            document.getElementById('slideum').style.display = "none";
            document.getElementById('slidedois').style.display = "none"; 
            document.getElementById('slidetres').style.display = "none";
            document.getElementById('slidequatro').style.display = "block";
            document.getElementById('slidecinco').style.display = "none";
        }
        function slidecincof(){
            document.getElementById('slideum').style.display = "none";
            document.getElementById('slidedois').style.display = "none"; 
            document.getElementById('slidetres').style.display = "none";
            document.getElementById('slidequatro').style.display = "none";
            document.getElementById('slidecinco').style.display = "block";
        }
    </script>

Here begins the CSS

        /* Style Inicial dos Inputs Button */
        #um{display: none;}
        #dois{display: none;}
        #tres{display: none;}
        #quatro{display: none;}
        #cinco{display: none;}

        /* Style Inicial das Div's dos Slides */
        #slideum{display: none;}
        #slidedois{display: none;}
        #slidetres{display: none;}
        #slidequatro{display: none;}
        #slidecinco{display: none;}
    </style>
</head>

Here Begins the HTML5

          <input type="range" name="rangeInput" min="1" max="4" onchange="updateTextInput(this.value);">
         <input id="um" type="button" value="1º Slide" onclick="slideumf()">
         <div id="slideum">
         <input type="range" min="1" max="5"><div id="slideum">1º Slide</div>
    <input id="dois" type="button" value="2º Slide" onclick="slidedoisf()">
    <div id="slidedois">2º Slide</div>
    <input id="tres" type="button" value="3º Slide" onclick="slidetresf()">
    <div id="slidetres">3º Slide</div>
    <input id="quatro" type="button" value="4º Slide" onclick="slidequatrof()">
    <div id="slidequatro">4º Slide</div>
    <input id="cinco" type="button" value="5º Slide" onclick="slidecincof()">
    <div id="slidecinco">5º Slide</div>
</body>

  • Post HTML as well, if possible. Otherwise we won’t be able to test possible solutions.

  • When I posted the question, she was already following the HTML. It’s down there, kkk It’s really short!

  • A yes, had not rolled enough. But it is good to separate when posting.

  • I’m new to the forum, I haven’t learned the tricks yet! I’ll try!

  • One thing I realized is that the first two buttons are always used. So you can delete the first one if of the first function and leave the first two lines before the if’s.

  • Mutlei, well noted but early on only the input range is visible... But you can still leave 1 and 2 displayBlock independent of if on onchange!

Show 1 more comment

2 answers

5


This code can be much reduced... there’s a lot of repetition there.

Hint (with slight HTML modifications -> see example below):

var slides = Array.from(document.querySelectorAll('input[type="button"]'));
var slideTexts = Array.from(document.querySelectorAll('div'));

/* Dinâmica do Input Range */
function onSliderChange(val) {
    slides.forEach(function(slide, i) {
        slide.style.display = i <= val ? 'block' : 'none';
    });
    toggleSlidetext();
}

function toggleSlidetext(id) {
    var which = document.getElementById(id);
    slideTexts.forEach(function(div) {
        div.style.display = div == which ? 'block' : 'none';
    });
}

Explanation:

The idea is to put the elements in question in memory. slides and slideTexts That’s right, Arrays with pointers to the elements.

When onSliderChange be called, go through all slides and compares the index (i) with the val which is passed down. Then he calls toggleSlidetext without any value, to hide all.

The logic of toggleSlidetext is similar. Traverses all elements and compares if the div to be iterated is the same as which. We could compare like this:

div.style.display = div.id == id ? 'block' : 'none';

and dispense with the logic of which.

Example: https://jsfiddle.net/un3gkrvv/

var slides = Array.from(document.querySelectorAll('input[type="button"]'));
var slideTexts = Array.from(document.querySelectorAll('div'));

/* Dinâmica do Input Range */
function onSliderChange(val) {
    slides.forEach(function(slide, i) {
        slide.style.display = i <= val ? 'block' : 'none';
    });
    toggleSlidetext();
}

function toggleSlidetext(id) {
    var which = document.getElementById(id);
    slideTexts.forEach(function(div) {
        div.style.display = div == which ? 'block' : 'none';
    });
}
/* Style Inicial dos Inputs Button */

#um {
    display: none;
}

#dois {
    display: none;
}

#tres {
    display: none;
}

#quatro {
    display: none;
}

#cinco {
    display: none;
}


/* Style Inicial das Div's dos Slides */

#slideum {
    display: none;
}

#slidedois {
    display: none;
}

#slidetres {
    display: none;
}

#slidequatro {
    display: none;
}

#slidecinco {
    display: none;
}
<input type="range" name="rangeInput" min="1" max="4" onchange="onSliderChange(this.value);">
<input id="um" type="button" value="1º Slide" onclick="toggleSlidetext('slideum')">
<div id="slideum">1º Slide</div>
<input id="dois" type="button" value="2º Slide" onclick="toggleSlidetext('slidedois')">
<div id="slidedois">2º Slide</div>
<input id="tres" type="button" value="3º Slide" onclick="toggleSlidetext('slidetres')">
<div id="slidetres">3º Slide</div>
<input id="quatro" type="button" value="4º Slide" onclick="toggleSlidetext('slidequatro')">
<div id="slidequatro">4º Slide</div>
<input id="cinco" type="button" value="5º Slide" onclick="toggleSlidetext('slidecinco')">
<div id="slidecinco">5º Slide</div>

  • Thanks Sergio! That’s what I wanted... Is there any way to explain your reasoning and the code? Valeuu

  • @Giancarlosolderagraziano great! Yes, of course, I joined explanation.

3

Your code has some CSS problems (and as @Sergio explained in his reply) a lot of repetition. Since your question is "how to optimize function". (link to example in Jsbin)

We start by redesigning your HTML: a slide, in reality, is nothing more than a section of your site. In your case, with a button that toggle the content.

<input type="range" value="6" name="rangeInput" min="1" max="6" onchange="onSliderChange(this.value);" />
<section class="slide-wrap">
    <button class="toggle-slide" onclick="toggleSliderContent(this)">1º Slide</button>
    <div class="slide-content hidden">Conteudo do 1º Slide</div>
</section>

By removing Ids and adding classes, we make not only our CSS much smaller but also our Javascript more concise - since we can point to several elements at once.

All classes in the above section, with the exception of hidden, are for our Javascript.

Then we add to CSS the simple rule of .hidden { display:none }

Let’s move on to Javascript: Now that we have a more prepared HTML and we already have the onclick from the button, let’s attack this first:

/** Quando clicamos no botão de mostrar o slide, o botão envia-se a ele mesmo
* como argumento, depois é só subirmos a DOM Tree até ao elemento parente e descermos
* à procura do element que contém o conteúdo do slide. Procuramos depois por um
* elemento que seja "slide-content" mas que não tenha a class "hidden" (e podemos 
* assumir que esse é o element que está visivel) - se este existir, então adicionarmos
* a class "hidden" e por fim removemos a class "hidden" do slide que queremos mostrar
*/
function toggleSliderContent(element) {
  var showSlideContent = element.parentNode.querySelector('.slide-content');
  var hidePrevious = document.querySelector('.slide-content:not(.hidden)');
  if (hidePrevious) hidePrevious.classList.add('hidden');
  showSlideContent.classList.remove('hidden');
}

We bridge the functionality with the reference of onchange of input:

var slides = document.querySelectorAll('section.slide-wrap');
/** Podias estar tentado a fazer um cast desta NodeList para array
* mas existem iteradores expecificos para a NodeList */

function onSliderChange(number) {
  var entry, slideElement, slideIndex;

  /** Para cada node na lista de slides, */
  for (entry of slides.entries()) {
    slideElement = entry[1];
    slideIndex = entry[0];

    /** se o index do slide que estamos a ver for menor que o numero
    * de slides que queremos mostrar e o elemento tiver a class "hidden"
    * então, remove a class para esse elemento aparecer: */
    if (slideIndex <= number && slideElement.classList.contains('hidden')) {
      slideElement.classList.remove('hidden');
    } else if (slideIndex >= number && !slideElement.classList.contains('hidden')) {
      /** de contrario, adiciona a class "hidden" para o elmento desaparecer */
      slideElement.classList.add('hidden');
    }
  }
}
  • I really liked this idea of a single class for visibility, even more of the dynamics of function with her help. I have already optimized the code based on Sergio’s response (nothing prevents to adapt dnv) and when I was moving forward I realized that maybe it can be optimized even more! In the same idea of input range for creating the slides, and from the definition of the number of slides appear the buttons to the respective ones, I would like that when pressing these buttons appear an equal only that groups an input range asking qnts media queries(max 5) and a button for each of them. I ask you, is there any way?

  • @Giancarlosolderagraziano you have to explain better that I didn’t realize

  • I will change the question by adding the code that induces what I want to do. After that I believe you will understand! qlqr thing just write here div kk

  • Ready! Look at that!

  • Giancarlosolderagraziano will be easier to open a new question and separate the two problems for the @Sergio answer do not stay out of Cope [and your question will not be closed for "ample more"]

  • truth! I was thinking about it

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.