Copy selected <li> to another <ul> with js - javascript

function addSelected(clicked_id) {
// alert(clicked_id);
const ul = document.getElementById("sortable2");
const listItems = ul.getElementsByTagName("li");
// const ul2 = document.getElementById('slottable1');
// Loop through the NodeList object.
for (let i = 0; i <= listItems.length - 1; i++) {
if (listItems[i].className == "selectedli") console.log(listItems[i]);
//need to copy these <li> tags in another <ul> list
}
}
<ul id="slottable">
//need to copy selected <li> here and also remove class from those selected <li> before adding here
</ul>
output of the console:
<li id="pc_103" class="selectedli">B73</li>
<li id="pc_104" class="selectedli">B74</li>
I have successfully printed li which I want to copy to another ul in console logs but not able to find the right code to copy them to my another ul. I also need to remove the class 'selectedli' from the li before adding it to the ul 'slottable'.

It's done by creating dynamic tag inside slottable.
See below example:
const getChild = document.getElementById("sortable2").children;
function addSelected() {
let createUl = document.createElement("ul");
createUl.id = "slottable";
document.getElementById("tagBox").appendChild(createUl);
for (let i = 0; i < getChild.length; i++) {
if (getChild[i].className == "selectedli")
{
var createLi = document.createElement("li");
createLi.id = getChild[i].id
createLi.classList.add(getChild[i].classList);
createLi.innerHTML = getChild[i].textContent;
createUl.appendChild(createLi);
console.log(getChild[i]);
}
}
document.getElementById("sortable2").innerHTML = "";
}
ul
{
list-style: none;
}
#sortable2
{
padding: 10px;
background: red;
width: 30px;
}
#slottable
{
padding: 10px;
background: green;
width: 30px;
}
<body>
<div id="tagBox">
</div>
<ul id="sortable2">
<li id="pc_103" class="selectedli">B73</li>
<li id="pc_104" class="selectedli">B74</li>
</ul>
<input type="button" onclick="addSelected()" value="submit">
</body>

The appendChild() method should work.
Like this:
sortable2.appendChild(selectedli)
To remove classes, use selectedli.classList.remove(selectedli)

You looking for something like that?
It copied from one ul to the new ul and removes the class.
classList.remove and appendChild:
lis.map((el) => {
el.classList.remove('selectedli');
el.innerText += ' (copied and without classs slectedli)'
ul2.appendChild(el)
})
const btn = document.getElementById('transfer');
btn.addEventListener('click', () => {
// copy from slottable to sortable2
const ul = document.getElementById("slottable").children;
const ul2 = document.getElementById("sortable2");
let lis = Object.values(ul);
lis.map((el) => {
el.classList.remove('selectedli');
el.innerText += ' (copied and without classs slectedli)'
ul2.appendChild(el)
})
ul.innerHTML = '';
});
.green {
background: green;
}
.gray {
background: gray;
}
<ul id="slottable" class="gray">
<li id="pc_103" class="selectedli">B73</li>
<li id="pc_104" class="selectedli">B74</li>
</ul>
<ul id="sortable2" class="green"></ul>
<button id="transfer">click </button>

Related

How to change the style element html?

