I need to get every element with a specific id, get the parent of the object, and set its ID.
How would I do this?
I have this code:
<li id="edge_top"> </li>
<!-- Menu Items Here -->
<li id="not_selected"><a id="selection_link" href="index.htm">Home</a></li>
<li id="not_selected"><a id="selection_link" href="page1.htm">Subitem 1</a></li>
<li id="not_selected"><a id="selection_link" href="page2.htm">Subitem 2</a></li>
<!-- Menu Items End Here -->
<li id="edge_bottom"> </li>
I need to find all the anchor elements with the id "selection_link", get the parent (the "list item" element [li]) and set its ID to "selected". How would I do this with jQuery? I'll be using the conditioning to determine if the li element will actually be allowed to get the new ID. (if the URL matches the href property of the anchor element).
HTML specification specifies that an ID should only be applied to 1 element. You can't have more then one element with the same ID.
In this case, it's better to use classes.
TO select by class:
$(".classname")...
EDIT: An example based on your code:
<li class="edge_top"> </li>
<!-- Menu Items Here -->
<li class="not_selected"><a class="selection_link" href="index.htm">Home</a></li>
<li class="not_selected"><a class="selection_link" href="page1.htm">Subitem 1</a></li>
<li class="not_selected"><a class="selection_link" href="page2.htm">Subitem 2</a></li>
<!-- Menu Items End Here -->
<li class="edge_bottom"> </li>
<script type="text/javascript">
$(document).ready(function(){
$(".selection_link").parent().removeClass("not_selected").addClass("selected")
});
</script>
You need to use classes for that. In HTML you not allowed to use ID's multiple times.
The id attribute should be unique across your XHTML document, so this question is not really valid.
Although this may work if you really insist:
$("[id=xx]")
$('li a').each(function(){
if ($(window).attr('location').href.match($(this).attr('href'))) {
//example with class
$(this).parent().addClass('selected');
// example with id
$(this).parent().attr('id', 'selected');
}
});
Related
say i have a list
<ul class="ul-1">
<li class="li-1">xx -1</li>
<li class="li-2">xx -2</li>
<li class="li-3">xx -3</li>
</ul>
i then save it as
var list = $('.ul-1').html();
i can populate another element i.e
$('.ul-2').html(list);
but what if I wanted to replace the first list element <li class="li-1">xx -1</li> with another list element, how do I do this using the list variable? thanks
Firstly note that it's generally better practice to work with references to the elements in the DOM rather than serialising them to strings which need to be deserialised again when re-added to the DOM.
In addition, if you work with the li references you can use jQuery to retrieve the first() of them and then replaceWith() to change it as necessary. Try this:
var $list = $('.ul-1 > li');
$list.appendTo('.ul-2');
$list.first().replaceWith('<li>Foobar</li>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="ul-1">
<li class="li-1">xx -1</li>
<li class="li-2">xx -2</li>
<li class="li-3">xx -3</li>
</ul>
<ul class="ul-2"></ul>
I have a menu of a list of article names list-A, and a corresponding list of articles content, list-B. Each list A and list B item pair share an identical value in their class eg. class="orderCntrl-6062347".
I want to be able to select an item from list A to bring the corresponding article from list B to the top of list B.
I know how to re-order the lists by using the following to bring a selected item to the top of a list:
$("li.orderIt").click(function() {
$(this).parent().prepend($(this));
});
This is what my code currently looks like:
<!-- List A selecting an item here should bring selected item and paired item in list B to the top of each of their lists -->
<ul class="list-A">
<li class="orderIt orderCntrl-6062347"><a>Item 1</a></li>
<li class="orderIt orderCntrl-6062348"><a>Item 2</a></li>
<li class="orderIt orderCntrl-6062349"><a>Item 3<a></li>
</ul>
<ul class="list-B">
<li class="orderCntrl-6062347"><h2 class="newsTitle">Item One</h2></li>
<li class="orderCntrl-6062348"><h2 class="newsTitle">Item Two</h2></li>
<li class="orderCntrl-6062349"><h2 class="newsTitle">Item Three</h2></li>
</ul>
<!-- Script to bring accompanying article to top of list on selecting side menu - currently only bring elements in List A to the top of their lists -->
<script>
$("li.orderIt").click(function() {
$(this).parent().prepend($(this));
});
</script>
Here's a link to how things will look, the green side menu is list-A (it may be above the page title on screens under 1300px).
How do I adjust the script to bring the corresponding list B item to the top as well?
Is this kind of what you are looking for?
https://jsfiddle.net/stevenkaspar/61oL0Lfm/
<ul class="list-A">
<li class="orderCntrl-6062347" data-news-target='#news1'><h2 class="newsTitle">Item One</h2></li>
...
<!-- List B -->
<ul class="list-B">
<li id='news1'>NEWS One</li>
<script>
$("[data-news-target]").click(function() {
$(this).parent().prepend($(this));
var target_element = $( $(this).data('newsTarget') );
target_element.parent().prepend( target_element );
});
</script>
You can use data-news-target to say what element it will move
Working JSFiddle Example
What you need to do is:
Get the unique name you want to use to match with the article element.
Use it to find the article element you want to move to the top.
Move the article element to the top.
Recommendations:
Set the unique name as an ID on the menu item. It'll be easier to get and cleaner (id's are supposed to be unique anyway).
Use .on("click", function() { ... }) rather than .click(function() { ... }) for the many reasons mentioned here.
Now, on click you need to find the id of this using this.id. Then you need to add a . to it and grab the element as an object using the symbols $(). Then prepend it in exactly the way you did before.
Example HTML:
<ul class="List-A">
<li class="orderIt" id="unique-name-1">Item 1</li>
<li class="orderIt" id="unique-name-2">Item 2</li>
<li class="orderIt" id="unique-name-3">Item 3</li>
</ul>
<ul class="List-B">
<li class="unique-name-1">Article 1</li>
<li class="unique-name-2">Article 2</li>
<li class="unique-name-3">Article 3</li>
</ul>
Example jQuery
$(".List-A").on("click", ".orderIt", function() {
$(this).parent().prepend($(this));
target_article = $('.' + this.id)
target_article.parent().prepend(target_article)
});
It could be simplified to:
$(".List-A").on("click", ".orderIt", function() {
$(this).parent().prepend($(this));
$('.' + this.id).parent().prepend($('.' + this.id));
});
but that's much less readable, which will make it more time-consuming to figure out what's going on 6 months later when you've forgotten what you did.
<ul id="my-list">
<li value="1001">item1 </li>
<li value="1002">item2 </li>
<li value="1003">item3 </li>
<li value="1004">item4 <li/>
</ul>
Is it allowed to have value for list item? If I can, how to access the value using javascript or jquery?
According to the W3C specification for LI element it is allowed to use value attribute for LI in some cases, but not this one. If you're using HTML5 use data-* attributes:
<ul id="my-list>
<li data-my-value="...">...</li>
<li data-my-value="123">...</li>
<li data-my-value="...">...</li>
</ul>
To get a reference to a particular element using jQuery use following selector:
$("ul#my-list li[data-my-value='123']")...
Or, if you already got reference to all LI elements use jQuery.filter():
var $items = $listItems.filter(function() {
retrun $(this).data("my-value") === "123";
});
You can add any sort of custom data attributes to your node (of course that HTML won't validate and it won't be a valid XHTML document). You can then access them using jQuery attr() function (for example).
That said it's a terrible practice and you should use a standard data- attribute, accessible for example with data() function (more details and examples in the provided link):
var theValue = $("#yourItemId").data("value");
For an attribute like:
<li id="yourItemId" data-value="1001">item1</li>
For this purposes I would recommended use jquery Data
<ul id="my-list">
<li data-value="1001">item1 </li>
<li data-value="1002">item2 </li>
<li data-value="1003">item3 </li>
<li data-value="1004">item4 <li/>
</ul>
Get second li value
$("#my-list").children().eq(2).data("value");
If you want to produce valid HTML5, you should stick to the data attributes for custom properties:
<li data-value="1001">
However, any element can have a custom attribute. In fact this has been standard in IE since version 5 (sometimes called expando properties).
I inherited template with the menu in which categories and subcategories is in the same scope. Here is an example:
<ul class="menu">
<li class="cat" data-item-type="category"></li>
<li data-item-type="sub-category"></li>
<li data-item-type="sub-category"></li>
<li data-item-type="sub-category"></li>
<li data-item-type="sub-category"></li>
<li class="cat" data-item-type="category"></li>
<li data-item-type="sub-category"></li>
<li data-item-type="sub-category"></li>
<li data-item-type="sub-category"></li>
<li data-item-type="sub-category"></li>
<li class="cat" data-item-type="category"></li>
<li class="cat" data-item-type="category"></li>
<li data-item-type="sub-category"></li>
<li data-item-type="sub-category"></li>
</ul>
I cant change the structure of this, but can add extra attributes to it.
So my question is if it is possible to select all categories subcategories when clicking on one of subcategories. In general i need to select all li until first class="cat" or data-item-type="category" occurrence including it - category and all it's subs.
Update answer per OP's update:
$('li[data-item-type="sub-category"]').click(function() {
$(this)
.add( $(this).nextUntil('.cat') )
.add( $(this).prevUntil('.cat') )
.prev('.cat').addBack() //in jQuery < 1.8, replace addBack by andSelf
//do something
});
Demo
After some brainstorming in the comments, here's a shorter alternative:
$('li[data-item-type="sub-category"]').click(function() {
$(this).prevAll('.cat:first').nextUntil('.cat').addBack()//do something
});
Demo
So .prevAll('.cat:first') matches the first previous .cat, nextUntil('.cat') gets all its subcategories and addBack (or andSelf in older versions) adds the .cat element back to the set of matched elements.
In up-to-date jQuery versions, the .add() and .addBack() methods sort the matched elements in document order, hence both alternatives will have .cat as the first element in the set followed by the subcategories in document order.
Reference
add
addBack
first
nextUntil
prev
prevUntil
This will solve your problem according to your request (updated) for category and subs (not buggy)
$('li').click(function() {
var x = $(this).add($(this).nextUntil('.cat')).add($(this).not('.cat').prevUntil('.cat')).andSelf().add($(this).not('.cat').prevAll('.cat:first'));
});
for clicking on the subs or the cat and selecting the other subs around it with it's category too
Use jQuery .nextUntil
$('li.cat').on('click', function() {
$(this).nextUntil('.cat');
/* then write you logic here */
});
I have a few tabs on a page that have this markup
<div id="holiday-details-nav">
<ul>
<li><a class="holidaydetails-description" title="Overview" href="#tab-holidaydetails-overview">Overview</a></li>
<li><a class="holidaydetails-included" title="Rooms" href="#tab-holidaydetails-rooms">Rooms</a></li>
<li><a class="holidaydetails-itinerary" title="Rates" href="#tab-holidaydetails-rates">Rates</a></li>
<li><a class="holidaydetails-accommodation" title="Information" href="#tab-holidaydetails-information">Information</a></li>
<li><a class="holidaydetails-reviews" title="Reviews" href="#tab-holidaydetails-reviews">Reviews</a></li>
</ul>
</div>
The hiding and showing of the content in these tabs are controlled by some JQuery code that begins thus
$(document).ready(function () {
// Hide all tabs apart from the overview
$('#holiday-details-tabs div:#tab-holidaydetails-rooms').hide();
$('#holiday-details-tabs div:#tab-holidaydetails-rates').hide();
$('#holiday-details-tabs div:#tab-holidaydetails-information').hide();
$('#holiday-details-tabs div:#tab-holidaydetails-reviews').hide();
...
The problem is that if I add, remove or rename tabs (like I have just done), then I have to change all this code. What I would like is to add, rename or remove as many tabs as I like but to not have to modify this JQuery code.
I'm not really looking for someone to code a solution for me but rather wanted to start a discussion on tools, techniques etc that can be used to avoid this sort of naming dependency.
EDIT
I also have this bit of ugliness for when a tab is clicked.
$('#holiday-details-nav ul li a').click(function () {
// Remove active class from all links
$('#holiday-details-nav ul li').removeClass('active');
//Set clicked link class to active
$(this).parent().addClass('active');
// Set variable currentTab to value of href attribute of clicked link
var currentTab = $(this).attr('href');
// Hide all tabs
$('#holidaydetails-description-imagecontainer').hide();
$('#holiday-details-tabs div:#tab-holidaydetails-overview').hide();
$('#holiday-details-tabs div:#tab-holidaydetails-rooms').hide();
$('#holiday-details-tabs div:#tab-holidaydetails-rates').hide();
$('#holiday-details-tabs div:#tab-holidaydetails-information').hide();
$('#holiday-details-tabs div:#tab-holidaydetails-reviews').hide();
$('#holiday-details-bottom').show();
$('#holiday-details-left-booknow').show();
// Show div with id equal to variable currentTab
$(currentTab).show();
$('#holidaydetails-description-imagecontainer').show();
return false;
});
Thanks,
Sachin
You could assign a common CSS class, say tab, to every li except overview, and then use a jQuery class selector to hide them all. For example:
<div id="holiday-details-nav">
<ul>
<li><a class="holidaydetails-description" title="Overview" href="#tab-holidaydetails-overview">Overview</a></li>
<li><a class="tab holidaydetails-included" title="Rooms" href="#tab-holidaydetails-rooms">Rooms</a></li>
<li><a class="tab holidaydetails-itinerary" title="Rates" href="#tab-holidaydetails-rates">Rates</a></li>
<li><a class="tab holidaydetails-accommodation" title="Information" href="#tab-holidaydetails-information">Information</a></li>
<li><a class="tab holidaydetails-reviews" title="Reviews" href="#tab-holidaydetails-reviews">Reviews</a></li>
</ul>
</div>
And then, to hide every tab except overview:
$("holiday-details-nav .tab").hide();
Or the other way around, that is, add a specific class to overview, and hide every other tab:
<div id="holiday-details-nav">
<ul>
<li><a class="overview holidaydetails-description" title="Overview" href="#tab-holidaydetails-overview">Overview</a></li>
<li><a class="holidaydetails-included" title="Rooms" href="#tab-holidaydetails-rooms">Rooms</a></li>
<li><a class="holidaydetails-itinerary" title="Rates" href="#tab-holidaydetails-rates">Rates</a></li>
<li><a class="holidaydetails-accommodation" title="Information" href="#tab-holidaydetails-information">Information</a></li>
<li><a class="holidaydetails-reviews" title="Reviews" href="#tab-holidaydetails-reviews">Reviews</a></li>
</ul>
</div>
Then, to hide, select all tabs, and exclude overview using .not():
$("#holiday-details-nav a").not(".overview").hide();
When dealing with tabs, especially in the setup you have (where the href attribute has the id of the div related to it), you don't need to hardcode anything, use the title attribute, or use any extra classes. Look at this:
http://jsfiddle.net/FAM2s/2/
All it does it find all of the tabs' detail divs and hide them all, then only show the one related to what was just clicked.
As long as you set the correct href attributes for the links, and set the corresponding divs with those id's, it will work, no matter how many tabs you add/remove whenever you want.