Jquery selecting hierarchies - javascript

Before I begin this question, if you're new to backbone.js and want to implement the following functionality you have to use the backbone relational model, or at least that's what it seems like.
I'm trying to create a hierarchy that will be implemented through backbone.js and I was wondering how to structure the hierarchy and access the elements. I need to be able to add and remove Lists/Sets/Items and hopefully keep a consistent numbering policy. (List1 would have a displayed name of list1. If I deleted Set1 I would want Set2 to become Set1 while retaining its corresponding items)
List1
^--->Set1
^--->Item1
^--->Item2
^--->Set2
^--->Item1
List2
^--->Set1
^--->Item1
^--->Set2
^--->Item1
^--->Item2
etc.
My question is this: How do you structure this in a way such that a set of functions following the same hierarchy can access them in the most compact and logical manner?
One idea I had:use div and just have your div id be something like id="List"+currentlistnum()+"Set"+currentsetnum()+"Item"+currentitemnum()
Is there a better way to do it than this?

If you have list of items that is semantically a "list", use ordered list(ol) or unordered list(ul). Then if you have sub lists nest more lists.
<ul id="mylist">
<li>
<span>List 1</span>
<ul>
<li>
<span>Set1</span>
<ul>
<li>List1Set1Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
</li>
<li>
<span>Set2</span>
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
</li>
</ul>
</li>
</ul>
And use jQuery nth Child selector and immediate child > for rest of logic to select particlar elements, so you can keep application logic away from HTML.
$('#mylist > li:nth-child(1) > span').text(); // List1
$('#mylist > li:nth-child(1) > ul > li:nth-child(1) > ul > li:nth-child(1)')
.text(); //List1Set1Item1
If you want a numbering system attached: Example refresing all Set to update its number according to present view:
$('#mylist > li > ul > li > span').each(function(){
var ordinalPositionOfMyParent = $(this).parent().index() + 1;
$(this).text('Set' + ordinalPositionOfMyParent);
});

Related

How to select the next immediate child using querySelector?

I want to loop through a div and store the <h4> and <ul> inside an object.
And I already used querySelectorAll but that will select all h4 or ul elements.
In the picture you can see I'm selecting the immediate <h4> and <ul> child, likewise I want to select the next <h4> and <ul> elements and store it in an object.
You can still use querySelectorAll and choose the correct index (next will be index 1)
document.querySelectorAll('#main > ul')[1]
document.querySelectorAll('#main > h4')[1]
Example proof of IMDB web
const secondH4 = document.querySelectorAll('#main > h4')[1]
const secondUL = document.querySelectorAll('#main > ul')[1]
console.log(secondH4, secondUL)
<div id="main">
<h4>11 August 2020</h4>
<ul>
<li>
Valley of the Gods (2019)
</li>
</ul>
<h4>14 August 2020</h4>
<ul>
<li>
Spree (2020)
</li>
<li>
Endless (2020)
</li>
<li>
The Bay of Silence (2020)
</li>
</ul>
</div>
NOTE
By using nextSibling you'd need more logic since nextSibling does not select the next h4 or next ul it selects whatever DOM element is next to the current one
You should probably select all 'h4' and 'ul' elements into their own collections, identify the current element in these collections and simply pick the following element. Here is a small snippet showing how to find the next <h4>:
const allH4s= [...document.querySelectorAll("h4")];
// assuming a <h4> has been selected:
const firstH4=document.querySelector("h4"),
// then nextH4 will be the immediately following h4 element in the document:
nextH4=allH4s[allH4s.indexOf(firstH4)+1];
[... collection] creates an Array from a collection. This is necessary, as we need to access the Array-method indexOf().
You can do a similar thing for your <ul>s.

Check if control present in main Ul tag or not?

I have following structure.
<ul id="main">
<li id="a"/>
<ul id="main1">
<li id="b"/>
</ul>
</ul>
In above code when the user clicked on the button, I want to check whether li with id=b present in id=main ul or not using jquery. So pleases let me know how can I check using jquery.
You can use below code to achieve what you want
if ($("ul[id='main']").find("li[id='b']").length > 0)
{
// Element is present.
}
else
{
// Element is not present.
}
Try this for a check:
if($('#main').has('li[id="b"]').length > 0)
This will check, if main has any li element with id equals b. The result is an array with all elements or zero elements.