My need to after load page paint over text tag <a> in
, but I've can't this do because of this style
doesn't change the colour. I've don't know how to remove this style. This is what I've tried.
var ParsLocat = window.location.href.replace(window.location.href.substring(0, window.location.href.lastIndexOf('/') + 1), '').split('&');
var ParsRazd = ParsLocat[0].split('=');
var nav = document.getElementById('nav');
navA = nav.getElementsByTagName('li');
for (var i = 0; i < navA.length; i++) {
var navAS = navA[i].children[0].search.split('&')
var navRaz = navAS[0].split('=');
if (ParsRazd[1] == navRaz[1]) {
navA[i].style.cssText = "color:white;";
break;
}
}
.navbar-nav > li > a {
color: #9d9d9d;
}
<ul class="nav navbar-nav" id="nav">
<li ><a >Архивная отчетность</a></li>
<li ><a >Мониторинг</a></li>
</ul>
Where am I doing it wrong?
Thanks.
Since the color of your anchor (a) is set to #9d9d9d, you will need to change the color of your a to white, not your li.
var nav = document.getElementById('nav');
navA = nav.getElementsByTagName('li');
for (var i = 0; i < navA.length; i++) {
navA[i].children[ 0 ].style.color = "white";
break;
}
.navbar-nav > li > a {
color: #9d9d9d;
}
body {
background-color: #000000;
}
<ul class="nav navbar-nav" id="nav">
<li ><a >Архивная отчетность</a></li>
<li ><a >Мониторинг</a></li>
</ul>
change
navA[i].style.cssText = "color:white;";
to
navA[i].children[0].style.color = "white";
.navbar-nav > li {
color: #9d9d9d;
}
it should be
navA[i].children[0].style.cssText = "color:white;";
Try to set the style like this:
navA[i].setAttribute('style', 'color: white;');

How to save results to localStorage

