Working with previousSibling and nextSibling to set attributes - javascript

so since I started studying JavaScript I've been reading this book called Learning JavaScript by Tim Wright.
In this book I found a chapter about how we can move and target elements in the DOM tree and one of them is making use of properties which target siblings, while doing the exercises in the book I simply could not make the following statement work:
<ul id="nav">
<li>Home</li>
<li>About Us</li>
<li>Contact Us</li>
</ul>
<script>
//Should add "next" class attribute to the "Contact Us" li tag.
document.getElementById("about").parentNode.nextSibling.setAttribute("class", "next");
</script>
After having a quick look at this code I was wondering if any of you more experienced developers could help me and explain me why this doesn't work properly. I feel confused because I can't know whether I'm doing something wrong or the article about these properties is misspelled.
Anyway thanks for your time and help in advance!
Cheers!
cs.almeida

nextSibling selects the very next sibling of the element. The very next sibling node can also be a textNode that doesn't have setAttribute method, i.e. what your code tries to do is adding a class to the next sibling textNode. If you remove the line break and other hidden characters between the 2 li elements then you code will work as expected.
Another option is using the nextElementSibling property instead of the nextSibling, which will select the next sibling node that has nodeType of 1, i.e. the next HTMLElement sibling of the element.
document.getElementById("about")
.parentNode
.nextElementSibling
.classList // https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
.add("next");

Related

How to find more than one element in focus

I have a HTML where more that one element is active.
`document.activeElement `
returns the first one, but I need to find the second element which is in focus.
sample code as follows.
`<ul Class="ul1" Active="true">
<!-- some tags-->
<ul class="ul2">
<li Active="true">My Element</li>
</ul>
</ul>`
I need to find My Element in the above code which is dynamic(Some tags part will have different combination of tags), also position of li in UL2 will vary.
Please help to get the second element with javascript.
document.querySelectorAll('[Active="true"] [Active="true"]')
this will select every active child of every active element. Sadly, though it will also select the 3rd, 4th... nth child.
So if you have any other way to differentiate which one is the 2nd one, then the task will be much simpler.
If it makes any difference - the very fist element in the returned array will be what you need. but If you have several "2nd active children" you want to select - then you'll have no luck.
also:
document.querySelector('[Active="true"] [Active="true"]')
will return the first match, which is an active child of an active element.

Clicking on span element existing in li in selenium

I have been trying in selenium to click span element which has class named bullet. It's a tree structure where it expands it's children once clicked. I have tried in the following way, but it's not working.
Below is the UI Code
<ul id="treelist" class="ltree">
<li class="liClosed">
<span class="bullet"> </span>
<b>Setup</b>
<ul>
<li></li>
<li></li>............
.....................
</ul>
</li>
</ul>
The error is:
The given selector //*ul[#id='treelist']//li[2]//span is either invalid or does not result in a WebElement
The code I am using is:
WebDriver driver = new FirefoxDriver();
driver.get("http://somewebapp");
WebElement userElement = driver.findElement(By.xpath("//*ul[#id='treelist']//li[2]//span"));
I tried many ways of editing the xpath, but couldn't succeed. Can someone please help solve this issue?
The XPath expression is indeed invalid, remove the * before the ul:
//ul[#id='treelist']//li[2]//span
Here is an another alternative to locate the desired span tag:
//ul[#id='treelist']//span[#class='bullet']
Or, with a CSS selector:
driver.findElement(By.cssSelector("ul#treelist span.bullet"));
If you aren't tied to XPath, you can try a simple CSS selector.
WebElement userElement = driver.findElement(By.cssSelector("span.bullet"));
Looks like you need to deal with an element that exists inside of a frame. You can google lots of examples of how to do this but here's one from SO.
Find elements inside forms and iframe using Java and Selenium WebDriver
Your span.bullet is not within the second li, it's within the first one. Try
//ul[#id='treelist']//li[1]//span

Selecting range of elements with jQuery and CSS

