Deal with multiple ID's in document - javascript

I have a problem dealing with duplicate ID's. I'm also aware it's very bad practise to have elements with the same ID but in this case, I'll end up having to change a massive part of the application to change the ID's so they can be unique.
I am having a problem toggling classes on an element in jQuery. My structure is below:
<ul>
<li id="wl-7050"> <!-- This acts as a main data group holder for the below li elements -->
<span></span>
<div id="wlHeader-7050"></div>
<div id="wlBody-7050">
<ul>
<li id="wl-7050"> <!-- This is the single element version of the data group header as above -->
<div id="wlHeader-7050"></div>
</li>
<li id="wl-7051"></li>
<li id="wl-7052"></li>
<li id="wl-7053"></li>
</ul>
</div>
</li>
</ul>
What I'm needing is a function where if I click the first instance of ID wl-7050, the child elements receive a new class. Whereas, if I select the second (single) element with ID of wl-7050 then only that one element has the new classes added to it.
I've tried using jQuery along with it's :first & :eq(0) attributes but still no luck unfortunately.
I do have classes assigned to each li element and it's child elements but whenever I run $('#wl-7050:eq(0)'), it returns both and the parent wl-7050 element get's used also.
I am flexible with JavaScript and jQuery answers.

The id attribute specifies a unique id for an HTML element (the value must be unique within the HTML document).
You can't have two wl-7050. Use classes. Then to work on "add new class on click" it's just hard code. If you need a help I can edit my answer. But is just coding. Html IDs is a concept

I've been there before: I've had to deal with applications that do weird things, where changing them to be "correct" causes more grief than just dealing with it and moving on. You know duplicate IDs are bad, I know duplicate IDs are bad; let's sort the problem. (Yes, they're bad. Yes, they shouldn't be there. Unfortunately, there they are.)
You can treat IDs just like any other attribute on an element: they're attributes, albeit special ones. Code like this will work to select all elements with the same ID: $('[id=wl-7050]').
Now, we need to bind a click event to them. We'll do the same thing as we always do:
var lis = $('[id=wl-7050]').click(function(e){
console.log(this);
});
Here's the trick, and it would happen even if these elements all had different IDs: when you're clicking in a child LI, that click event will bubble up to the parent. We'll need to shut off event propagation so we don't trigger our click event twice:
var lis = $('[id=wl-7050]').click(function(e){
e.stopPropagation();
console.log(this);
});
Now we're in business and can work to figure out which type of LI we're working with: top-level or child.
var lis = $('[id=wl-7050]').click(function(e){
e.stopPropagation();
if ($(this).children('li').length > 0) {
// Top-level LI
}
else {
// Child-level LI
}
});
That should get you where you need to be. Let's all agree to never speak of those duplicate IDs again.

If you can't change the IDs, you could try adding a different class name to both elements:
<ul>
<li id="wl-7050" class="wl-7050-main">
<span></span>
<div id="wlHeader-7050"></div>
<div id="wlBody-7050">
<ul>
<li id="wl-7050" class="wl-7050-single">
<div id="wlHeader-7050"></div>
</li>
<li id="wl-7051"></li>
<li id="wl-7052"></li>
<li id="wl-7053"></li>
</ul>
</div>
</li>
</ul>
Then you query with:
$("#wl-7050.wl-7050-main");
$("#wl-7050.wl-7050-single");

