1

Im programming a calculator and Im trying that all the buttons in the same column has the same width. For that Im using jQuery (Im doing it this way cause I have an exam in some days and I wanna practice).

My HTML code:

<html>
  <head>
    <meta charset="UTF-8">
    <title>CORE2017 P3</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script type="text/javascript" src="calculadora.js"></script>
    <link href="calculadora.css" rel="stylesheet" type="text/css" media="all">
  </head>
  <body onload="igualarBotones()">
    <header>
      <p>Calculator</p>
    </header>
    <section id="main">
      <p>
        Número: <input type="text" id="pantalla"> <button id="Limpiar">Limpiar</button>
      </p>

      <p>
        <button id="suma" class="columna1">+</button>
        <button id="resta" class="columna2">-</button>
        <button id="cuadrado" class="columna3">x<sup>2</sup></button>
      </p>
      <p>
        <button id="inverso" class="columna1">1/x</button>
        <button id="raiz" class="columna2">sqrt(x)</button>
        <button id="pentera" class="columna3">parte_entera(x)</button>
      </p>
      <p>
        <button id="potencia2" class="columna1">2<sup>x</sup></button>
        <button id="factorial" class="columna2">x!</button>
        <button id="igual" class="columna3">=</button>
      </p>


    </section>
  </body>
</html>

My JavaScript code:

$(function() {
  function igualarBotones(){   
    var columna1 = $(".columna1");
    setMax(columna1);    
    var columna2 = $(".columna2");
    setMax(columna2);
    var columna3 = $(".columna3");
    setMax(columna3);
  }

  function setMax(columna){
    var maxColumna = -1;
    for(i=0; i<columna.length; i++){
      if(columna[i].css("width") > maxColumna){        
        maxColumna = columna[i].css("width");
      }
    }
    for(i=0; i<columna.length; i++){
      columna[i].css("width",maxColumna);
    }
  }

});

Anyone knows why it isnt working?

EDIT: I used $(columna[i]).css instead of columna[i].css and it worked. However I dont achieve that my function igualarBotones() gets defined when loading the body, I think it must be something related to how I named or wrote the function. If I write the Javascript this way:

$(function() {
  var columna1 = $(".columna1");
  setMax(columna1);    
  var columna2 = $(".columna2");
  setMax(columna2);
  var columna3 = $(".columna3");
  setMax(columna3);

  function setMax(columna){
    var maxColumna = -1;
    for(i=0; i<columna.length; i++){
      if(parseFloat($(columna[i]).css("width")) > parseFloat(maxColumna)){        
        maxColumna = $(columna[i]).css("width");
      }
    }
    columna.css("width",maxColumna);    
  }  
});

it works, but I want to do it with a function igualarBotones() that gets loaded with the body. Any idea what am I doing wrong?

Thank you all, Luis.

Luiscri
  • 913
  • 1
  • 13
  • 40
  • 1
    Use css flexbox...no need for script to do this – charlietfl Jul 08 '17 at 13:55
  • I know, but I wanna practice jQuery and this was a way I could test jQuery. css() method. Could it be done as I showed on the post? – Luiscri Jul 08 '17 at 14:00
  • I would suggest using CSS for this, the problem in your code is that you're looping the non-jquery way.. your logic should work if you used `$(columna[i])` instead of `columna[i]` - if you're going the jquery route - i strongly suggest used the `.each` function – Gulfaraz Rahman Jul 08 '17 at 14:01
  • Change `columna[i]` to `columna.eq(i)`. The first returns an element... second returns jQuery object for element – charlietfl Jul 08 '17 at 14:02

2 Answers2

1

The issue is understanding the different between jquery representation of elements and "raw" elements in javascript.

Given var columna1 = $(".columna1"); what this means is that it will return a jquery object that is a collection of all elements that the selector (.column1 in this case) has specified.

