Clone and Change on new radio check - javascript

Firstly I don't want to edit the html but use JavaScript/jQuery to achieve this.
One input is selected(checked) by default and in this example 'Express Shipping'. Then all of the html is cloned / copied from within the parent which is < li > that is holding the input. I don't need the < li > copied just the input within it.
This is then placed inside the #dumpinfohere < div >.
I can manage up to this point, however I want it so when I then toggle between both radio buttons, or if I add additional radio buttons then the complete html of that checked input plus it's < li > replaced the #dumpinfohere section.
This is the code I've done to try and achieve this:
JSFiddle. You can view what I've done here.
HTML
<ul id="shipping_method">
<li>
<input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_betrs_shipping_12-1" value="betrs_shipping_12-1" class="shipping_method "> Free Shipping
</li>
<li>
<input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_betrs_shipping_12-2" value="betrs_shipping_12-2" class="shipping_method" checked="checked"> Express Shipping
</li>
</ul>
Javascript
jQuery(document).ready(function($){
var changeShip = function() {
$('#shipping_method input:checked')
.parent()
.clone()
.appendTo(".woocommerce-billing-fields #dumpinfohere");
};
$('#shipping_method input').change(changeShip);
changeShip();
});
CSS
#shipping_method {
float: left; width: 100%;
list-style: none;
padding: 0px;
}
#shipping_method li {
/* display: none; */
float: left; width: 100%;
background: #ccc;
padding: 5px 10px;
}
#shipping_method .red { background: red; }
.woocommerce-billing-fields {
background: #000; color: #fff;
width: 100%; height: 300px;
padding: 5px 10px;
float: left;
}
.woocommerce-billing-fields li { padding: 10px 0px; color: #e024a7; list-style: none; }
.woocommerce-billing-fields li input { display: none; }
However you can see if you toggle between the two radio buttons it doesn't change/replace the text but rather just adds to it?

You just need to add
$("#dumpinfohere").html('');
after
var changeShip = function() {
So your final code would be:
jQuery(document).ready(function($){
var changeShip = function() {
$("#dumpinfohere").html('');
$('#shipping_method input:checked')
.parent()
.clone()
.appendTo(".woocommerce-billing-fields #dumpinfohere");
};
$('#shipping_method input').change(changeShip);
changeShip();
});
Basically, you need to empty the container before appending any new text in it.

Related

How to change elements selected using querySelectorAll

Suppose I have 3 buttons:
.all-buttons{
display:flex;
width: 100%
}
.bttn{
width: 33%
border: none;
background-color: blue;
padding: 20px 20px;
color: white;
}
<html>
<head><title>yes</title></head>
<body>
<div class="all-buttons">
<button class="bttn">BUTTON1</button>
<button class="bttn">BUTTON2</button>
<button class="bttn">BUTTON3</button>
</div>
</body>
</html>
As of my understanding I can use JavaScript const buttons = document.querySelectorAll('bttn'); which will create an array with every element with the class 'bttn'. How do I change the style of a button? For example, say I want to change the background-color of Button2 if I click on it. How do I get Button2 using classes in javascript?
I have tried this:
const buttons = document.querySelectorAll('link');
Array.from(buttons).forEach(el => {
el.addEventListener('click', function(event) {
//code
});
});
My end goal is to create a drop-down menu for each of the buttons but I would like to avoid adding an id for each button.
Any input is appreciated.
For getting elements by className, you have 2 options:
getElementsByClassName (without ".")
const buttons = document.getElementsByClassName('bttn');
querySelectorAll (with ".")
const buttons = document.querySelectorAll('.bttn');
And for changing the style of an element, you can use .style property on that element:
element.style.backgroundColor = 'blue';
So this code will help you:
const buttons = document.querySelectorAll('.bttn');
Array.from(buttons).forEach(el => {
el.addEventListener('click', function(event) {
el.style.backgroundColor = "blue";
});
});
Read more here.
First, document.querySelectorAll('bttn'); will not get elements with class equal to .bttn but it gets the elements with tag name equal to bttn.
You need to add the . like document.querySelectorAll('.bttn');
Then, you need to loop through with forEach and on each button add an event listener with addEventListener method on click, then you can change the color with style or create a class for the color and use classList methods.
const buttons = document.querySelectorAll('.bttn');
buttons.forEach(button => {
button.addEventListener('click', () => {
button.classList.toggle('red');
})
})
.all-buttons{
display:flex;
width: 100%
}
.bttn{
width: 33%
border: none;
background-color: blue;
padding: 20px 20px;
color: white;
}
.red {
background-color: red;
}
<html>
<head><title>yes</title></head>
<body>
<div class="all-buttons">
<button class="bttn">BUTTON1</button>
<button class="bttn">BUTTON2</button>
<button class="bttn">BUTTON3</button>
</div>
</body>
</html>
Hope it helps!
const buttons = document.querySelectorAll('.bttn'); // You must declare element's type; class (.) or id (#).
Array.from(buttons).forEach(el => {
el.addEventListener('click', function(event) {
el.style.color = "red"; // Added the line for changing the style of the button.
});
});
<button class="bttn">BUTTON1</button>
<button class="bttn">BUTTON2</button>
<button class="bttn">BUTTON3</button>
i think you need,
change element using queryseletorall
dropdown menu to each button
without using id to each button
to achieve this try like below,
const nodeList = document.querySelectorAll(".dropbtn");
const submenuList = document.querySelectorAll(".dropdown-content");
//alert(nodeList.length);
for (let i = 0; i < nodeList.length; i++) {
nodeList[i].addEventListener('click', function(event) {
submenuList[i].classList.toggle("show");
});
}
.dropbtn {
background-color: #3498DB;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus {
background-color: #2980B9;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {background-color: #ddd}
.show {display:block;}
<div class="dropdown">
<button class="dropbtn">Dropdown</button>
<div class="dropdown-content">
Link 1
Link 2
Link 3
</div>
</div>
<div class="dropdown">
<button class="dropbtn">Dropdown</button>
<div class="dropdown-content">
Link- 1
Link- 2
Link- 3
</div>
</div>
if any query please comment

Issue with ToDO list app and list item length

I'm working on a Q/A bare bones todolist app and notice that when a list item that is really long is added to the list, it pushes the button out.
Is there a way I can make the LI element larger when the textnode hits the button margin instead of pushing the button out of the LI element. Below is a screenshot. I'll post my source code below, but maybe this is a question that is a quick fix?
My source code can be found here - Issue with floating buttons right of my to do list
A) If I understood you well, you can easily fix it with CSS-Grid:
li {
display: grid;
grid-template-columns: 3fr 100px;
grid-template-areas: 'text button';
}
li > span {
grid-area: text;
}
li > button {
grid-area: button;
height: 30px;
}
https://jsfiddle.net/axqwhj29/
Play with the example linked above resizing the result area to check if that's what you are looking for.
B) Also, but I don't recommend you, if you really don't wanna change your li hight and you have a maximum text width (ex: 25 characters), you can clip parts of your message in a phone vertical view and if the user flips to horizontal show the whole text automatically.
https://jsfiddle.net/qfy3mz01/
Hope this help :)
Okay I have wrapped the text inside the li with span element and and added I add grid display to li and give every element inside the li a width and then I have added word-break: break-word; so the line will break when the text of the span reach the width limit and don't affect the delete button and I've deleted height from li so the li will grow with the lines on it
var addItemButton = document.getElementById('addItem')
var onEnter = document.getElementById('newNote')
//below event listener adds an item to the list on click
addItemButton.addEventListener('click', function() {
let item = document.getElementById('newNote').value
let node = document.createElement("li")
let span = document.createElement("span")
let textnode = document.createTextNode(item)
span.appendChild(textnode)
node.appendChild(span)
if (item) {
document.getElementById('list-body').appendChild(node)
}
let node2 = document.createElement('BUTTON')
let textnode2 = document.createTextNode('Delete')
node2.appendChild(textnode2)
node.appendChild(node2)
node2.addEventListener('click', function() {
node2.parentNode.parentNode.removeChild(node)
});
document.getElementById('newNote').value = ''
});
onEnter.addEventListener('keyup', function(event) {
if (event.keyCode === 13) {
// Cancel the default action, if needed
event.preventDefault();
// Trigger the button element with a click
addItemButton.click();
}
})
function applyButton() { //onload for dummy data or data from db
let getListObjects = document.querySelectorAll("li")
for (let i = 0; i < getListObjects.length; i++) {
let node2 = document.createElement('BUTTON')
let textnode2 = document.createTextNode('Delete')
node2.appendChild(textnode2)
getListObjects[i].appendChild(node2)
let y = getListObjects[i].querySelector('button')
y.addEventListener('click', function() {
y.parentNode.parentNode.removeChild(getListObjects[i])
});
}
}
.container {
height: 100%;
width: 40%;
margin: 0 auto;
}
.container2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
background-color: grey;
border: 1px solid grey;
}
#main-grid {
width: 100%;
}
#newNote {
height: 25px;
}
#inputIdForGrid {
justify-content: left;
align-items: center;
display: flex;
padding-left: 0.3em;
padding-top: 0.5em;
padding-bottom: 0.5em;
}
button {
padding: 10px 18px;
background-color: green;
border: none;
color: white;
font-size: 14px;
align-self: center;
justify-self: end;
}
#addItem {
margin-left: 1em;
padding: 0.5em;
color: white;
font-size: 1.5em;
float: right;
}
ul {
list-style-type: none;
padding: 0px;
margin: 0px;
}
li {
padding: 5px 15px;
display: grid;
grid-template-columns: 2.5fr .5fr;
}
span {
word-break: break-word;
grid-column: 1 / 2;
display: flex;
align-items: center;
}
li:nth-child(2n) {
background-color: grey;
}
li>button {
background-color: red;
}
h1 {
text-align: center
}
<body onload="applyButton()">
<h1>Vanilla JS ToDo List - No Jquery, No Bootstrap</h1>
<div class='container'>
<div id='main-grid'>
<div class="container2">
<div id='inputIdForGrid'>
<input type='text' placeholder="Enter List Items Here" id='newNote'>
</div>
<div>
Hi
</div>
</div>
<ul id='list-body'>
<li><span>run all around town. walk all around town. drive all around town</span></li>
<li><span>Buy Apples</span></li>
<li><span>Hit Gym and Lift Bro</span></li>
<li><span>Stretch</span></li>
</ul>
</div>
</div>
</body>
P.S. I've edited your js code so it will generate span and add the text inside it