You don't need to add an id to each li that would make it overly complicated. Just use classes inside your items and call them this way:
$("#group li").on("click", function(){
alert($(this).data("id"));
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="wl-7050"> <!-- This acts as a main data group holder for the below li elements -->
<span></span>
<div id="header"></div>
<div id="body">
<ul id="group">
<li data-id="1"> <!-- This is the single element version of the data group header as above -->
<div class="wlHeader"></div>
</li>
<li data-id="2"> <!-- This is the single element version of the data group header as above -->
<div class="wlHeader"></div>
</li>
<li data-id="3"> <!-- This is the single element version of the data group header as above -->
<div class="wlHeader"></div>
</li>
</ul>
</div>
</li>
</ul>

Related

Dynamically calling attirb value from li class through jQuery

Could you please help me in dynamically calling attrib value through jQuery from the 'li class' by identifying the 'itemprop'?
My HTML is as below,
<ul class="blockNoBordr">
<li class="specHeading">Model</li>
<li class="specText" itemprop="model">
<span class="attribVal newattribVal">32LJ573D</span>
</li>
</ul>
I want to dynamically call Model value into a JS code i.e., 32LJ573D
console.log($('ul li[itemprop="model"].specText').first().text());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="blockNoBordr">
<li class="specHeading">Model</li>
<li class="specText" itemprop="model">
<span class="attribVal newattribVal">32LJ573D</span>
</li>
</ul>
You need to pick li inside your ul with a specific class. The following code will work for you. I have printed text of li with class "specText" for reference. You could modify any attribute as per your requirement.
console.log($('ul li[itemprop="model"].specText').first().text());
When you choose elements by classname, multiple elements are returned in an array. So choose the first element by adding index [0].
$('.classname')[0].innerHTML

How to add html after the first <li> tag?

<div class="box">
<ul class="test">
<li>test1</li>
<a class="add">test2</a>
</ul>
</div>
Above my HTML content coming dynamic. I want to add li tag in my test2 anchor link in JQUERY.
Here I have tried-
$('.box .test li:first-child').after('<li>');
But this li tag creating in wrong place. But I want my output should be like this -
<div class="box">
<ul class="test">
<li>test1</li>
<li><a class="add">test2</a></li>
</ul>
</div>
The best and correct way would be to fix your source html! A a tag inside a ul element is not valid. So your first task should be to get a correct html output.
If not possible you could use a :not selector and wrap(). So every child element, which is not a li, will be wrapped with a li element. This keeps it dynamic ...
$('ul > *:not(li)').wrap('<li>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
<ul class="test">
<li>test1</li>
test2
<strong>test3</strong>
</ul>
</div>
The problem is with your initial HTML, since an a element can't be a direct child of a ul element. Try to fix this in you initial rendering, and not later using javascript, simply for the reason that different browsers will act differently upon invalid HTML fragment (auto-fix it, drop it, you name it...).
Having said that, in general $('selector').wrap('<wrapperElement />') is the traditional jQuery's way of wrapping an existing element with a newly created one.
Below code will wrap li tag around a tag having class add.
$("a.add").wrap("<li>");
$(document).ready(function(){
$("a.add").wrap("<li>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
<ul class="test">
<li>test1</li>
<a class="add">test2</a>
</ul>
</div>
you're actually looking to add an element as a parent of another one, use Jquery wrap function instead:
$(".add:eq(0)").wrap("li")

targeting a li with javascript without a ID

I have a mobile nav, that looks like this
<ul id="mobile-menu" class="menu>
<li class="normal-link">link-1</li>
<li class="dropdown-link">link-2
<ul class="submenu">
<li class="link-of-dropdown>blabla</li>
<li class="link-of-dropdown>blabla</li>
<li class="link-of-dropdown>blabla</li>
</ul>
</li>
<li class="dropdown-link">link-3
<ul class="submenu">
<li class="link-of-dropdown>blabla</li>
<li class="link-of-dropdown>blabla</li>
</ul>
</li>
<li class="normal-link">link-1</li>
</ul>
I cant change the html/wordpress generated code, but I can add css and javascript. So is there a way for me to get next to the dropdown-link's a image that will let the submenu free. if the image is pushed the image will change. if pushed again it will go back to the normal image and the dropdown dissappears again?
I am mostly looking for answer for the problem with of javascript on the dropdown link's but just so you know what i want to do with it.
This question is so very, very vague. But I guess you're looking for the nth-child() selector.
See the docs here for more information. Target your 'mobile-menu' ul, and use nth-child to select the li elements within.
My big question would be, why can't you change the HTML? If it's Wordpress, you can modify the template to change the HTML.
You question is not really clear but if you want to retrieve an element without using id, first you may use their classes
var myClass = document.getElementsByClassName("classname"); //returns a nodeList like array
myClass[0] //first element with "classname"
You may also use tag names
var divs = document.getElementsByTagName("div");
divs[2] //third "divs"
You may also use querySelectorAll, this works pretty much like CSS selector and also returns a nodeList
var qs = document.querySelectorAll(".class");
I hope this helps
You could add a class and use the Jquery class selector: $(".class-name") to target a specific <li>

How do I hide the proper panel in jQuery where there are 2 with the same class?

I am trying to hide only one panel at the time depending on the link you clicked on
Here is the html which its been generated with Handlebars
<li>
<a class="hide-me"><h3>Enterprise</h3></a>
<ul class="sections">
{{#each chart-container.[0].enterprise}}
<li>
<a>
<span>
<img src="{{picture}}" />
{{name}} <br> {{role}}
</span>
</a>
</li>
{{/each}}
</ul>
</li>
<li>
<a class="hide-me"><h3>Consumer</h3></a>
<ul class="sections">
{{#each chart-container.[1].consumer}}
<li>
<a>
<span class="name-role" id="{{id}}">
<img src="{{picture}}" />
{{name}} <br> {{role}}
</span>
</a>
</li>
{{/each}}
</ul>
</li>
and here is the jQuery
$('.hide-me').on('click', function() {
$('.sections').slideToggle();
});
but obviously its hiding every with that class, what should I do in this case?
You need to track down the one you're looking for. Given this structure, it would look like:
var $li = jQuery(this).closest("li"); // Gets the parent li element
var $sections = $li.find(".sections"); // Within that li, finds the sections ul
$sections.slideToggle(); // Applies directly to this element
There are probably other ways to get there - jQuery has a ton of ways of hitting the DOM - but I find this nice and clean.
EDIT
The other answers, using next, should work fine - the reason I'd avoid it is because you may manipulate the way your list looks - maybe moving the anchor to the end instead of the beginning, or throwing an image or something else in there - if you did that, your code would no longer work. My way, as long as you keep the basic structure and don't move things outside of this structure, you're all good.
Use next() based on html shown
$('.hide-me').on('click', function() {
$(this).next().slideToggle();
});

jQuery: Simple way to slideToggle multiply elements independently (and similar questions)

Firstly, I need to say that I'm pretty new to jQuery.
I have this situation: http://jsfiddle.net/dVf8m/
I've been wondering if there is a way to do the slideToggle simplier. Now I have two ids on menu elements (#trigger1 and #trigger2) and two ids on the hidden divs (#one and #two). This also results in double jQuery. Is it possible to avoid all the ids and make it simpler?
Another thing is that if I click on both menu elements (First and Second) both divs appear. I want only one of the hidden divs to be visible at one time? How can I force the first div to disappear when the other one is appearing?
Also, if I'd want to use fadeIn/fadeOut in this situation, how to do it when both of them use the .click event?
Change your code to something like below. Have a class for the div and add click listener to it. add any attribute to the div and give the id of the div to be toggled.
<div id="top">
<ul>
<li><span id="trigger1" class="toggler" data-item="item1">First</span></li>
<li><span id="trigger2" class="toggler" data-item="item2">Second</span></li>
<li>Third</li>
</ul>
</div>
<div class="hidden" id="item1">
<ul>
<li>Smthn</li>
<li>Smthn2</li>
<li>Smthn3</li>
</ul>
</div>
<div class="hidden" id="item2">
<ul>
<li>Apple</li>
<li>Orange</li>
<li>...</li>
</ul>
</div>
$(document).ready(function() {
$('.toggler').click(function(e) {
$("#"+$(this).attr("data-item")).slideToggle(500);
});
});
JSFIDDLE

Categories

Resources