Jquery - Auto Increment ID's for Nested List - javascript

I have a nested list that resembles this:
<div id="treeview-left">
<ul>
<li>Country
<ul>
<li>Region
<ul>
<li>District
<ul>
<li>Group
<ul>
<li>People</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
This list is dynamically generated, and I need to auto increment ID's for each list item at each level.
Eg.
Country li's would have #Lv1-1 , #Lv1-2, #Lv1-3
Region li's would have #Lv2-1 , #Lv2-2, #Lv2-3
Each level needs to start with at 0 or 1, and increment the id based on it's index in that specific ul.
This is my current code, I am unable to even get the first level working.
<script>
$(function () {
$("#treeview-left > ul li").each(function () {
var TopPosition = $(this).index();
console.log(TopPosition);
$(this).id("Lvl1"+TopPosition);
});
});
</script>
Your help is appreciated.
Thanks

demo: https://so.lucafilosofi.com/jquery-auto-increment-ids-for-nested-list/
$(function () {
$("#treeview-left ul").each(function (i, item) {
var Tp = i + 1;
$(this).find('li').each(function (j, item) {
$(this).attr('id', "Lvl" + Tp + '-' + (j + 1));
});
});
});

here is a Recursive solution
function updateIds($node, index) {
if ($node.is('ul')) {
updateIds($node.children(), index);
} else {
$node.each(function (i, el) {
$(el).attr('id', 'Lv' + index + '-' + (i+1));
var $child = $node.children('ul');
if ($child.length > 0) {
updateIds($child, index+1);
}
});
}
}
demo: http://jsfiddle.net/3xpBw/1/

Another solution could be:Fiddle
<script type="text/javascript">
$(function () {
var count=0
$('ul').each(function(i, ul) {
count++
ul = $(ul);
var first=count
ul.children('li').each(function(i, li) {
li = $(li);
var second = first + '.' + (li.index() + 1);
li.prepend('<span>' + second + '</span>');
li.attr('id',second)
})
})
});
</script>

Related

sort list ul->li in function for different ids

