Reverse children elements with jQuery - javascript

I need to reorder some children elements with defined class and maintain the old order of the others that doesn't have the class. I have other sub elements
Code - html
<ul class="menu_dinamico">
<li class="reverseMenu">Item 1</li>
<li class="reverseMenu">Item 2</li>
<ul>
<li>item 2.1</li>
<li>item 2.2</li>
</ul>
<li class="reverseMenu">Item 3</li>
<li class="reverseMenu">Item 4</li>
<li>Item 4.5</li>
<li>Item 5</li> </ul>
Code - javascript
$.fn.reverse = [].reverse;
var list = $('.menu_dinamico');
var listItems = list.children('.reverseMenu');
list.prepend(listItems.get().reverse());
The result
item 4
item 3
item 2
item 1
item 2.1
item 2.2
item 4.5
item 5
The result wanted
item 4
item 3
item 2
item 2.1
item 2.2
item 1
item 4.5
item 5
P.s: I have to maintain the html structure like links, attributes etc.
Any clues? Thanks!
Edit:
After #bubicsaszar response I realized that my question was incomplete because my list can have infinite sub lists and their structure must be preserved.

try this, if the constant items always in the end of the list:
$.fn.reverse = [].reverse;
var list = $('.menu_dinamico');
var listItems = list.children('.reverseMenu');
list.prepend(listItems.get().reverse());

Related

AJAX: Add <li>s to existing

