Add attribute based on image dimensions

293 Views Asked by At

I'm working for a client who's using a third-party platform which only allows me to override CSS and partially edit the HTML templates. I can also make changes by adding Javascript, and in this instance I need to append classes and IDs based on the dimensions of thumbnail images, represented as images within list-items. I've started a fiddle, replacing the images with a div.

http://jsfiddle.net/dbudell/SYTsP/4/

Here's the HTML:

<ul>
  <li><div class="item item1"></div></li>
  <li><div class="item item2"></div></li>
</ul>

And the CSS. As you can see, I've set .item1 to "portrait" dimensions and .item2 to "landscape dimensions. I want to append to IDs based on these dimensions:

li {
   display:inline-block;
   margin:5px;
}

.item1, .item2 {
  border:1px solid #333;
}

.item1 {
   width:100px;
   height:200px;
}

.item2 {
    width:200px;
    height:100px;
}

#fill-portrait {
  background:#333;
}

#fill-landscape {
  background:#888;
}

And here's the JQuery code, which seems to be syntactically correct but is yielding no results. Not sure what the problem is.

var itemWidth = $('.item').width();
var itemHeight = $('.item').height();

if (itemWidth > itemheight) {
  $('.item', this).addAttr('id','fill-landscape');
} else {
  $('.item', this).addAttr('id','fill-portrait');
}

Again, the link to the fiddle is http://jsfiddle.net/dbudell/SYTsP/4/.

2

There are 2 best solutions below

3
On

You need to select the individual elements you're trying to get the dimensions of. Otherwise, you're $('li') selector is selecting every "li" element on the page. For example:

$('.item1').height();

Then you can add an id as follows:

$('.item1').attr('id', 'blah');

An explicit example http://jsfiddle.net/SYTsP/7/:

var $item1 = $('.item1');
var $item2 = $('.item2');

setId($item1);
setId($item2);

function setId($item){
  var itemWidth = $item.width();
  var itemHeight = $item.height();

  if (itemWidth > itemHeight) {
    $item.parent('li').attr('id','fill-landscape');
  } else {
    $item.parent('li').attr('id','fill-portrait');
  }
}

Now with more iteration!!

http://jsfiddle.net/SYTsP/9/

0
On

There is several things that don't look right:

  • typo in your current code itemheight should be itemHeight
  • addAttr("id, "value") should be attr("id", "value")
  • this in your selector $("li", this) is refering to the window which cannot be used in a selector like this as $("li", this).length = 0
  • you are only accessing the first li you come across and not all li elements in the ul

DEMO - Combining all of the above


I used your existing HTML and CSS in the above DEMO and the following script:

var $listItems = $("ul>li");

$listItems.each(function () {
  var $item = $(this);
  var itemWidth = $item.width();
  var itemHeight = $item.height();

  if (itemWidth > itemHeight) {
    $item.attr('id', 'fill-landscape');
  } else {
    $item.attr('id', 'fill-portrait');
  }
});

Side-note on id vs class
If you are planning on having several of those elements using the same id values you might want to switch those to classes instead, i.e: .addClass("fill-landscape") instead of attr("id", "fill-landscape"). id values have to be unique. It would be invalid HTML and jQuery selectors also only match the first matching id and won't return a collection. Off course this would mean you have to update your CSS as well from #fill-landscape to .fill-landscape.


DEMO - Using classes instead of ids just in-case


The above DEMO used the following changed CSS (#fill-x is now .fill-x):

.fill-portrait {
  background:#333;
}
.fill-landscape {
  background:#888;
}

Changed Script (using .addClass() instead of .attr()):

var $listItems = $("ul>li");

$listItems.each(function () {
  var $item = $(this);
  var itemWidth = $item.width();
  var itemHeight = $item.height();

  if (itemWidth > itemHeight) {
    $item.addClass('fill-landscape');
  } else {
    $item.addClass('fill-portrait');
  }
});