I have this long list of checkboxes with specific labels that look something like this:
<input type='checkbox' name='check[]' id='159' value='159' />
<label for='159'>Person 1</label>
<input type='checkbox' name='check[]' id='160' value='160' />
<label for='160'>Person 2</label>
And below this form I have six div's like so:
<div id="member1"></div>
<div id="member2"></div>
<div id="member3"></div>
<div id="member4"></div>
<div id="member5"></div>
<div id="member6"></div>
I have this JS function so that when I click on a checkbox, it's label is inserted into the first div. Here's what it looks like:
$(function(){
$('input:checkbox').click(function(){
var id = $(this).attr('id');
if($(this).is(':checked')){
$('#member1').text($('label[for="'+ id +'"]').text());
}
else{
$('#member1').text('');
}
});
});
So one problem is the function currently has to specify which div to put it into (#member1). It's supposed to work that when the first div is "full", the next checkbox will insert its label into the second div, and when that one is full, the third checkbox will insert its label into the third div, etc.
The other issue is if a checkbox bees unchecked, its label should be removed from its div and the labels in the divs below it should move up. Anyone know if that's possible? I'll accept help for either problem!
I have this long list of checkboxes with specific labels that look something like this:
<input type='checkbox' name='check[]' id='159' value='159' />
<label for='159'>Person 1</label>
<input type='checkbox' name='check[]' id='160' value='160' />
<label for='160'>Person 2</label>
And below this form I have six div's like so:
<div id="member1"></div>
<div id="member2"></div>
<div id="member3"></div>
<div id="member4"></div>
<div id="member5"></div>
<div id="member6"></div>
I have this JS function so that when I click on a checkbox, it's label is inserted into the first div. Here's what it looks like:
$(function(){
$('input:checkbox').click(function(){
var id = $(this).attr('id');
if($(this).is(':checked')){
$('#member1').text($('label[for="'+ id +'"]').text());
}
else{
$('#member1').text('');
}
});
});
So one problem is the function currently has to specify which div to put it into (#member1). It's supposed to work that when the first div is "full", the next checkbox will insert its label into the second div, and when that one is full, the third checkbox will insert its label into the third div, etc.
The other issue is if a checkbox bees unchecked, its label should be removed from its div and the labels in the divs below it should move up. Anyone know if that's possible? I'll accept help for either problem!
Share Improve this question asked Jun 20, 2012 at 15:24 aaduaadu 3,25410 gold badges42 silver badges65 bronze badges 12- why do you need all those divs to insert labels? – GnrlBzik Commented Jun 20, 2012 at 15:26
- 3 First, IDs can not start with a number. Second, how do you determine a div is "full"? Third, you should probably put a data-attribute in each div to keep a count of its current labels, and when it hits that magic number, start on the next. If it goes below that, bubble the rest up. – gcochard Commented Jun 20, 2012 at 15:28
-
@j08691: In HTML5, yeah, but not in CSS -- so if using CSS selectors (as you do with jQuery), let's just say it's problematic. A standards-pliant browser will throw on
document.querySelector("#123")
. – T.J. Crowder Commented Jun 20, 2012 at 15:29 - Why can't you append labels into one div? – GnrlBzik Commented Jun 20, 2012 at 15:30
- I assume you could add up heights of the inserted labels and check that value against height of the parent container. And if height of the container filled up by the labels you can then insert them into next one. – GnrlBzik Commented Jun 20, 2012 at 15:31
6 Answers
Reset to default 2Caveat: I would do this pletely differently.
But using your current structure: Live copy | source (using valid id
s)
$(function(){
$('input:checkbox').click(function(){
var $cb = $(this),
id = this.id, // No need for `attr`
member,
prev;
if(this.checked){ // No need for `attr`
$("div[id^=member]").each(function() {
if (!this.firstChild) {
// It's empty, use it
$(this).text($('label[for="'+ id +'"]').text()).attr("data-contents", id);
return false; // Done
}
});
}
else {
member = $('div[data-contents="' + id + '"]');
if (member[0]) {
member.empty().removeAttr('data-contents');
prev = member[0];
member.nextAll().each(function() {
if (!this.firstChild) {
return false; // Done
}
prev.appendChild(this.firstChild);
prev = this;
});
}
}
});
});
Minimum changes I would make:
- Put the
#memberX
divs in a container so we don't have to do theid^=
search. - Don't use
id
values on the#memberX
divs at all. - If you don't absolutely, positively need them, don't have empty
#member
divs at all. This would simplify the code markedly. - If you do need them, when clearing, remove the div and just append a new, empty one to the end.
Example: Live copy | source
HTML:
Just replace the #membersX
divs with <div id="members"></div>"
.
JavaScript:
$(function(){
$('input:checkbox').click(function(){
var $cb = $(this),
id = this.id; // No need for `attr`
if(this.checked){ // No need for `attr`
$("<div>")
.text($('label[for="'+ id +'"]').text())
.attr("data-contents", id)
.appendTo("#members");
}
else {
$('div[data-contents="' + id + '"]').remove();
}
});
});
You can simplify even more by moving the checkbox input the label
s (which also means you can do away with the for
attribute): Live copy | source
HTML:
<label><input type='checkbox' name='check[]' id="x159" value='159' />
Person 1</label>
<label><input type='checkbox' name='check[]' id="x160" value='160' />
Person 2</label>
<div id="members"></div>
JavaScript:
$(function(){
$('input:checkbox').click(function(){
var id = this.id; // No need for `attr`
if(this.checked){ // No need for `attr`
$("<div>")
.text($(this.parentNode).text())
.attr("data-contents", id)
.appendTo("#members");
}
else {
$('div[data-contents="' + id + '"]').remove();
}
});
});
Try this: jsFiddle example.
jQuery
$('input:checkbox').click(function() {
if ($(this).is(':checked')) {
$('div:empty:first').html($(this).next('label').html());
}
else {
var foo = $(this);
$('div').each(function() {
if ($(this).html() == foo.next('label').html()) {
$(this).html($(this).next('div').html());
$(this).nextAll('div').each(function() {
$(this).html($(this).next('div').html());
});
}
});
}
});
If I understood your question correctly, you have X amount of spots available and you can only fill that many. If that is the case, I think this is what you are looking for: jsFiddle. If not, some of the other solutions might be better...
var $selections = $('ul.selections');
$('input:checkbox').click(function() {
var id = $(this).val();
if($(this).is(':checked')) {
var $label = $(this).next('label');
var $spot = $selections.find('li:not(.full)');
if($spot.length == 0) {
alert('no more spots open!');
return false;
}
$spot.eq(0).addClass('full').html($label.clone());
} else {
var $label = $selections.find('label[for=' + id + ']');
$label.closest('li').remove();
$selections.append($('<li/>').html(' '));
}
});
With this HTML:
<p>Options</p>
<ul>
<li><input type='checkbox' name='check[]' id='159' value='159' /> <label for='159'>Person 1</label></li>
<li><input type='checkbox' name='check[]' id='160' value='160' /> <label for='160'>Person 2</label></li>
....
</ul>
<p>Selections</p>
<!-- spots available = as many list items initially in HTML -->
<ul class='selections'>
<li> </li>
<li> </li>
<li> </li>
<li> </li>
<li> </li>
<li> </li>
</ul>
I made them lists since that is what they really are, but the code would work the same with DIVs if that is what you want. Since the labels are cloned over, clicking on a label on the selection list will remove it.
Simple way based on your code here http://jsfiddle/joevallender/rTQMe/
$(document).ready(function(){
$('input:checkbox').click(function(){
var $checked = $('#checked');
$checked.html('');
$('input:checkbox').each(function(index){
if($(this).is(':checked')) {
$checked.append('<div>' + $('label[for="'+ $(this).attr('id') +'"]').text() + '</div>');
}
});
});
});
There are ways to make this more efficient, but this should work for your purposes:
$(function(){
var numberOfDivs = 6;
$('input:checkbox').click(function(){
var id = $(this).attr('id');
if($(this).is(':checked')){
for(i = 1; i < numberOfDivs - 1; i++)
{
var div = $('#member' + i);
if(div.text() !== ''){
div.text( ($('label[for="'+ id +'"]').text() );
}
}
}
else{
var searchText = $('label[for="'+ id +'"]').text();
for(i = 1; i < numberOfDivs - 1; i++)
{
var div = $('#member' + i);
if(div.text() === searchText){
div.text('');
}
}
}
});
});
Here's how I would do it:
$(function(){
$('input:checkbox').click(function(){
var id = this.id;
if(this.checked){
var member = $('#member1');
var i = 1;
while(member.data('num') == 1)
{
member = $('#member'+(++i));
}
member.text($('label[for="'+ id +'"]').text()).data('num',1);
}
else{
var removed = false;
$('div').each(function(){
$(this).children('label').each(function(){
if(!removed && id == $(this).attr('for'))
{
removed = true;
$(this).parent().remove('label[for="'+$(this).attr('for')+'"]');
}
}
if(removed) //bubble the labels up into the next highest div.
{
if($(this).data('num') == 1)
var lastObject = $(this).children('label');
$(this).prev().append(lastObject);
}
}
}
});
});
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744929286a4601632.html
评论列表(0条)