I have indexed my document using Jquery index Given a certain index value, I would like to 'locate' the 'nearest' element with some class. This will not work for me:
$(variableIndexNumber).closest('.class');
The reason is that sometimes the .class changes its position, meaning it could be anywhere in the document. Sometimes its a sibling, sometimes a parent, sometimes way up in document or in the bottom. So the usual selctors next closest first nextAll etc don't work for me (because of document tree)
What can I try to get the nearest .class relative to some other element (given by variable)?
Use .prevUntil('.class'), .nextUntil('.class'), .parentsUntil('.class'), then compare their sizes.
Whichever one has the least size is the closest to the element in terms of DOM structure.
UPDATE: In the process, you will also need .andSelf(), .filter() and typical .next() and .prev() to actually get to the target you want. Demo has been updated. You can see that now the code is more generic.
You'll probably need a sorting function too, as I've did in the proof-of-concept below.
DEMO: http://jsfiddle.net/terryyounghk/FzA78/
Side-note: There's no .childrenUntil(), because that's branching outwards the DOM tree, not inwards towards the document root, in case you're wondering. But my guess is, you could do a $('.me').find('.class') first, then for each of them, do a .parentsUntil('.me') instead, then compare the sizes. I'm not sure if this would work though.
Related
Actual case is much more complicated but please play along. I am trying to select siblings of element that has class 'sss', by using
$('.sss').parent().parent().find(">div.childCollapsible>div[data-onthemovecollapsible=true]")
I can only use CSS selectors (this is part of Selenium thest). I expected to get only siblings of 'sss' however I am getting all the children of sub elements too.
How could I restrict it only to siblings?
or any other workaround that can get me from any element in the tree siblings only of any
data-onthemovecollapsible="true"
attribute holder.
EDIT: Firstly I would like apologise for failing to express myself clearly. The structure that I am working with is 'infinite tree structure' that has unknown amount of nodes on each layer, mechanism I am looking for is ability to get siblings on the same level that I am starting search from is and only children of his parent (his brothers + himself). All levels of tree have identical HTML syntax, so looking at them relatively from element one starts from, each layer is identical, hence the CSS selector should be identical too. I cannot use any other Jquery method but 'find', and only can use CSS selectors, as mechanism is part of selenium test so only By.CssSelector("...") can be used. I can traverse up the elements by using element.FindElements(By.XPath("..")) that gets me parent as I know how many levels up parent is, but from parent position I need to get all siblings without children (that have identical html syntax) in one go, so i would assume selector with only certain layer should do (like one in jsfiddle below), however it selects all the children nodes too - does not respect '>' for some reason. This would do nicely if I could use all JQuery functions.
$('.sss').parent().parent().children().children()
what I need is same result but with CSS selector.
http://jsfiddle.net/2a46U/
I think this will work for you:
.find("body>div>div>div>div.childCollapsible>div[data-onthemovecollapsible=true]")
If I'm understanding this correctly, you have two different restrictions here. One is that you only want siblings of an .sss element. The other is that the parent of the element is div.childCollapsible. I don't believe you will be able to do this with a single selector/find. You would need something like this:
// get the siblings of .sss with appropriate data attribute
var $els = $('.sss').siblings("div[data-onthemovecollapsible=true]");
// filter the collection to only those with appropriate parent
$els = $els.filter(function(){
return $(this).parent().is("div.childCollapsible");
});
http://jsfiddle.net/2a46U/4/
I've updated your jsfiddle with two options (check the console please):
Get all the siblings:
$('.sss').siblings();
Get specific siblings:
$('.sss').siblings("div.AppletBase")
If you need to set styles you can use the siblings selector in CSS3:
.sss ~ div.AppletBase {/* Your styles in here */}
Anything please leave a comment and I will review it again if is needed
I have a webpage in which I have two <div>s. Both elements are draggable; when one is dropped over the other, the positions are switched. Currently, the way the JS works is to actually switch the innerHtml property of both elements (meaning we get the innerHtml of the dragged element, the innerHtml of the drop zone element, and set both properties to the other element's value).
This works fine for switching the element's position. However, when the switch happens, data that is in <input> elements in both <div>s gets removed. How do I preserve this data when dragging and dropping?
I've tried the following:
Switching the DOM node reference itself, instead of the innerHtml property
Using cloneNode() and $.clone()
Getting the value property, in addition to innerHtml, and switching that too. This was rejected because it would be impractical due to the way the code is structured.
I have JQuery available, if that helps.
You can use jQuery's .detach() and .append() methods.
To move a div on the DOM, call $(div).detach(); to remove it from its current location, and then call $(newParent).append(div); to append it to its new location.
I'm assuming both div and newParent are either the elements themselves, or a selector to retrieve the correct element.
See also this answer.
I'm trying to further my understanding of traversing and correctly using $(this).
I understand $(this) is used in reference to the context. However, say I have three items that are identical to each other (HTML-wise) and if a user clicks on an input, I want the events to not only happen for the item the user selected, but be able to access the parent element ".item" as well. This way, I can hide other elements within ".item" because, again, the context would be the "input" that the user clicked.
This is where I am confused. When a user clicks on the input ($('input').on('click', doSomething);), I am limited to the context of the input - nothing is inside the input, so I want to access other elements that are out of the input context.
I then try and use $(this) to say I only want THIS event to happen for THIS item only, not affecting ALL items.
Here is a code example: JSFIDDLE
I've tried researching this and I can't find much information on an instance like this so hopefully this could benefit others too. Feel free to make edits to the content / heading as I've tried to be as specific as possible.
To get the immediate parent(s) of the element(s) in a jQuery set: parent. (If your set has only one element, as $(this) will, that will give you that element's immediate parent.)
To find the closest element(s) to the elements(s) in a jQuery set matching a given selector, starting with the current element(s): closest. (If your set has only one element, as $(this) will, that will give you the first element matching a selector starting with that one element, then looking at its parent, then its parent, etc.)
This should be your click-handler code :
function doSomething(event) {
$(event.target).parent().find('ul').hide();
}
I'm doing some quite rudimentary jQuery stuff, getting started really, and I'm frequently navigating up the dom by doing things like
$(this).parent().parent().addClass('hello');
I was just wondering if there's a nicer way to do this?
You can use parents, which returns all ancestor elements in turn. If you want to stop traversing at a particular level, use eq to filter the resulting collection. For example, to get the grandparent:
// 0 = parent, 1 = parent of parent, etc.
$(this).parents().eq(1).addClass('hello');
If you want to go upwards through the tree and stop not at a particular level, but at a particular selector match, use closest instead, e.g.:
$(this).closest("table").addClass('hello');
Say you have the following HTML:
<div>
<span>
<strong>Hi there</strong>
</span>
</div>
You could just use .parents() to get the div element:
$("strong").parents("div").addClass("hello");
Simply replace "strong" with this and you can use a selector to find a specific parent element.
You can use the closest() method, which returns the first element that matches the given selector in the ancestor chain.
$(this).closest(SELECTOR_OF_THE_PARENT).addClass('hello')
Sounds like your after .parents() or .closest() -- the latter being the most efficient, as it stops progressing up the DOM once it matches the closest selector.
"I was just wondering if there's a nicer way to do this?"
It's definitely a great idea to be intimately familiar with jQuery's selection and traversal methods.
However, if in the future you find yourself overwhelmed by traversal and discover:
That your "data model" is actually contained in your DOM
Maintaining and changing applications of this nature is very painful
...it might be time to consider a formal model-view approach.
I have a table with some radiobuttons in it. When i click on a radiobutton, i want to update two of the sorrounding containers ID attribute (a div and a table). The problem is, i need to go 4 and 6 levels up, and the only way i know how to do this is parent().parent().parent().parent() etc.
I am looking for a better solution, and was hoping someone could point me in the right direction. You can see an image of how the "parent-child" tree is here:
http://imageshack.us/photo/my-images/834/imgkz.png/
I already have a clickhandler etc set up.
Basicly i need to check if the table's id attribute is "answeredTable", if not i need to change it. Also i need to check if the div two levels up from the table is "answered", if not, i need to change that too.
Thanks
You can use .closest('#answeredTable') or .parents('#answeredTable').
Using .parent() only selects the first parent element upon the DOM tree, selecting .closest() will allow you to walk up to DOM tree and match until it finds the element, while .parents() will return the whole parentset of the DOM and match the element in the whole parentset.
You need to use .parents() that go through multiple level of the DOM
For instance, in your example, you could get the surrounding div with this code:
$("#Q_18_2015").parents("div#answered")
By the way, id should be unique, or else, your code might probably not work. You should use classes instead.
<div class="answered">
Thus, the code would become:
$("#Q_18_2015").parents("div.answered")
provided that Q_18_2015 is really a unique id
I think what you want to use is closest http://api.jquery.com/closest/
you can use .parents
$("element").parent(".parentClass")
parents will go up the DOM until finds the parent with class parentClass