user1881482
user1881482

Reputation: 746

Allow only one div to have selected class jquery

I am using jquery in a form to select one of the uploaded images in a form to be the primary image. Essentially the user uploads up to 8 images on the previous step. They are then presented with thumbnails of the images, each has a corresponding hidden input with there value being the href to the image. The name of each input is galleryImage1, galleryImage2 and so on. What I would like to do is on click of one of the images the hidden input's name get's changed to primaryImage and a class of primaryImage is added. I have this working. However in this group of pictures only 1 is supposed to be selected. Right now you could pick all of them and the action would happen. How do I change this so this can only be applied to one image at a time. And then the catch is if the user changes their mind they could click a different image, the class and name would be removed, as well as the original name added to the hidden input from the first and added to the second choice.

html

<div class="outputimages">
    <div class="galleryImage">
        <img src="http://example.com/images/12345.png" name="galleryImage1">
        <input type="hidden" name="galleryImage1" data-origname="galleryImage1" value="12345.png">
    </div>
    <div class="galleryImage">
        <img src="http://example.com/images/123456.png" name="galleryImage2">
        <input type="hidden" name="galleryImage2" data-origname="galleryImage2" value="123456.png">
    </div>
    <div class="galleryImage">
        <img src="http://example.com/images/1234567.png" name="galleryImage3">
        <input type="hidden" name="galleryImage3" data-origname="galleryImage3" value="1234567.png">
    </div>
</div>

so if the first div was clicked on it would look like this

<div class="galleryImage primaryImage">
    <img src="http://example.com/images/12345.png" name="primaryImage">
    <input type="hidden" name="primaryImage" data-origname="galleryImage1" value="12345.png">
</div>

And on selection of the second div it would change back to original and the second div would get these changes. I have added the data-origname attribute so the name can be changed back.

my current js. These are dynamically generated items so I had to use .on to affect change.

$(document).on( 'click', '.galleryImage', function(){
    $(this).addClass('primaryImage');
    $(this).children().attr('name', 'primaryImage');    
});

Upvotes: 0

Views: 2024

Answers (3)

Robert Messerle
Robert Messerle

Reputation: 3032

It seems like you need something a bit more involved to truly restore the state, assuming you keep the HTML as is.

$( document ).on( 'click', '.galleryImage', function () {
  var $this = $( this ),
      clss  = 'primaryImage',
      name  = $this.data( 'name' );
  // If name hasn't been fetched yet, fetch and store it
  if ( !name ) $this.data( 'name', $this.attr( 'name' ) );
  // Reset old element
  $this
    .siblings( '.' + clss )
    .removeClass( clss )
    .children()
    .attr( 'name', name );
  // Update new element
  $this
    .addClass( clss )
    .children()
    .attr( 'name', clss );
} );

Upvotes: 0

Mike Brant
Mike Brant

Reputation: 71424

A couple of suggestions:

First, let's think about the input naming and HTML structure. Your current naming scheme doesn't scale. I would suggest using array access notation like this:

<div class="galleryImage">
    <img src="http://example.com/images/12345.png">
    <input type="hidden" class="galleryImageInput" name="galleryImage[]" value="12345.png">
</div>

This removes the need to track galleryImage1, galleryImage2, etc. Note I have also added a class to the input to make selecting it easier and removed the name attribute from <img> (it is meaningless there). I have also removed the data attributes as they will no longer be needed as you will see.

Now, let's change the on-click handler:

$(document).on( 'click', '.galleryImage', function(){
    // reset current primaryImage back to default
    $('.primaryImage')
        .removeClass('primaryImage')
        .find('.galleryImageInput')
        .attr('name', 'galleryImage[]');
    // set class and input name for clicked item
    $(this)
        .addClass('primaryImage')
        .find('.galleryImageInput')
        .attr('name', 'primaryImage');    
});

When POSTing the data, you will now have one input with name primaryImage and an array at the key galleryImage. This should make the data much easier to work with on the server side than having to deal individually with galleryImage1, galleryImage2, etc. and checking whether each has been converted to primaryImage.

Upvotes: 3

falinsky
falinsky

Reputation: 7438

$(document).on( 'click', '.galleryImage', function(){
    $('.galleryImage').removeClass('primaryImage');
    $('.galleryImage').children().each(function(i, el){
       $(this).attr('name', $(this).attr('data-origname'));
    });
    $(this).addClass('primaryImage');
    $(this).children().attr('name', 'primaryImage');    
});

Upvotes: 1

Related Questions