JavaScript: query children and modify parent - javascript

I have a static generated unsorted list and need to modify the parent li for a given child-href-match. This action should perform by rendering, not by interaction. I am using jQuery 1.12.4.
<div id="archive_widget" class="widget-odd widget-last widget-first widget-1 widget Archive_Widget">
<h3>Archive</h3>
<ul>
<li>2018</li>
<li>2017</li>
<li>2016</li>
<li>2015</li>
<li>2014</li>
<li>2013</li>
<li>2012</li>
<li>2010</li>
<li>2009</li>
</ul>
</div>
I don't know how to do this with JS, but this imaginary JS was in my mind.
jQuery(document).ready(function() {
var current = "<?php echo $current; ?>";
var ArchiveList = document.querySelector('#archive_widget ul li').children;
for (i = 0; i < productList.length; i++) {
if (productList[i].text == current) {
$(productList[i]).parent().addClass('active-menu');
}
}
});
Thank you.

There are some problems with your code:
document.querySelector select only one element, in your case the first LI
variable productList is never declared
The parent of a LI is always a list, not the LI itself.
Here is a working version of it:
$(document).ready(function() {
var current = "2014";
var productList = $('#archive_widget ul li a'); // select all A elements
for (i = 0; i < productList.length; i++) {
if ($(productList[i]).text() === current) {
$(productList[i]).parent().addClass('active-menu'); // Parent of A will be LI
}
}
});

Ideally, this would be set when SSR, but here's a scant attempt:
$(document).ready(function () {
let current = "2015";//set server-side
let found = false;
$("#archive_widget").children('ul').children("li").children("a").each(function () {
if (!found && $(this).text() === current) {
$(this).parent().addClass('active-menu');
found = true;
}
});
});
.active-menu { background: red }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="archive_widget" class="widget-odd widget-last widget-first widget-1 widget Archive_Widget">
<h3>Archive</h3>
<ul>
<li>2018</li>
<li>2017</li>
<li>2016</li>
<li>2015</li>
<li>2014</li>
<li>2013</li>
<li>2012</li>
<li>2010</li>
<li>2009</li>
</ul>
</div>
I hope this helps!

Change ArchiveList to productList since that's what your code is using and use .textContent instead of .text.
Your query selector only matches one element. You want to match all of the anchor elements whose parents are a li, so use document.querySelectorAll instead:
document.querySelectorAll('#archive_widget ul li a');
Fixed Code:
jQuery(document).ready(function() {
var current = "<?php echo $current; ?>";
var productList = document.querySelectorAll('#archive_widget ul li a');
for (i = 0; i < productList.length; i++) {
if (productList[i].textContent == current) {
$(productList[i]).parent().addClass('active-menu');
}
}
});

Related

How to skip element with specific class in jQuery for loop?

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 would I set a Jquery variable based on the location and a list of li elements?

I’m using JQuery 1.11. I have the following HTML …
<div id="tabs">
<ul class="nav">
<li><a href=“/my_object/index”>My Objects</a></li>
<li>Lookup Results</li>
…
<li><a href="/my_object/edit”>Edit Stuff</a></li>
</ul>
</div>
How would I set a variable, “activeIndex” that would be the index of the anchor tag if its href attributes matches the current location? So for example, if the current location is “https://mydomein.com/my_object/search”, the activeIndex variable would be “1”.
You could use window.location.pathname:
function activeIndex() {
var ul = document.getElementsByClassName("nav");
var listItems = ul[0].getElementsByTagName("li");
for (var i = 0; i < listItems.length; i++) {
var a = listItems[i].getElementsByTagName("a");
if (a[0].getAttribute("href") === window.location.pathname)
return i;
}
return -1;
}
You can use index method to determine the index of an element within a array of jquery elements.
var activeIndex;
$('ul.nav li a').each(function()
{
if($(this).attr('href') == window.location.pathname)
activeIndex = $('ul.nav li a').index(this);
});
Example : https://jsfiddle.net/DinoMyte/jmLynLsg/4/

jQuery UI sortable - Sort around stationary items [duplicate]

