I have a dynamically created navigation, where i can not make parent/child list for navigation.
I want to add a link named "More..." at the end of the list, according to available space. And then show all remaining elements as child of More...
For example if i have elements list1, list2, list3, ..... list10.
It will be displayed as list1, list2, list3, more... and rest of the links will be child of more...
I tried creating a script for this, and i think i am very close. But i have following 2 issues:
How to add UL around child list.
Sometimes "More..." is broken to next line.
Following is my JS code:
$(document).ready(function() {
var nav = $('ul');
var more = '<li>More...</li>';
nav.prepend( more );
var availableSpace = nav.innerWidth();
var list = 0;
var countedSpace = 0;
$('li').each(function(){
var current = $(this);
countedSpace = countedSpace+current.outerWidth();
if (countedSpace < availableSpace) {
list++;
}
})
var showInList = list; //Space available for xx no. of items.
var newList = [];
// Start at 2, don't include dynamically added more link.
for (i = 2; i < showInList; i++) {
newList.push($(nav).find("li:nth-child("+i+")"));
}
newList.push(more);
var childList = [];
for (i = showInList; i <= nav.children().length; i++) {
childList.push($(nav).find("li:nth-child("+i+")"));
}
//nav.empty();
nav.html(newList);
$(nav).find("li:last-child").append(childList);
});
jsfiddle: http://jsfiddle.net/alokjain_lucky/Lhh019ru/
1. How to add UL around child list.
Try creating a jquery UL object and then appending the li items to it. Like this:
var ulChildren = $("<ul/>").append(childList);
$(nav).find("li:last-child").append(ulChildren);
2. Sometimes "More..." is broken to next line.
This is happening because the li children are visible and stacking to the right, try adding
li ul{
display:none;
}
to test the correct layout, after step 1.
Here is an example of the above on JSFiddle, click on "More..." to toggle children visibility
Example code
I think this will accomplish what you're looking for:
var availableWidth= $('ul').innerWidth();
var totalWidth= $('<li class="more">More</li>').appendTo($('ul')).outerWidth();
$('li').each(function(index) {
totalWidth+= $(this).outerWidth();
if(totalWidth >= availableWidth) {
$('ul li:eq('+(index-2)+')').after(
$('.more').click(function() {
$('ul li:gt('+(index-1)+')').toggle()
})
);
$('ul li:gt('+(index-1)+')').css({
display: 'none'
});
return false;
}
});
var availableWidth= $('ul').innerWidth();
var totalWidth= $('<li class="more">More</li>').appendTo($('ul')).outerWidth();
$('li').each(function(index) {
totalWidth+= $(this).outerWidth();
if(totalWidth >= availableWidth) {
$('ul li:eq('+(index-2)+')').after(
$('.more').click(function() {
$('ul li:gt('+(index-1)+')').toggle()
})
);
$('ul li:gt('+(index-1)+')').css({
display: 'none'
});
return false;
}
});
ul {
padding:0px;
margin:0px;
border:1px solid #ccc;
overflow:hidden;
width: 500px;
}
li {
list-style:none;
float:left;
margin:10px;
border:1px solid #f1f1f1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>a Home</li>
<li>b Services</li>
<li>c Meet our team</li>
<li>d work process</li>
<li>e About us</li>
<li>f Contact us</li>
<li>g Meet out team</li>
<li>h work process</li>
<li>i About us</li>
<li>j Contact us</li>
</ul>
totalWidth is initialized as the width of the More list item. I gave it a class of more, so it could be referred to within each.
When totalWidth is greater-or-equal-to availableWidth, .more is inserted in the appropriate position (index) of the ul.
The click handler toggles the display of list items at higher positions. Those higher-positioned list items are then hidden.
return false prevents each from continuing to run once this is done.
Related
I'm trying to highlight the current section items in a sticky table of contents as you scroll down the page.
The structure is currently like:
<div>
<div>
<div>
<div>
<h2 id="twitter-chats-for-ecommerce">Header</h2>
<div>content...</div>
</div>
</div>
</div>
</div>
And the table of contents like:
<ul>
<li>Item 1</li>
<li>Item 1</li>
<li>Twitter Chats for Ecommerce</li>
</ul>
The anchor is being applied to the header automatically via a Gutenberg block in WordPress (in this case, the h2).
The existing JavaScript for this is the following:
(function($) {
/* Table of contents - highlight active section on scroll */
window.addEventListener('DOMContentLoaded', () => {
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
const id = entry.target.getAttribute('id');
if (entry.intersectionRatio > 0) {
document.querySelector(`nav li a[href="#${id}"]`).parentElement.classList.add('active');
} else {
document.querySelector(`nav li a[href="#${id}"]`).parentElement.classList.remove('active');
}
});
});
// Track all sections that have an `id` applied
document.querySelectorAll('h2[id]').forEach((section) => {
observer.observe(section);
});
});
})( jQuery );
But as you can see from the below example screenshot, the item in the table of contents is highlighting when the matching header (in this case h2) is visible on the page.
So in the case where there are multiple headers visible on the page, more than one item is highlighted in the TOC.
Ideally, I guess that it should be matching the div of the section but the id anchor is being applied to the header and I don't have control over this.
Is there a way I can modify the JS to somehow only detect the entire div section instead of just the header so that it will only ever have one item highlighted in the TOC - or is there even a better way than this?
An example of one that works perfectly that I'd like to achieve can be seen here (see the 'On This Page' section in right hand sidebar).
I modified randomdude's answer to highlight the lowest scrolled-to header. This will persist highlighting of that link until the user scrolls down far enough to another one.
const anchors = $('body').find('h1');
$(window).scroll(function(){
var scrollTop = $(document).scrollTop();
// highlight the last scrolled-to: set everything inactive first
for (var i = 0; i < anchors.length; i++){
$('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').removeClass('active');
}
// then iterate backwards, on the first match highlight it and break
for (var i = anchors.length-1; i >= 0; i--){
if (scrollTop > $(anchors[i]).offset().top - 75) {
$('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').addClass('active');
break;
}
}
});
forked fiddle link: http://jsfiddle.net/tz6yxfk3/
I think you are looking for this:
$(window).scroll(function(){
var scrollTop = $(document).scrollTop();
var anchors = $('body').find('h1');
for (var i = 0; i < anchors.length; i++){
if (scrollTop > $(anchors[i]).offset().top - 50 && scrollTop < $(anchors[i]).offset().top + $(anchors[i]).height() - 50) {
$('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').addClass('active');
} else {
$('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').removeClass('active');
}
}
});
nav {
position: fixed;
right: 20px;
top: 20px;
}
div {
height: 2000px;
}
div > h1 {
height: 200px;
}
.active {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<ul>
<li id="whatbutton">What We Are</li>
<li id="whybutton">Why Us</li>
<li id="offerbutton">What We Offer</li>
<li id="contactbutton">Contact Us</li>
</ul>
</nav>
<div>
<h1 id="whatissm" name="whatissm"><span>sometexthere</span></h1>
<h1 id="whyusesm" name="whyusesm"><span>somtexthere</span></h1>
<h1 id="whatdoessmoffer" name="whatdoessmoffer"><span>sometexthere</span></h1>
<h1 id="contactus" name="contactus"><span>Contact Us</span></h1>
</div>
credits: Making a menu class active when scrolled past
fiddle link:
http://jsfiddle.net/yrz54fqm/1/
This is same answer as above, but is written in pure JavaScript, no need for jQuery. Great work, Crane, works like a champ.
const anchors = document.querySelectorAll('h1');
const links = document.querySelectorAll('nav > ul > li > a');
window.addEventListener('scroll', (event) => {
if (typeof(anchors) != 'undefined' && anchors != null && typeof(links) != 'undefined' && links != null) {
let scrollTop = window.scrollY;
// highlight the last scrolled-to: set everything inactive first
links.forEach((link, index) => {
link.classList.remove("active");
});
// then iterate backwards, on the first match highlight it and break
for (var i = anchors.length-1; i >= 0; i--) {
if (scrollTop > anchors[i].offsetTop - 75) {
links[i].classList.add('active');
break;
}
}
}
});
I have a list of elements:
<ul id="wpsl-stores">
<li>list</li>
<li>list</li>
<li class="skipthis">list</li>
<li>list</li>
<li>list</li>
<li>list</li>
<li class="skipthis">list</li>
<li>list</li>
</ul>
I'm looping through the elements and appending the number of that element:
var locCount = $('#wpsl-stores li').length;
for (i = 1; i < locCount+1; i++) {
$('#wpsl-stores ul li:nth-child('+i+') strong:before').hide();
$('body').append('<style>#wpsl-stores ul li:nth-child('+i+') strong:before {content:"'+i+'";}</style>');
}
I need to skip the elements that have the "skipthis" class.
On the actual site, the elements with the "skipthis" class are hidden but still in the dom. This means the loop above is still counting them.
Right now, the output is something like this:
1 list
2 list
4 list
5 list
6 list
etc.
etc.
I need it to be
1 list
2 list
3 list
4 list
You should select all the elements that aren't skipthis and loop through to add:
$('#wpsl-stores li:not(.skipthis)').each(function(i,li) {
$('body').append('<style>#wpsl-stores ul li:nth-child('+(i+1)+') strong:before {content:"'+(i+1)+'";}</style>');
});
EDIT:
If you want to remove the skipthis ones and add a counter to the others:
var listCount = 0;
$('#wpsl-stores li').each(function(i,li) {
if ($(this).hasClass('skipthis')) {
$(this).remove();
} else {
listCount++;
$('body').append('<style>#wpsl-stores ul li:nth-child('+listCount+') strong:before {content:"'+listCount+'";}</style>');
}
});
How about:
for (i = 1; i < locCount+1; i++) {
var $listElt = $('#wpsl-stores ul li:nth-child('+i+') strong:before');
if (!$listElt.hasClass('skipThis') {
$listElt.hide();
$('body').append('<style>#wpsl-stores ul li:nth-child('+i+') strong:before {content:"'+i+'";}</style>');
}
}
reference
try adding .not
$('#wpsl-stores li').not( ".skipthis" )
source: http://api.jquery.com/not/
You can use .each() for iteration and .hasClass() to skip some li elements:
$("#wpsl-stores li").each(function (index, element) {
if (!$(element).hasClass('skipthis')) {
// do something
}
});
How do you properly delete list item by clicking on it?
I have been using the following line for code to delete an item but instead this deletes the entire list itself:
var list = document.getElementById("shoppinglist");
list.onclick = function() { list.parentNode.removeChild(list);}
I have been searching online on how to do this and the same kind of code keeps appearing and I am not sure how to solve this. I assumed that the list item generated was a child of the "shoppinglist".
I am very new to Javascript and I know this is a rookie mistake but I would really appreciate any help. Thank you.
<!doctype html>
<html dir="ltr" lang="en-gb">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<style>
body {
/* Sets the width then uses the margin auto feature to centre the page in the browser */
width:800px;
margin: 0px auto; /*0px top/bottom auto left/right */
font-size:10px; /* By default fonts are usually 16px but may not be in some browsers */
}
p, li {
font-size:1.5em; /* Set all text to be 1.5 * overall font size = 15 pixels */
}
section {
/* each of the two sections will use just under half the width of the width of the body */
width:395px;
display:block;
}
#choices {
/* float the choices list to the left of the page */
float:left;
background-color: #FFFF99;
}
#cart {
/* float the shopping cart to the right of the page */
float:right;
background-color: #7FFF00;
}
.cartlist {
/* Simplify the display of the lists, removing default bullet points and indentation */
list-style-type:none;
margin:0px;
padding:0px;
width:inherit;
}
.cartlist li {
/* Set each list item to be 2* the height of the text */
height:2em;
}
.cartlist li:nth-child(odd) {
/* Colour odd list items ie first, third, fifth etc, a different colour */
background-color:#eee;
}
#outputinfo {
/* prevents the DIV from joining the floating behaviour so it displays below the lists */
clear:both;
}
</style>
</head>
<body>
<section id="choices">
<p>Available Choices</p>
<ul id="sourcelist" class="cartlist">
<li data-value="2.99">£2.99 : Chocolate</li>
<li data-value="3.49">£3.49 : Cereal</li>
<li data-value="0.98">£0.98 : Milk</li>
<li data-value="0.89">£0.89 : Bread</li>
<li data-value="3.79">£3.79 : Coffee</li>
<li data-value="2.53">£2.53 : Strawberries</li>
<li data-value="3.89">£3.89 : Cheesecake</li>
</ul>
</section>
<section id="cart">
<p>Shopping Cart</p>
<ul id="shoppinglist" class="cartlist"></ul>
</section>
<div id="outputinfo">
<p><button id="calctotal">Calculate Total</button> : <span id="totalresult"></span></p>
</div>
</body>
<script>
function getTargetElement(e) {
var targetelement=null;
targetelement=(e.srcElement || e.target || e.toElement)
return targetelement;
}
function calcTotal() {
var shoppinglist=document.getElementById("shoppinglist");
var total=0;
for(i=0;i<shoppinglist.children.length;i++) {
total+=parseFloat(shoppinglist.children[i].getAttribute("data-value"));
}
var totalresult=document.getElementById("totalresult");
totalresult.innerHTML="£"+total.toFixed(2);
}
function handleEvent(e) {
var listclicked=getTargetElement(e);
var newlistitem=document.createElement("li");
var datavalue=listclicked.getAttribute("data-value");
newlistitem.setAttribute("data-value",datavalue);
newlisttext=document.createTextNode(listclicked.innerHTML)
newlistitem.appendChild(newlisttext);
var shoppinglist = document.getElementById("shoppinglist");
shoppinglist.appendChild(newlistitem);
var list = document.getElementById("shoppinglist");
list.onclick = function() { list.parentNode.removeChild(list);}
console.log(listclicked);
}
function removeItem(e){
var listclicked=getTargetElement(e);
var node = document.getElementById('shoppinglist');
listclicked.parentNode.removeChild(listclicked);
}
document.onreadystatechange = function(){
if(document.readyState=="complete") {
var sourcelist=document.getElementById("sourcelist");
for(i=0;i<sourcelist.children.length;i++) {
if(document.addEventListener) {
sourcelist.children[i].addEventListener("click", handleEvent, false);
} else {
sourcelist.children[i].attachEvent("onclick", handleEvent);
}
var totalbutton=document.getElementById("calctotal");
if(document.addEventListener) {
totalbutton.addEventListener("click",calcTotal,false);
} else {
totalbutton.attachEvent("onclick",calcTotal);
}
}
}
}
</script>
</html>
You don't want to remove the entire list, just the clicked LI element.
As you don't seem to have nested elements, event delegation becomes a little easier
var list = document.getElementById("shoppinglist");
list.addEventListener('click', function(evt) {
list.removeChild(evt.target);
},false);
FIDDLE
For the future, if you wanted nesten elements, you could use element.closest()
var list = document.getElementById("shoppinglist");
list.addEventListener('click', function(evt) {
var p = evt.target.closest('li');
list.removeChild(p);
}, false);
Note the somewhat lacking support in older browsers for closest(), but there are several polyfills available if needed.
Also note that you're binding event handlers inside event handlers, which is a big no-no, your code does the equivalent of
var sourcelist = document.getElementById("sourcelist");
for(i = 0; i < sourcelist.children.length; i++) {
sourcelist.children[i].addEventListener("click", handleEvent, false);
...
// and then
function handleEvent(e) {
var list = document.getElementById("shoppinglist");
list.addEventListener('click', function(evt) {
list.removeChild(evt.target);
},false);
....
so every time you add another list item to the list, you bind a new event handler, and it adds up, but you only need one single event handler, having multiple event handlers will just try to remove the same element over and over again, but it's removed the first time.
list.onclick = function() { list.parentNode.removeChild(list);}
list is the whole list (<ul id='list'>). You're listening for a click on the whole list. Then grabbing the whole list's parent node with list.parentNode ( which gives you <section id="cart">) and deleting the list from it.
Your code is doing exactly what you told it to do.
Like this:
list.removeChild(list.childNodes[indexToRemove])
You need to specify what node to remove. You can test this in chrome by opening up the console and pasting the following:
var list = document.getElementById("shoppinglist");
console.log('List:', list)
console.log('List children:', list.childNodes)
var indexToRemove = 0;
list.removeChild(list.childNodes[indexToRemove]);
console.log('List:', list)
console.log('List children:', list.childNodes)
You can use this:
var list = document.getElementById("shoppinglist");
list.onclick = function(e) { e.target.parentNode.removeChild(e.target);}
You can read more about target and currentTarget and checkout this example http://fiddle.jshell.net/hidoos/Lpz917vo/
The scrollspy effect was working fine, but suddenly it stopped working. I mean the active element of the menu is identified while scrolling the onepage site, when the href links are given as like this href="#id". But It stops working when href is given like "/home#id". I want to use it like this. Since the site uses a common navigation.
This is my code:
/ Cache selectors
var lastId,
topMenu = $("#timenav"),
topMenuHeight = topMenu.outerHeight()+15,
// All list items
menuItems = topMenu.find("a"),
// Anchors corresponding to menu items
scrollItems = menuItems.map(function(){
var item = $($(this).attr("href"));
if (item.length) { return item; }
});
// Bind click handler to menu items
// so we can get a fancy scroll animation
menuItems.click(function(e){
var href = $(this).attr("href"),
offsetTop = href === "#" ? 0 : $(href).offset().top-topMenuHeight+1;
$('html, body').stop().animate({
scrollTop: offsetTop
}, 300);
e.preventDefault();
});
// Bind to scroll
$(window).scroll(function(){
// Get container scroll position
var fromTop = $(this).scrollTop()+topMenuHeight;
// Get id of current scroll item
var cur = scrollItems.map(function(){
if ($(this).offset().top < fromTop)
return this;
});
// Get the id of the current element
cur = cur[cur.length-1];
var id = cur && cur.length ? cur[0].id : "";
if (lastId !== id) {
lastId = id;
// Set/remove active class
menuItems
.parent().removeClass("active")
.end().filter("[href=#"+id+"]").parent().addClass("active");
}
});
can someone help me with this
http://www.drkeenly.com/
Here is a Fiddle
http://jsfiddle.net/aGjTV/
Any help would be great. Thanks in advance !
var cur = scrollItems!=null?scrollItems.map(...):null;
After this line cur is either something or null.
If it's null, then you can't index it like and array, or for that matter get its length with cur.length.
You haven't specified the error, but I bet it's saying "TypeError: cur is null".
The solution depends on what you actually want your code to do, but I'd suggest wrapping the remainder of the function in
if (cur) {
...
}
I just wrote a custom scroll-spy script, if you wish.
Check the DEMO http://jsfiddle.net/yeyene/L4Gpq/
No need scrollspy plugin anymore and you only need to add in below;
1) target to your navi link.
2) Same class to your DIVs and id: same as your target of navi.
HTML
<nav>
<ul>
<li><a target="main">Home</a></li>
<li><a target="story">Our Story</a></li>
<li><a target="work">Our Work</a></li>
<li><a target="our-news">Our News</a></li>
<li><a target="contact">Contact Us</a></li>
</ul>
</nav>
<div id="main" class="content">main</div>
<div id="story" class="content">story</div>
<div id="work" class="content">work</div>
<div id="our-news" class="content">our-news</div>
<div id="contact" class="content">contact</div>
JQUERY
$('nav li a').click(function () {
var id = $(this).attr('target');
$('html, body').stop().animate({
scrollTop: $('#'+id).offset().top
}, 500);
});
$(window).scroll(function() {
var myArray = new Array();
$('div.content').each(function() {
myArray.push($(this).offset().top);
});
for( var i=0; i<= myArray.length; i++){
if($(this).scrollTop() >= myArray[i]){
$('nav a').removeClass('active');
$('nav a').eq(i).addClass('active');
}
}
});
CSS
li {
float:left;
margin-right:10px;
list-style:none;
text-decoration:none;
}
li a {
cursor:pointer;
text-decoration:none;
z-index:11;
padding:0 5px;
}
li a.active {
background:red;
color:#fff;
}
.content {
float:left;
width:90%;
padding:45% 5%;
background:#dfdfdf;
margin-bottom:10px;
}
nav {
position:fixed;
width:100%;
padding:0 0 10px 0;
top:0;
left:0;
z-index:10;
background:green;
}
var item = $($(this).attr("href")); in your code was creating problem because when you write href="#id" it is var item = $(#id); but when you write href="/home#id" it becomes var item = $(/home#id); which is incorrect.I fixed it:
scrollItems = menuItems.map(function(){
var indexItm = $(this).attr('href').indexOf('#');
var str = $(this).attr('href').substring(indexItm);
var item = $(str);
if (item.length) { return item; }
});
Another change filter("[href*=#"+id+"]") which will check for string #id within href even in href contains any text before #:
Edited line:
menuItems
.parent().removeClass("active")
.end().filter("[href*=#"+id+"]").parent().addClass("active");
Fiddle were only foo is given href="/home#foo"
Note : the above fiddle will require a text along with # for Top href also.Otherwise it will set .active to all menu items:
Top
.
.
.
<a id="top">top</a>
I have an issue. I am getting data from a MySQL database, and make a list of it. That's all good, and works fine, but the list is now over 100 items long if I don't limit it.
I've tried Googling how to shorten list, and found some things with jQuery and JavaScript, but that didn't work too well.
What I'm looking for is a way to make the list limit itself on 10 items, with a [More] button under it. When pressed, the next 10 items show, and when pressed again, 10 more etc.
I have my list in normal <li> and <ul> bits.
If there's any more information needed, please ask me. This is the webpage it's about: http://lolmewn.nl/stats/
A bit of my PHP code:
echo "<li><a href=\"?player=" . $row['player'] . "\">" . $row['player'] .
"</a></li>\n";
Maybe you can try this. In this example I used 2 items instead of 10. I used css to hide all li elements starting from the 3rd li element inside the ul. I used jQuery to reveal additional 2 lis every time show more is clicked.
Hope this helps
Updated Link Again...
EDIT
$(function () {
$('span').click(function () {
$('#datalist li:hidden').slice(0, 2).show();
if ($('#datalist li').length == $('#datalist li:visible').length) {
$('span ').hide();
}
});
});
ul li:nth-child(n+3) {
display:none;
}
ul li {
border: 1px solid #aaa;
}
span {
cursor: pointer;
color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<ul id="datalist">
<li>dataset1</li>
<li>dataset1</li>
<li>dataset2</li>
<li>dataset2</li>
<li>dataset3</li>
<li>dataset3</li>
<li>dataset4</li>
<li>dataset4</li>
<li>dataset5</li>
<li>dataset5</li>
</ul>
<span>readmore</span>
One method is to use ajax to load the list items & restrict them to 10 items using mysql limit.
Otherwise, if you load all at once, you can do the following: (write the code yourself)
Load all of them in a ul and make the display of all none.
Then using jquery eq selector display the first 10 li elements.
on clicking more, just toggle those li which you want to display.
If you want this is pure javascript I made a example on jsfiddle
Javascript
function showMore() {
var listData = Array.prototype.slice.call(document.querySelectorAll('#dataList li:not(.shown)')).slice(0, 3);
for (var i=0; i < listData.length; i++)
{
listData[i].className = 'shown';
}
switchButtons();
}
function showLess() {
var listData = Array.prototype.slice.call(document.querySelectorAll('#dataList li:not(.hidden)')).slice(-3);
for (var i=0; i < listData.length; i++)
{
listData[i].className = 'hidden';
}
switchButtons();
}
function switchButtons() {
var hiddenElements = Array.prototype.slice.call(document.querySelectorAll('#dataList li:not(.shown)'));
if(hiddenElements.length == 0)
{
document.getElementById('moreButton').style.display = 'none';
}
else
{
document.getElementById('moreButton').style.display = 'block';
}
var shownElements = Array.prototype.slice.call(document.querySelectorAll('#dataList li:not(.hidden)'));
if(shownElements.length == 0)
{
document.getElementById('lessButton').style.display = 'none';
}
else
{
document.getElementById('lessButton').style.display = 'block';
}
}
onload= function(){
showMore();
}
HTML
<ul id="dataList">
<li class="hidden">One</li>
<li class="hidden">Two</li>
<li class="hidden">Three</li>
<li class="hidden">Four</li>
<li class="hidden">Five</li>
<li class="hidden">Six</li>
<li class="hidden">Seven</li>
<li class="hidden">Eight</li>
<li class="hidden">Nine</li>
<li class="hidden">Ten</li>
<li class="hidden">Eleven</li>
</ul>
<input id="moreButton" type="button" value="More" onclick="showMore()"/>
<input id="lessButton" type="button" value="Less" onclick="showLess()"/>
CSS
.shown{
display:block;
}
.hidden{
display:none;
}
Have you ever try jquery datatable yet?
Simple solution in pure javascript:
var ul = document.getElementsByTagName("ul")[0], //Your <ul>
readmore = document.createElement("li"),
lisColl = ul.getElementsByTagName("li"),
len = lisColl.length,
lis = [],
pos = 0;
readmore.textContent = "Read more";
for (var i = 0; i < len; i++) {
lisColl[i].style.display = "none";
lis.push(lisColl[i]);
}
readmore.onclick = function () {
if (this.parentNode) {
this.parentNode.removeChild(this);
}
for (var c = 0; pos < len; pos++) {
if ((c++) === 10) {
ul.insertBefore(this, lis[pos + 1]);
break;
}
lis[pos].style.display = "";
}
}
readmore.onclick.call(readmore);
If you want to limit the number of results from the database, add LIMIT 10 (or any number) to the MySQL query.
If you want to actually hide the lists, but leave them available, you will need CSS to initially hide them, and Javascript/Jquery to unhide them. (CSS3 might let you unhide them without Javascript/Jquery, but it isn't fully supported everywhere yet).
Assuming all the list items have the same CSS class then a javascript loop like the following may work:
function unhide(number) {
var items = document.getElementsByClassName('tagnamehere');
var shown=0;
for (var i=0; shown<number && i<items.length; i++) {
if (items[i].style.display=="" || items[i].style.display=="none") {
items[i].style.display="list-item";
shown+=1;
}
}
}
In the CSS, all you need to add is .tagnamehere {display:none;}
Feel free to substitute with your own tags.