JavaScript: Slide a UL down to last element - javascript

Can't think how best to do this. Thought it would be a simple show/hide but it dosn't seem as simple as that.
There is a UL with an indeterminable amount of items in it. It needs to be able to show the first 10 but no more unless a 'show more' button is clicked. When the 'show more' button is clicked it will expand the list open to show the complete list.
http://jsfiddle.net/kbUhW/
Interested to see how this is achieved.

Here is an example: http://jsfiddle.net/WqxGf/
JS:
count = 0;
$('ul li').hide();
$('ul').children().each(function(){
if(count >= 10) return;
$(this).show();
count++;
})
$('.slide').click(function(){$('ul li').show('blind');})
HTML:
<ul>
<li>Item One</li>
<li>Item Two</li>
<li>Item Three</li>
<li>Item Four</li>
<li>Item Five</li>
<li>Item Six</li>
<li>Item One</li>
<li>Item Two</li>
<li>Item Three</li>
<li>Item Four</li>
<li>Item Five</li>
<li>Item Six</li>
<li>Item One</li>
<li>Item Two</li>
<li>Item Three</li>
<li>Item Four</li>
<li>Item Five</li>
<li>Item Six</li>
<li>Item One</li>
<li>Item Two</li>
<li>Item Three</li>
<li>Item Four</li>
<li>Item Five</li>
<li>Item Six</li>
<li>Item One</li>
<li>Item Two</li>
<li>Item Three</li>
<li>Item Four</li>
<li>Item Five</li>
<li>Item Six</li>
</ul>
<a href="#" class='slide'>Slide Down</a>

All the other answers use jQuery, but your question didn't actually specify it. So here's one way to do it with plain JavaScript. Let's assume your <ul> has the ID foo, your "reveal" link has the ID reveal, and that there's a class hide with display: none. Then we have:
(function getChildNodes(id, num) { // ID of element, number to show
var obj = document.getElementById(id),
children = obj.childNodes,
elemcounter = 0;
for (var i = 0; i < children.length; i++) { // loop all children
if (children[i].nodeType === 1) { // examine elements only
elemcounter++;
if (elemcounter > num) { // element number in range to hide?
children[i].className = 'hide';
}
}
}
}('foo', 3)); // id foo, show 3
document.getElementById('reveal').onclick = function() { // handle click
var items = document.getElementsByTagName('li');
for( var i = 0; i < items.length; i++ ){ // for all list elements...
var tempclass = items[i].className;
// if the class is "hide", unhide
items[i].className = tempclass === 'hide' ? '' : tempclass;
}
}
Of course there are many other ways to do this more thoroughly -- and this one doesn't even slide. jQuery does make life a bit easier.
Here's the working example: http://jsfiddle.net/redler/jsQ47/

Here's with the slide down effect:
http://jsfiddle.net/deNzh/
That's what you're looking for, right?

you could assign the first ten < li >s a class like < li class="always_show">Stuff goes here< /li > and then make a script that hides all, shows the "always_show" class and waits for a button click to show the whole thing.
might look something like:
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(function(){
$("#listorama").hide();
});
$(function(){
$(".always_show").show();
});
$(function(){
$("#show_all").click(function(){
$("#listorama").show();
});
});
</script>
<ul id="listorama">
<li class="always_show"></li>
<li class="always_show"></li>
<li class="always_show"></li>
<li class="always_show"></li>
<li class="always_show"></li>
<li class="always_show"></li>
<li class="always_show"></li>
<li class="always_show"></li>
<li class="always_show"></li>
<li class="always_show"></li>
<li>stuff to hide first</li>
<li>stuff to hide first</li>
<li>stuff to hide first</li>
<li>stuff to hide first</li>
<li>stuff to hide first</li>
</ul>
<button id="show_all">Show All</button>
Hope this helps!
Andy

function toggleListDisplay (list, cap) {
cap = parseInt(cap);
if (cap == null || cap < 0) { return; }
var elements = $(list).children();
if ($(elements[cap]).css('display') == 'none') {
// means we need to expand the list
elements.each(function(ind, ele) {
if (ind >= cap) { $(ele).slideDown(); }
});
$('.slide').html('Slide Up');
} else {
// means we need to shorten the list
elements.each(function(ind, ele) {
if (ind >= cap) { $(ele).slideUp(); }
});
$('.slide').html('Slide Down');
}
}
$('.slide').click(function(){
toggleListDisplay('#tester', 10);
})
toggleListDisplay('#tester', 10);
JSFiddle: http://jsfiddle.net/WqxGf/7/