When you iterate through this jquery collection (columna[i]) you don't get a jquery representation of the elements but actually the raw elements themselves (or a native javascript representation of the elements). Native javascript elements do not have a .css function.

So when you wrap each element around $(...) by doing this $(columna[i])you are then once again dealing with a jquery representation of each element and as such you are able to use .css. That is why the former does not work and the later works.

EXTRA SUGGESTION

Since you are learning jquery let me add this: Jquery has a .each function that you should actually use to loop over a jquery object that contains elements.

So this function:

function setMax(columna){
    var maxColumna = -1;
    for(i=0; i<columna.length; i++){
        if(parseFloat($(columna[i]).css("width")) > parseFloat(maxColumna)){        
            maxColumna = $(columna[i]).css("width");
        }
    }
    columna.css("width",maxColumna);    
}   

Could/Should be:

function setMax(columna){
    var maxColumna = -1;
    columna.each(function(){
        // note the use of "this" to represent each 
        // element currently being iterated over.
        // this = raw element, $(this) = jquery object representing element.
        if(parseFloat($(this).css("width")) > parseFloat(maxColumna)){        
            maxColumna = $(this).css("width");
        }
    });
    columna.css("width",maxColumna);    
} 

LAST TIP

I personally assist/help myself remember jquery object in my javascript code by prepending $ to all variables that are jquery objects so as to not forget them.

So this:

var columna1 = $(".columna1");

Would be:

var $columna1 = $(".columna1");
Zuks
  • 1,247
  • 13
  • 20
0

I'm not familiar with a .css function in vanilla javascript. I changed that so it would call the jQuery .css function. Also, at least in the pen, the function wasn't defined when the body was loading. Something is still off in how you're finding the max size, but this should get you started.

  function igualarBotones(){   
    var columna1 = $(".columna1");
    setMax(columna1);    
    var columna2 = $(".columna2");
    setMax(columna2);
    var columna3 = $(".columna3");
    setMax(columna3);
  }

  function setMax(columna){
    var maxColumna = -1;
    for(var i=0; i<columna.length; i++){
      if($(columna[i]).css("width") > maxColumna){        
        maxColumna = $(columna[i]).css("width");
      }
    }
    for(i=0; i<columna.length; i++){
      $(columna[i]).css("width",maxColumna);
    }
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
  <head>
    <meta charset="UTF-8">
    <title>CORE2017 P3</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script type="text/javascript" src="calculadora.js"></script>
    <link href="calculadora.css" rel="stylesheet" type="text/css" media="all">
  </head>
  <body onload="igualarBotones();">
    <header>
      <p>Calculator</p>
    </header>
    <section id="main">
      <p>
        Número: <input type="text" id="pantalla"> <button id="Limpiar">Limpiar</button>
      </p>

      <p>
        <button id="suma" class="columna1">+</button>
        <button id="resta" class="columna2">-</button>
        <button id="cuadrado" class="columna3">x<sup>2</sup></button>
      </p>
      <p>
        <button id="inverso" class="columna1">1/x</button>
        <button id="raiz" class="columna2">sqrt(x)</button>
        <button id="pentera" class="columna3">parte_entera(x)</button>
      </p>
      <p>
        <button id="potencia2" class="columna1">2<sup>x</sup></button>
        <button id="factorial" class="columna2">x!</button>
        <button id="igual" class="columna3">=</button>
      </p>


    </section>
  </body>
</html>
Russell
  • 476
  • 2
  • 10
  • Do you know how to fix that the function isnt defined when the body is loading? – Luiscri Jul 08 '17 at 14:21
  • @Luiscri the function is defined in jQuery's ready context and is not available in the global scope. https://stackoverflow.com/questions/1055767/why-can-i-not-define-functions-in-jquerys-document-ready – Russell Jul 08 '17 at 16:22
  • Thank you very much @Russell I knew it was a simple mistake and I finally understood it. Thanks for all your answers. – Luiscri Jul 08 '17 at 20:34