Reputation: 3
I've got a weird bug happening on a music library site that I'm working on. The intended functionality (take a form of checkboxes, dynamically change them into selectable words that highlight and "check" the associated checkbox on click, then automatically update the songs below based on the highlighted tags) works fine -- but when you click a selected tag to remove it, it does the correct functionality with the data below and the highlight is removed, but all other selected tags are getting "display: none" added to them.
Here, I think, is the function causing the weird issue:
// Given an label "$label," if it hasn't been selected, then
// highlight the label area and set the "checked" value of the
// appropriate checkbox input to true; if it is already selected,
// remove the highlight and set the "checked" value of the appropriate
// checkbox to "false"
function highlightAndCheck( $label )
{
var id = $label.attr("id"),
$checkbox = $label.prev(),
val = $checkbox.attr("value");
if( id === val )
{
if( $label.hasClass("clicked") )
{
$checkbox.prop("checked", false);
$label.removeClass("clicked");
} else
{
$checkbox.prop("checked", true);
$label.addClass("clicked");
}
}
}
Here's the full jQuery code for the page. I can provide more code if anything is confusing, but I hope the labeling, etc. are straightforward:
$(function() { //on document ready
var $categoriesAndTags = $("div#categories-and-tags"),
$tagCategory = $categoriesAndTags.find("div.tag-category"),
$searchButton = $categoriesAndTags.find("input#public-user-tag-search-submit");
// First, hide the checkboxes and search button, since we don't need them in the dynamic version
$tagCategory.addClass("tag-spinner-skin")
.find("input[type=checkbox]").hide();
$tagCategory.find("br").hide();
$searchButton.hide();
// Make it so then clicking on the text of a tag makes the hidden select box "select"
$tagCategory.find("label").each(function(){
$(this).on("click",function(){
var $this = $(this);
highlightAndCheck( $this );
searchByTags();
//While the unwanted "display:none" bug is happening, use this to make them re-appear on next click
$this.siblings("label").show();
});
});
// Make the search update automatically when a select box is clicked or unclicked.
var tagIDs = getUrlVarValArray( "tagID" );
$tagCategory.find("label").each(function(){
var $this = $(this),
id = $this.attr("id");
if( tagIDs.indexOf( id ) > -1 )
{ highlightAndCheck( $this ); }
});
});
function searchByTags( tags )
{
data = $("form#tag-select input").serialize()
if( data.length > 0 )
{
data += "&search=search";
}
$.ajax({
url: "songs/",
data: data,
type: "GET",
success: function(data){
// DO THIS if we successfully do the Ajax call
$newSongPlayers = $(data).find("div#songs-area");
$("div#songs-area").replaceWith( $newSongPlayers );
$.getScript("javascripts/public.js");
}
});
}
// Given an label "$label," if it hasn't been selected, then
// highlight the label area and set the "checked" value of the
// appropriate checkbox input to true; if it is already selected,
// remove the highlight and set the "checked" value of the appropriate
// checkbox to "false"
function highlightAndCheck( $label )
{
var id = $label.attr("id"),
$checkbox = $label.prev(),
val = $checkbox.attr("value");
if( id === val )
{
if( $label.hasClass("clicked") )
{
$checkbox.prop("checked", false);
$label.removeClass("clicked");
} else
{
$checkbox.prop("checked", true);
$label.addClass("clicked");
}
}
}
function getUrlVarValArray( needle )
{
var results = [],
hash,
hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
if( needle.length > 0 )
{
if( hash[0] === needle )
{
results[ results.length ] = hash[1]; // array[ array.length ] is a faster way to apend than array.push() in small arrays
}
}
}
return results;
}
Thanks in advance for your help! If it's helpful to login and see this in context, please go to the test site and use username: stackoverflowuser; password: HelpMeFigureThisOut -- once you're logged in, click on "View Songs"and the jQuery is referencing the tags at the top of the page.
Upvotes: 0
Views: 275
Reputation: 21482
Look at the following code in the public.js
file:
$("html").on("click", function(event){
if(!$(event.target).is('.options-button')
&& !$(event.target).is('input.add-new-playlist')
&& !$(event.target).is('button.submit-new-playlist')
&& !$(event.target).is('button.add-song-to-playlist')
&& !$(event.target).is('button.playlist-popup-button')
)
{
if(!$(event.target).is('.clicked') && !$(event.target).is('.clicked > div') )
{ $(".clicked").hide().removeClass("clicked"); }
}
});
This handler gets executed because the click event propagates from the <label>
element to the <html>
element. It executes after the click handler on the <label>
element, which removes the "clicked" class from the <label>
element. Since the <label>
element is the event.target
and no longer has the "clicked" class, the following line is executed:
$(".clicked").hide().removeClass("clicked");
That line hides all the labels that still have the "clicked" class.
Upvotes: 1