I came from What is the easiest way to order a <UL>/<OL> in jQuery?
works fine.
But I need this on different ids, so I tried to put it in a function.
I tried:
var sortmenues = ['#firstid', '#secondid', '#anotherid'];
function sortuls(paths) {
jQuery.each(paths,function(index, value) {
var items = jQuery(value).get();
items.sort(function(a,b){
var keyA = jQuery(a).text();
var keyB = jQuery(b).text();
if (keyA < keyB) return -1;
if (keyA > keyB) return 1;
return 0;
});
var ul = jQuery(value);
jQuery.each(items, function(i, li){
ul.append(li);
});
});
}
jQuery(function() {
sortuls(sortmenues);
});
But I doesn't work, just for the first element in array.
I tried to duplicate the snippet, but I just works on first element, too.
like:
var items = jQuery('#firstid li').get();
...
var ul = jQuery('#firstid');
...
});
var items = jQuery('#secondid li').get();
...
var ul = jQuery('#secondid');
...
});
also this doesn't work for all elements:
jQuery.each([ '#firstid', '#secondid' ], function( index, value ) {
var items = jQuery(value + ' li').get();
items.sort(function(a,b){
var keyA = jQuery(a).text();
var keyB = jQuery(b).text();
if (keyA < keyB) return -1;
if (keyA > keyB) return 1;
return 0;
});
var ul = jQuery(value);
jQuery.each(items, function(i, li){
ul.append(value + 'li');
});
});
Can somebody please tell me, what I am doing wrong?
the html is
...
<ul id="firstid">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
<li>Delta</li>
</ul>
...
<ul id="anotheridNosortinghere">
<li>Alphaa</li>
<li>Betaa</li>
<li>Gammaa</li>
<li>Deltaa</li>
</ul>
...
<ul id="secondid">
<li>Alphaa</li>
<li>Betaa</li>
<li>Gammaa</li>
<li>Deltaa</li>
</ul>
...
Given your HTML you can just do a simple loop through the selectors for each ul your provide, sorting the child li elements by their text value as you go. Try this:
$('#firstid, #secondid').each(function() {
$(this).find('li').sort(function(a, b) {
return $(a).text() < $(b).text() ? -1 : 1;
}).appendTo(this);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="firstid">
<li>Delta</li>
<li>Beta</li>
<li>Alpha</li>
<li>Gamma</li>
</ul>
<ul id="anotheridNosortinghere">
<li>Deltaa</li>
<li>Gammaa</li>
<li>Alphaa</li>
<li>Betaa</li>
</ul>
^ Not sorted
<ul id="secondid">
<li>Betaa</li>
<li>Alphaa</li>
<li>Deltaa</li>
<li>Gammaa</li>
</ul>

Sorting array by HTML data attribute?

I'm trying to learn local storage. I have five links each with a data-date attribute and I want them to be sorted using that attribute. I've tried numerous ways but nothing seems to work. From what I understand, I should parse before sorting but it didn't work for me. I must have done it wrong because I don't see how else to do it.
Here is my HTML:
<div id="div1">
<input id='clearHistory' type='button' value='Remove All History' />
<input id='showHistory' type='button' value='Show History' />
<ul id='history'>
<li>
<a class='date' href="#aa" data-date="November 12, 2001 03:24:00">Link 1</a>
</li>
<li>
<a class='date' href="#bb" data-date="August 4, 1993 03:24:00">Link 2</a>
</li>
<li>
<a class='date' href="#cc" data-date="October 17, 1995 03:24:00">Link 3</a>
</li>
<li>
<a class='date' href="#dd" data-date="December 1, 2010 03:24:00">Link 4</a>
</li>
<li>
<a class='date' href="#ee" data-date="August 17, 2004 03:24:00">Link 5</a>
</li>
</ul>
</div>
<p>Click on 'Show History' to see the 'user history'.</p>
<ul id='storedHistory'></ul>
And my JavaScript:
$(document).ready(function() {
var storedHistory = document.getElementById('storedHistory');
Storage.prototype.setObject = function(key, value) {
this.setItem(key, JSON.stringify(value));
};
Storage.prototype.getObject = function(key) {
var value = this.getItem(key);
return value && JSON.parse(value);
};
//function sortDatesAscending(a, b) { return a.valueOf() - b.valueOf(); } function sortDatesDescending(a, b) { return b.valueOf() - a.valueOf(); }
function sortLinkDatesAscending(obj1, obj2) {
return obj1.date.valueOf() - obj2.date.valueOf();
}
function sortLinkDatesDescending(obj1, obj2) {
return obj2.date.valueOf() - obj1.date.valueOf();
}
var history = {
items: []
};
// Get each anchor and retrieve its date and link. Add to an object and add that object to the history's array Sort by ascending. Add to local storage.
$('ul > li > a').click(function(e) {
var date = $(this).attr('data-date');
var listData = {
link: $(this).attr("href"),
date: date
};
history.items.push(listData);
window.localStorage.setObject("history", history);
});
/* Remove items from local storage */
$('#clearHistory').click(function() {
window.localStorage.clear();
});
/* Retrieve items from local storage and add to stored history unordered list */
$('#showHistory').click(function() {
console.log(window.localStorage);
var listHistory = localStorage.getObject('history');
var counter = 1;
for (var i = 0; i < listHistory.items.length; i++) {
$("#storedHistory").append('<li>' + counter + '. Link: ' + listHistory.items[i].link + '<br>' + 'Date: ' + listHistory.items[i].date + '</li>');
counter++;
}
});
});
And here is the jsfiddle: https://jsfiddle.net/fLLsfd5j/2/
Try this for sorting! (http://trentrichardson.com/2013/12/16/sort-dom-elements-jquery/)
var $history = $('#history li'),
$historyA = $history.children();
$historyA.sort(function (a, b) {
var an = Date.parse(a.getAttribute('data-date')).valueOf(),
bn = Date.parse(b.getAttribute('data-date')).valueOf();
if (an > bn) {
return 1;
}
if (an < bn) {
return -1;
}
return 0;
});
$('#history').empty();
$.each($historyA, function () {
$('#history').append($('<li>').html(this));
});
I guess this should do your job
function getHistory(){
var as = document.querySelectorAll(".date"); // get elements with date class
Array.prototype.map.call(as, e => e.cloneNode(true)) //clone them into an array and sort
.sort((p,c) => Date.parse(p.dataset.date)<=Date.parse(c.dataset.date) ? -1 : 1)
.forEach((e,i) => as[i].parentNode.replaceChild(e, as[i]));
}
showHistory.onclick = getHistory; //add "click" eL to the DOM element with showHistory id
http://jsbin.com/yoraqusora/2/edit?js,console,output

Creating search bar

I am trying to make a pure JavaScript search box. I want it to search very loosely, i.e. it shouldn't be case sensitive, it shouldn't take spaces into account, etc.
I came upon this codepen, which has what I'm looking for, but it's written using JQuery. I'm trying to convert it to JavaScript only, but I'm having trouble doing it.
My question isn't on the animation, it's on the bare minimum search code. So basically here's the only part I need help with:
$.extend($.expr[':'], {
'containsi': function(elem, i, match, array) {
return (elem.textContent || elem.innerText || '').toLowerCase()
.indexOf((match[3] || "").toLowerCase()) >= 0;
}
});
var searchSplit = searchTerm.replace(/ /g, "'):containsi('")
$("#list li").not(":containsi('" + searchSplit + "')").each(function(e) {
$(this).addClass('hidden');
});
$("#list li:containsi('" + searchSplit + "')").each(function(e) {
$(this).removeClass('hidden');
});
I got the JavaScript equivalent of JQuery's extend which is in the JSFiddle bellow.
JSFiddle
$(document).ready(function() {
// My JavaScript code
var input = document.getElementById('search-text');
input.addEventListener("keyup", function() {
var searchTerm = input.value,
listItem = document.getElementsByClassName('searchArray');
// JavaScript equivalent of jQuery's extend method
function extend(a, b) {
for (var key in b)
if (b.hasOwnProperty(key))
a[key] = b[key];
return a;
}
});
// Bare minimum code from http://codepen.io/robooneus/pen/ivdFH
//we want this function to fire whenever the user types in the search-box
$("#search-text").keyup(function() {
//first we create a variable for the value from the search-box
var searchTerm = $("#search-text").val();
//then a variable for the list-items (to keep things clean)
var listItem = $('#list').children('li');
//extends the default :contains functionality to be case insensitive
//if you want case sensitive search, just remove this next chunk
$.extend($.expr[':'], {
'containsi': function(elem, i, match, array) {
return (elem.textContent || elem.innerText || '').toLowerCase()
.indexOf((match[3] || "").toLowerCase()) >= 0;
}
}); //end of case insensitive chunk
//this part is optional
//here we are replacing the spaces with another :contains
//what this does is to make the search less exact by searching all words and not full strings
var searchSplit = searchTerm.replace(/ /g, "'):containsi('")
//here is the meat. We are searching the list based on the search terms
$("#list li").not(":containsi('" + searchSplit + "')").each(function(e) {
//add a "hidden" class that will remove the item from the list
$(this).addClass('hidden');
});
//this does the opposite -- brings items back into view
$("#list li:containsi('" + searchSplit + "')").each(function(e) {
//remove the hidden class (reintroduce the item to the list)
$(this).removeClass('hidden');
});
});
});
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="search-text" placeholder="search">
<ul id="list">
<li class="searchArray">Apple pie</li>
<li class="searchArray">Pumpkin pie</li>
<li class="searchArray">Banana-creme pie</li>
<li class="searchArray">Peach-blackberry cobbler</li>
<li class="searchArray">Chocolate-strawberry torte</li>
<li class="searchArray">Chocolate-zucchini cake</li>
<li class="searchArray">Anything involving chocolate and mint</li>
<li class="searchArray">Red-velvet cake</li>
<li class="searchArray">Anything involving fruits that aren't cherries</li>
</ul>
You can use a version of typeahead.js substringMatcher function
var substringMatcher = function(strs, q, cb) {
return (function(q, cb, name) {
var matches, substrRegex;
// an array that will be populated with substring matches
matches = [];
// regex used to determine if a string contains the substring `q`
substrRegex = new RegExp(q, 'i');
// iterate through the pool of strings and for any string that
// contains the substring `q`, add it to the `matches` array
strs.forEach(function(str, i) {
if (substrRegex.test(str)) {
// the typeahead jQuery plugin expects suggestions to a
// JavaScript object, refer to typeahead docs for more info
matches.push(name(str));
}
});
cb(matches);
}(q, cb, function(res) {
return res
}));
};
var elems = document.getElementsByClassName('searchArray');
// My JavaScript code
var listItem = Array.prototype.slice.call(elems);
var list = listItem.map(function(el) {
el.className = el.className + " " + "hidden";
return el.textContent;
})
var input = document.getElementById('search-text');
input.addEventListener("keyup", function() {
var searchTerm = this.value;
if (searchTerm.length === 0) {
listItem.forEach(function(el, i) {
el.className = el.className + " " + "hidden"
});
return false
}
substringMatcher(list, searchTerm, function(results) {
results.forEach(function(value, index) {
if (list.indexOf(value) > -1) {
elems[list.indexOf(value)].className = elems[list.indexOf(value)]
.className.replace("hidden", "");
} else {
listItem.forEach(function(el, i) {
if (i !== list.indexOf(value)) {
el.className = el.className + " " + "hidden";
}
})
}
})
})
});
.hidden {
display: none;
}
<input type="text" id="search-text" placeholder="search">
<ul id="list">
<li class="searchArray">Apple pie</li>
<li class="searchArray">Pumpkin pie</li>
<li class="searchArray">Banana-creme pie</li>
<li class="searchArray">Peach-blackberry cobbler</li>
<li class="searchArray">Chocolate-strawberry torte</li>
<li class="searchArray">Chocolate-zucchini cake</li>
<li class="searchArray">Anything involving chocolate and mint</li>
<li class="searchArray">Red-velvet cake</li>
<li class="searchArray">Anything involving fruits that aren't cherries</li>
</ul>

Add and Remove class to click a dynamic Button

Trying to Add and Remove class to click dynamic Buttons, means this button <button class="one"></button> get class dynamically like this: <button class="one text1">text1</button>
So if button one has class .text1 and by click this add class .hide to list item <li class="text1"> like <li class="text1 show">
Same for button two <button class="two"></button> and by click add class <li class="text2 show">
Note: when click button two, then should remove class .show and add new class .hideto button one.
Main HTML:
<div id="main-id">
<button class="one"></button>
<button class="two"></button>
<ul>
<li>
<!--List 1-->
<div class="label">
text1
</div>
</li>
<li>
<!--List 2 is Same-->
<div class="label">
text1
</div>
</li>
<li>
<!--List 3 is different-->
<div class="label">
text2
</div>
</li>
</ul>
</div>
Script:
$('.label a').each(function() {
var $this=$(this);
$this.closest('li').addClass($this.text());
});
// Combine This
$('button').each(function(){
var liInd = 0;
var cl = '';
var txt = '';
var clses = [];
var ind = $('button').index($(this)) + 1;
$('li').each(function(){
if(clses.indexOf($(this).attr('class')) === -1){
clses.push($(this).attr('class'));
liInd = liInd + 1;
}
if(ind === liInd){
cl = $(this).attr('class');
txt = $(this).find('a').text();
return false; //break
}
});
$('button:nth-child(' + ind + ')').addClass(cl);
$('button:nth-child(' + ind + ')').text(txt);
});
See Example on Fiddle
I have tried this by add/remove class by click function, but problem is Buttons get class dynamically from List items, so I'm not able to target button.
Any suggestion for other way to do this by JS/ Jquery?
Here is an alternative solution
$('button').each(function () {
var liInd = 0;
var cl = '';
var txt = '';
var clses = [];
var ind = $('button').index($(this)) + 1;
$('li').each(function () {
if (clses.indexOf($(this).attr('class')) === -1) {
clses.push($(this).attr('class'));
liInd = liInd + 1;
}
if (ind === liInd) {
cl = $(this).attr('class');
txt = $(this).find('a').text();
return false; //break
}
});
if (txt != '') {
$('button:nth-child(' + ind + ')').addClass(cl);
$('button:nth-child(' + ind + ')').text(txt);
}
});
$('button').click(function () {
if ($(this).attr('class')[0] == 'all') {
showAll();
return false; // end this function
}
var allCls = $(this).attr('class').split(' ');
$('li').each(function () {
if (allCls.indexOf($(this).find('a').text()) > -1) {
$(this).closest('li').removeClass('show').addClass('hide');
} else {
$(this).closest('li').removeClass('hide').addClass('show');
}
});
});
function showAll() {
$('li').removeClass('hide').addClass('show');
}
Fiddle: https://jsfiddle.net/taleebanwar/yaLm4euk/13/
DEMO
$('.label a').each(function () {
var $this = $(this);
$this.closest('li').addClass($this.text());
});
// Combine This
$('button').each(function () {
var liInd = 0;
var cl = '';
var txt = '';
var clses = [];
var ind = $('button').index($(this)) + 1;
$('li').each(function () {
if (clses.indexOf($(this).attr('class')) === -1) {
clses.push($(this).attr('class'));
liInd = liInd + 1;
}
if (ind === liInd) {
cl = $(this).attr('class');
txt = $(this).find('a').text();
return false; //break
}
});
$('button:nth-child(' + ind + ')').addClass(cl);
$('button:nth-child(' + ind + ')').text(txt);
});
$(document).on('click', 'button',function(e){
var textClass = $.grep(this.className.split(" "), function(v, i){
return v.indexOf('text') === 0;
}).join();
console.log(textClass);
$('li').removeClass('show').addClass('hide')
$('li').each(function(){
if($(this).hasClass($.trim(textClass))){
$(this).removeClass('hide').addClass('show');
} else {
$(this).removeClass('show').addClass('hide');
}
})
})
.show{display:list-item;}
.hide{display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="main-id">
<button class="one"></button>
<button class="two"></button>
<ul>
<li>
<!--List 1-->
<div class="label">
text1
</div>
</li>
<li>
<!--List 2 is Same-->
<div class="label">
text1
</div>
</li>
<li>
<!--List 3 is different-->
<div class="label">
text2
</div>
</li>
</ul>
</div>

how to change active tab from code behind?

I create a tab control by javascript, as per the below code. It works well but I want to change it in a way that when I change each tab, the value of asp:HiddenField is set to tab id, and based on the asp:HiddenField, active tab changes. I need this in order to change asp:HiddenField value from code behind so that I can activate tabs from code behind.
<script>
$(document).ready(function () {
var activeTabIndex = -1;
var tabNames = ["tab1", "tab2", "tab3"];
$(".tab-menu > li").click(function (e) {
for (var i = 0; i < tabNames.length; i++) {
if (e.target.id == tabNames[i]) {
activeTabIndex = i;
} else {
$("#" + tabNames[i]).removeClass("active");
$("#" + tabNames[i] + "-tab").css("display", "none");
}
}
$("#" + tabNames[activeTabIndex] + "-tab").fadeIn();
$("#" + tabNames[activeTabIndex]).addClass("active");
var htab = document.getElementById('<%= hfTab.ClientID %>');
htab.value = activeTabIndex;
return false;
});
});
</script>
<asp:HiddenField runat="server" ID="hfTab" Value="1"/>
<div id="tab-container">
<ul class="tab-menu">
<li id="tab1" class="active">Report</li>
<li id="tab2">Manager</li>
<li id="tab3">User</li>
</ul>
<div class="clear"></div>
<div class="tab-top-border"></div>
<div id="tab1-tab">test111111111111
</div>
<div id="tab2-tab">test 222222222222
</div>
<div id="tab3-tab">test 333333333333
</div>
</div>
This a little hackey :) but it works fine. It should be refactored.
$(document).ready(function () {
var tabId = 'tab' + $('#hfTab').attr('value');
setTab(tabId); // intial set
function setTab(tabId) {
var tabId = tabId,
tab = $('#' + tabId + '-tab'),
$allContainers = $('.tab'),
$allTabs = $('.tab-menu li');
$allContainers.hide();
$allTabs.removeClass('active');
$(this).addClass('active');
tab.fadeIn();
var id = $('#hfTab').attr('value');
$('#hfTab').attr({
value: id
});
}
$(".tab-menu").on('click', 'li', function (e) {
e.preventDefault();
var tabId = e.target.id;
setTab(tabId);
});
});
JSFIDDLE

Categories

Resources