I don't know why the others feel like making such a simple task more complicated than it is, but here is a much easier, shorter, and simpler way of achieving this:
$("a").click(function() {
var ul = $("#myid");
ul.animate({"height": ul[0].scrollHeight}, 1000);
});
Example: http://jsfiddle.net/kbUhW/13/

Related

Loop through html elements and check if the text contains a specific word

I would like to loop through a list of html elements and log to the console only the ones which contain a specific word.
const li = $('ul li');
for (let i = 0; i < li.length; i++) {
//If any of the li's match with a specific word. 'Item A' for example then log it to the console.
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<div>
<ul>
<li>Item A</li>
<li>Item B</li>
<li>Item C</li>
</ul>
</div>
Can use jQuery :contains selector:
$('ul li:contains(A)').each((_,el) => console.log(el.id))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<div>
<ul>
<li id="li-A">Item A</li>
<li id="li-B">Item B</li>
<li id="li-C">Item C</li>
</ul>
</div>
I would use $.each() for this one
$.each($('ul li'), function(){
if($(this).text().toLowerCase() === "item a"){
console.log($(this).text())
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul>
<li>Item A</li>
<li>Item B</li>
<li>Item C</li>
</ul>
</div>
const li = $('ul li');
for (let i = 0; i < li.length; i++) {
if(li[i].innerText === 'Desired String') {
//do something
}
}
A library like jquery is not necessary for this simple task. You can use a filter for filtering and you can use match for your regular expression. With es6 you get concise syntax, and with vanilla you get performance. Everything else is an abstraction.
let elements = document.getElementsByTagName('ul')[0].children;
let arr = Array.from(elements, node => node.innerText);
arr = arr.filter(items => items.match('A'));
console.log(...arr);
<div>
<ul>
<li>Item A</li>
<li>Item B</li>
<li>Item C</li>
</ul>
</div>

JQuery. apply css to each element with a class using delay

I've just take a look on a lot of answer on stack but nothing seems can work on this.
I'me trying to apply a style to all element of a list li sequentially using delay. The script show just the last item of the list. What's the problem? thanks in advance for your help
$('ul li').each(function(i){
licont = this
setTimeout(function(){
$(licont).css('opacity','1')
},i * 10);
});
li{
opacity:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>ITEM 1</li>
<li>ITEM 2</li>
<li>ITEM 3</li>
<li>ITEM 4</li>
</ul>
You can pass the current element as a jQuery object as a parameter to setTimeout to reference current jQuery object within .each() when function passed to setTimeout is called
$('ul li').each(function(i) {
setTimeout(function(el) {
el.css('opacity', '1')
}, i * 1000, $(this));
});
li {
opacity: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>ITEM 1</li>
<li>ITEM 2</li>
<li>ITEM 3</li>
<li>ITEM 4</li>
</ul>

JQuery - How to move a li to another position in the ul? (exchange 2 li's)

What is a cool way to apply this? I need a script that exchange two < li>'s position in an < ul>.
It think that should be possible to achieve. Thanks for your response.
HTML
<div id="awesome">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
Pseudo Javascript (JQuery)
$("#awesome ul li:eq(1)").exchangePostionWith("#awesome ul li:eq(3)");
HTML Result
<div id="awesome">
<ul>
<li>Item 1</li>
<li>Item 4</li>
<li>Item 3</li>
<li>Item 2</li>
<li>Item 5</li>
</ul>
</div>
You can use jQuery's .after() for moving elements around. I cloned one of them so the original can remain as a placeholder. It's like if you wanted to switch variables a and b, you'd need a third temporary variable.
$.fn.exchangePositionWith = function(selector) {
var other = $(selector);
this.after(other.clone());
other.after(this).remove();
};
Now your pseudocode $("#awesome ul li:eq(1)").exchangePositionWith("#awesome ul li:eq(3)"); isn't so pseudo :-)
$("ul li a").click(function () {
$(this).parent().insertBefore('ul li:eq(0)');
});
<ul>
<li><a>a</a></li>
<li><a>b</a></li>
<li><a>c</a></li>
<li><a>d</a></li>
<li><a>e</a></li>
<li><a>f</a></li>
</ul>

Expand list with slideToggle

I have an unordered list like this one:
Show the rest
<ul id="myList">
<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>Item 10</li>
</ul>
and this jQuery code:
var list = $('#myList li:gt(4)');
list.hide();
$('a#myList-toggle').click(function() {
list.slideToggle(400);
return false;
});
The problem is that it slides each individual li item, i need to slide the rest of the list, like i would slide the whole list.
How can I do that?
your method didn't work because it would find the height with height: auto.
After a lot of fail and try, I came up with something that works, almost.
Do you have any comment on my code, I would really appreciate it.
And how would I do it, if I want the same link to collapse the list again
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var list = $('ul#myList');
var original_height = list.height();
list.css({height:$('#myList li').height()*5});
$('a#myList-toggle').click(function() {
list.animate({height:original_height})
return false;
});
});
</script>
<style type="text/css">
ul#myList {
overflow: hidden;
}
</style>
</head>
<body>
Show the rest
<ul id="myList">
<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>Item 10</li>
</ul>
</body>
</html>
Pretty clumsy solution IMHO, but if it works for you - it works for you...
For the list to collapse and expand by clicking on the same link:
$(document).ready(function() {
var list = $('ul#myList');
var original_height = list.height();
var new_height = $('#myList li').height()*5;
list.css({height:new_height});
$('a#myList-toggle').click(function() {
if( list.height() == original_height ) {
list.animate({height:new_height});
} else {
list.animate({height:original_height});
}
return false;
});
});
Quick & not-so-dirty way: wrap it with a div element and slideToggle('#myList div.wrapper').
You can give a height to UL tag with overflow:hidden. Then you use animation({height:auto}) to show all. Otherwise, you don't have any viable solution.
Whats the problem with simply toggeling the list instead of the elements?
$(function(){
var listheight = $("#mylist").height();
$("a#myList-toggle").toggle(function(){
$("#mylist").slideToggle();
},function(){$("#mylist").animate({height:listheight})});
});

jQuery Expanding & Collapsing lists

The code expands and collapses a list in which list items can have sublists. Any ideas to refactor this code - especially the toggling part. Is it necessary to use closures here ?
$(function()
{
$('li:has(ul)')
.click(function(event){
if (this == event.target)
{
var that = this;
$('li:has(ul)').children().filter(':not(:hidden)').parent().each(function(x){
if(this != that)
toggleList(this);
});
toggleList(this);
}
})
.css({cursor:'pointer', 'list-style-image':'url(plus.gif)'})
.children().hide();
$('li:not(:has(ul))').css({cursor: 'default', 'list-style-image':'none'});
});
function toggleList(L)
{
$(L).css('list-style-image', (!$(L).children().is(':hidden')) ? 'url(plus.gif)' : 'url(minus.gif)');
$(L).children().toggle('fast');
}
EDIT:
The script works on the following HTML snippet (source: jQuery in Action). Actually I was trying to extend the script given in the book.
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>
Item 3
<ul>
<li>Item 3.1</li>
<li>
Item 3.2
<ul>
<li>Item 3.2.1</li>
<li>Item 3.2.2</li>
<li>Item 3.2.3</li>
</ul>
</li>
<li>Item 3.3</li>
</ul>
</li>
<li>
Item 4
<ul>
<li>Item 4.1</li>
<li>
Item 4.2
<ul>
<li>Item 4.2.1</li>
<li>Item 4.2.2</li>
</ul>
</li>
</ul>
</li>
<li>Item 5</li>
</ul>
Your code doesn't work for me in Safari. When I click on a sub-list, the top-list is toggled.
How about:
$(document).ready(function() {
$('li:has(ul)').click(function(event) {
$(this).css('list-style-image', $(this).children().is(':hidden') ? 'url(minus.gif)' : 'url(plus.gif)')
$(this).children().toggle('fast')
return false
})
.css({cursor:'pointer', 'list-style-image':'url(plus.gif)'})
.children().hide()
$('li:not(:has(ul))').click(function(event) { return false })
.css({cursor:'default', 'list-style-image':'none'})
})

Categories