I am trying to select a range of anchor elements using nth-child pseudo selector. The problem is that nth-child will work only with child elements, but I have a structure like this:
<div>
<a>first link>
</div>
<div>
<a>Second link</a>
</div>
<div>
<a>Third link</a>
</div>
In this case, the following selector that I found useful for selecting first 2 matched elements doesn't work:
$("a:nth-child(n+1):nth-child(-n+2)")
I created an example here: http://jsfiddle.net/o6w5orom/ , in the first example all the elements are returned instead of first 2. In the second one works but only with direct children.
So, is there a way to construct CSS selector for jQuery that will basically return a range of elements, something like nth-child, but will work on matched elements of a jQuery object ? I want to construct the selector, don't wan't to write logic to process a jQuery object.
Use: $("div:nth-child(n+1):nth-child(-n+2) a")
Select the divs with the nth-child then descend to the a's
Yes, you are right - :nth-child returns only direct children.
But what's the problem? Use find.
$("div:nth-child(n+1):nth-child(-n+2)").find('a')

Is it an ok practice to change an ID using javascript if the element is unique?

I have an unordered list, where I am using an ID to identify the current list item that was last clicked. On click of a different item, I am using js to switch the id to a different item in the list, so that styling could be applied.
It seems intuitive to me that a unique item that can only be used once (a selected li item) should be identified as an ID, and that is why I did that, but I was told it is bad practice to do so.
I wouldn't do so. This rather seems an opportunity for you to discover HTML 5's data attribute, which you can use for both CSS styling (using attribute selector) and JS use (with dataset or jQuery's .data() method).
Quick definition from MDN :
HTML5 is designed with extensibility in mind for data that should be
associated with a particular element but need not have any defined
meaning. data-* attributes allow us to store extra information on
standard, semantic HTML elements without other hacks such as
classList, non-standard attributes, extra properties on DOM, or
setUserData.
In HTML side :
<!-- You can use data without value, and just test its presence -->
<li data-selected>
...
</li>
In CSS :
li[data-selected]{
...
}
Your question actually has a couple of interesting components, let me try to answer them as good as I can :-)
"Is it an ok practice to change an ID using javascript if the element is unique?"
You could say it's a justifiable case, if the element really is unique, then there's no real harm in "moving" the ID with JavaScript.
BUT
In your description you touch on something more fundamental:
"On click of a different item, I am using js to switch the id to a different item in the list, so that styling could be applied."
If this is the case (you change the ID for styling), then I'd recommend using a class instead. People previously already gave you a good hint, something like an "is-active" class would be very useful as it's less specfic than an ID, can be used on multiple items if needed and if you use classes that determine a state (like "is-active", "has-children", "is-animating", etc.), it's really easy to re-use them in later parts of code as well and it is clear what the element is doing at the moment.
A little code for reference:
HTML
<ul>
<li>Some item</li>
<li class="is-active">Some item</li>
<li>Some item</li>
<li>Some item</li>
</ul>
CSS
.is-active {
color: #eee;
background-color: #222;
}
jQuery
// You probably want a bit more specific selector, but it's just an example.
$('li').on('click', function() {
var $element = $(this),
$elements = $('li');
if (!$element.hasClass('is-active')) {
$elements.removeClass('is-active');
$element.addClass('is-active');
}
});
Since you might need to reference the specific id of an element at some future point, changing it is probably a bad idea. In your case it would be better to just apply a class to the last item clicked.

Toggle multi-level ul with mootools

Greetings,
I would like to toggle a huge multi-level ul with mootools 1.1 or plain javascript.
The list looks like:
HTML:
<ul>
<li>aaa</li>
<li>bbb</li>
<li>ccc</li>
<li>
<ul>
<li>ddd
<ul>
<li>fff</li>
<li>ggg</li>
</ul>
</li>
<li>eee</li>
</ul>
</li>
</ul>
What I would like to do initially is to show the first level expanded, and the other levels collapsed and when each of the list items is clicked, to expand the ul below it.
Is it possible to do it without (greatly) modifying the html above?
From the documentation, I see that Fx.Slide is the most appropriate, however it accepts the id of the element as a parameter, which means I have to assign id's to each list item.
Is there a way by using selectors of collections of elements starting from the top?
I'm not sure whay I'll say apply with the very old 1.1 version. However, at least since 1.2, the element you need to pass is either the ID (like you said), either the actual element.
If you can use another version than 1.1, try the 1.3 which makes it easier to select the elements you want.
Here, I believe you need every <ul> element which has a direct <li> as parent. MooTools 1.3 features this new selector engine Slick, which would accomplish it fairly easilly: ul !> li.
However, I'm not sure (I didn't success) that the direct child selectors works properly with 1.1.
Here is what I came up with: http://jsfiddle.net/rCfwq/

Categories

Resources