Is it possible to lock list items in JQuery sortable list in a way that those items will stay in that particular place in the list.
For example,
consider this pseudo list with locked items...
item A
item B(locked)
item C(locked)
item D
item E
item F
item G(locked)
So, I'd like to have the items B,C and G to be fixed in a way that if user drag and drop item D at the start of the list, the item A "jumps" over fixed/locked items B and C with following results...
item D
item B(locked)
item C(locked)
item A
item E
item F
item G(locked)
I've been searching for something like this without luck. Is it possible..?
Here's a hopefully bug-free version, updating as you drag. It's generating the current desired positions of the items when sorting starts, which means you should be able to change the classes whenever you need, refresh the widget's list items and you're good to go.
It also uses the sortable's built-in items property to prevent dragging the fixed items and to sort out any sorting problems at the top and the bottom of the list.
I tried to move the fixed items around, but that resulted in horribly buggy behaviour, especially when there are multiple fixed items in groups. The final solution detaches all fixed items from the list, adds a helper element to the front, then re-inserts the fixed elements to their desired position, which seems to fix all bugs.
Try the demo here: http://jsfiddle.net/PQrqS/1/
HTML:
<ul id="sortable">
<li>oranges</li>
<li class="static">apples</li>
<li>bananas</li>
<li>pineapples</li>
<li>grapes</li>
<li class="static">pears</li>
<li>mango</li>
</ul>
CSS:
.static { color:red; }
li { background-color:whitesmoke; border:1px solid silver; width:100px; padding:2px; margin:2px; }
Javascript:
$('#sortable').sortable({
items: ':not(.static)',
start: function(){
$('.static', this).each(function(){
var $this = $(this);
$this.data('pos', $this.index());
});
},
change: function(){
$sortable = $(this);
$statics = $('.static', this).detach();
$helper = $('<li></li>').prependTo(this);
$statics.each(function(){
var $this = $(this);
var target = $this.data('pos');
$this.insertAfter($('li', $sortable).eq(target));
});
$helper.remove();
}
});
I extended the jQuery.Ui.sortable:
Overview
jQuery.Ui.sortable widget extension with fixed feature. This feature allows user to fix elements in the list.
With the .fixedsortable() constructor you construct a .sortable() class which extended with the features. You can use the original methods and the extended as well.
Code
https://gist.github.com/3758329#file_fixedsortable.js > fixedsortable.js
Example
http://jsfiddle.net/omnosis/jQkdb/
Usage
General:
To use, add the fixed property to the sortable list optios:
$("#list").fixedsortable({
fixed: (value)
})
the value can be:
integer example: 3
array of integers example : [1,2,5]
a html element or a list of html elements
a css selector
jquery object
HTML:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script> //the jquery
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js"></script> //the original jquery-ui
<script type="text/javascript" src="https://raw.github.com/gist/3758329/91749ff63cbc5056264389588a8ab64238484d74/fixedsortable.js"></script> //the extended sortable
...
<ul id="sortable1">
<li>oranges</li>
<li class="static">apples</li>
<li>bananas</li>
<li>pineapples</li>
<li>grapes</li>
<li class="static">pears</li>
<li>mango</li>
</ul>
<ul id="sortable2">
<li>bananas</li>
<li foo="asd">oranges</li>
<li foo="dsa">apples</li>
<li>pineapples</li>
<li>grapes</li>
<li>pears</li>
<li>mango</li>
</ul>
<ul id="sortable3">
<li>bananas</li>
<li>oranges</li>
<li>apples</li>
<li>pineapples</li>
<li>grapes</li>
<li>pears</li>
<li>mango</li>
</ul>
Javascript
$(function() {
$("#sortable1").fixedsortable({
fixed: "> .static"
});
$("#sortable2").fixedsortable({
fixed: $("li[foo]").css("background","red")
});
$("#sortable3").fixedsortable({
fixed: 2
})
});
Notes:
If you insist to use the .sortable instead of .fixedsortable you can use this https://gist.github.com/3758329#file_sortable.js instead of the jquery.ui library. This is a complete replacement of the jQuery.ui, but i don't recommend to use this because of later updates.
i have been working on this more than 12 hours :( i am insane..
Check this out: Forcing an item to remain in place in a jQuery UI Sortable list
Also, I've implemented the above solution with multiple fixed elements here: http://jsfiddle.net/enBnH/12/ (obsolete, see below)
It's rather self-explanatory, i think.
EDIT:
I've automated the process for generating the lockto values as well as adding ID's to those lis with the class "fixed" (note that i have to add an ID so we can reference it)
See the COMPLETE solution HERE: http://jsfiddle.net/enBnH/44/
EDIT
Okay, after a gazillion errors with the above, i just rewrote the dang thing myself:
http://jsfiddle.net/thomas4g/GPMZZ/15/
NOTE: The above does work, but #DarthJDG's answer seems a lot nicer to me. I'm leaving mine up on the offchance someone might prefer how mine behaves (i've learned not to delete stuff just beceause there's a better version :P )
Using the items parameter you can achieve what you want like this:
$("#mytable tbody").sortable({items: 'tr.sortable'});
Only rows with a .sortable CSS class can be sorted now.
If you want to lock only the 1st row you can do this:
$("#mytable tbody").sortable({items: 'tr:not(:first)'});
The possibilities are endless...
This is based on #DarthJDG code. However it wasn't retrieving all the id's and the sorting wasn't working with the table. So I managed to update his solution which works with both list and tables and keeps the id in the array.
Javascript:
var fixed = '.static'; //class which will be locked
var items = 'li'; //tags that will be sorted
$('ul').sortable({
cancel: fixed,
items: items,
start: function () {
$(fixed, this).each(function () {
var $this = $(this);
$this.data('pos', $this.index());
});
},
change: function () {
var $sortable = $(this);
var $statics = $(fixed, this).detach();
var tagName = $statics.prop('tagName');
var $helper = $('<'+tagName+'/>').prependTo(this);
$statics.each(function () {
var $this = $(this);
var target = $this.data('pos');
$this.insertAfter($(items, $sortable).eq(target));
});
$helper.remove();
}
});
Demo: http://plnkr.co/edit/hMeIiRFT97e9FGk7hmbs
Connected sortables and fixed items
I ran into the problem when we have several connected sortables. The code suggested by #sarunast and #DarthJDG has erroneous behavior when dragging items from one list to another.
Therefore, I have modified it a little, and now you can drag items from different lists with saving positions in both of them.
javascript:
let connected = '.soratble';
let fixed = '.static';
let newParentContainer;
//wrap the code suggested by #sarunast and #DarthJDG into the function
//code was modified a little
function sortingAroundFixedPositions(container) {
let sortable = $(container);
let statics = $(fixed, container).detach();
let tagName = statics.prop('tagName');
let helper = $('<' + tagName + '/>').prependTo(container);
statics.each(function() {
let target = this.dataset.pos;
let targetPosition = $(tagName, sortable).eq(target);
if (targetPosition.length === 0) {
targetPosition = $(tagName, sortable).eq(target - 1)
}
$(this).insertAfter(targetPosition);
});
helper.remove();
}
$('ul').sortable({
connectWith: connected,
cancel: fixed,
start: function() {
$(fixed, connected).each(function() {
this.dataset.pos = $(this).index();
});
},
change: function(e, ui) {
sortingAroundFixedPositions(this);
if (ui.sender) {
newParentContainer = this;
}
if (newParentContainer) {
sortingAroundFixedPositions(newParentContainer);
}
},
update: function(e, ui) {
newParentContainer = undefined;
}
});
demo: http://plnkr.co/edit/blmv4ZjaWJFcjvO2zQH0
Just use the "Include/Exclude" items selectors.
Here is the link: https://jqueryui.com/sortable/#items
oh no! gist link is broken. here is code dump from https://gist.github.com/peterh-capella/4234752
code accessed Jan 6, 2016
//this code is created to fix this problem: http://stackoverflow.com/questions/4299241/
(function( $, undefined ) {
$.widget("ui.fixedsortable", $.ui.sortable, {
options: $.extend({},$.ui.sortable.prototype.options,{fixed:[]}),
_create: function() {
var o = this.options;
this.containerCache = {};
this.element.addClass("ui-sortable");
//Get the items
$.ui.sortable.prototype.refresh.apply(this,arguments);
if( typeof this.options.fixed == "number") {
var num = this.options.fixed
this.options.fixed = [num];
}
else if( typeof this.options.fixed == "string" || typeof this.options.fixed == "object") {
if(this.options.fixed.constructor != Array) {
var selec = this.options.fixed;
var temparr = [];
var temp = $(this.element[0]).find(selec);
var x = this;
temp.each(function() {
var i;
for(i=0;i<x.items.length && x.items[i].item.get(0) != this;++i) {}
if(i<x.items.length) temparr.push(i);
});
this.options.fixed = temparr;
}
}
//Let's determine if the items are being displayed horizontally
this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
//Let's determine the parent's offset
this.offset = this.element.offset();
//Initialize mouse events for interaction
$.ui.sortable.prototype._mouseInit.apply(this,arguments);
},
_mouseCapture: function( event ) {
this._fixPrev = this._returnItems();
return $.ui.sortable.prototype._mouseCapture.apply(this,arguments);
},
_mouseStart: function( event ) {
for(var i=0;i<this.options.fixed.length;++i) {
var num = this.options.fixed[i];
var elem = this.items[num];
if(event.target == elem.item.get(0)) return false;
}
return $.ui.sortable.prototype._mouseStart.apply(this,arguments);
},
_rearrange: function(event, i, a, hardRefresh) {
a ? a[0].appendChild(this.placeholder[0]) :
i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
this._refix(i);
//Various things done here to improve the performance:
// 1. we create a setTimeout, that calls refreshPositions
// 2. on the instance, we have a counter variable, that get's higher after every append
// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
// 4. this lets only the last addition to the timeout stack through
this.counter = this.counter ? ++this.counter : 1;
var self = this, counter = this.counter;
window.setTimeout(function() {
if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
},0);
},
_refix: function(a) {
var prev = this._fixPrev;
var curr = this._returnItems();
var Fixcodes = this.options.fixed;
var NoFixed = [];
var Fixed = [];
var Mixed = []
var post = [];
for(var i=0;i<Fixcodes.length;++i) {
var fix_index = Fixcodes[i];
var fix_item = prev[fix_index];
var j = 0;
for(j=0;j<curr.length && curr[j].item.get(0) != fix_item.item.get(0);++j) {}
curr.splice(j,1);
Fixed.push(fix_item);
}
for(var i=0;i<curr.length;++i) {
if(curr[i].item.get(0) != this.currentItem.get(0)) {
NoFixed.push(curr[i]);
}
}
var fix_count = 0;
var nofix_count = 0;
for(var i=0;i<Fixed.length + NoFixed.length;++i) {
if(Fixcodes.indexOf(i) >= 0) {
Mixed.push(Fixed[fix_count++]);
}
else {
Mixed.push(NoFixed[nofix_count++]);
}
}
var parent = this.currentItem.get(0).parentNode;
var allchild = parent.children;
for(var i=0;i<Mixed.length;++i) {
parent.removeChild(Mixed[i].item.get(0));
parent.appendChild(Mixed[i].item.get(0));
}
},
_returnItems: function(event) {
this.containers = [this];
var items = [];
var self = this;
var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
var connectWith = $.ui.sortable.prototype._connectWith.apply;
if(connectWith) {
for (var i = connectWith.length - 1; i >= 0; i--){
var cur = $(connectWith[i]);
for (var j = cur.length - 1; j >= 0; j--){
var inst = $.data(cur[j], 'sortable');
if(inst && inst != this && !inst.options.disabled) {
queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
this.containers.push(inst);
}
};
};
}
for (var i = queries.length - 1; i >= 0; i--) {
var targetData = queries[i][1];
var _queries = queries[i][0];
for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
var item = $(_queries[j]);
item.data('sortable-item', targetData); // Data for target checking (mouse manager)
items.push({
item: item,
instance: targetData,
width: 0, height: 0,
left: 0, top: 0
});
};
};
return items;
},
value: function(input) {
//console.log("test");
$.ui.sortable.prototype.value.apply(this,arguments);
}
});
})(jQuery);
And dumping rest of his answer, just in case
dependencies
https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js
https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js
Script
function randomColor() { //for a little fun ;)
var r = (Math.floor(Math.random()*256));
var g = (Math.floor(Math.random()*256));
var b = (Math.floor(Math.random()*256));
return "#" + r.toString(16) + g.toString(16) + b.toString(16)
}
$(function() {
$("#sortable1").fixedsortable({
fixed: "> .static", //you can use css selector
sort: function() { //you can add events as well, without getting confused. for example:
$(".static").css("background",randomColor()) //change the fixed items background
},
change: function(event,ui) {
$(ui.item[0]).css("border","2px solid "+randomColor()) //change the captured border color
},
stop: function(event,ui) {
$(ui.item[0]).css("border","2px solid #777"); //change the back the css modifications
$("#sortable1 > li.static").css("background","#aaa");
}
});
$("#sortable2").fixedsortable({ //you can use jQuery object as selector
fixed: $("li[foo]").css("background","red")
});
$("#sortable3").fixedsortable({
fixed: [2,4], //you can use array of zero base indexes as selector
update: function(event, ui) {
alert($(this).fixedsortable('toArray')) //the fixedsortable('toArray') also works
}
})
$("#sortable4").fixedsortable({
fixed: 5 //you can fix a single item with a simple integer
})
});
HTML
<body>
<div style="width:120px;float:left;">
<ul id="sortable1">
<li>oranges</li>
<li class="static">apples</li>
<li>bananas</li>
<li>pineapples</li>
<li>grapes</li>
<li class="static">pears</li>
<li>mango</li>
</ul>
<ul id="sortable2">
<li>bananas</li>
<li foo="asd">oranges</li>
<li foo="dsa">apples</li>
<li>pineapples</li>
<li>grapes</li>
<li>pears</li>
<li>mango</li>
</ul>
</div>
<div style="width:120px;float:left;">
<ul id="sortable3">
<li id="fru_1">bananas</li>
<li id="fru_2">oranges</li>
<li id="fru_3" style="background:#f4f">apples</li>
<li id="fru_4">pineapples</li>
<li id="fru_5" style="background:#faaba9">grapes</li>
<li id="fru_6">pears</li>
<li id="fru_7">mango</li>
</ul>
<ul id="sortable4">
<li>bananas</li>
<li>oranges</li>
<li>apples</li>
<li>pineapples</li>
<li>grapes</li>
<li style="background:#dada00">pears</li>
<li>mango</li>
</ul>
</div>
</body>
CSS
ul {margin:10px;}
ul#sortable1 > li, ul#sortable2 > li, ul#sortable3 > li, ul#sortable4 > li {
display:block;
width:100px;
height:15px;
padding: 3px;
background: #aaa;
border: 2px solid #777;
margin: 1px;
}
ul#sortable1 > li.static {
opacity:0.5;
}
Maybe this will help to someone: use methods "disable" and "enable". Example
HTML:
<ul class="sortable">
<li>You can move me</li>
<li data-state="lifeless">You can't move me.</li>
</ul>
Script:
$('#sortable').sortable();
$('#sortable').mousedown(function() {
if($(this).data('state')=='lifeless') $('#sortable').sortable('disable');
else $('#sortable').sortable('enable');
});
Live example here: https://jsfiddle.net/ozsvar/0ggqtva5/2/
There is a slightly better way to solve this.
You need to use a grid instead of a list and then you can fix the position of an element by declaring where the element should be arranged with css:
.fixed-element {
grid-column-start: 1;
grid-column-end: 1;
grid-row-start: 1;
grid-row-end: 1;
}