I am new in HTML and jQuery, and this was my first implementation, and I am not sure it's correct, I need your help, I tried to make simple counter to begin counting per click, and to store the results in localStorage, this is all I could do
but it didn't work, may you tell me what I've done wrong?
Thanks
$(function() {
$('.container li').click(function() {
var btn = $(this).attr("data-page");
var element = $('.counter[data-page="' + btn + '"]').html();
element++
$('.counter[data-page="' + btn + '"]').html(element);
localStorage.setItem('save', $('.counter[data-page="' + btn + '"]').html());
if (localStorage.getItem('save')) {
$('.counter[data-page="' + btn + '"]').html(localStorage.getItem('save'));
}
});
});
ul {
padding: 0;
margin: 0;
list-style: none;
}
a {
text-decoration: none;
background: blue;
color: #fff;
padding: 10px;
}
ul li {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="container">
<li data-page="facebook">
4100
</li>
<li data-page="twitter">
4100
</li>
</ul>
You need to init first your buttons with values from localStorage. Then you don't need to retrieve them again, you just need to manipulate the value inside the html and to set the new counter in the localStorage.
Also you need to have one counter by button in your localStorage
// Just to make this snippet work,
// because localStorage is forbiden here
// database = localStorage
database = {
store: {},
getItem: function(key) {
return this.store[key];
},
setItem: function(key, val) {
this.store[key] = val;
},
}
$(function() {
$(".counter").each((_, element) => {
const $btn = $(element);
const key = `save-${$btn.attr("data-page")}`;
$btn.html(database.getItem(key) || 0);
});
$(".container li").click(function() {
const $btn = $(this).find(".counter");
const key = `save-${$btn.attr("data-page")}`;
const counter = (+$btn.html()) + 1;
$btn.html(counter);
database.setItem(key, counter);
});
});
ul {
padding: 0;
margin: 0;
list-style: none;
}
a {
text-decoration: none;
background: blue;
color: #fff;
padding: 10px;
}
ul li {
display: inline-block;
}
<ul class="container">
<li data-page="facebook">
4100
</li>
<li data-page="twitter">
4100
</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You need to load the data from the local storage when the page loads. Right now it only loads after saving, which has no effect.
Each element is also saving to the same part of the local storage, so they will be the same every time the page loads. You need to save to an index based on the data-page.
Here you go with one more solution https://jsfiddle.net/thrh78u0/
$(function() {
$('.container li').click(function() {
var btn = $(this).attr("data-page");
var element = $('.counter[data-page="' + btn + '"]').html();
element++
$('.counter[data-page="' + btn + '"]').html(element);
localStorage.setItem('save' + btn, element);
if (localStorage.getItem('save')) {
$('.counter[data-page="' + btn + '"]').html(localStorage.getItem('save'));
}
});
});
ul {
padding: 0;
margin: 0;
list-style: none;
}
a {
text-decoration: none;
background: blue;
color: #fff;
padding: 10px;
}
ul li {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="container">
<li data-page="facebook">
4100
</li>
<li data-page="twitter">
4100
</li>
</ul>
Hope this will help you.
Try this simple one:
$('.container li').click(function() {
if (localStorage.count) {
localStorage.count++
} else {
localStorage.count = 1;
}
})
Updated script using different variables for different counters. It loads counters values from localStorage or sets them to 0 if not available. It also uses two separate variables to store the values.
I used your code so you can see what is different and what you missed in your solution
$(function() {
var cntfb = localStorage.getItem('save-facebook');
$('.counter[data-page="facebook"]').html(cntfb ? cntfb : 0);
var cnttw = localStorage.getItem('save-twitter');
$('.counter[data-page="twitter"]').html(cnttw ? cnttw : 0);
$('.container li').click(function() {
var btn = $(this).attr("data-page");
var element = $('.counter[data-page="' + btn + '"]').html();
element++;
$('.counter[data-page="' + btn + '"]').html(element);
localStorage.setItem('save-' + btn, $('.counter[data-page="' + btn + '"]').html());
if (localStorage.getItem('save-' + btn)) {
$('.counter[data-page="' + btn + '"]').html(localStorage.getItem('save-' + btn));
}
});
});

dynamically Adding and removing elements based on checkbox values with DOM

I'm just trying to dynamically add to a div within a form depending on which checkboxes are checked. So, I am creating the li tag and then they are added as li elements within an ol parent element so its just a list of values. I do not know what is wrong with my code, I'm not sure how to remove the appropriate value if the relevant checkbox is unchecked, and when I uncheck and then recheck a checkbox, it keeps adding the value over and over again.
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
input {
margin: 18px;
}
#o {
list-style-type: none;
}
.u {
list-style: none;
}
</style>
</head>
<body style="width: 700px">
<div style="float: left; width: 340px; height: 250px; border: 1px solid black; padding: 20px 0 10px 20px;">
<form id="myForm">
<ul class="u">
<li><input id="showAlert1" type="checkbox" name="thing" value="laptop">laptop</li>
<li><input id="showAlert2" type="checkbox" name="thing" value="iphone">iphone</li>
</ul>
</form>
</div>
<div id="myDiv" style="float: right; width: 317px; height: 250px; border: solid black; border-width: 1px 1px 1px 0; padding: 20px 0 10px 20px;">
<ol id="o">
</ol>
</div>
<script>
document.getElementById('myForm').addEventListener('change', function () {
var a = document.getElementsByName('thing');
for (var i = 0; i < a.length; i++) {
if (a[i].checked){
createDynamicElement();
} else if (!a[i].checked){
removeDynamicElement();
}
}
function createDynamicElement(){
var node = document.createElement("LI");
node.setAttribute("id1", "Hey");
var textnode = document.createTextNode(event.target.nextSibling.data);
node.appendChild(textnode);
document.getElementById("o").appendChild(node);
}
function removeDynamicElement() {
document.querySelector("#o li").innerHTML = "";
}
});
</script>
</body>
</html>
It looks like that you are adding an event listener to the form instead of the input elements themselves. I dont think the change event will be fired when an input element in a form changes. (see: https://developer.mozilla.org/en-US/docs/Web/Events/change)
On your event listener, try targeting the input elements themselves.
} else if (!a[i].checked){
removeDynamicElement();
}
...
function removeDynamicElement() {
document.querySelector("#o li").innerHTML = "";
}
Will empty the first or all matches(not sure) but wont remove them. Instead you should give li tags a unique ID and remove them completely via something like:
for (var i = 0; i < a.length; i++) {
if (a[i].checked){
console.log(a[i])
createDynamicElement(a[i].value);
} else if (!a[i].checked){
removeDynamicElement(a[i].value);
}
}
function createDynamicElement(id){
var node = document.createElement("LI");
node.setAttribute("id", id);
var textnode = document.createTextNode(id);
node.appendChild(textnode);
console.log(node)
document.getElementById("o").appendChild(node);
}
function removeDynamicElement(id) {
var target = document.getElementById(id)
target.parentElement.removeChild(target);
}
Or you could clear the ol completely on every change and repopulate it again like:
var a = document.getElementsByName('thing');
document.getElementById("o").innerHTML = null;
for (var i = 0; i < a.length; i++) {
if (a[i].checked){
console.log(a[i])
createDynamicElement(a[i].value);
}
}
function createDynamicElement(id){
var node = document.createElement("LI");
var textnode = document.createTextNode(id);
node.appendChild(textnode);
console.log(node)
document.getElementById("o").appendChild(node);
}
Edit:
A proper FIFO solution:
var a = document.getElementsByName('thing');
for (var i = 0; i < 2; i++) {
var target = document.getElementById(a[i].value);
if (a[i].checked && !target){
createDynamicElement(a[i].value);
} else if ((!a[i].checked) && target){
removeDynamicElement(a[i].value);
}
}
function createDynamicElement(id){
var node = document.createElement("li");
node.setAttribute("id", id);
var textnode = document.createTextNode(id);
node.appendChild(textnode);
document.getElementById("o").appendChild(node);
console.log("a")
}
function removeDynamicElement(id) {
target.parentElement.removeChild(target);
}
});

