If this checkbox is checked then do this to its neighbors - javascript

I am overlooking something pretty fundamental here. I want to color a specific element in a group whenever a checkbox is clicked. So I need to make these elements observable.
This is what my html looks like
<p>
<label>
<i>bla2</i>
<input type="checkbox" />
</label>
</p>
<p>
<label>
<i>bla3</i>
<input type="checkbox" />
</label>
</p>
My JS looks like this
$(document).ready(function() {
function handleCheckbox () {
if ( $(this).closest(':checkbox').is(':checked') ) {
$('this').closest('i').css('color','green');
} else {
$('this').closest('i').css('color','red');
}
}
handleCheckbox();
$('label').on('click', handleCheckbox() );
});

.closest() looks at the current element and then up the hierarchy at ancestors, not at neighbors. In your case, this will point to the label object so you can look at children to find the <i> tag and <input> tag. You also have several other coding errors.
Also, your handleCheckbox() function needs the value of this set to a <label> object in order to work properly so you can't just call it direct and expect it to set all the colors appropriately. Instead, you will have to iterate over all the labels in the page and call handleCheckbox() for each one. I've done that in the code below with .each().
Here's a way to fix it:
$(document).ready(function() {
function handleCheckbox() {
// the this pointer here will point to the label object so you need
// can use .find() to find children of the label object
var newColor;
if ($(this).find("input").is(":checked")) {
newColor = "green";
} else {
newColor = "red";
}
$(this).find("i").css("color", newColor);
}
// hook up click handler and initialize the color for all labels
$('label').on('click', handleCheckbox).each(handleCheckbox);
});
See working demo: http://jsfiddle.net/jfriend00/tRQ99/ and also notice that the initial color is set based on the initial checkbox state too.
Your code had these issues:
.closest() goes up to ancestors. It doesn't find neighbors.
When passing a callback function, you don't use the () at the end because that causes it to execute immediately and pass the return value of executing the function. You just want to pass a reference to the function which is done without the parens.
You don't quote this. Treat it like a javascript variable, not a string.
The this pointer will point to the label object in your callback so you need to look at child elements to find the <i> and <input> objects. You can use either .children() or .find() to find them.
You initial call of handleCheckbox() was not working because it works only when this is set to a <label> object (the way it works in the event handler). So, to use the same function for initialization as the event handler, you need to iterate over all the labels and make sure this is set appropriately for that function. A simple way to do that is with .each() as I've shown in my code suggestion.

You're passing a function in rather than using an anonymous function, so remove the ()
$('label').on('click', handleCheckbox);
Else this will execute right away on page load. Also, unquote this:
$(this).closest('i').css('color','green');

Fiddle for what you probably want here:
http://jsfiddle.net/93CeR/2
$(document).ready(function() {
function handleCheckbox () {
if ( $(this).find(':checkbox').is(':checked') ) { // Use .find instead of closest because the element you want is a child
$(this).find('i').css('color','green'); // Remove qoutes from this and use .find for same reason as above
} else {
$(this).find('i').css('color','red'); // Ditto
}
}
$('label').each(function(){
handleCheckbox.apply(this); // We need to call the function initially using 'label' for this.
});
$('label').on('click', handleCheckbox ); // You want a reference to handleCheckbox not to invoke it so remove the parenthesis
});

Related

how to know the element that performed the click in a checkbox list dynamically added (javascript)

I have to add a list of checkboxes dynamically. I then need to know which one performed the click, then ask if it's checked or not.
I have this code:
$('#MyContainerOfChecksDiv').click( '.MySelectorClass', function(){
if ("MyCheckClicked".is(':checked'))
{
//...here i need to use the label and id
}
else{...}
})
using "$(this)" i get the "MyDiv", obviously using $(this).find('input:checkbox') I get the whole list of checks.
I have to get this checkbox because I need to use its properties.
Add a formal parameter to click handler and use it like this
$('#myDiv').click('.MySelectorClass', function (e) {
if ($(e.target).is(':checked')) {
alert(e.target.id);
}
})
fiddle
Also it's not quite clear to me how you distinguish dynamically added elements and static. Do you have different class for them? If so then you dynamic and static elements can have different handlers and this will be the way to tell whether it was created dynamically
To delegate to dynamic elements you have to use .on(). The element that you clicked on will be in this.
$("#myDiv").on("click", ".MySelectorClass", function() {
if (this.clicked) {
// here you can use this.id
} else {
// ...
}
});
You can't use .click() to delegate like you tried. You're just binding the click handler to the DIV, and the string ".MySelectorClass" is being passed as additional data to the handler.