include variable with addEventListener

I´ve just started to learn JavaScript and made a click function to change value of i depending on which li element is being clicked. Instead of having 3x of basically same function is it possible to send variable with addEventLisener to check with a if statement. Because if I add 1 or 2 more li it would add a lot of unnecessary code.
HTML:
<div><img src="image1" />
<ul>
<li id="list1">1</li>
<li id="list2">2</li>
<li id="list3">3</li>
</ul>
</div>
JavaScript:
var list1 = getElementById('list1');
var list2 = getElementById('list2');
var list3 = getElementById('list3');
list1.addEventListener("click", clicked1);
list2.addEventListener("click", clicked2);
list3.addEventListener("click", clicked3);
var i = 0;
function clicked1(){
i= 0;
loop();
}
function clicked2(){
i = 1;
loop();
}
function clicked3(){
i = 2;
loop();
}
function loop(){
if (i > 2){
i=0;
}
var imageloop = getElementById('slideshow').getElementsByTagName('img');
imageloop[0].src = 'image' + i;
i++
setTimeout(loop,3000);
}
So when one of the li element is being clicked it will change the img currently displaying.
Bind to the list, not the list item - <ul id="ul1">... :
document.getElementById('ul1').addEventListener('click', function (e) {
var li = e.target;
alert(li.id); // list1, list2, respectively, etc.
});
http://jsfiddle.net/seancannon/D6HX4/
As Teemu said, bind to the list and use e.target. Then, change i according to e.target.innerHTML (because for your purposes, that's easier since the innerHTML is similar to the id, but simpler).
Assuming the <ul> element now has an id of "list":
var list = document.getElementById("list");
var i = null;
list.addEventListener("click", function(e) {
window.i = parseInt(e.target.innerHTML, 10);
console.log(window.i);
});
You don't need Separate code for each <li>,
Here is How to do it in single function:
HTML:
<div>
<ul id="All_List">
<li id="list1">1</li>
<li id="list2">2</li>
<li id="list3">3</li>
</ul>
</div>
JavaScript:
var clicked_li=0; /* It'll store the number of <li> being clicked */
var ul=document.getElementById("All_List"); /* <ul> Element with all <li> */
window.onload=function(){
var lis=ul.getElementsByTagName("li"); /* All <li>'s from <ul> */
for(var i=0;i<lis.length;i++){
var li=lis[i]; /* Specific <li> from <ul> ie, lis[0] means first <li> of <ul> */
li.addEventListener("click", function(){ /* Listen and bind click event to that <li> */
clicked_li=getIndex(this); /* Store Which <li> Was clicked in clicked_li */
alert("'list"+clicked_li+"' was clicked!");
/* if you just want to get the id you can use event.target.id; instead of getIndex(); */
}, false);
}
};
function getIndex(node) {
var childs = node.parentNode.getElementsByTagName("li"); /* Get parent <ul> and all child <li> of that parent */
for (var i = 0; i < childs.length; i++) {
if (node == childs[i]) break; /* Find which <li> from current <ul> was clicked */
}
return (i+1); /* Return No.(index) of that <li> starting with 1 */
}
and here is the:
fiddle for the same.
Hope it'll help you. Cheers!
This is an "improve/clearer" of Vedant Terkar answer. Which may give a more clear aspect on
the answer he gave.
if we give ul id group. We dont need id for each of the list-item inside the ul.
<ul id="group">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
Javascript
var i=0;
we set i to be a global variable and equal to 0 assuming it will display image(0) if nothing else is called.
window.onload=function(){
var lis=document.getElementById("group").getElementsByTagName('li');
We are now creating a Nodelist which is called lis. Then we loop through the NodeList to se which list-element is being clicked at.
for(i=0;i<lis.length;i++){
var li=lis[i];
li.addEventListener("click",index, false);
}
}
function index(){
var lis = document.getElementById("group").getElementsByTagName('li');
i = getIndex(this);
for(var a=0; a < lis.length; a++){
if(a ==i){
lis[i].innerHTML = 'Choosen';
}else{
lis[a].innerHTML = 'list'+a;
}
}
}
function getIndex(node) {
var childs = node.parentNode.getElementsByTagName("li");
for (var i = 0; i < childs.length; i++) {
if (node == childs[i]) break;
}
return (i);
}

Hiding list items with a "show more" button

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.

Categories

Resources