jQuery target next `ul` element from `li` with class `active`

Cannot figure what I am doing wrong, as I get no errors. Essentially I want to target the very next ul element from the one and only li containing a class of active.
My HTML is:
<li id="abc"></li>
<li id="account" class="active">
<img class="menu-logo-symbol" src=" /img/app/logo-symbol.png">Your Account
<ul class="nav-pills nav-stacked sub-nav nav-list" style="display: none;">
<li id="account-details"></li>
......
</ul>
</li>
I have tried the following:
var checkElement = $('li.active').next('ul');
checkElement.slideDown('normal');
and
$('li.active').next('ul').show();
and also
$('li.active').next('ul').slideDown('normal');
Thanks
In jQuery, next() and prev() find siblings, or elements at the same depth in the DOM. In this case, since the ul is a child element of .active, you'd actually need to use the find() method like so: $('li.active').find('ul').first().show();
Using first() in combination with find() ensures that it'll only return that single ul element and not any others that may be nested deeper.
Done as follows:
$('.active ul:first').slideDown('normal');
I still do not understand why this did not work
$('li.active').next('ul').show();

Protractor - Finding elements by any attribute

<ul class="menu">
<li ui-sref-active="active">
<a class="ng-scope" translate="menu.home" href="#/home">Home</a>
</li>
<li ui-sref-active="active">
<a class="ng-scope" ui-sref="customer.list" translate="menu.customers" href="#/customers">Customers</a>
</li>
</ul>
I want to search for the element using the text "Home" as in code below:
element(by.linkText("Home")).click();
But I need use too any other available attribute, in this case translate, to make it more accurate.
Is there any possibility in doing that? I've seen things like this
by.css(".ng-scope input[translate='menu.customers']");
But it does not seem to work.
by.css(".ng-scope input[translate='menu.customers']");
This basically translates to: give me the input element having menu.customers translate attribute value, somewhere inside the parent element having ng-scope class. This is not working since there is no parent element with ng-scope class in the HTML you've provided and it is a instead of input you are looking for.
Instead, you probably meant to:
a.ng-scope[translate='menu.customers']
Though, I would not recommend relying on the quite broad ng-scope class.
Here are several rather precise CSS selectors, given the HTML you've provided:
ul.menu > li > a[href*=home] // href contains "home"
ul.menu > li > a[href$=home] // href ends with "home"
ul.menu > li > a[translate="menu.home"] // translate equals to "menu.home"
ul.menu > li > a[translate$=home] // translate contains "home"

jQuery Prepend Open Tag Append Closing Tag

Firstly, I am familiar with .wrapAll() and that is not what I need. I have some markup that I am not able to change and I need to wrap everything in a <li>.
Here is what I am trying to do:
$('nav[role="breadcrumb"] ul a').wrap('<li></li>');
$('nav[role="breadcrumb"] ul li:last').after('<li>');
$('nav[role="breadcrumb"] ul').append('</li>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav role="breadcrumb">
<ul class="clearfix">
Home
Health Care Professionals Healthy Choices Cholesterol Kits
</ul>
</nav>
The problem is that jQuery closes each of these <li> tags. Here is the original markup:
<nav role="breadcrumb">
<ul class="clearfix">
Home
Health Care Professionals Healthy Choices Cholesterol Kits
</ul>
</nav>
As you can see, I have some loose text at the bottom of this <ul> and I am trying to get it wrapped in an <li>.
.contents() will get all the children, including the text nodes
$('nav[role="breadcrumb"] ul').contents().filter(function() {
return $.trim($(this).text())!=="";
}).wrap('<li/>');
EDIT: Added the filter method to get rid of the whitespace text nodes
Try creating your <li> first and then append your selector to it:
var $li = $('<li>').append('nav[role="breadcrumb"] ul a');
Then use $li to replace or append anywhere you like.
jQuery only works with complete elements, you can't append just a closing or opening tag.
If the ul doesn't have any other list items, you could simply use wrapInner
$('nav[role="breadcrumb"] ul').wrapInner("<li />");
If it does contain LI's, the easiest way would be to detach them, wrap inner, then append them.
var $lis = $('nav[role="breadcrumb"] ul > li').detach();
$('nav[role="breadcrumb"] ul').wrapInner("<li />").prepend($lis);

Categories

Resources