0

So I'm working on a Polymer element that is supposed to be responsive. For that I need access to the current image's width.

Here's my markup

  <div class="meme">
    <div id="memeImage"><img id="memeimg" src="{{img}}"></div>
  </div>

And the (relevant) styling.

  .meme {
    position: relative;
    -webkit-box-align:center;
    -webkit-box-pack:center;
    display:-webkit-box;
  }
  #memeImage {
    z-index: -1;
    border: 0px;
    margin: 0px;
    text-align: center;
    position: relative;
  }

Now what I want is to get the width of the image. For that, in my ready event, I add these two lines:

    console.log(this.$.memeImage);
    console.log(this.$.memeImage.clientWidth);

The first prints the element just fine and I can see the clientWidth and offsetWidth are numbers. But the second line prints 0. The same is true when I use getComputedStyle().

I thought that this might be because the image hasn't loaded yet, so I added an event handler:

    this.$.memeImage.addEventListener('onload', function() {
      console.log("image loaded");
    })

But this never gets hit.

What am I doing wrong and how do I fix it?

KGo
  • 18,536
  • 11
  • 31
  • 47

3 Answers3

2

Looks like your onload event handler for the image does not get called. Try using the onload event of the window:

window.onload = function () {
      console.log(document.getElementById('memeimg').clientWidth);
}

window.onload should be fired after all images have been loaded (not just the first). anyway, if for some weird Polymer related reason the normal load event for the image does not fire, this should do the trick per image: JS:

function onThisImageLoaded(thisImage) {
            console.log(thisImage.clientWidth);
}

then markup:

<div id="memeImage"><img id="memeimg" src="https://www.gravatar.com/avatar/f9d1450403b864d6b17f30ba0ce0aee3?s=48&d=identicon&r=PG" onload="onThisImageLoaded(this);"></div>
orcaman
  • 6,263
  • 8
  • 54
  • 69
  • This works for just the first instance of the element, and not the others. I want it to work whenever `this` image loads. – KGo May 18 '14 at 18:11
2

I believe the most idiomatic polymer solution for this is to use Polymer's event handling.

<div class="meme">
  <div id="memeImage"><img id="memeimg" on-load="{{imageLoaded}}" src="{{img}}"></div>
</div>

Then in your Polymer declaration

Polymer('my-meme', {
  imageLoaded: function() {
    console.log('meme image loaded');
  }
});

This is nice because it doesn't add anything to the top level namespace, it keeps the code related to the meme packaged up together, and it will work even if you show the image only conditionally (e.g. with a <template if="{{something}}">)

You mention in your post that you've tried this:

this.$.memeImage.addEventListener('onload', function() {
  console.log("image loaded");
});

Generally speaking that should work, but there are a couple of typos. Try this (note memeImage -> memeimg and onload -> load):

this.$.memeimg.addEventListener('load', function(loadEvent) {
  console.log("image loaded: ", loadEvent);
})

Also it may be worth experimenting with ready vs domReady though I don't think it should make a difference in this case.

Peter Burns
  • 44,401
  • 7
  • 38
  • 56
  • That's great advice. This is what I'm using for now: https://github.com/karan/x-meme/blob/master/x-meme.html#L178-L183 – KGo May 18 '14 at 19:16
0

Agree with @charlietfl - you can't get dimensions of an image that hasn't loaded yet -

The event is 'load' and not 'onload'

if you are using jquery - just try this -

 $("#memeimg").on('load', function () {
        console.log("image loaded");
    }).attr('src', 'http://i.imgur.com/xENQisG.jpg');

The key is to attach the event before setting the source - jsfiddle here - If that is not doable - Check the alternative approach from here

Community
  • 1
  • 1
Johnbabu Koppolu
  • 3,212
  • 2
  • 22
  • 34
  • @Karan Goel - Updated my answer – Johnbabu Koppolu May 18 '14 at 18:22
  • This won't work because #memeimg is in the shadow dom of the polymer element and thus hidden from the rest of the document. If you did want to use jquery you could do this instead (inside of the ready handler of the polymer element): `$(this.shadowRoot).find('#memeimg').on('load', ...);` – Peter Burns May 18 '14 at 19:09