I'm trying to add <li>s to an existing <ul> with AJAX. It is a very simple test.
HTML:
<ul id="full_list">
<li>Existing item 1</li>
<li>Existing item 2</li>
<li>Existing item 3</li>
<li>Existing item 4</li>
<li>Existing item 5</li>
</ul>
<button type="button" onclick="addMoreItems()"></button>
JS:
function addMoreItems () {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("full_list").appendChild = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "filler.txt", true);
xmlhttp.send();
}
filler.txt:
<li>New item 6</li>
<li>New item 7</li>
<li>New item 8</li>
<li>New item 9</li>
<li>New item 10</li>
Desired result:
<ul id="full_list">
<li>Existing item 1</li>
<li>Existing item 2</li>
<li>Existing item 3</li>
<li>Existing item 4</li>
<li>Existing item 5</li>
<li>New item 6</li>
<li>New item 7</li>
<li>New item 8</li>
<li>New item 9</li>
<li>New item 10</li>
</ul>
<button type="button" onclick="addMoreItems()"></button>
I have no problems populating the <ul> with filler.txt's <li>s if I use innerHTML. I have spent time searching this and other sites, and have seen it said that unlike innerHTML which replaces all of an element node's contents, appendChild expects an object as opposed to a string, and so can't be added to the DOM after the page has loaded.
Unfortunately I'm still not able to figure out how to append a text string with a lot of <li>s back-to-back to the existing <ul>. Thoughts?
(The filler.txt document in xmlhttp.open()'s second parameter is something I'm only using for testing purposes. Once I figure out how to append more <li>s into the <ul> with AJAX, I'll use a PHP page instead which generates the <li>s with information from my MySQL db.)
This will give you the output:
var newItems = "
New item 6
New item 7
New item 8
New item 9
New item 10";
document.getElementById("full_list").innerHTML += newItems;
For simplicity, I used a variable already with html and added in innerHTML property.
If you really want to use appendChild(), rather than .innerHtml += ... try it like this:
var element = document.createElement("li");
var elementContent = document.createTextNode(xmlhttp.responseText);
element.appendChild(elementContent);
document.getElementById("full_list").appendChild(element);

JS: remove lastChild only works every second button click

I use this code to delete the last item of an <ul> list, but only on the second, fourth, sixth, ... every second click on the button the item gets removed, but every click the message appears. What can I do that the element gets deleted on every click.
document.getElementsByTagName('input')[0].onclick = function () {
'use strict';
var list = document.getElementById('list'), item = list.lastChild;
list.removeChild(item);
window.alert("Removed");
};
<ul id="list">
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
<li id="child">List item 4</li>
<li>List item 5</li>
</ul>
<input type="button" value="Delete last">
This is because .lastChild returns all nodes, including empty text nodes which exist in your <ul>. Use .lastElementChild instead to target your <li> nodes
The difference between this property and lastElementChild, is that
lastChild returns the last child node as an element node, a text node
or a comment node (depending on which one's last), while
lastElementChild returns the last child node as an element node
(ignores text and comment nodes).
See HTML DOM lastChild Property and HTML DOM lastElementChild Property for more information
document.getElementsByTagName('input')[0].onclick = function () {
var list = document.getElementById('list'), item = list.lastElementChild;
list.removeChild(item);
};
<ul id="list">
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
<li id="child">List item 4</li>
<li>List item 5</li>
</ul>
<input type="button" value="Delete last">
Some more details on why this is happening... When you format your markup with clean spacing, what I think of as "phantom" text nodes silently exist within your <ul>. If you minify this markup to the following, your first example would indeed work fine
<ul id="list"><li>List item 1</li><li>List item 2</li><li>List item 3</li><li id="child">List item 4</li><li>List item 5</li></ul>
Plunker Link - minifed markup example using .lastChild
Change:
item = list.lastChild;
to
item = list.lastElementChild;

Displaying li when clicking on item

I am beginner in javascript. I have this list:
<p class="lead">parent item1</p>
<ul class="list bot-2">
<li>child item 1
</li>
<li>child item 2
</li>
<li>child item 3
</li>
</ul>
<p class="lead">parent item2</p>
<ul class="list bot-2">
<li>child item 1
</li>
<li>child item 2
</li>
<li>child item 3
</li>
</ul>
<p class="lead">parent item3</p>
<ul class="list">
<li>child item 1
</li>
<li>child item 2
</li>
<li>child item 3
</li>
</ul>
I need to display the matching div when one child item clicked, and hide other divs, the matching items is in this html structure:
<ul class="list-services">
<li class="clearfix"></li>
<li class="clearfix"></li>
<li class="clearfix"></li>
</ul>
How I can do this, I see similar posts in stackoverflow, but it didn't have the similar structure.
Well, you could use this:
$(".list a").click(function(){
var x = $(this).parents(".list").children().get();
var find = $(this).parent().get(0);
var nth = x.indexOf(find) + 1;
$(".list-services .clearfix:not(:nth-child(" + nth + "))").hide();
});
http://jsfiddle.net/wumm/v7Ks7/1/
var x = $(this).parents(".list").children().get(); gets the current .list children.
Then var find = $(this).parent().get(0); find is set to the liin which this a was.
And now nth is set to the index of this li in the current .list. (1 is added because CSS has a 1 based index)
Last thing: hiding anything else then the nth link in .list-services
This can be done with plain javascript as well, here's the jQuery solution:
$('a').on('click', function (event) {
$('.clearfix').hide();
$('.clearfix').eq($(this).closest('li').prevAll('li').length).show();
});
The $(this).closest('li').prevAll('li').length bit gives the index of the clicked child item by finding the immediate li parent and counting the number of previous li tags inside the parent ul tag. Then we just show the .clearfix item with that index using eq and show
DEMO

Limit a List to the last 5 items

Looking for a solution to the following: I have a list of items e.g.
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>...</li>
</ul>
The list is added to (for each person) each time they look at products on the site i.e. "recently viewed items" and the last product looked at is added to the bottom of the list. The list is taken from a MYSQL database. The list doesn't reset for that person it simply gets longer each time the same person viewing the site views more products.
Is there anyway to only show the last 5 items in the list ignoring the ones before bearing in mind new list items are added to the bottom of the list and the list is continually growing?
I'd like the list to just show the last five products at any one time for each person who views the site i.e. the list on the site maybe
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9
Item 10
Item 11
Item 12
Item 13
Item 14
Item 15
Item 16
but I only want the person who has veiwed all 16 products to just see the last 5 recently viewed products i.e.
Item 11
Item 12
Item 13
Item 14
Item 15
Item 16
Another person may come to the site and view just 4 products e.g.
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
and they would see these 4 products in their recently viewed list.
A third person may come to the site and view 12 products and they would see
<ul>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
</ul>
When the person above who viewed 16 items comes back to the site they will see the last 5 items from their previous session and when they start viewing products the fisrt item will disappear and a new item will show at the bottom of the list
<ul>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
<li>Item 15</li>
<li>Item 16</li>
</ul>
then as they start browsing they will see
Item 12
Item 13
Item 14
Item 15
Item 16
Item 17
etc...
is this possible?
I'm going to leave everything from my previous answer but I believe the scope of the question has changed and is now a database/sql question.
I think what you're looking for is a SQL query to limit the number of rows returned and order them for you.
You can check out the documentation for MySQL 5.0 SELECT which can give you an idea of how to do this, but I will also give you an example below.
Assuming you have a table of recently viewed items that looks like the following:
CREATE TABLE user_product_viewings (
ID INT(32) NOT NULL auto_increment,
product_id INT(32) NOT NULL,
user_id INT(32) NOT NULL,
viewed_at DATETIME NOT NULL,
primary KEY (ID));
You can use the following query to select the 5 latest entries for a specific user:
SELECT product_id FROM user_product_viewings WHERE user_id = #{USER_ID} ORDER BY viewed_at DESC LIMIT 5;
Old Answer
It looks like you are trying to do this with javascript, so maybe your appending data to the list as the user browses the page.
I would not simply try to hide the items, but remove them complete from the DOM. The best way to do this is to write a function that will check the current length of the list and then remove the oldest children (top) before appending a new one.
An example of that might be something like the following:
var addToList = function (item_value) {
while ( list.children.length >= 5 )
{
list.removeChild(list.firstChild );
}
var item = document.createElement("li");
item.innerText = item_value;
list.appendChild(item);
}
http://jsbin.com/oriwut/3/edit
Here is another solution which combines the above with only showing the last 5 items of a 10 item list.
var addToList = function (item_value) {
while ( list.children.length >= 10 )
{
list.removeChild(list.firstChild );
}
var item = document.createElement("li");
item.innerText = item_value;
list.appendChild(item);
list.scrollTop = list.scrollHeight;
}
A little CSS:
#list {
overflow-x:scroll;
width: 100px;
height: 120px;
}
#list li {
height: 20px;
}
http://jsbin.com/ujuxer/2/edit
You can use the following CSS, but I'm not sure about browser compatibility (it's unclear if this is the proper compatibility table):
li { display: none; }
li:nth-last-child(-n+5) {
display: list-item;
}
http://jsfiddle.net/TzDqV/

Adding a seperate class to list items parent using jquery?

I have a list with different levels of depth:
<ul id="top-level" class="top-level">
<li>Item 1</li>
<li>Item 2
<ul class="sub-menu">
<li>Sub item 1</li>
<li>Sub item 2</li>
<li>Sub item 3
<ul class="sub-menu">
<li>Subsub item 1</li>
<li>Subsub item 2</li>
</ul>
</li>
<li>Sub item 4</li>
</ul>
</li>
<li>Item 3</li>
</ul>
I am using the following jquery script to add a class to the parents:
$("ul li ul").parent().addClass("menuparent");
Is there a way to add this class only to the top level parent li's and a different class for all other (deeper) parent li's?
Just use the > selector from your top level ul.
Based on your current selector:
$("ul.top-level > li > ul").parent().addClass("menuparent");
Or for li only:
$("ul.top-level > li").parent().addClass("menuparent");
For top level lis
$("#top-level > li").addClass("menuparent");
and for lower level li
$("#top-level li li").addClass("someotherclass");
If I understand correctly, people are not giving you answers for locating the deeper parent li's, here's my take:
$("ul.top-level > li > ul").find('li > ul').parent().addClass("deeper-parent-li");

Categories

Resources