Get updated order after jQuery Sort - javascript

I am using jQuery UI's Sortable to reorder some list items. I would like to update the class of each li based on the updated order after sorting. Here is my html:
<ul id="sortable">
<li class="1">apple</li>
<li class="2">orange</li>
<li class="3">pear</li>
<li class="4">peach</li>
</ul>
What I am trying to achieve is AFTER sorting pear above apple, my classes update like this:
<ul id="sortable">
<li class="1">pear</li>
<li class="2">apple</li>
<li class="3">orange</li>
<li class="4">peach</li>
</ul>
This JSFiddle is close to what I'm after, but I would like to update the class rather than the html: http://jsfiddle.net/4mcpq/3/

As changing the position of one li would change the class of every other li, the only sane way to accomplish this is to iterate over the li elements on the update callback for .sortable:
"update": function (event, ui) {
$(this).children().each(function (i, elem) {
var li = $(elem), // cache lookup
cssClass = elem.className.split(' ').filter(function (name, i, array) {
return /^js[-]\d+$/g.test(name);
}).join(''); // adding .join('') to transform to string
// classes cannot start with a number (see http://www.w3.org/TR/CSS21/grammar.html#scanner).
// using pattern of "js-#" for the custom class
$(elem).removeClass(cssClass).addClass('js-' + i);
});
}
Working demo: http://jsfiddle.net/4mcpq/210/
A caveat: if you have thousands of li elements, this will likely slow your UI. There are much easier (and saner) ways to get the correct target li depending on what you're trying to do.

Why not use something like nth-child() selector in your css.
For example:
#sortable li:nth-child(1) {
/*insert your style for the first child here*/
}
#sortable li:nth-child(2) {
/*insert your style for the second child here*/
}

So I have found I can use .index() to find the updated sort order. Then I can set the class of each li to it's index.
$("#sortable").sortable({
update: function(event, ui) {
$("#sortable li").each(function() {
$(this).removeClass();
var $index = $(this).index();
$(this).prop("class", $index);
});
}
});
See this Fiddle: http://jsfiddle.net/2f9vkhxj/8/

Related

Checking list item hover states to trigger an action - jQuery

I have 4 images in an unordered list. Ideally I want to be able to load all the list items into an array and do a check to see which one is currently hovered.
I know using the jQuery is() function I can check which is in an :hover state. How would I apply this check to all items within that list array?
<ul class="image-list">
<li class="image-item"><img src="/image1.jpg"/></li>
<li class="image-item"><img src="/image1.jpg"/></li>
<li class="image-item"><img src="/image1.jpg"/></li>
<li class="image-item"><img src="/image1.jpg"/></li>
</ul>
Thanks for any help.
DIM3NSION
Use the mouseover() function:
// Add mouseover event to all your image-items
$('.image-list > .image-item').mouseover(function() {
// $(this) is your hovered image-item object
alert($(this).find('img').attr('src'));
});
Working jsfiddle
Demo: http://jsfiddle.net/GCu2D/758/
JS:
$(function () {
var li = $("ul li"); //get all li. All li are stored in an array.
$(document).on("mouseover", "ul li.image-item", function (e) {
var ele = $(this); //get currently hovered li.
var item = li.index(ele); //get the index of the currently hovered li in that array
console.log(item); //this logs the index. Using this index, do whatever you want with that item.
});
});

Find if current class contains word, then append new class to those li's - jquery

Having some problems with jQuery methods - perhaps overcomplicating things...
What I need to find is if any of the li elements classes contain the word 'current', then if they do, append the word active to them.
I'm struggling to add the word to the end of the current class. For example:
Markup:
<div class="menu-navigation-container">
<ul>
<li class="current_page_item menu-item-8787"><span>The Magazine</span>
</li>
<li class="menu-item menu-item-type-post_type"><span>Snapped</span>
</li>
</ul>
</div>
jQuery:
$(document).ready(function () {
var classNames = $('.menu-navigation-container ul li').attr("class").match(/[\w-]*current[\w-]*/g);
$(classNames).each(function () {
$(this).addClass("active");
});
});
Running classnames; up in the console produces just the string - I want it to reference the li elemens that have the word 'current' in their class names, then append the word 'active' at the end.
Can I do this with jQuery's attribute contains selector?
Simply like this :
$(document).ready(function () {
$('.menu-navigation-container ul li[class*=current]').addClass('active');
});
Try this
$(document).ready(function () {
$('.menu-navigation-container ul li').each(function(){
if ( $(this).is(".current") )
{
$(this).addClass("active");
}
})
});