Html,css3, jquery how to create on click event

I want to make a button inside auto generated block to change overflow from hidden to auto.
I created recursive responsive auto-grid in Less, css like this:
.container {
.container-fixed();
[class*='col-'] {
float: right;
width: 100%;
}
.make-grid(#container-xs);
.make-grid(#container-sm);
.make-grid(#container-md);
.make-grid(#container-lg);
}
.container-fixed(#gap: #grid-gap-width) {
margin-right: auto;
margin-left: auto;
padding-left: (#gap / 2);
padding-right: (#gap / 2);
}
.generate-columns(#container-width;
#number-cols;
#i: 1) when (#i =< #number-cols) {
.col-#{i} {
#single-width: #container-width / #number-cols - 0.5;
width: #i * #single-width; // 800px
}
.generate-columns(#container-width;
#number-cols;
#i + 1);
}
.make-grid(#container-width) {
#media(min-width: #container-width) {
width: #container-width;
.generate-columns(#container-width, #grid-c);
}
}
[class*='col-'] {
text-align: center;
overflow: hidden;
height: 250px;
background: #color-h;
display: block;
margin: 1px;
color: #color-text;
position: relative;
}
And now I have long text in HTML inside one of blocks no matter which one, eg. col-9 where is part hidden because I used overflow:hidden;.
What I would like to do is to create a button and on click to change from overflow:hidden; to overflow: auto;.
My question is how to do that, to change from hidden to auto, on click and again to return back to previous state on new click.
I tried something like this but that is not good:
Less - >
[class*='col-'] {
text-align: center;
overflow: hidden;
height: 250px;
background: #color-h;
display: block;
margin: 1px;
color: #color-text;
position: relative;
.show {
overflow: auto;
}
}
JS - >
var content = document.getElementsByClassName("[class*='col-']");
var button = document.getElementbyID("show");
button.onclick = function() {
if (content.className == "show") {
content.className= "";
button.inerHTML = "Read";
} else {
content.className="show";
button.inerHTML = "Close";
}
};
html - >
<div class="col-9">
<a id="button-show">Read</a>
<script src="js/read.js"></script>
<p> some long text ........ </p>
</div>
I hope I am clear enough, what I want to do.
<-- language: lang-javascript -->
$("#button-show").click(function(){
$(".col-9").toggleClass("show")
})
<-- -->
so whenever you click the button, it will add or remove the class show on your elements with the col-9 classnames
You should use .toggle() to toggle the contents between show and hide. Here is an example
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
$(document).ready(function(){
$("#button-show").click(function(){
$("#show").toggle();
});
});
[class*='col-'] {
text-align: center;
overflow: hidden;
height: 250px;
background: #color-h;
display: block;
margin: 1px;
color: #color-text;
position: relative;
}
#show {
overflow: auto;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-9">
<a id="button-show">Read</a>
<p id="show"> some long text ........ </p>
</div>
You have multiple problems in your code.
document.getElementsByClassName returns a list of elements (A.K.A. array), so your content.className is wrong as you accesing the array className property (which is non-existant) instead of the className property of each element inside the array. You have to iterate the array and access each element individually. Also, you are not accesing by class, but by selector (There's no class [class*='col-'], but class col-1, col-2, etc...). To select with selectors you have to use querySelector, which selects one element, or querySelectorAll which selects all elements.
Also, to hide an element you don't have to change overflow. overflow is for scrollbars. You have to change the display property to display: none and also as the class show is not a child element, it needs an & character:
[class*='col-'] {
text-align: center;
[...CSS THINGYS...]
position: relative;
&.show { // Note the & before the dot
display: none;
}
}
Your code don't has any jQuery actually. Is plain JS.
Also, the best way to attach events to HTML elements is via addEventListener, so:
var content = document.querySelectorAll("[class*='col-']");
var button = document.getElementbyID("show");
button.addEventListener("click", function() {
var anyShown = false;
content.forEach(function(element) {
if (element.className == "show") {
anyShown = true;
element.className= "";
} else {
element.className="show";
}
});
if (anyShown) {
button.inerHTML = "Read";
} else {
button.inerHTML = "Close";
}
});
If you want it in a more jQuery way you can do this, which do the same as above, but way shorter:
$("#show").on("click", function() {
if ($("[class*='col-']").hasClass("show")) {
$("#show").html("Read");
} else {
$("#show").html("Close");
}
$("[class*='col-']").toggleClass("show");
});
Relevant info:
addEventListener
getelementsbyclassname
querySelector
querySelectorAll
Less "&" operator
jQuery hasClass
jQuery toggleClass
I found solution:
JQ:
$(document).ready(function(){
$("button").click(function(){
$("p3").toggle();
});
});
CSS:
[class*='col-'] {
text-align: center;
overflow:auto;
height: 250px;
background: #color-h;
margin: 1px;
color: #color-text;
position: relative;
.border-radius(10px);
p3 {
margin: 10px ;
padding: 5px;
width: 95%;
text-align: justify;
display: none;
}
}
HTML:
<div class="col-9">
<button>Read</button>
<h1>TITLE</h1>
<p>some tekst.</p>
<p3>Tekst i want to hide ....</p3>
</div>

positioning a button child wihtin a list parent

I am working on a to-do list. Whenever the user enters a new task, it is displayed as a list item. Within the list item I am attempting to position a button element, so that when the user clicks on it, the item can shift into another list - "completed tasks".
I am having a bit of trouble poistioning the button element within the list to suit my requirements. I am trying to posistion it equivalant to "right-aligned", at the end of the list element, so that the button is after the text has finished of the given to-do task (I hope that makes sense!)
HTML:
<div id="incomplete-tasks">
<h4>INCOMPLETE TASKS</h4>
<ul id="task-to-do">
</ul>
</div>
CSS:
ul {
list-style: none;
}
ul li {
position: relative;
margin: auto;
width: 80%;
padding: 10px;
margin-bottom: 10px;
color: white;
border: 1px solid white;
border-radius: 3px;
background-color: #6363B6;
}
li button {
display: block;
width: auto;
padding: 1%;
position: absolute;
margin-left: 80%;
}
JS:
document.getElementById("add").addEventListener("click", function () {
var taskinput = document.getElementById("task").value;
if (taskinput) {
var tasktext = document.createTextNode(taskinput);
var list = document.createElement("li");
list.appendChild(tasktext);
var button = document.createElement("button");
button.innerHTML = "completed";
list.appendChild(button);
document.getElementById("task-to-do").appendChild(list);
document.getElementById("task").value ="";
} else {
alert("Please enter a task");
}
});
Try using this, It may help you:
li button {
display: block;
width: auto;
padding: 1%;
clear:both;
float:right;
}
Try this float property It may help you.

Hold ul visible when parent loses hover (pure css if possible)

I'm quite new with css. I want hold the ul visible when hovering from parent to ul. I don't know how do it.
HTML Markup
<drop-down class="dropdown">
<span>Dropdown menu<i class="fa fa-cog"></i></span>
<ul>
<li>
Github<i class="fa fa-github"></i>
</li>
<li>
BitBucket<i class="fa fa-bitbucket"></i>
</li>
<li>
Dropbox<i class="fa fa-dropbox"></i>
</li>
<li>
Google drive<i class="fa fa-google"></i>
</li>
</ul>
</drop-down>
CSS
drop-down {
background-color: #e9e9e9;
border: 1px solid #d2c2c2;
border-radius: 2px;
display: flex;
flex-flow: column nowrap;
height: 40px;
justify-content: center;
position: relative;
width: 160px;
}
drop-down:hover { cursor: pointer; }
drop-down > span {
align-items: center;
color: #555;
display: flex;
font-family: 'segoe ui';
font-size: .9rem;
justify-content: space-between;
padding: 0px .75rem;
pointer-events: none;
}
drop-down > span > i {
color: inherit;
}
drop-down ul {
background-color: #e9e9e9;
border: 1px solid #d2c2c2;
border-radius: 2px;
box-shadow: 0px 2px 5px 1px rgba(0,0,0,.15);
display: block;
right: 10%;
list-style: none;
padding: .5rem 0;
position: absolute;
opacity: 0;
pointer-events: none;
visibility: hidden;
top: 160%;
transition: all .2s ease-out;
width: 100%;
z-index: 999;
}
drop-down ul > li {
color: #555;
display: block;
}
drop-down ul > li:hover {
background-color: #007095;
color: rgba(255,255,255,.9);
}
drop-down ul > li > a {
align-items: center;
color: inherit;
display: flex;
font-family: 'segoe ui';
font-size: .95rem;
justify-content: space-between;
padding: .5rem .75rem;
text-decoration: none;
}
drop-down ul > li > a > i {
color: inherit;
}
drop-down:focus {
outline: none;
}
drop-down:hover ul {
pointer-events: auto;
opacity: 1;
top: 120%;
visibility: visible;
}
You can see it running at this fiddle: http://jsfiddle.net/vt1y9ruo/1/
I can do it with javascript, but I don't want use it for something small.
Here's a working fiddle: http://jsfiddle.net/vt1y9ruo/8/
It works by inserting an invisible bridge between the button and the list.
drop-down:hover ul, #ulwrap:hover ul {
pointer-events: auto;
opacity: 1;
top:120%;
visibility: visible;
}
#ulwrap {
display: block;
height:0;
width:100%;
position:absolute;
}
drop-down:hover #ulwrap, #ulwrap:hover {
height:100px;
}
if you want to do this using the hover feature of css, the gap between the button and the list is what's killing you. either remove this gap or use js
on a side note there is no harm in using js for something small, this is what its used for, just make it nice and reusable
Well, pure css solution (many thanks #JBux) is a little dirty (mark up). I finally go for JS solution and for this, created a custom tag:
const helper = new Helper(); // helper functions
var ddProto = Object.create(HTMLElement.prototype);
ddProto.properties = {
list: null,
options: null,
value: null,
icon: null,
index: -1,
};
ddProto.initEvents = function() {
var self = this;
// mouse over button
this.addEventListener('mouseover', function(e) {
if(!helper.hasClass(this, 'dropdown-active'))
helper.addClass(this, 'dropdown-active');
});
// mouseleave over button
this.addEventListener('mouseleave', function(e){
var rect = this.getBoundingClientRect();
var left = e.pageX;
var bottom = e.pageY;
// if mouse is out of X axis of button and if mouse is
// out (only of top) of Y axis of button, hide ul
if(left < rect.left || left >= rect.right || bottom < rect.top) {
helper.delClass(this, 'dropdown-active');
}
});
// list loses hover
this.properties.list.addEventListener('mouseleave', function(e) {
if(helper.hasClass(self, 'dropdown-active'))
helper.delClass(self, 'dropdown-active');
});
// elements click
[].forEach.call(this.properties.options, function(e) {
e.addEventListener('click', function(event){
event.preventDefault();
// set the text of selected value to button
helper.text(self.properties.value, e.innerText);
// set the position of selected value
self.properties.index = helper.position(e.parentNode);
// set the <i> class name to the button (fontawesome)
self.properties.icon.className = this.children[0].className;
// hide ul
helper.delClass(self,'dropdown-active');
},true);
});
};
ddProto.value = function() {
return this.properties.value;
};
ddProto.index = function() {
return this.properties.index;
}
ddProto.createdCallback = function() {
this.properties.list = this.querySelector('ul');
this.properties.options = this.querySelectorAll('ul > li > a');
this.properties.value = this.querySelector('span');
this.properties.icon = this.querySelector('span > i');
this.initEvents();
};
document.registerElement('drop-down', {prototype: ddProto});
Working fiddle: http://jsfiddle.net/m2dtmr24/2/
Thank you so much.
The thing you could check is the + selector (more here)
In short it lets you add styles to elements right next to each other. The actual css might look something like this:
.dropdown{
display: none;
}
.button:hover+.dropdown{
display: block;
}
This will only work when .dropdown is directly below .button in the DOM
The animation might be harder, but you could achieve something similar by for example using transition on opacity, and toggle opacity instead of display

Categories