I have the following code.Now I am building the list using Jquery. How do I do this using Javascript/JQuery?
Html(raw)after completion should look like this
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul id="listOne">
<li class="columnItem">John</li><!--will be removed and put under CommonLister-->
<li class="columnItem">James</li>
<li class="columnItem">Mary</li><!--will be removed and put under CommonLister-->
</ul>
<ul id="listTwo">
<li class="columnItem">John</li><!--will be removed and put under CommonLister-->
<li class="columnItem">Mark</li>
<li class="columnItem">Mary</li><!--will be removed and put under CommonLister-->
</ul>
<ul id="CommonLister">
<li class="columnItem">John</li>
<li class="columnItem">Mark</li>
</ul>
</div>
Jquery/JavaScrpit
function myFunctioner(){
$(() => {
let names = [];
let nameSet = new Set();
$("li.columnItemer").each((idx, ele) => {
nameSet.add($(ele).html())
});
var $common = $("<ul>").addClass("commmonLister");
nameSet.forEach((name) => {
if ($("li:contains(" + name + ")").length > 1) {
$("li:contains(" + name + ")").remove();
$("<li>").addClass("columnItemer").html(name).appendTo($common);
}
});
$common.appendTo($(".CommonLister"));
});
}
The above code only works if the list already exists on HTML not when dynamically creating the list. I will be building the list by Ajax query. really appreciate in if you guys can show me how to implement the above code dynamically as the list is built on click event.
Here is what I've got. I don't use the new Javascript notation (not really a fan of it), though I'm sure you could transcribe what I've written into ES if you want to keep it consistent in your project.
I took a very similar approach to you, however I did not dynamically create the element. If you know this element will exist on the page anyway, my personal philosophy is just let it exist there and be empty so that you don't have to create it on your own.
If these lists are being loaded dynamically (something I couldn't really test out while using codepen) then put this into a function called after the list elements have been created. Preferably you would simply go through the data when it is loaded and make the applicable DOM changes only once, but sometimes we do what we must
$(function() {
$('#run-code').on('click', function(e) {
e.preventDefault();
//What were you doing? nope.
var currentItems = {}; //Blank object
var $mergeColumn = $('#CommonLister'); //Common list reference
$('.columnItem').each(function(i, el) {
var $el = $(el); //Notation I use to differentiate between the regular HTML Element and jQuery element
if (!currentItems.hasOwnProperty($el.html())) {
//Has this name come up before? if not, create it.
currentItems[$el.html()] = []; //Make it equal to a brand spanking new array
}
currentItems[$el.html()].push(el);
//Add the item to the array
});
$.each(currentItems, function(name, data) {
//Loop through each name. We don't actually use the name variable because we don't care what someone's name is
if (data.length > 1) {
//Do we have more than 1 element in our array? time to move some stuff
$.each(data, function(i, el) {
var $el = $(el); //See note above
if (i == 0) {
//If this is the first element, let's just go ahead and move it to the merge column ul
$el.appendTo($mergeColumn);
} else {
$el.remove(); //Otherwise, we've already got this element so delete this one.
} //end if/else
}); //end $.each(data)
} //end if data.length >1
}); //end $.each(currentItems)
}); //end $.on()
}); //end $()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="run-code" class="btn btn-success">Click Me</button>
<h4>List 1</h4>
<ul id="listOne">
<li class="columnItem">John</li>
<!--will be removed and put under CommonLister-->
<li class="columnItem">James</li>
<li class="columnItem">Mary</li>
<!--will be removed and put under CommonLister-->
</ul>
<h4>List 2</h4>
<ul id="listTwo">
<li class="columnItem">John</li>
<!--will be removed and put under CommonLister-->
<li class="columnItem">Mark</li>
<li class="columnItem">Mary</li>
<!--will be removed and put under CommonLister-->
</ul>
<h4>Common List</h4>
<ul id="CommonLister">
</ul>
Related
I'm trying to clean my html/css. How can I get this Javascript to still work, without inserting the class name in each li element from the ul?
How to make the html more pretty and readable?
const ProfileForm = document.getElementsByClassName('profile_container');
const dash = document.getElementsByClassName('dashboard_buttons');
var index;
var array = [];
for (var i = 0; i < dash.length; i++) {
array.push(dash[i]);
dash[i].onclick = function() {
index = array.indexOf(this);
ProfileForm[index].style.display = "block";
var check = ProfileForm[index];
for (var i = 0; i < ProfileForm.length; i++) {
if (ProfileForm[i].style.display == "block" && ProfileForm[i] != check) {
ProfileForm[i].style.display = "none";
}
}
}
}
<ul>
<li class="dashboard_buttons"><i class="far fa-user"></i>Profile</li>
<li class="dashboard_buttons"><i class="far fa-list-alt"></i>My Properties</li>
<li class="dashboard_buttons"><i class="far fa-money-bill-alt"></i>My Offers</li>
<li class="dashboard_buttons"><i class="fas fa-file-contract"></i>My Utilities & Ejari</li>
<li class="dashboard_buttons"><i class="far fa-heart"></i>Favourite Properties</li>
<li class="dashboard_buttons"><i class="far fa-envelope"></i>Messages</li>
<li class="dashboard_buttons"><i class="fas fa-cogs"></i>Settings</li>
</ul>
A simple document.querySelectorAll("ul li") should work. Be careful however, as this will select all the <li> in your whole document. If you want to select a specific <ul>, give it a class or an ID, and select only this one :
<ul id="myList"><li>...<li></ul>
document.querySelectorAll("ul#myList li")
You can use event delegation to notice all events within some "ancestor" element.
(Using event listeners instead of inline event handlers allows this and also promotes separation of concerns between HTML and JavaScript.)
Since I wasn't sure what you wanted to do in your loop, the demo below just "un-highlights" all the list items (and then highlights whichever one was clicked). See the in-code comments for further explanation.
Does this show you how to accomplish what you're trying to do?
// Identifies the `ul` element, and calls `hightlightItem` when user clicks inside it
const list = document.getElementsByClassName("list")[0];
list.addEventListener("click", highlightItem);
// Defines the listener function
function highlightItem(event){ //Listener can access the triggering event
const clickedThing = event.target; // Event's `target` property is useful
// Makes sure the click was on an `li` element before proceeding
if(clickedThing.tagName.toLowerCase() == "li"){
// Collects the list items
const items = list.querySelectorAll("li");
// Loops through the collection
for(let item of items){
// Changes the classList for the current item in the loop
item.classList.remove("highlight");
// Maybe changes it again before continuing to next item in loop
if(item == event.target){ item.classList.add("highlight"); }
}
}
}
.highlight{ background-color: yellow; }
<ul class="list">
<li>Profile</li>
<li>My Properties</li>
<li>My Offers</li>
</ul>
you can do it by query selector
// Get all 'li' elements in the document with class="example"
var x = document.querySelectorAll("li.example");
Instead of using document.getElementByClassName, use document.querySelectorAll
I have a <ul> of elements like this:
<ul id="task-list">
<li class="task"></li>
<li class="task"></li>
<li class="task"></li>
<li class="task"></li>
</ul>
Every time a .task is changed, added, or removed, I generate the entire <ul> again through a Handlebars template and display it with .html():
function addHTML(allTasks) {
var tasks = compileTemplate(allTasks);
return $('#task-list').html(tasks);
}
function compileTemplate(allTasks) {
var source = $('#task-template').html();
var template = Handlebars.compile(source);
return template({
tasks: allTasks
});
}
The list uses Slip.js for reordering, and new items are added at the top of the list. The height of each item could be anything.
Is it possible to have a CSS animation for new additions where the list "slides down" to pop in the new task, or will I need to change my logic to add each task to an existing list, instead of generating the whole <ul> each time?
You can solve this with some simple jquery functions, although AngularJS would look much cleaner. A little example for adding and removing elements with JSFiddle example.
HTML
<ul id="task-list">
<li class="task"><button class="remove">remove</button>Lorem</li>
<li class="task"><button class="remove">remove</button>Ipsum</li>
<li class="task"><button class="remove">remove</button>Dilor</li>
<li class="task"><button class="remove">remove</button>Test</li>
</ul>
<li class="task" id="hidden-task"><button class="remove">remove</button>Test</li>
<button class="add">add last Child</button>
jQuery
//.remove is class of your remove button, task is the list element
$('.remove', '.task').on('click', function(){
var li = $(this).parent();
li.slideToggle({
'complete':function(){
li.remove()
}
});
})
//use hidden element as dummy
var element = $('#hidden-task');
//cache tasklist
var taskList = $('#task-list');
$('.add').on('click', function(){
//create a deep clone
var clone = element.clone(1,1);
taskList.append(clone);
setTimeout(function(){
clone.slideToggle()
}, 200);
});
var nth = 2;
$('.c2th').on('click', function(){
var clone = element.clone(1,1);
$('li').eq(nth-1).after(clone);
setTimeout(function(){
clone.slideToggle()
}, 200);
});
Well i think .child() function is my problem... But im not sure about this.
I have this in html
<div class="tabs" data-name="1st level tabs">
<ul class="nav">
<li>1st level link</li>
<li>1st level link</li>
</ul>
<ul class="content">
<li>
1st TEXT
<div class="tabs" data-name="2st level tabs">
<ul class="nav">
<li>2nd level link</li>
<li>2nd level link</li>
</ul>
<ul class="content">
</ul>
</div>
</li>
<li>1st TEXT</li>
</ul>
</div>
One element with class "tabs" inside another... ok; in JS:
$(function($) {
var Tabs = function(element,options){
self = this;
self.$element = element;
self.testdrive = function (){
console.log(self.$element.attr("data-name"));
}
self.$element.children(".nav").children("li").children("a").click(function(e){
e.preventDefault();
//Returns EVER 2nd level
self.testdrive();
//Triggering directly a Tabs instance returns EVER 2nd level
$(this).closest(".tabs").data("test.tabs").testdrive();
});
}
//JQuery plugin
$.fn.tabs = function () {
return this.each(function () {
var $this = $(this);
var data = $this.data('test.tabs');
//Creating only one instance of Tabs
if(!data){
data = new Tabs($this);
$this.data('test.tabs',data);
}
});
}
//Adding tabs plugin to all ".tabs"
$(function() {
$('.tabs').each(function(){
$(this).tabs();
});
});
}( jQuery ));
When $(element).tabs() called, creates a instance of function Tabs inside a data attribute test.tabs. If test.tabs has been defined only uses an old instance to preserve it.
To test it, i created a function called testdrive, to print in console "data-name" attribute when .tabs>.nav>li>a has been clicked.
The code works but, in console i receive "2st level tabs" if i clicked on 1st level item.
Is a problem with child() function? Something wrong in my code?
Thanks for help.
The problem is the variable declaration for self, since you haven't used var to declare it is created in the global context. So
var self = this;
also you are setting the data using key test.tabs, but is reading it using key simple.tabs
$(this).closest(".tabs").data("test.tabs").testdrive();
Demo: Fiddle
Also I think you can use self.$element.find(" > .nav > li > a").click(function (e) {}); to register the click handler
<ul id="types" style="list-type:none;">
<li id="categories" style="list-type:none;">1
<ul>
<li style="list-type:none;">1</li><br/>
<li style="list-type:none;">1</li>
</ul>
</li>
<li id="categories" style="list-type:none;">2
<ul>
<li style="list-type:none;">2</li><br/>
<li style="list-type:none;">2</li>
</ul>
</li>
<li id="categories" style="list-type:none;">3
<ul>
<li style="list-type:none;">3</li><br/>
<li style="list-type:none;">3</li>
</ul>
</li>
</ul>
i am moving the li up and down ,when i am doing like this i have written the code for calling one jquery _mouseStop function(event,noPropagation))
in this function i am writing
var tagetNode = this.currentItem[0].parentNode.id
if (this.element[0].id == "categories") {
var targetlistlength = document.getElementById(targetListId).getElementsByTagName("li").length;
// var targetlistlength = this.parentNode.getElementsByTagName("li").length;
var PageIds = "";
for (var i = 0; i < targetlistlength; i++) {
PageIds += document.getElementById(targetListId).getElementsByTagName("li")[i].getAttribute("value") + ",";
}
}
when i am sorting the child li's the above function get called but it is always getting the first child ul of first li length only.. i want the current ul li's length which i am trying to sort
i have tried with the commented line also to get the length of li's but iam getting error as this.parentNode is undefined
anyone please suggest me what can i do
As there is no working demo available, you can check what you get when you use console.log($(this)); inside that function when mouseStop event occurs in console. If you get the expected li in the console then you can executing the following code to get the length of its parent's childs.
alert($(this).parent().children().length);
There mustn't be multiple elements with the same id.
Try to replace them with classes or make them unique.
The if-condition could be the following if you have unique id's (e.g. categories-1, categories-2, ...)
if (this.element[0].id.match("^categories") != null) { ... }
Or if you use classes the if-condition could be:
if (this.element[0].className.match("(^| )categories( |$)") != null) { ... }
This question already has answers here:
How may I sort a list alphabetically using jQuery?
(10 answers)
Closed 5 years ago.
Is it possible to reorder <li> elements with JavaScript or pure jQuery. So if I have a silly list like the following:
<ul>
<li>Foo</li>
<li>Bar</li>
<li>Cheese</li>
</ul>
How would I move the list elements around? Like put the list element with Cheese before the list element with Foo or move Foo to after Bar.
Is it possible? If so, how?
var ul = $("ul");
var li = ul.children("li");
li.detach().sort();
ul.append(li);
This is a simple example where <li> nodes are sorted by in some default order. I'm calling detach to avoid removing any data/events associated with the li nodes.
You can pass a function to sort, and use a custom comparator to do the sorting as well.
li.detach().sort(function(a, b) {
// use whatever comparison you want between DOM nodes a and b
});
If someone is looking to reorder elements by moving them up/down some list one step at a time...
//element to move
var $el = $(selector);
//move element down one step
if ($el.not(':last-child'))
$el.next().after($el);
//move element up one step
if ($el.not(':first-child'))
$el.prev().before($el);
//move element to top
$el.parent().prepend($el);
//move element to end
$el.parent().append($el);
One of my favorite things about jQuery is how easy it is to write tiny little add-ons so quickly.
Here, we've created a small add-on which takes an array of selectors, and uses it to order the children of the target elements.
// Create the add-on
$.fn.orderChildren = function(order) {
this.each(function() {
var el = $(this);
for(var i = order.length - 1; i >= 0; i--) {
el.prepend(el.children(order[i]));
}
});
return this;
};
// Call the add-on
$(".user").orderChildren([
".phone",
".email",
".website",
".name",
".address"
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="user">
<li class="name">Sandy</li>
<li class="phone">(234) 567-7890</li>
<li class="address">123 Hello World Street</li>
<li class="email">someone#email.com</li>
<li class="website">https://google.com</li>
</ul>
<ul class="user">
<li class="name">Jon</li>
<li class="phone">(574) 555-8777</li>
<li class="address">123 Foobar Street</li>
<li class="email">jon#email.com</li>
<li class="website">https://apple.com</li>
</ul>
<ul class="user">
<li class="name">Sarah</li>
<li class="phone">(432) 555-5477</li>
<li class="address">123 Javascript Street</li>
<li class="email">sarah#email.com</li>
<li class="website">https://microsoft.com</li>
</ul>
The function loops backwards through the array and uses .prepend so that any unselected elements are pushed to the end.
Here is a jQuery plugin to aid with this functionality: http://tinysort.sjeiti.com/
something like this?
var li = $('ul li').map(function(){
return this;
}).get();
$('ul').html(li.sort());
demo
I was somewhat lost you may be wanting something like this...
$('ul#list li:first').appendTo('ul#list'); // make the first to be last...
$('ul#list li:first').after('ul#list li:eq(1)'); // make first as 2nd...
$('ul#list li:contains(Foo)').appendTo('ul#list'); // make the li that has Foo to be last...
more of it here1 and here2
Have a look at jquery ui sortable
http://jqueryui.com/demos/sortable/