How to get the items inserted in the DOM using DOMNodeInserted

I want to get the values of items in a Dynamically generated DOM using DOMNodeInserted.
Here is my code.The items #I want to get the values are li eg
<div id="demo">
<ul>
<li class="req">Chemistry</li>
<li class="req">English</li>
<li class="req">Maths</li>
</ul>
</div>
Here is the code
$('#demo').on('DOMNodeInserted', function(e) {
var that = $(this);
if ($(e.target).is('.req')) {
alert(oneoftheitemsintheli);
}
});
I want to get on of the items in the li eg Maths, Chemistry etc. I need to know how to get the items.
Thanks
Given that each li has the class req, you can use each to iterate over them and get the text value - or any other property you need.
$('#demo').on('DOMNodeInserted', function(e) {
$('.req').each(function() {
alert($(this).text());
});
});
Example fiddle

Determine if element has children with X tag

I am looping through some elements and need to determine if an element has a child(grandchild?) with the li tag, like in the information element below. The li elements will vary in id so I am not referencing them that way. I am currently looping through the li elements and if I check for children it always returns true because there are "a" tag children, I just want to check for 'lil' tag children.
<ul id="navMenu">
<li id="home">Home</li>
<li id="information">Information
<ul>
<li>Credits</li>
<li>Lorem Ipsum</li>
</ul>
</li>
<li id="contact">Contact</li>
</ul>
Here is what I have now...
$('#test').load('../common.html #navMenu', function() {
$.each($("#test #navMenu li"), function(i,v) {
var theElement = $(v);
if ($(theElement).children('li')){
alert('This Element has children');
}
});
});
Thank you once again,
Todd
You could try -
$('#test').load('../common.html #navMenu', function() {
$.each($("#test #navMenu li"), function(i,v) {
var theElement = $(v);
if ($(theElement).find('li').length > 0){
alert('This Element has children');
}
});
});
find will go deeper into the current element than children which only searches one level down.
$(theElement).children('li') returns a jQuery object which always passes an if clause, even when it's empty.
Moreover, you want .find, since .children only returns direct children and not grandchildren.
So:
if ($(theElement).find('li').length > 0) {
or:
if ($(theElement).find('li').length) {
// 0 won't pass an if clause, and all other numbers will, so you can eliminate `> 0`
Given:
> var theElement = $(v);
> if ($(theElement).children('li')) {
> alert('This Element has children');
> }
doesn't $(v) return an jQuery object? So $(theElement) is redundant.
Anyhow, if v is a reference to one of the elements passed to .each, then you can replace all of the above with:
if (v.getElementsByTagName('li').length) {
/* v has li descendants */
]
you could also add the extra li to your query: "#test #navMenu li li"

Need clean jQuery to change parent's class when children are clicked

I needed some method of adding/removing classes of a parent element when it's children are clicked to reflect which child is currently selected. In this case a UL parent and LI children in a tab scheme. I needed a way to mark the current tab on the UL so I could style a background sprite on the UL; since styling my LI's backgrounds would not work with the graphics in this case.
I am a jQuery/Javascript/DOM novice, but was able to piece together an ugly solution for starters,
HTML
<!-- tabs -->
<ul class="tabs currenttab-info">
<li id="tab-info" class="info"><strong>Information</strong></li>
<li id="tab-write" class="write"><strong>Write Feedback</strong></li>
<li id="tab-read" class="read"><strong>Read Feedback</strong></li>
</ul>
Javascript
// send '.currenttab-x' to '.tabs' and remove '.currenttab-y' + '.currenttab-z'
// when LI #tab-X is clicked ...
$( '#tab-info' ).click(function() {
// ... find the UL and remove the first possible conflicting class
$('.tabs').removeClass("currenttab-read");
// ... find the UL and remove the other possible conflicting class
$('.tabs').removeClass("currenttab-write");
// ... find the UL and add the class for this LI
$('.tabs').addClass("currenttab-info");
});
// ... repeat ...
$( '#tab-write' ).click(function() {
$('.tabs').removeClass("currenttab-info");
$('.tabs').removeClass("currenttab-read");
$('.tabs').addClass("currenttab-write");
});
$( '#tab-read' ).click(function() {
$('.tabs').removeClass("currenttab-info");
$('.tabs').removeClass("currenttab-write");
$('.tabs').addClass("currenttab-read");
});
This actually seems to be working, BUT it's a fumbling solution and I am sure there is a better way. Some of you jQuery ninjas will know how to put this functionality together really elegantly, any help?
Also I would like to add onto this so that the clicked LI is also given a class to show it is selected while the other LIs are stripped of any such class. The same sort of thing I already am doing for the UL; I can see how to do that with my awkward approach, but it will mean even more and more lines of messy code. If your improvement also included a way to do change classes of the LIs I'd appreciate it
FYI: I'm using jQuery Tools Tabs with this so there is more jQuery then I showed, but only the bit I quoted seems relevant.
html
I will remove ids of li if you are not using it for other purposes.
<ul class="tabs currenttab-info">
<li class="info"><strong>Information</strong></li>
<li class="write"><strong>Write Feedback</strong></li>
<li class="read"><strong>Read Feedback</strong></li>
</ul>
jQuery
$('.tabs li').click(function() {
var $li = $(this);
$li.addClass('current').siblings().removeClass('current'); // adds a current class to the clicked li
var $ul = $li.parent();
$ul.removeClass("currenttab-info currenttab-read currenttab-write")
.addClass("currenttab-" + this.class ); // assuming li only holds one class e.g. class="write"
});
You can just do something like this:
$('.tabs > li').click(function() {
$(this).parent().attr('class', 'tabs').addClass('currenttab-'+$(this).attr('class'));
});
$("UL.tabs LI A").bind('click',function(e){ //bind a Click-Event handler to the Links
var $target = $(e.target); //the jQuery-Object-Reference to the clicked target ( $(this) should work too)
var LIClasses = $target.parents('LI').attr('class'); //A list of all Classes the parrent LI of the clicked Link have
$target
.parents('UL.tabs')
//now you can remove and add classes to the parent "UL.tabs"
.removeClass('...')
.addClass('...')
.end() //after .end() the chain for .parents-match is broken
.parents('LI')
//here you can add and remove classes from the parent LI
.removeClass('...')
.addClass('...')
.end() //after .end() the chain for .parents-match is broken
;
});
Notes:
jQuery is chainable.
.removeClass() and .addClass() can work with multiple classnames at the same time by speration with a space (like .removeClass('class1 class2'))
The full solution:
var relevantClasses = ['read','write','info'];
$("UL.tabs LI A").bind('click',function(e){
var $target = $(e.target);
var relevantClass = '';
for( var cl in $target.parents('LI').attr('class').split(' ') )
if( jQuery.inArray(relevantClasses , cl) > -1 ){
relevantClass = cl;
break;
}
$target
.parents('UL.tabs')
.removeClass(jQuery.map(relevantClasses , function (className) { return 'currenttab-' + className; }).join(' '))
.addClass('currenttab-'+relevantClass )
.end()
;
});
First of all you can chain the method calls...
$('.tabs').removeClass("currenttab-read currenttab-write").addClass("currenttab-write");
This would make the code much cleaner...
EDIT: I'll try such things in Fiddle http://jsfiddle.net/JvtAz/

Categories

Resources