Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Interactive Photo Gallery

Ian MacDonald
seal-mask
.a{fill-rule:evenodd;}techdegree
Ian MacDonald
UX Design Techdegree Student 12,443 Points

Altering element margin style dynamically on key press - working out bugs

For my search function, I am attempting to dynamically change the margin on the 4th element so that the layout of the gallery remains consistent with the mocks.

The problem I am running into is that the styling of the original 4th element before key press is not being altered at the correct time.

$('input').on('keyup', function(){
  search = $(this).val().toLowerCase();
  for (var i = 1; i <= imageCaptionArray.length; i++) {
    caption = imageCaptionArray[i-1].toLowerCase();
    var thisImage = $('#galleryContainer a:nth-child('+ i +')');
    if( caption.indexOf(search) >=0 ) {
      thisImage.fadeIn();
    } else {
      thisImage.fadeOut();
    }
  }
//function to change margin based on position
    $('#galleryContainer a img:visible').each(function (i) {
    $(this).css('margin', '0 60px 55px 0');
    if ((i + 1) % 4 == 0) { 
      $(this).css('margin', '0 0 55px 0');
    } else {
      $(this).css('margin', '0 60px 55px 0');
    }
    });
});

Hi Ian,

This project isn't accessible to us so the only thing we know about it is what you have posted here.

Can you explain what's going on with the margins?

Is this a 4 column layout?

Are all of the images initially visible and then once you start typing you hide what doesn't match?

The best I can gather is that every 4th original image has a zero right margin so it fits in the container. Once images start hiding you need every 4th visible image to have a zero right margin. Plus all non multiples of 4 need to have a 60px right margin.

Is that anywhere close to what the situation is?

If not, then please try to explain more and maybe someone will be able to help.

2 Answers

Ian MacDonald
seal-mask
.a{fill-rule:evenodd;}techdegree
Ian MacDonald
UX Design Techdegree Student 12,443 Points

Ultimately I ended up coding things this way, which seems to work pretty well. Just need to make sure to call this function after any animations that are on the elements you are setting the margins on.

function setMarginsImages() {
  $('#galleryContainer a img').filter(':visible').each(function(i) {
  $(this).css('margin', '0');
  var modulus = (i + 1) % 4;
    if (modulus === 0) { 
      $(this).css('margin', '0 0 55px 0');
    } else {
      $(this).css('margin', '0 60px 55px 0');
    }
  });
}

// Example of calling this function when fade animation has completed. 
// (was still not setting margins properly till I realized this)

thisImage.fadeIn(600, 'linear', setMarginsImages);
Damien Watson
Damien Watson
27,419 Points

Hi Ian,

If I understand correctly, you are wanting to fade elements out, to make it look like they are removed but the styling is not working as expected at the right time. Rather than fix the timing issue, I will suggest another direction.

CSS should do the trick for you, but the problem is that '.fadeout()' makes the element invisible, it doesn't remove it from the dom flow, so the next element doesn't automatically take on the css as it should.

I suggest still using fadeout but then on the fadeout complete, use '.hide()' which will remove the element from the flow. This should allow your css to take over and save you from coding it.

thisImage.fadeOut(fadeDuration, function() {
    $(this).hide();
});

I'm pretty sure this should work for you and save some headaches.

Ian MacDonald
seal-mask
.a{fill-rule:evenodd;}techdegree
Ian MacDonald
UX Design Techdegree Student 12,443 Points

Hey Damien,

Thanks for the reply. Your suggestion sounds great, but seems to run into the same issues. .hide() applies display: none to the elements but does not remove them from the DOM. But your suggestion got me thinking in a new way, I might try .detach() and .appendTo() or some variation.

.fadeOut() and .hide() both ultimately do the same thing in that they set display to none. So there's likely not going to be any difference between those two. fadeOut sets the display to none after animating the opacity down to 0.

Ian,

I'm not sure you'd want to go down the path of detaching the elements from the dom. It seems like it would be inefficient manipulating the dom frequently as the user is typing unless I'm misunderstanding the project.

Plus you'll have to keep track of their original spot to know where to put them back in.