views:

78

answers:

5

Hello there,

I have no idea how to do this.

My markup:

<table>
    <tr>
        <td id="colLeft">
            Lorem ipsum dolor<br/>
            Lorem ipsum dolor<br/>
            Lorem ipsum dolor<br/>
            Lorem ipsum dolor<br/>
            Lorem ipsum dolor<br/>
            Lorem ipsum dolor.
        </td>
        <td id="colRight">
            <div>1</div>
            <div>2</div>
        </td>
    </tr>
</table>

$(document).ready(function() {
    $('#colRight > div').each(function() { // I try to: select all divs in #colRight
        $(this).height(function(){ // I try to: sets the height of each div to:
            $('#colLeft').height() / $('#colRight > div').length(); // the height of #colLeft divided by the number of divs in colRight.  
        });
    });     
});

What I am trying to do is to change the height of each div to the height of #colLeft divided by the number of divs in #colRight.

However, it doesnt work.

I've never understood how to chain functions, and never found anyone to teach me.

So I would like to ask two favours of you.

  1. Why doesnt my above jQuery code.
  2. Does anyone know of a tutorial that explains it more detailed than in the tutorials on the jQuery website?

Thank you for your time.

Kind regards,
Marius

+1  A: 

I'm not sure from glancing at your code why it isn't working but this is a much more straightforward way of achieving the same thing:

$(function() {
  var divs = $("#colRight > div");
  var height = $("#colLeft").height() / divs.length;
  divs.height(height);
});

There is nothing magical about chaining functions in jQuery. By the way, when people say "chaining" they mean calls like:

$("div").css("background", "yellow").addClass("foo");

The only thing you need to know to understand that is that most jQuery methods return the jQuery object so it's equivalent to:

var div = $("div");
div.css("background", "yellow");
div.addClass("foo");
cletus
Incorrect - you can pass a function to height: http://api.jquery.com/height/#height2
DisgruntledGoat
@Disgruntled, yes that is incorrect...but in this case, you'd still want to go this route over the function, much simpler and more efficient.
Nick Craver
@cletus, just make sure you ID that not all functions will return a jQuery object. For instance, .height() returns an int, .height(20) returns a jQuery. That slight difference will cause headaches for a green jQuery programmer.
drachenstern
A: 

The function that you pass to height() must return a value. Try this on your inner code:

    $(this).height(function(){ 
        return $('#colLeft').height() / $('#colRight > div').length(); 
    });

As for chaining, it doesn't really come into play in your code above. Basically, most jQuery functions return the object you just acted on. So for example if you set the height on an object, that object is returned. In stead of this:

$('#someid').height(300);
$('#someid').click(functionName);

You can do this:

$('#someid').height(300).click(functionName);
DisgruntledGoat
+1  A: 

I'll tackle Question #1, the why, so many tutorials out there I'm not sure what's best. Your overall view of chaining isn't far off, just needs a little adjustment on this line:

$('#colLeft').height() / $('#colRight > div').length();

You need to add a return, and call .length not as a function, like this:

return $('#colLeft').height() / $('#colRight > div').length;

A function needs to return something (in this case!), and .length is a property (of the object array inside the jquery object). However, in this case, see cletus's answer, it's a much better overall solution to set the height like you want.

Nick Craver
A: 

So the two div's should each be the same height as the left list? In other words:

-      --
-      --
-      --
-      --
       +
       +
       +
       +

because that doesn't look right. Granted, I'm using simplistic box shapes to illustrate a point, but I wanna make sure. Seems like you would rather have:

-      --
-      --
-      +
-      +

And so, I would probably aim for (but I haven't tried this in a browser just yet:

$(document).ready(function() {
  /* it should already apply the height to "each" so you don't have to do that */
  $('#colRight > div').height( 
     /* I give the line it's own parens so I can make sure the grouping is correct */
     ( $('#colLeft').height() / $('#colRight > div').length() ) 
                           ); 
});
drachenstern
+1  A: 

As for the chaining, I would hazard you this: Don't assume you can always blindly chain. Most of the core jQuery and the jQuery UI stuff will chain with no problem, but some third party modules will not return jQuery objects (which is what the jQuery libs return).

The basics is like this:

$( some selector ) is a function call that has a return value of jQueryObject[] like so:

/* in "pretend land" because this isn't accurate */
public jQueryObject[] $( some selector ) {
  /* do some magic here with some selector */
  return jQueryObject[];
}

and because you're returning a jQueryObject[] then you can substitute it somewhere else. But the magic of chaining says "whatever I am attached to by a period on my left I use as input". So, if we had:

int a = 20;

and a function like so:

public int Doubler(int someInt) {
  return ( someInt * 2 );
}

then we could chain like thus:

a.Doubler();

and get 40. But if we were to:

a.Doubler().Doubler();

then we would have chained twice and our result would be 80;

But sometimes you'll see them where they also accept options, which I'm not going to go into. You wanted the basics on how chaining works, so I'll assume the more advanced stuff you can lookup later. Such as reading the non-min source.

Now, my earlier caveat was that sometimes libraries for jQuery will return an object to themselves and the object inside the library is not guaranteed to be a jQueryObject[] (to use my own nomenclature again). So that's outside the scope of the chaining. All libraries will tell you what an object returns, whether it's an int, string, object, jQuery or whatever.

So for instance, at the jQuery .height() page, in the blue bar down the page you see: .height() Returns: Integer but further down the page: .height( value ) Returns: jQuery and on the .each() page, in the blue bar we see: .each( function(index, Element) ) Returns: jQuery

So you can see how the API documentation writers tell you what is being returned from each function. That's how you can know what the next object will take in upon chaining. That's why sometimes you can't chain certain things together.

Ok, that's a LOT of information in one blow, but you wanted the quick and dirty and if that doesn't bring you up to speed I don't know what will.

tl;dr: sorry for the wall of text, but it's a contiguous chunk of answer. Ya wanna know, go back and read it.

drachenstern