0

I cannot figure out how to compress this code to make it DRY. It works fine with different elements or when repeating code, but I want to keep it clean. This is the html:

<div class = "face left">
  <img src = "/images/faces/empty.jpg"><br>
  <select>
    <option value="empty">Select one</option>
    <option value="ab18e97e6c64f8db588e95772daf51b4">Takeshi</option>
    <option value="d27b579c196202648ba7c4b1904e8e20">Osuka</option>
  </select>
</div>
<div class = "face right">
  <img src = "/images/faces/empty.jpg"><br>
  <select>
    <option value="empty">Select one</option>
    <option value="ab18e97e6c64f8db588e95772daf51b4">Takeshi</option>
    <option value="d27b579c196202648ba7c4b1904e8e20">Osuka</option>
  </select>
</div>

The not working jquery I've got so far:

$('.face').children('select').change(function()
   {
   $(this).
     siblings('img').
     replaceWith('<img src = "/ajax/faces/' + $(this).siblings('select option:selected').attr('value') + '">');
   });

I want to achieve that, when I change the select, the img of that div gets replaced for a new one (with the src dynamically created from the value of the choosen option). I can get it to kind of work if I do this (deleting the $(this).siblings):

$('.face').children('select').change(function()
   {
   $(this).
     siblings('img').
     replaceWith('<img src = "/ajax/faces/' + $('select option:selected').attr('value') + '">');
   });

But with that code I can only have one 'face', and I actually want two. So, how can I modify my jquery code to replace it's sibling <img> and not to affect other ones? The first code doesn't work because it tries to find the image /ajax/faces/undefined.

Francisco Presencia
  • 8,732
  • 6
  • 46
  • 90
  • I tend to have problems tracking what `$(this)` is in this kind of situation. Try storing `$(this)` or the desired siblings of `$(this)` before the `replaceWith`. – astex May 02 '13 at 00:47
  • Me too, I'm just learning jquery so far and having trouble without the `echo` or `var_dump` from PHP. However even storing it I cannot make it much better. I don't think dumping all my failed attempts will improve much my question... – Francisco Presencia May 02 '13 at 00:54
  • I could solve it finally changing my point of view! I will write it as an answer. – Francisco Presencia May 02 '13 at 01:02

3 Answers3

1

The problem is that siblings does not return the element it is called on. In this case, $(this) was the selector, so $(this).siblings('select') returns nothing. There are also a few ways that you could clean up your code. <select> elements have a value assigned to them, so you can simply use $('select').val(). It may also be pertinent to use the on() function.

Here is some jsFiddle solving a very similar problem.

astex
  • 1,045
  • 10
  • 28
1

Try this:

$('.face > select').change(function()
   {
   $(this).
     siblings('img').attr('src', '/ajax/faces/' + $(this).val());
   });

The main problem with your code is that the options are not siblings, they're children, so you should have used find(). But the value of the selected option is also the value of the select, so that can be simplified away entirely.

And rather than replace the entire <img> element, I just replace the src attribute of the existing element.

FIDDLE

Barmar
  • 741,623
  • 53
  • 500
  • 612
0

After about 1 hour digging and now from a different point of view, I could solve it. This is the solution that worked for me, thanks to this SO question:

$('.face').children('select').change(function()
 {
 $(this).
   siblings('img').
   replaceWith('<img src = "/ajax/faces/' + $("option:selected", this).attr('value') + '">');
  });

And here is a working version of what I wanted (with random internet faces).

Note: although I am answering, since there has been a couple of much better answers since I started writting this, I will accept one of them.

Community
  • 1
  • 1
Francisco Presencia
  • 8,732
  • 6
  • 46
  • 90