onClick populated by variable without triggering it

I want to append this to my document:
$('#myDiv).append("<div id='myDiv2' onclick="+extElementConfig.onClickDo+">Do</div>");
The snippet above has it's onClick populated by a certain object with properties,
this:
var extElementConfig={onClickDo:sampleFunc()};
Unfortunately declaring a function into the object property also fires it, as was expected.
How can I achieve the above functionality without triggering the
sampleFunc()?
I just need to dynamically populate the onClick event through an object property.
Assuming you have control over the extElementConfig object, remove the parenthesis from sampleFunc
var extElementConfig={extElementPosition :10,extElementId:'mailOrderBtn',onClickDo:sampleFunc};
As Rob. M. pointed out the real problem with your code was the fact you were running the code when it was in the object instead of assigning a reference. And when you tried to assigning the onclick, that had issues too since you are trying to use a function reference when it was a string.
To get your code to run, it would be something like
function sampleFunc () {
alert("clicked");
}
var extElementConfig={onClickDo:"sampleFunc()"};
$('#myDiv').append("<div id='myDiv2' onclick='"+extElementConfig.onClickDo+"()'>Do</div>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="myDiv"></div>
To get rid of this, do not use the sting method to build up the element, instead leverage the power of jQuery. Below is an example where I build a div and pass in some arguments to change the element's text and css when clicked.
function sampleFunc(txt, css) {
$(this).text(txt).css(css);
}
var extElementConfig = {
onClickDo: sampleFunc,
onClickArgs : ["Clicked", {"background-color":"green"}]
};
$('<div/>', {
id: 'myDiv2',
text: 'Do!'
}
).on("click",
function() {
extElementConfig.onClickDo.apply(this, extElementConfig.onClickArgs);
}
).appendTo("#myDiv");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="myDiv"></div>

Using remove as opposite of append not working

Here's how I append the value:
$('<div>someText</div>').appendTo(self);
And here's how I want to remove it:
$(self).remove('<div>someText</div>');
The appending works, the removing doesnt. What am I doing wrong?
The .remove() function takes a selector to filter the already matched elements, not to match elements inside of them. What you want is something like this:
$(self).find('div:contains(someText)').remove();
That will find a <div> element containing the text someText inside of whatever element self is, then removes it.
The API http://api.jquery.com/remove/ sais that a selector is required.
Try $(self).remove('> div');
This will remove the first childs of div.
You can use $(self).filter('div:contains("someText")').remove(); to remove a div with a specific content or $(self).find('> div').remove(); to remove the first childs of div.
EDIT: removed first version I posted without testing.
It most likely has to do with the scope of self. Since you've named it self I am assuming that you are getting this variable using $(this) on the click event. If that's the case, and you want to call the remove method, you can only do so from within the same function. Otherwise you need to either store the element in a variable or provide another selector to access it.
Example:
<div class="div1"></div>
this will be the div with the click event
$(document).ready(function(){
var self = null;
$('.div1').click(function(e){
self = $(this);
var itemToAdd = '<div>SomeText</div>';
$(itemToAdd).appendTo(self);
});
// to remove it
// this will remove the text immediately after it's placed
// this call needs to be wrapped in a function called on another event
$('.div1').find('div:contains(someText)').remove();
});

jQuery single event for several DOM objects

I'm trying to make a change event trigger for several objects in the DOM. Let me show you; I have this code
$(document).ready(function() {
$(".select_something").change(function() {
if (!($(".select_something option[value='0']").attr("selected"))) {
$(".write_something").css('display','');
}
else
{
$(".write_something").css('display','none');
}
});
});
And with this I have several selectors/dropdowns all of which is called .select_something. When the option is not the default value (which is 0), it should show a <textarea></textarea> appear, again all of which is called .write_something.
All in all it's a quite simplistic function.
The problem I'm experiencing is that this only affects the very first .select_something, .write_something pair, and the rest is unaffected.
I've tried mixing around with .find(), .parent() and .children() to see if it could stick, but it don't.
How can I make it so all of my .select_something, .write_somethingpairs get changed when triggered?
Edit: The IDs was supposed to be classes, of course.
#select_something
Is an id. IDs must be unique over your entire page. If you have multiple elements with this same id, that's fundamentally wrong (and will cause you massive problems).
Having said that, the fix is easy: change those ids to css classes.
<select id="select_something">
becomes
<select class="select_something">
Then you could select against the css class, but of course you'll have to select the : write_something element relative to the current select. Something like this might work depending on your structure:
$(".select_something").change(function() {
if (!($("option[value='0']", this).attr("selected"))) {
$(this).siblings(".write_something").css('display','');
}
else
{
$(this).siblings(".write_something").css('display','none');
}
});
You should be using a common class for the multiple objects, not a common ID.
The ID attribute is used to IDentify a single item. The CLASS attribute is used to define that an item is part of a group of items, all which have the same class name.
Use the class name selectObject on all of them, and then..
$(document).ready(function() {
$(".selectObject").change(function() {
//inside of an event, $(this) refers to the object that triggers the event,
//in this case, the item that was clicked.
if (!($(this).val()==0)) {
...
}
else
{
...
}
});
});
Here is something for illustration.
http://jsfiddle.net/FxLSR/1/
As mentioned in other answers and comments, only use an ID for unique elements, use a class for multiple elements.
This is how I would setup my code:
HTML:
<div>
<select class="select_something"> ... </select>
<textarea class="write_something"> ...</textarea>
</div>
<div>
<select class="select_something"> ... </select>
<textarea class="write_something"> ...</textarea>
</div>
etc...
Javascript:
$(document).ready(function() {
$(".select_something").change(function() {
if (!($(this).val() == "0") {
$(this).next().show();
}
else
{
$(this).next().hide();
}
});
});
If the elements can't be placed next to each other as in the example HTML code I have given, then just make sure to select the textarea using some sort of relative selector such that you're not selecting all of the text areas. For example, if the two are siblings but they're not next to each other use: $(this).siblings(".write_something")

how to add onclick event to create new element in javascript

I have created a label element. I need to add onclick event to that...
function a(me) {
var d=document.createElement("label");
d.id=me.id;
d.onClick="a(10)";
d.innerHTML="welcome";
document.body.appendChild(d);
}
HTML:
<label id="1" onclick="a(this)">aa</label>
<label id="2" onclick="a(this)">bb</label>
<label id="3" onclick="a(this)">aa</label>
actually what happens is when i click the any of three labels in html. another label is created and displays welcome. now when i click the newly created label "welcome" it does not display anything...... that is the onclick event added to newly created label is not working ....... any suggestion.................
You need to set d.onclick=function(){a(1);};, note that the case matters here (not "onClick").
[Edit]
Based on your comments and updated questions I've created a jsFiddle to demonstrate how you might turn your code into something that works.
d.setAttribute('onclick', 'alert(\'hello\');');
For creating an attribute to a HTML tag, sometimes we have to add this:
yourTag.src
yourTag.src = 'http://lolxd.com/404.png'
But there are special attributes, and them have diferents ways for editing:
yourTag.classList
yourTag.className
And there is the onclick attribute, wichwe can use it like this:
// The first way
obj.onclick = function () { alert('lalala') }
// With the Event Listener
obj.addEventListener('click', function () { alert('lalala') }, false)
// Or, a text-render way
obj.setAttribute('onclick', 'alert(`lalala`)')
I recomend you the Event Listener way, but try all :D

Categories

Resources