Change checkbox tickmark color - javascript

I've implemented a function to change the background color of my checkbox , but it makes the tickmark turns to color black which I don't want , I want the mark to still white , how can I achieve this ?
HTML :-
<div v-for="category in categories" :key="category.id">
<div>
<input type="checkbox" class="categoryInput" #change="input()"
:true-value="category.id" false-value="0" v-model="currentCategory"/>
<label class="form-label">{{category.name}}</label>
</div>
</div>
here's the function :-
input(){
var color = JSON.parse(localStorage.getItem('coloring') || '[]').CTAButtons
let collection = document.getElementsByClassName("categoryInput");
for (let i = 0; i < collection.length; i++) {
collection[i].style.accentColor = color
}
}
and here's the output :-
the background changed successfully but the tickmark changed to color black

The tickmark color for the default HTML checkbox is decided by the browser and cannot be changed. You can however create your own custom checkbox and style it however you want.
HTML
<label class="container">
<input type="checkbox" checked="checked" />
<span class="checkmark"></span>
</label>
CSS
.container {
display: block;
position: relative;
padding-left: 35px;
margin-bottom: 12px;
cursor: pointer;
font-size: 22px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* Hide the browser's default checkbox */
.container input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
/* Create a custom checkbox */
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 25px;
width: 25px;
background-color: #eee;
}
/* On mouse-over, add a grey background color */
.container:hover input ~ .checkmark {
background-color: #ccc;
}
/* When the checkbox is checked, add a teal background */
.container input:checked ~ .checkmark {
background-color: #3bb0a8;
}
/* Create the checkmark/indicator (hidden when not checked) */
.checkmark:after {
content: '';
position: absolute;
display: none;
}
/* Show the checkmark when checked */
.container input:checked ~ .checkmark:after {
display: block;
}
/* Style the checkmark/indicator */
.container .checkmark:after {
left: 9px;
top: 5px;
width: 5px;
height: 10px;
border: solid white;
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
JSFiddle

The advantage of going with vue is to build custom components. So you can try something as shown below.
Working StackBlitz
You might want to tweak your code depending on your exact requirement.
<template>
<div v-for="category in categories" :key="category.id">
<div>
<label class="form-label categoryInput">
<span class="material-icons icon" v-if="isChecked(category.id)"
>check_box</span
>
<span
class="material-icons-outlined icon"
v-if="!isChecked(category.id)"
>check_box_outline_blank</span
>
<input
type="checkbox"
class=""
#change="input()"
:value="category.id"
v-model="currentCategory"
/>
{{ category.name }}</label
>
</div>
</div>
</template>
<script>
export default {
name: 'Checkbox',
data: function () {
return {
currentCategory: [],
categories: [
{ id: 1, name: 'alpha' },
{ id: 2, name: 'beta' },
],
};
},
props: {},
methods: {
isChecked(categoryId) {
return this.currentCategory.indexOf(categoryId) !== -1;
},
input() {
var color = '#3bb0a8';
let collection = document.getElementsByClassName('categoryInput');
for (let i = 0; i < collection.length; i++) {
const icons = collection[i].querySelectorAll('.icon');
icons.forEach((iconEle) => {
iconEle.style.color = color;
});
}
},
},
};
</script>
<style scoped>
label.categoryInput {
display: flex;
justify-content: center;
align-items: center;
}
label.categoryInput input[type='checkbox'] {
width: 0;
height: 0;
}
</style>
Important
Add below to your index.html header
<link href="https://fonts.googleapis.com/css?family=Material+Icons|Material+Icons+Outlined|Material+Icons+Two+Tone|Material+Icons+Round|Material+Icons+Sharp" rel="stylesheet">

Related

Changing background color doesn't work well

I am trying to change the background color of my webpage using a hamburger menu. There are 4 color options on my hamburger menu. I managed to get a change on the background when clicking on the color of my choice. But that change only happens once. When I clicked another color and come back to click that same color from earlier on, it doesn't respond. The color seems to change only once, and not more than that.
The repository to my GitHub code is here: https://github.com/tand100b/Winc_Academy
const changeColorButton1 = document.getElementById("color1");
changeColorButton1.addEventListener("click", function() {
changeClassRedBackground();
});
const changeColorButton2 = document.getElementById("color2");
changeColorButton2.addEventListener("click", function() {
changeClassOrangeBackground();
});
const changeColorButton3 = document.getElementById("color3");
changeColorButton3.addEventListener("click", function() {
changeClassPurpleBackground();
});
const changeColorButton4 = document.getElementById("color4");
changeColorButton4.addEventListener("click", function() {
changeClassGreenBackground();
});
const changeClassRedBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("red-background");
}
const changeClassOrangeBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("orange-background");
};
const changeClassPurpleBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("purple-background");
};
const changeClassGreenBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("green-background");
};
body {
background-color: pink;
}
.red-background {
background-color: red;
}
.orange-background {
background-color: orange;
}
.purple-background {
background-color: purple;
}
.green-background {
background-color: green;
}
.btn-toggle-nav {
width: 60px;
height: 20%;
background-color: #f98f39;
background-image: url("https://i.stack.imgur.com/tniUv.png");
background-repeat: no-repeat;
background-size: 60%;
background-position: center;
cursor: pointer;
}
.btn-toggle-nav:hover {
opacity: 0.5;
}
.navbar ul {
padding-top: 15px;
/* visibility: hidden; */
}
.navbar ul li {
line-height: 60px;
list-style: none;
background-color: white;
width: 300px;
padding-top: 0px;
padding-top: 0px;
}
.navbar ul li a {
display: block;
height: 60px;
padding: 0 10px;
text-decoration: none;
font-family: arial;
font-size: 16px;
}
.navbar {
background-color: red;
width: 50px;
padding: 0 5px;
height: calc(100vh-60px);
z-index: 1000;
}
.list {
margin-top: 0px;
}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<div class="btn-toggle-nav"></div>
<aside class="navbar">
<ul class="list">
<li><a id="color1" href="#">Red</a></li>
<li><a id="color2" href="#">Orange</a></li>
<li><a id="color3" href="#">Purple</a></li>
<li><a id="color4" href="#">Green</a></li>
</ul>
</aside>
Can someone please look at my code and suggest what I can do?
Firstly, I suggest declaring variable bodyElement only once at the top of the file because each time it would be the same body element:
const bodyElement = document.body
Next, we create function that will check if body has any style classes in its classList. If it's not empty (length more than one) we remove all classes, and do nothing otherwise:
const isBodyHasStyle = () => bodyElement.classList.length ? bodyElement.classList = '' : null
Then, on each button click we going to call our new function:
changeColorButton1.addEventListener("click", function() {
isBodyHasStyle()
changeClassRedBackground();
});
Do the same with other buttons.
You need to make sure that you don't have multiple classes conflicting with each other, also try to DRY your code, here is an alternative I came up with:
const changeColor = (e) => {
const bodyElement = document.querySelector('body');
const colorIdMap = {
"color1": "red-background",
"color2": "orange-background",
"color3": "purple-background",
"color4": "green-background"
}
bodyElement.className = colorIdMap[e.target.id];
}
const btns = document.querySelectorAll('.list li');
btns.forEach(btn => btn.addEventListener('click', changeColor))
An easier way to accomplish this is by setting a data attribute on the background, based on the selected color. Just add a color data value to each of the menu items and set the body background to that color.
const toggleMenu = (event) => {
event.target.closest('.navbar').classList.toggle('open');
};
const changeColor = (event) => {
document.body.dataset.background = event.target.dataset.color;
toggleMenu(event); /* do not call ~ to stay open */
};
document.querySelector('.btn-toggle-nav')
.addEventListener('click', toggleMenu)
document.querySelectorAll('.color-picker')
.forEach(e => e.addEventListener('click', changeColor));
/* CSS reset */
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
body { display: flex; background-color: #222; }
ul { list-style-type: none; margin: 0; }
body[data-background="red"] { background-color: red }
body[data-background="orange"] { background-color: orange }
body[data-background="purple"] { background-color: purple }
body[data-background="green"] { background-color: green }
body[data-background="default"] { /* Do not set the background-color */ }
a[data-color="red"] { color: red; }
a[data-color="orange"] { color: orange; }
a[data-color="purple"] { color: purple; }
a[data-color="green"] { color: green; }
a[data-color="default"] { color: #222; }
.list {
position: absolute;
display: none; /* hide menu (default) */
flex-direction: column;
gap: 0.5em;
padding: 0.5em;
width: 6em;
left: 2em;
background: #444;
}
.list li a { text-decoration: none; font-weight: bold; }
.list li a:hover { text-decoration: underline; }
.navbar {
position: relative;
width: 2em;
background-color: #444;
}
.navbar.open .list {
display: flex; /* show menu */
}
.btn-toggle-nav {
width: 2em;
height: 2em;
background-image: url("https://i.stack.imgur.com/tniUv.png");
background-repeat: no-repeat;
background-size: 60%;
background-position: center;
cursor: pointer;
}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<aside class="navbar">
<div class="btn-toggle-nav"></div>
<ul class="list">
<li><a class="color-picker" href="#" data-color="red">Red</a></li>
<li><a class="color-picker" href="#" data-color="orange">Orange</a></li>
<li><a class="color-picker" href="#" data-color="purple">Purple</a></li>
<li><a class="color-picker" href="#" data-color="green">Green</a></li>
<li><a class="color-picker" href="#" data-color="default">Default</a></li>
</ul>
</aside>

v-calendar datepicker date range event after first date is picked

Is there a way of triggering an event for the date range picker of v-calendar after the first date is picked or stopping the inputs from adding the dates until both dates have been selected?
I have the following vue component:
new Vue({
el: "#app",
data() {
return {
range: {
start: null,
end: null
}
};
},
methods: {
handleBlur(event) {
if (event.currentTarget.value === '') {
event.currentTarget.parentNode.classList.remove("entered");
}
},
handleFocus(event) {
event.currentTarget.parentNode.classList.add("entered");
},
moveLabels() {
changeClass(this.$refs.filterDateForm);
changeClass(this.$refs.filterDateTo);
}
}
});
function changeClass(input) {
if (input.value === '') {
input.parentNode.classList.remove("entered");
} else {
input.parentNode.classList.add("entered");
}
}
#import url 'https://unpkg.com/v-calendar#2.3.4/lib/v-calendar.min.css';
.filter__date-range-holder {
display: flex;
justify-content: space-between;
width: 95%;
}
.filter__date-range-column {
width: calc(50% - 15px);
}
.form__row {
position: relative;
margin: 1.5em 0;
background: white;
}
.form__control {
width: 100%;
border: 1px solid grey;
font-size: 1rem;
line-height: 1.5rem;
color: black;
padding: 0.75em;
background: transparent;
}
.invalid .form__control {
border-color: red;
outline-color: red;
}
.form__control:focus {
border-radius: 0;
}
.form__label {
display: inline-block;
position: absolute;
top: 50%;
left: calc(0.75em + 1px);
transform: translateY(-50%);
z-index: 1;
color: black;
background: white;
transition: all 0.25s ease-in-out;
pointer-events: none;
}
.entered .form__label {
top: 0;
left: 0.5rem;
font-size: 0.6875rem;
line-height: 0.6875rem;
padding: 0.2em;
}
.invalid .form__label {
color: red;
}
<script src="https://unpkg.com/vue#2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/v-calendar#2.3.4/lib/v-calendar.umd.min.js"></script>
<div id='app'>
<v-date-picker v-model="range" :popover="{ visibility: 'focus' }" is-range #input="moveLabels">
<template #default="{ inputValue, inputEvents }">
<div class="filter__date-range-holder">
<div class="filter__date-range-column">
<div class="form__row filter__date-range-row">
<label class="form__label filter__date-range-label" for="filter-date-from">From</label>
<input id="filter-date-from" ref="filterDateForm" type="text" name="from" class="form__control form__control--textbox" :value="inputValue.start" v-on="inputEvents.start" #focus="handleFocus" #blur="handleBlur">
</div>
</div>
<div class="filter__date-range-column">
<div class="form__row filter__date-range-row">
<label class="form__label filter__date-range-label" for="filter-date-to">To</label>
<input id="filter-date-to" ref="filterDateTo" type="text" name="to" class="form__control form__control--textbox" :value="inputValue.end" v-on="inputEvents.start" #focus="handleFocus" #blur="handleBlur">
</div>
</div>
</div>
</template>
</v-date-picker>
</div>
As you can see, the label starts off inside the textbox and animates to the top on focus or if there is a value in the input. However, with the date range picker, as soon as you select the first date, it updates both inputs with the selected date and so my label is over the value.
I have tried setting the #input event of the date picker and putting a watch on the range variable, but both only fire once both dates have been selected so I can only move my labels after the second date is selected.
I have also tried adding an #change event to the inputs, but as the value is only change via js, the change event is not picked up
In the end I solved this by doing the following:
Add an #input event to handle when date range is selected properly
Add a #dayclick event to add the entered class when a day is selected
Add a timeout to the handleBlur method (the #dayClick event seemed to take a bit of time to fire so the blur animation started before it kicked in)
Add a mutation observer to see if the calendar closes - as the calendar doesn't have a close event, I needed to see if the calendar was closed without valid date range selected - if this happened and the inputs were emptied, this observer removed the entered class
new Vue({
el: "#app",
data() {
return {
range: {
start: null,
end: null
}
};
},
mounted() {
const overlay = document.querySelector('.filter__overlay');
const config = {
attributes: false,
childList: true,
subtree: true
};
// watch to see if calendar is closed
const observer = new MutationObserver(mutationsList => {
mutationsList.forEach(mutation => {
if (mutation.type === 'childList' &&
mutation.removedNodes.length > 0 &&
mutation.removedNodes[0].classList &&
mutation.removedNodes[0].classList.contains('vc-popover-content')) {
removeClass(this.$refs.filterDateForm);
removeClass(this.$refs.filterDateTo);
}
});
});
observer.observe(overlay, config);
},
methods: {
handleBlur(event) {
const input = event.currentTarget;
setTimeout(() => {
removeClass(input);
}, 150);
},
handleFocus(event) {
event.currentTarget.parentNode.classList.add("entered");
},
handleCalendarBlur() {
changeClass(this.$refs.filterDateForm);
changeClass(this.$refs.filterDateTo);
},
handleCalendarClick() {
this.$refs.filterDateForm.parentNode.classList.add("entered");
this.$refs.filterDateTo.parentNode.classList.add("entered");
},
}
});
function removeClass(input) {
if (input.value === '') {
input.parentNode.classList.remove("entered");
}
}
function changeClass(input) {
if (input.value === '') {
input.parentNode.classList.remove("entered");
} else {
input.parentNode.classList.add("entered");
}
}
#import url 'https://unpkg.com/v-calendar#2.3.4/lib/v-calendar.min.css';
.filter__date-range-holder {
display: flex;
justify-content: space-between;
width: 95%;
}
.filter__date-range-column {
width: calc(50% - 15px);
}
.form__row {
position: relative;
margin: 1.5em 0;
background: white;
}
.form__control {
width: 100%;
border: 1px solid grey;
font-size: 1rem;
line-height: 1.5rem;
color: black;
padding: 0.75em;
background: transparent;
}
.invalid .form__control {
border-color: red;
outline-color: red;
}
.form__control:focus {
border-radius: 0;
}
.form__label {
display: inline-block;
position: absolute;
top: 50%;
left: calc(0.75em + 1px);
transform: translateY(-50%);
z-index: 1;
color: black;
background: white;
transition: all 0.25s ease-in-out;
pointer-events: none;
}
.entered .form__label {
top: 0;
left: 0.5rem;
font-size: 0.6875rem;
line-height: 0.6875rem;
padding: 0.2em;
}
.invalid .form__label {
color: red;
}
<script src="https://unpkg.com/vue#2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/v-calendar#2.3.4/lib/v-calendar.umd.min.js"></script>
<div id='app'>
<div class="filter__overlay">
<v-date-picker v-model="range" :popover="{ visibility: 'focus' }" is-range #input="handleCalendarBlur" #dayclick="handleCalendarClick">
<template #default="{ inputValue, inputEvents }">
<div class="filter__date-range-holder">
<div class="filter__date-range-column">
<div class="form__row filter__date-range-row">
<label class="form__label filter__date-range-label" for="filter-date-from">From</label>
<input id="filter-date-from" ref="filterDateForm" type="text" name="from" class="form__control form__control--textbox" :value="inputValue.start" v-on="inputEvents.start" #focus="handleFocus" #blur="handleBlur">
</div>
</div>
<div class="filter__date-range-column">
<div class="form__row filter__date-range-row">
<label class="form__label filter__date-range-label" for="filter-date-to">To</label>
<input id="filter-date-to" ref="filterDateTo" type="text" name="to" class="form__control form__control--textbox" :value="inputValue.end" v-on="inputEvents.start" #focus="handleFocus" #blur="handleBlur">
</div>
</div>
</div>
</template>
</v-date-picker>
</div>
</div>
Please note this example works differently to the one in my site - for some reason the one in my site will remove the dates from the inputs if only one date is selected - this one seems to keep it

Requesting assistance troubleshooting HTML forms/cards

I am currently working on an exercise in HTML/CSS/JS. The premise is a library website. The idea is that I have a collapsable form that when deployed allows the user to enter the title of the book, the author, and page numbers. When submit is clicked it takes the user input and generates a html card on the webpage. This title card will display the user input information along with a slider to denote if it was read or not.
I have a few test cards generated in my code that creates the cards as intended, however when utilizing the html form i can not seem to get additional cards to create. I ran some tests to the console to ensure that the form is in fact capturing the user input and assigning it.
If anyone could point me in the right direction that would be amazing. I have been messing with this issue for almost 2 weeks with no luck. I have a feeling that my "wires" are not connected right in the javascript. Thank you in advance.
Javascript:
// set up library
let myLibrary = [];
//set up object
function Book(title, author, pages) {
this.title = title;
this.author = author;
this.pages = pages;
}
//add object to library
function addBookToLibrary(Book){
myLibrary.push(Book);
}
//test books
const lotr = new Book('The Fellowship of the Ring', 'J.R.R. Tolkein', '423 pages');
const ender = new Book('Enders Game', 'Orson Scott Card', '324 pages');
const martian = new Book('The Martian', 'Anthony Weir', '369 pages');
addBookToLibrary(lotr);
addBookToLibrary(ender);
addBookToLibrary(martian);
//inject html to create cards
let htmlCode = ``;
myLibrary.forEach(function(singleBookObjects){
htmlCode =
htmlCode +
`
<entry>
<div>
<h3>Title: ${singleBookObjects.title}</h3>
<h3>Author: ${singleBookObjects.author}</h3>
<h3>Pages: ${singleBookObjects.pages}</h3>
<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>
</div>
</entry>
`;
});
function newBookCard() {
let newdiv = document.createElement('div');
newdiv.className+= 'item';
let newp = document.createElement('p');
newp.innerHTML = "Title";
newdiv.appendChild(newp);
document.getElementById('main').appendChild(newdiv);
}
const addBtn = document.getElementById("submit");
addBtn.onclick = function() {
let a = document.getElementById("bookTitle").value
let b = document.getElementById("bookAuthor").value
let c = document.getElementById("bookPages").value
let newBook = new Book(a, b, c);
addBookToLibrary(newBook);
console.log(myLibrary);
newBookCard();
document.getElementById("bookTitle").value = ""
document.getElementById("bookAuthor").value = ""
document.getElementById("bookPages").value = ""
}
const bookCards = document.querySelector(".all-book-cards");
bookCards.innerHTML = htmlCode;
function openForm() {
document.getElementById("myForm").style.display = "block";
}
function submitForm(){
let a = document.getElementById("bookTitle")
}
function closeForm() {
document.getElementById("myForm").style.display = "none";
}
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Library</title>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id = "container" img src="images/bookShelf.jpeg">
<div id = "titleCard"> My Library</div>
<div class = "all-book-cards"></div>
<button class="open-button" onclick="openForm()">Add Book</button>
<div class="form-popup" id="myForm">
<form action="index.html" class="form-container">
<h1>Add Book</h1>
<label for="bookTitle"><b>Title:</b></label>
<input id="bookTitle" type="text" placeholder="Enter Title" name="bookTitle" required>
<label for="bookAuthor"><b>Author:</b></label>
<input id="bookAuthor" type="text" placeholder="Enter Author" name="bookAuthor" required>
<label for="bookPages"><b>Pages:</b></label>
<input id="bookPages" type="text" placeholder="Enter Pages" name="bookPages" required>
<button id="submit" type="button" class="btn">Add</button>
<button type="button" class="btn cancel" onclick="closeForm()">Close</button>
</form>
</div>
</div>
<script src ="script.js"></script>
</body>
</html>
CSS
.all-book-cards{
width: 20em;
display: flex;
flex-direction: column;
}
entry {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
border: black;
border-width: 3px;
border-style: groove;
padding-left: 5px;
padding-right: 5px;
margin-bottom: 2px;
}
{box-sizing: border-box;}
.open-button {
background-color: #555;
color: white;
padding:16px 20px;
border: none;
cursor: pointer;
opacity: 0.8;
position: fixed;
bottom: 23px;
right: 28px;
width: 90px;
}
.form-popup {
display: none;
position: fixed;
bottom: 0;
right: 15px;
border: 3px solid #f1f1f1;
z-index: 9;
}
.form-container {
max-width: 300px;
padding: 10px;
background-color: white;
}
.form-container input[type=text] {
width: 100%;
padding: 15px;
margin: 5px 0 22px 0;
border: none;
background: #f1f1f1;
}
.form-container input[type=text]:focus {
background-color: rgb(161, 161, 161);
outline: none;
}
.form-container .btn {
background-color: #04AA6d;
color: white;
padding: 16px 20px;
border: none;
cursor: pointer;
width: 100%;
margin-bottom: 10px;
opacity: 0.8;
}
.form-container .cancel {
background-color: red;
}
.form-container .btn:hover, .open-button:hover {
opacity: 1;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
There is a few issues with your code, but the main reason you don't see any changes in the DOM is that you try to find an element by id "main", but no such element is defined.
So step one is putting an id on the element containing your books:
<div id="main" class="all-book-cards"></div>
Another issue is that you change the DOM in different ways on many places in your javascript code which makes it harder to figure out what's going on. You could change the addBookToLibrary to actually add elements to the DOM aswell. To ensure consistency with the initial books you create in the foor loop, I have changed the addBookToLibrary to handle the entire creation and removed the for loop.
//add object to library
function addBookToLibrary(Book){
myLibrary.push(Book);
let html = `
<entry>
<div>
<h3>Title: ${Book.title}</h3>
<h3>Author: ${Book.author}</h3>
<h3>Pages: ${Book.pages}</h3>
<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>
</div>
</entry>
`;
var newEl = document.createElement("template");
newEl.innerHTML = html.trim();
document.getElementById('main').appendChild(newEl.content.firstChild);
}
Below is a CodePen for the full example.
https://codepen.io/rasm586c/pen/PoKdNdd

How do I manipulate the same function in javascript for two different classes

I have to use two different sizes of checkbox on the same page. I will determine which size to use based on the checkbox name. If name='room' I will use the big image of class 'custom-checkbox'. Else if name='request', I will use small image of class custom-checkbox2.
Now, how do I modify the below script so that it can determine which class to use based on the name of the checkbox?
CSS:
.custom-checkbox{
width: 50px;
height: 50px;
display: inline-block;
position: relative;
z-index: 1;
top: 3px;
background: url("../img/big-check-nopass.png") no-repeat;
}
.custom-checkbox:hover{
background: url("../img/big-check-pass.png") no-repeat;
}
.custom-checkbox.selected{
background: url("../img/big-check-pass.png") no-repeat;
}
.custom-checkbox input[type="checkbox"]{
margin: 0;
position: absolute;
z-index: 2;
cursor: pointer;
outline: none;
opacity: 0;
/* CSS hacks for older browsers */
_noFocusLine: expression(this.hideFocus=true);
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
-khtml-opacity: 0;
-moz-opacity: 0;
}
/* Let's Beautify Our Form */
label{
display: block;
padding: 2px 0;
}
/*for small cehckbox*/
.custom-checkbox2{
width: 20px;
height: 20px;
display: inline-block;
position: relative;
z-index: 1;
top: 3px;
background: url("../img/small-check-nopass.png") no-repeat;
}
.custom-checkbox2:hover{
background: url("../img/small-check-pass.png") no-repeat;
}
.custom-checkbox2.selected{
background: url("../img/small-check-pass.png") no-repeat;
}
.custom-checkbox2 input[type="checkbox"]{
margin: 0;
position: absolute;
z-index: 2;
cursor: pointer;
outline: none;
opacity: 0;
/* CSS hacks for older browsers */
_noFocusLine: expression(this.hideFocus=true);
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
-khtml-opacity: 0;
-moz-opacity: 0;
}
/* Let's Beautify Our Form */
label2{
display: block;
padding: 2px 0;
}
Javascript:
function customCheckbox(checkboxName){
var checkBox = $('input[name="'+ checkboxName +'"]');
$(checkBox).each(function(){
$(this).wrap( "<span class='custom-checkbox'></span>" );
if($(this).is(':checked')){
$(this).parent().addClass("selected");
}
});
$(checkBox).click(function(){
$(this).parent().toggleClass("selected");
});
}
$(document).ready(function (){
customCheckbox("room[]");
})
HTML
<div class="row">
<div class="large-3 right columns">
<label><input type="checkbox" name="room[]" value="" /></label>
</div>
</div>
<div class="row">
<div class="large-3 right columns">
<label><input type="checkbox" name="request[]" value="" /></label>
</div>
</div>
EDIT**
Removed function and modified script:
<script>
$(document).ready(function (){
$("input:checkbox").each(function(){
if($(this).attr("name") == "room[]") {
$(this).wrap( "<span class='custom-checkbox'></span>" );
if($(this).is(':checked')){
$(this).parent().addClass("selected");
}
} else if($(this).attr("name") == "request[]") {
$(this).wrap( "<span class='custom-checkbox2'></span>" );
if($(this).is(':checked')){
$(this).parent().addClass("selected");
}
}
});
})
</script>
You can use the "each" jQuery function, which will check every inputs of the checkbox type on the page. So, you simple get it's name, if it's "room[]", add the custom-checkbox-big-size class to the span wrap, if it's name is "request[]", add the custom-checkbox-small-size class to the span wrap (I changed your CSS to make the things simple).
JS:
var wrapSpan = $('<span class="custom-checkbox-span"</span>');
$('input:checkbox').each(function() {
if ($(this).is(':checked')) {
wrapSpanspan.addClass('checked');
}
if($(this).attr("name") == "room[]") {
wrapSpan.addClass("custom-checkbox-big-size");
}
if($(this).attr("name") == "request[]") {
wrapSpan.addClass("custom-checkbox-small-size");
}
$(this).wrap(wrapSpan).hide();
});
$(".custom-checkbox-span").on("mouseup",function(){
checkSpan($(this));
});
function checkSpan(el) {
if(el.hasClass("selected")) {
el.removeClass("selected");
el.children().prop("checked",false);
} else {
el.addClass("selected");
el.children().prop("checked",true);
}
}
CSS:
.custom-checkbox-big-size {
background:red;
width: 50px;
height: 50px;
display: inline-block;
}
.custom-checkbox-big-size:hover, .custom-checkbox-big-size.selected {
background:yellow;
}
.custom-checkbox-small-size {
background:blue;
width: 20px;
height: 20px;
display: inline-block;
}
.custom-checkbox-small-size:hover, .custom-checkbox-small-size.selected {
background:green;
}
Check the jsFiddle. I did it with colors, because I don't have your original images, you have to change the background: color; rules.
This is handled in the selector, assuming you are using CSS3,like so...
input[type*='checkbox'][name*='room'] {
... styles here
}

Is it possible multiple text color in a single placeholder?

I want a placeholder with multiple color text.Is it possible
please help me.
I have a input text filed where placeholder showing I'm a good boy.
I want good word different in color.
No, it is not possible to color the default placeholder but you can create a element similar to placeholder. So, that you can color the letters. This is a workaround to the default placeholder.
Note that I am using opacity: 0.5, you can change it as per your need.
HTML
.input-field {
position: relative;
display: inline-block;
}
.input-field > label {
position: absolute;
left: 0.5em;
top: 50%;
margin-top: -0.5em;
opacity: 0.5;
}
.input-field > input[type=text]:focus + label {
display: none;
}
.input-field > label > span {
letter-spacing: -2px;
}
.first-letter {
color: red;
}
.second-letter {
color: blue;
}
.third-letter {
color: orange;
}
.fourth-letter {
color: green;
}
.fifth-letter {
color: yellow;
}
<div class="input-field">
<input id="input-text-field" type="text"></input>
<label for="input-text-field">
<span class="first-letter">H</span>
<span class="second-letter">E</span>
<span class="third-letter">L</span>
<span class="fourth-letter">L</span>
<span class="fifth-letter">O</span>
</label>
</div>
Working Fiddle
Updated:
Only CSS (with :placeholder-shown)
The above fiddle has a bug which is when you type something in the textbox and click outside, the placeholder is visible again above the entered text.
So, to make it perfect, we can use :placeholder-shown which hasn't have much support yet other than chrome and firefox.
Here is the code:
.input-field {
position: relative;
display: inline-block;
}
.input-field > label {
position: absolute;
left: 0.5em;
top: 50%;
margin-top: -0.5em;
opacity: 0.5;
display: none;
}
.input-field > input[type=text]:placeholder-shown + label {
display: block;
}
.input-field > label > span {
letter-spacing: -2px;
}
.first-letter {
color: red;
}
.second-letter {
color: blue;
}
.third-letter {
color: orange;
}
.fourth-letter {
color: green;
}
.fifth-letter {
color: yellow;
}
<div class="input-field">
<input id="input-text-field" type="text" placeholder=" "></input>
<label for="input-text-field">
<span class="first-letter">H</span>
<span class="second-letter">E</span>
<span class="third-letter">L</span>
<span class="fourth-letter">L</span>
<span class="fifth-letter">O</span>
</label>
</div>
Working Fiddle
Using JS (without :placeholder-shown):
addListenerMulti(document.getElementById('input-text-field'), 'focus keyup', blurme);
function blurme(e) {
var element = e.currentTarget;
element.classList[(element.value.length !== 0) ? "add" : "remove"]('hide-placeholder');
}
function addListenerMulti(el, s, fn) {
s.split(" ").forEach(function(e) {
return el.addEventListener(e, fn, false)
});
}
.input-field {
position: relative;
display: inline-block;
}
.input-field > label {
position: absolute;
left: 0.5em;
top: 50%;
margin-top: -0.5em;
opacity: 0.5;
}
.hide-placeholder + label {
display: none;
}
.input-field > label > span {
letter-spacing: -2px;
}
.first-letter {
color: red;
}
.second-letter {
color: blue;
}
.third-letter {
color: orange;
}
.fourth-letter {
color: green;
}
.fifth-letter {
color: yellow;
}
<div class="input-field">
<input id="input-text-field" type="text"></input>
<label for="input-text-field">
<span class="first-letter">H</span>
<span class="second-letter">E</span>
<span class="third-letter">L</span>
<span class="fourth-letter">L</span>
<span class="fifth-letter">O</span>
</label>
</div>
Working Fiddle
CSS could help you (not IE yet). mix-blend-mode + gradient and background dispatch in 2 containers.
i used required (attribute) and :invalid (CSS) to trigger effect only when placeholder is shown.
For info , take a look at :
Example (for browser that deals with mix-blend-mode)
input {
font-family:monospace;
vertical-align:middle;
font-size:2em;
}
input:invalid {
mix-blend-mode:screen;
text-shadow:0 0 1px black,0 0 1px black,0 0 1px black,0 0 1px black,0 0 1px black; /* increase visibility */
}
label {
background:repeating-linear-gradient(to right,
pink 10%,
blue 10%,
blue 20%,
purple 20%,
purple 30%,
red 30%,
red 40%,
green 40%,
green 50%,
turquoise 50%,
turquoise 60%)
left ;
background-size: 10em 400px;
}
<form>
<label><input type="text" required placeholder="show me colors"/></label>
</form>
another example with image backgrounds and gradients still in use : http://codepen.io/gc-nomade/pen/WwgzVv

Categories