how to make li (active) and visible on click of its parent li

helo , i just wanted to make my li child visibile on the click of parent li,if you want to check what i want to make check out http://technologyvs.co.uk
go to the what client say section
var selector, elems, makeactive,//this is for li one
childSelector,childElems , makeChildActive;//this is for li two
selector = ".parent li";
elems = document.querySelectorAll(selector);
makeactive = function () {
for (var i = 0; i < elems.length; i++) {
elems[i].classList.remove('active');
this.classList.add('active');
}
}
for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener("mousedown", makeactive);
}
childSelector = ".child li"
childElems = document.querySelectorAll(childSelector);
makeChildActive = function (){
for (var j=0;j<childElems.length;j++){
childElems[j].classList.remove('child-active');
this.classList.add('child-active');
}
}
for(var j=0; j<childElems.length;j++){
childElems[j].addEventListener("mousedown",makeChildActive);
}
li.active{
color: red;
}
.text li{
visibility:visible;
transition: all 1s ease-in-out;
}
li.child-active{
visibility: hidden;
width: 200px;
margin-left: 25px;
font-size: 25px;
}
<!Doctype html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="custom.css" type="text/css">
</head>
<body>
<h1>heloo</h1>
<ul class="parent">
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</ul>
<ul class="child">
<li>text1</li>
<li>text2</li>
<li>text3</li>
<li>text4</li>
</ul>
<script src="custom.js"></script>
</body>
</html>
Heres the simple code to do it, there are probably some edge-cases that I am not looking at but in essence this will do the trick. I added the code to a modified version of yours in the snippet below so you can see it works. I have taken out all the code that was not necessary to show how this works.
// A handler that allows us to remember the 'i' value when executing the click
function eventHandlerClosure(i){
parents[i].addEventListener('click', function(e){
// disable the currently active one
var active = document.querySelector('.child li.active');
// (if there is one)
if(active) active.className = '';
// add the active class to the newly selected child
if(children[i]) children[i].className = 'active';
}, false);
}
// select all parents and children
var parents = document.querySelectorAll('.parent li');
var children = document.querySelectorAll('.child li');
// attach the click events
for(var i = 0; i < parents.length; i++) eventHandlerClosure(i);
function eventHandlerClosure(i){
parents[i].addEventListener('click', function(e){
var active = document.querySelector('.child li.active');
if(active) active.className = '';
children[i].className = 'active';
}, false);
}
var parents = document.querySelectorAll('.parent li');
var children = document.querySelectorAll('.child li');
for(var i = 0; i < parents.length; i++) eventHandlerClosure(i);
.child li { visibility: hidden; }
.child li.active { color: red; visibility: visible; }
<ul class="parent">
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</ul>
<ul class="child">
<li>text1</li>
<li>text2</li>
<li>text3</li>
<li>text4</li>
</ul>

