I am storing a div which gets selected
var selectedCell = null;
$(".selectableBox").on('click', function (event) {
selectedCell = $(this);
}
Later I want to hide one of selectableCell's children name selectableCellChild
$('#deleteConfirmed').on('click', function (event) {
selectedCellList.($'selectableCellChild').hide();
});
How can I correctly hide this child div? I know the syntax of the above example isn't right, and I have tried it many ways including using children() and next() methods of selectedCellList
selectedCellList.find('{selectableCellChild}').hide();
Where selectableCellChild is a placeholder for the real selector of the cell.
I have tried it many ways including using children() and next()
children - traverse only one level deep.
find - traverse the all the DOM levels deep.
next select the next immediate sibling.
For the second part, this is what you want:
$('#deleteConfirmed').on('click', function (event) {
$(selectedCellList).find('.selectableCellChild').hide();
});
If I understood correctly, you are trying to hide the children of clicked div. Try like below,
var selectedCell = null;
$(".selectableBox").on('click', function (event) {
selectedCell = $(this);
}); //Your missed );
$('#deleteConfirmed').on('click', function (event) {
//v-- Changed from selectedCellList to selectedCell as this is the clicked div.
selectedCell.find('.selectableCellChild').hide();
//assuming selectableCellChild-^ is class of child elements in the clicked div
});
Use .find.
selectedCellList.find('selectableCellChild').hide(); // I hope selectableCellChild isn't your real selector, it won't work
Also, when declaring your variable, make it a jQuery object since you intend to store a jquery object in it to avoid undefined method errors.
var selectedCell = $();
Related
I'm trying to figure out, when iterating through some list items, how to target each "$(this)" equivalent within nested foreach loops. Here is an example of my problem:
$('li').each(function(){
// I believe $(this) would target each li item...
$(this).children("li").each(function(){
// ... but how can I target each of these li items? Doesn't $(this) target the original loop?
});
});
$('li').each(function(){
var $this = $(this);
$this.children("li").each(function(){
$this; // parent li
this; // child li
});
});
Don't use this! Use function parameters!
$('li').each(function(i, li){
$(li).children("li").each(function(ii, li2){
$(li)...
$(li2)...
});
});
This is more in keeping with the native JavaScript iterators.
...though an <li> can't be the direct child of another <li>
Look at the basic "prototypes" of jQuery functions (or methods, if you will):
$[jQobject].[func]([callback]);
The callback is the function that will be invoked in the context of the jQ object. The context being this, obviously. Put simply that means that:
$('#foo').click(function(){});
/\ /\
|| Is the context ||
=====================
The same applies to your case, regardless of the loops being nested or not:
$('ul').each(function()
{
//this is ul
var that = this;//you'll often see code like this
$('li', this).each(function()
{
//this is li
//that is parent ul
});
});
but how can I target each of these li items? Doesn't $(this) target the original loop?
Nope.
this comes from the function you're directly in.
Nope, this refers to each of the child <li> items. Try it out.
Most (if not all) DOM-interacting jQuery callbacks set this to to the DOM element that you're working with.
You could also write:
$('li').children("li").each(function(){
var $this = $(this);
});
I find my self doing this a lot:
$(document).on("click","li",function(){
$(".selected").removeClass("selected"); // Remove any old selected
$(this).addClass("selected"); // Apply selected to this element
});
Is there a better and less repetitive way of doing a task like this? Like toggle a class. Btw, only one element can be selected at a given time.
Thanks.
A more efficient way is to keep track of the last selected item:
var $selected = null;
$(document).on("click", "li", function() {
if ($selected) {
$selected.removeClass('selected');
}
$selected = $(this).addClass('selected');
});
Of course, this should work as long as that particular function is the only one that will ever add / remove the selected class.
This could optionally be wrapped inside a closure to remove the $selected variable.
Btw, using document as the anchor for your delegation isn't best practice. It's better to choose the nearest node that will not get removed from the document.
Update
As Kevin B has mentioned, you could eliminate the branch like so:
var $selected = $();
$(document).on("click", "li", function() {
$selected.removeClass('selected');
$selected = $(this).addClass('selected');
});
The ability to use $() was introduced in 1.4; before that you would use $([]).
You can do this:
<script>
$(document).ready(function(){
$(this).on("click", "li", function() {
$(this).addClass('selected').siblings().removeClass('selected');
});
});
</script>
After debating with Jack I propose mine.
Assuming your list is here :
var $myList = $('#list');
Then:
$myList.on("click","li",function(){
$(".selected",$myList).removeClass("selected"); // Remove any old selected
$(this).addClass("selected"); // Apply selected to this element
});
or
$myList.on("click","li",function(){
$(this).siblings(".selected").removeClass("selected"); // Remove any old selected
$(this).addClass("selected"); // Apply selected to this element
});
Your way of doing it is good enough for me but Jack's is faster and mine is in between both.
I like this one because you don't need to assume there will only be one selected element. And searching is faster when we provide context as far as I know
Thinking about this, you could keep your list elements in a variable, such as:
var $liElements = $('#yourContainer > li');
$(document).on("click","li",function(){
$liElements.not($(this)).removeClass("selected");
$(this).addClass("selected");
});
The notion of keeping track of the current element is the same as the other answers, but you can wrap this logic up cleanly in a function such as
function class_swapper=function(cls){
var cur;
return function(elt){
if (cur) { cur.classList.remove(cls); }
elt.classList.add(cls);
cur=elt;
};
};
A call to class_swapper returns a function used to actually apply the specified class to a particular element (and remove it from the previous one, which is remembered inside the function). You can use this as follows:
var swapper=class_swapper("selected");
swapper(elt1);
swapper(elt2);
or in terms of your example
$(document).on("click","li",function(){swapper(this);});
I've used classList.add and classList.remove, which is a classy way (ouch) of manipulating classes in modern browsers, but of course these could be replaced by jQuery's addClass etc. as necessary.
In my project. I am trying to check whether a certain number already present in any other adjacent div's which are present in a parent div.
//generated dynamically using jQuery
<div> //parent div
//many div's
//one of the child div is selected by the user.
</div>
<div> //another parent div
//my function is checking one of these div's instead of the above, rarely
</div>
I used the following below code. but it sometimes(rarely) selecting the another parent div's child elements which I dont want to check for (I checked with debugger in chrome). and if sometimes even if the function selects the correct parent div it is always selecting the same child div element which is selected by the user.
jQuery
function checkInGroup(){
var selectedDiv = $('#' + _selectedDivId); //updated after engineer's comment
selectedDiv.parent("div").children().each(function(){
debugger;
if(this !== selectedDiv[0]){ //selecting the same div
var self = $(this);
if(self.text() == _randomNumber){
debugger; //never executing
//do some function here
}
}
});
}
EDIT: I am not sure why my code is not working when it is working fine in jsbin. I need to check why so.. It is always checking with the same user selected div?? Hence the function is not entering into the if statement..
The debugger which is present inside the if statement is never executing. and also the each function loop is happening only once with the same selected div (hence the function is not entering in to the if statement)
Here is the jsfiddle
The $.each() function has an actual signature of $.each([Array], index, element). In your case:
function checkInGroup(){
var selectedDiv = $('#' + _selectedDivId);
$.each(selectedDiv.parent("div").children(), function(index, element){
debugger;
if($(element) !== selectedDiv){ //selecting the same div
if($(element).text() == _randomNumber){
//do some function here
}
}
});
}
try:
selectedDiv.parent("div").children().not(selectedDiv).each(function(){
//your code
});
Use siblings .
$('#' + _selectedDivId).siblings().each(function(){
});
Updated:
selectedDiv id is not actually div it is button id. that's the problem. please
change your code like below.
selectedDiv.parent("div").parent("div").find("button").each(function(){
demo
selectedDiv may be an array in your example.
I don't think you can compare two jQuery objects like this.
You could consider using data attributes?
e.g.
var selectedDiv = $('#' + _selectedDivId);
selectedDiv.data('selected', true);
then
selectedDiv.parent("div").children().each(function(){
debugger;
if($(this).data('selected') !== true){ //selecting the same div
if($(this).text() == _randomNumber){
//do some function here
}
}
});
Just remember to set selected to false on the div when it's deselected.
There's probably a more efficient way to do this but this should work.
I am trying to use the following code to reference anything focused inside my contenteditable div, which has an id of rt:
var lastfocused;
$("#rt *").focus(function () {
lastfocused = $(this);
});
For some reason, lastfocused always equals $("#rt");, but never anything else which may be inside the contenteditable div. How do I make it so that anything focused inside the contenteditable div will be stored in the lastfocused variable?
Looks like your problem is elsewhere. The above code perfectly works for me:
http://jsfiddle.net/8hZWq/
EDIT
If the children elements aren't inputs as you said, but divs - the focus() method is not applicable to them, as it works only for input, textareas, select etc.
You can also use .click() instead of focus() to store the reference to the last clicked element. Bear in mind though, it also depends to the structure of your elements.
For example if you have multiple levels of containers within children divs, the #ID * selector will actually trigger multiple times each level of children starting from the #ID.
If you like to store reference to only the first level of children of the #ID, you should use #ID > * selector to refer only direct children.
If you like to store the reference to only the very element that was clicked upon regardless of it's level in relation to the container, you should use click event target reference instead:
var clicked;
$('#ID').click(function(event){
clicked = $(event.target);
});
Indeed your problem is because of variable declaration out of the function. Setting it in, in each focus event the 'lastfocused' variable will be re-assigned.
I came later, but if i arrive here someone else can.
Do this:
$("#rt *").focus(function () {
var lastfocused = $(this);
});
$('#cont > fieldset').each(
function(index){
var $self = $(this);
// Here how to get child elements? How to write this selector?
//$('$self > div') ?? this seems does not work.
});
$self.find("div"); // return all descendant divs
or:
$self.children("div"); // return immediate child divs
depending on whether you want immediate children or any descendants.
You can even do this to get immediate child divs, but children is prettier :
$self.find(">div");
Look at the .children method in jQuery. This will get direct children of the element, e.g.:
$self.children('div') // returns divs that are direct children
You can also use the similar .find method if you need to go deeper than one level.
$self.find('div') // returns divs that are direct children, or children of children
Also, you can select using $self as the context, like:
$('div', $self) //returns all divs within $self
using children
$(this).children('div')
or
using find
$(this).find('div');
look on this post
You can use the children() method, to get all immediate children of self.
var children = $self.children();