Multiple drop events in HTML5

I'm trying to create a drag and drop feature in HTML5 where I can drag from one list to another. I have one list with draggable items and another list with items that have drop events added. The problem is, regardless of what element I drop onto, the last drop event that was added is the one that gets called.
Thanks for any help or suggestions.
I've included my code below:
<!DOCTYPE html>
<head>
<title>List Conversion Test</title>
<style type="text/css">
#list, #cart {
display: inline;
float: left;
border: 1px solid #444;
margin: 25px;
padding: 10px;
}
#list p {
background-color: #036;
color: #fff;
}
#cart p {
background-color: #363;
color: #fff;
}
.listitem {
}
.listitem_done {
text-decoration: line-through;
}
.product {
background-color: #CCC;
}
.product_over {
background-color: #363;
}
</style>
<script type="text/javascript" src="http://html5demos.com/js/h5utils.js"></script>
</head>
<body>
<article>
<div id="list">
<p>On My List</p>
<ul>
<li class="listitem" id="L001">Shopping List Item #1</li>
<li class="listitem" id="L002">Shopping List Item #2</li>
</ul>
<div id="done">
<p>In My Cart</p>
<ul></ul>
</div>
</div>
<div id="cart">
<p>Cart</p>
<ul>
<li class="product" id="P001">Product #1</li>
<li class="product" id="P002">Product #2</li>
</ul>
</div>
</article>
<script>
// make list items draggable
var list = document.querySelectorAll('li.listitem'), thisItem = null;
for (var i = 0; i < list.length; i++) {
thisItem = list[i];
thisItem.setAttribute('draggable', 'true');
addEvent(thisItem, 'dragstart', function (e) {
e.dataTransfer.effectAllowed = 'copy';
e.dataTransfer.setData('Text', this.id);
});
}
// give products drop events
var products = document.querySelectorAll('li.product'), thisProduct = null;
for (var i = 0; i < products.length; i++) {
thisProduct = products[i];
addEvent(thisProduct, 'dragover', function (e) {
if (e.preventDefault) e.preventDefault();
this.className = 'product_over';
e.dataTransfer.dropEffect = 'copy';
return false;
});
addEvent(thisProduct, 'dragleave', function () {
this.className = 'product';
});
addEvent(thisProduct, 'drop', function (e) {
//alert(thisProduct.id);
if (e.stopPropagation) e.stopPropagation();
var thisItem = document.getElementById(e.dataTransfer.getData('Text'));
thisItem.parentNode.removeChild(thisItem);
thisProduct.className = 'product';
handleDrop(thisItem, thisProduct);
return false;
});
}
// handle the drop
function handleDrop(i, p) {
alert(i.id + ' to ' + p.id);
var done = document.querySelector('#done > ul');
done.appendChild(i);
i.className = 'listitem_done';
}
</script>
</body>
</html>
This is why it's often a bad idea to define functions (such as callback functions) within a loop. You're assigning thisProduct within the loop, but it will be reassigned for the next iteration of the loop. The way your closures are set up, each callback is bound to the same variable thisProduct, and will use the latest value.
One possible fix is to create a new closure where thisProduct is needed such as
(function(thisProduct) {
addEvent(thisProduct, 'drop', function (e) {
//alert(thisProduct.id);
if (e.stopPropagation) e.stopPropagation();
var thisItem = document.getElementById(e.dataTransfer.getData('Text'));
thisItem.parentNode.removeChild(thisItem);
thisProduct.className = 'product';
handleDrop(thisItem, thisProduct);
return false;
});
}(thisProduct));
This jsFiddle seems to work for me now. See here for more explanation.

Categories