When a select changes, the text should change. Here's a fiddle.
(function($) {
'use strict';
function funcFormCalc() {
var s1_is_1 = $("#s1").value === '1',
s1_is_2 = $("#s1").value === '2';
var s2_is_1 = $("#s2").value === '1',
s2_is_2 = $("#s2").value === '2';
$('#myForm').onchange = function() {
if (s1_is_1 && s2_is_1) {
$('#result').html('result 1');
} else if (s1_is_2 && s2_is_1) {
$('#result').html('result 2');
} else if (s1_is_1 && s2_is_2) {
$('#result').html('result 3');
} else {
$('#result').html('result 4');
}
};
}
funcFormCalc();
})(window.jQuery);
<form action="#" method="post" id="myForm">
<label for="s1">
Tree Number
<select id="s1">
<option value="1">1</option>
<option value="2">2</option>
</select>
</label><br>
<label for="s2">
Tree Height
<select id="s2">
<option value="1">1 story house</option>
<option value="2">2 story house</option>
</select>
</label>
<div id="result">Result Displays Here</div>
</form>
Why does the result text not change when a selection changes?
You are using the selectVariant booleans to determine which value to show, however these variables are only being calculated once on load. You probably meant to have the calculations in your onchange function.
Also your values do not match the options for select2.
<option value="1 story house">1 story house</option>
<option value="2 story house">2 story house</option>
<option value="3 story house +">3 story house +</option>
-- See snippet at bottom for original answer with some additional refactoring. --
EDIT: You completely changed the code in your question since my first answer...
Though my answer is the same. You need to recalculate selectVariant1, selectVariant2, select2Variant1, and select2Variant2 inside the onchange method.
(function($) {
'use strict';
function funcFormCalc() {
var formCalc = document.getElementsByClassName('form-calc')[0],
formCalcResult = document.getElementsByClassName('form-calc__result')[0],
selectHowManyTrees = document.getElementById('selectHowManyTrees'),
selectApproximateHeightTree = document.getElementById('selectApproximateHeightTree');
formCalc.onchange = function() {
var selectVariant1 = selectHowManyTrees.value === '1',
selectVariant2 = selectHowManyTrees.value === '2';
var select2Variant1 = selectApproximateHeightTree.value === '1',
select2Variant2 = selectApproximateHeightTree.value === '2';
if (selectVariant1 && select2Variant1) {
formCalcResult.innerHTML = 'variant text 1';
} else if (selectVariant2 && select2Variant1) {
formCalcResult.innerHTML = 'variant text 2';
} else if (selectVariant1 && select2Variant2) {
formCalcResult.innerHTML = 'variant text 3';
} else {
formCalcResult.innerHTML = 'for all variants';
}
};
}
funcFormCalc();
})(window.jQuery);
* {
padding: 0;
margin: 0;
}
*,
*:before,
*:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
html,
body {
overflow-x: hidden;
}
html {
font-family: sans-serif;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body {
background: #fff;
color: #2C2D2C;
text-align: left;
font-family: 'Montserrat', Arial, "Helvetica CY", "Nimbus Sans L", sans-serif;
font-size: 16px;
line-height: 1.5;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
}
.form-calc {
max-width: 400px;
margin: 15px auto;
background: #FAFAFA;
padding: 15px 30px;
}
.form-calc__item {
margin-bottom: 28px;
}
.form-calc__label {
font-size: 14px;
display: block;
margin: 6px 0 9px;
letter-spacing: 0.25px;
}
.form-calc__select-container {
position: relative;
display: inline-block;
vertical-align: top;
width: 100%;
}
.form-calc__select-container:before,
.form-calc__select-container:after {
content: '';
position: absolute;
right: 7px;
width: 0;
height: 0;
border-style: solid;
pointer-events: none;
}
.form-calc__select-container:before {
top: 16.5px;
border-width: 0 3.5px 4px 3.5px;
border-color: transparent transparent #333 transparent;
}
.form-calc__select-container:after {
bottom: 16.5px;
border-width: 4px 3.5px 0 3.5px;
border-color: #333 transparent transparent transparent;
}
.form-calc__select {
font-family: 'Montserrat', Arial, "Helvetica CY", "Nimbus Sans L", sans-serif;
-webkit-appearance: none;
-moz-appearance: none;
text-indent: 1px;
text-overflow: '';
width: 100%;
height: 43px;
line-height: 43px;
border: 1px solid #D9D9D9;
padding: 0 7px;
color: #2C2D2C;
}
.form-calc__select::-ms-expand {
display: none;
}
.form-calc__select option {
padding: 3px 7px;
border: none;
}
.form-calc__result {
font-size: 36px;
font-weight: 500;
color: #3E3F3E;
line-height: 1.4;
margin-bottom: 6px;
}
.form-calc__result-subtext {
font-size: 12px;
text-transform: uppercase;
color: #3E3F3E;
letter-spacing: .6px;
line-height: 1.25;
}
.form-calc__submit {
font-family: 'Montserrat', Arial, "Helvetica CY", "Nimbus Sans L", sans-serif;
display: inline-block;
vertical-align: top;
color: #fff;
text-align: center;
min-width: 170px;
padding: 14px 20px;
background: #42BF8D;
text-transform: uppercase;
text-decoration: none;
border: none;
letter-spacing: 0.5px;
font-size: 12px;
cursor: pointer;
-webkit-transition: .3s;
transition: .3s;
}
.form-calc__submit:hover,
.form-calc__submit:focus,
.form-calc__submit:active {
color: #fff;
background: #2F8B66;
}
.form-calc__submit:focus {
box-shadow: inset 0 0 6px rgba(0, 0, 0, .25);
}
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,500,600,700&subset=latin-ext" rel="stylesheet">
<form action="#" method="post" class="form-calc" autocomplete="off">
<div class="form-calc__item">
<label for="selectHowManyTrees" class="form-calc__label">Label 1</label>
<div class="form-calc__select-container">
<select name="select1" id="selectHowManyTrees" class="form-calc__select">
<option value="1" selected>1</option>
<option value="2">2</option>
</select>
</div>
</div>
<div class="form-calc__item">
<label for="selectApproximateHeightTree" class="form-calc__label">Label 2</label>
<div class="form-calc__select-container">
<select name="select2" id="selectApproximateHeightTree" class="form-calc__select">
<option value="1">1 story house</option>
<option value="2">2 story house</option>
</select>
</div>
</div>
<div class="form-calc__item">
<div class="form-calc__result">variant text 1</div>
</div>
</form>
Edit 2: Responding to question in comment.
Excuse me! Not a big question. How would you solve this problem? (other logic).
This is a pretty opinionated question, so this answer is just my opinion. In general I think you have a pretty decent solution.
Your problem is essentially:
Display a result dependent on a combination of inputs.
So there needs to be some way to calculate a value based on the inputs. It would be best if you could do this mathematically, like value1 + value2 + value3 = result. Unfortunately this doesn't seem possible for your problem, but if you are able to do a slight design change then you could try this alternative:
Modify your form so each option has a low-value and high-value.
<select name="select1" id="selectHowManyTrees" class="form-calc__select">
<option low-value="20" high-value="30" selected>1</option>
<option low-value="30" high-value="40">2</option>
<option low-value="40" high-value="50">3</option>
<option low-value="50" high-value="60">4</option>
</select>
<select name="select2" id="selectApproximateHeightTree" class="form-calc__select">
<option low-value="100" high-value="180" story house">1 story house</option>
<option low-value="170" high-value="300" story house">2 story house</option>
<option low-value="220" high-value="600" story house +">3 story house +</option>
</select>
Sum up all the selected low-value and all the selected high-value to calculate the result.
var low = 0, high = 0;
var selects = document.getElementsByClassName('form-calc__select');
for(var s of selects) {
var selectedOption = s.options[ s.selectedIndex ];
low += selectedOption.getAttribute('low-value');
high += selectedOption.getAttribute('high-value');
}
Display this as a range for your result.
formCalcResult.innerHTML = '$' + low + ' - $' + high;
or with ES6 string interpolation
formCalcResult.innerHTML = `$${low} - $${high}`;
Now it may be that you cannot do this, and that there is no way to mathematically calculate the result. In this scenario you are forced to find a way to link a combination of inputs to a result, which is what you did using a bunch of booleans.
How could you do it better? A database.
The ideal place for storing data relationships is in a database. Then your application can dynamically display all the options and results. This will allow you whenever there is a change to a value you just update the data rather than updating the entire application. It is also a very readable way of storing the different option combinations. For example you could have a table that looks like this:
NumberOfTreesId | TreeHeightId | JobTypeId | LocationPropertyId |Result
1 | 1 | 1 | 1 | '$250 - $610'
1 | 1 | 1 | 2 | '$350 - $825'
This example resembles SQL, but you could do something very similar using a non-relational database if you wanted.
Of course, using a database adds a lot of complexity to your application and you are just doing a JS tutorial, so definitely overkill. So after all that I would say design-wise your code is perfectly fine. There is a lot of ways you could refactor to make it more readable and less code, but in the end the concept will be the same.
There are a lot of ways this could be written differently, here is one way:
(function($) {
'use strict';
var results = [ ];
function addResult(s1, s2, s3, s4, r) {
results.push({
select1 : s1,
select2 : s2,
select3 : s3,
select4 : s4,
result : r
});
}
var defaultResult = '$450 - $750';
addResult('1', '1', '1', '1', '$250 - $610');
addResult('1', '1', '1', '2', '$350 - $825');
addResult('1', '1', '1', '3', '$250 - $610');
addResult('1', '2', '1', '1', '$425 - $1200');
addResult('1', '2', '1', '2', '$546 - $1620');
addResult('1', '2', '1', '3', '$420 - $1200');
addResult('1', '3', '1', '1', '$750 - $1800');
addResult('1', '3', '1', '2', '$900 - $2000');
addResult('2', '1', '1', '1', '$500 - $850');
addResult('2', '1', '1', '2', '$650 - $1000');
addResult('2', '1', '1', '3', '$500 - $850');
function funcFormCalc() {
var formCalc = document.getElementsByClassName('form-calc')[0],
formCalcResult = document.getElementsByClassName('form-calc__result')[0],
selectHowManyTrees = document.getElementById('selectHowManyTrees'),
selectApproximateHeightTree = document.getElementById('selectApproximateHeightTree'),
selectJobType = document.getElementById('selectJobType'),
selectLocationProperty = document.getElementById('selectLocationProperty');
formCalc.onchange = function() {
var s1 = selectHowManyTrees.value,
s2 = selectApproximateHeightTree.value,
s3 = selectJobType.value,
s4 = selectLocationProperty.value;
var text = defaultResult;
for(var result of results)
{
if(s1 === result.select1 &&
s2 === result.select2 &&
s3 === result.select3 &&
s4 === result.select4) {
text = result.result;
}
}
formCalcResult.innerHTML = text;
//console.log(`${s1} ${s2} ${s3} ${s4}`);
};
}
funcFormCalc();
})(window.jQuery);
* {
padding: 0;
margin: 0;
}
*,
*:before,
*:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
html,
body {
overflow-x: hidden;
}
html {
font-family: sans-serif;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body {
background: #fff;
color: #2C2D2C;
text-align: left;
font-family: 'Montserrat', Arial, "Helvetica CY", "Nimbus Sans L", sans-serif;
font-size: 16px;
line-height: 1.5;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
}
.form-calc {
max-width: 400px;
margin: 15px auto;
background: #FAFAFA;
padding: 15px 30px;
}
.form-calc__item {
margin-bottom: 28px;
}
.form-calc__label {
font-size: 14px;
display: block;
margin: 6px 0 9px;
letter-spacing: 0.25px;
}
.form-calc__select-container {
position: relative;
display: inline-block;
vertical-align: top;
width: 100%;
}
.form-calc__select-container:before,
.form-calc__select-container:after {
content: '';
position: absolute;
right: 7px;
width: 0;
height: 0;
border-style: solid;
pointer-events: none;
}
.form-calc__select-container:before {
top: 16.5px;
border-width: 0 3.5px 4px 3.5px;
border-color: transparent transparent #333 transparent;
}
.form-calc__select-container:after {
bottom: 16.5px;
border-width: 4px 3.5px 0 3.5px;
border-color: #333 transparent transparent transparent;
}
.form-calc__select {
font-family: 'Montserrat', Arial, "Helvetica CY", "Nimbus Sans L", sans-serif;
-webkit-appearance: none;
-moz-appearance: none;
text-indent: 1px;
text-overflow: '';
width: 100%;
height: 43px;
line-height: 43px;
border: 1px solid #D9D9D9;
padding: 0 7px;
color: #2C2D2C;
}
.form-calc__select::-ms-expand {
display: none;
}
.form-calc__select option {
padding: 3px 7px;
border: none;
}
.form-calc__result {
font-size: 36px;
font-weight: 500;
color: #3E3F3E;
line-height: 1.4;
margin-bottom: 6px;
}
.form-calc__result-subtext {
font-size: 12px;
text-transform: uppercase;
color: #3E3F3E;
letter-spacing: .6px;
line-height: 1.25;
}
.form-calc__submit {
font-family: 'Montserrat', Arial, "Helvetica CY", "Nimbus Sans L", sans-serif;
display: inline-block;
vertical-align: top;
color: #fff;
text-align: center;
min-width: 170px;
padding: 14px 20px;
background: #42BF8D;
text-transform: uppercase;
text-decoration: none;
border: none;
letter-spacing: 0.5px;
font-size: 12px;
cursor: pointer;
-webkit-transition: .3s;
transition: .3s;
}
.form-calc__submit:hover,
.form-calc__submit:focus,
.form-calc__submit:active {
color: #fff;
background: #2F8B66;
}
.form-calc__submit:focus {
box-shadow: inset 0 0 6px rgba(0, 0, 0, .25);
}
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,500,600,700&subset=latin-ext" rel="stylesheet">
<form action="#" method="post" class="form-calc" autocomplete="off">
<div class="form-calc__item">
<label for="selectHowManyTrees" class="form-calc__label">How many trees?</label>
<div class="form-calc__select-container">
<select name="select1" id="selectHowManyTrees" class="form-calc__select">
<option value="1" selected>1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</div>
</div>
<div class="form-calc__item">
<label for="selectApproximateHeightTree" class="form-calc__label">What is the approximate height of the tree?</label>
<div class="form-calc__select-container">
<select name="select2" id="selectApproximateHeightTree" class="form-calc__select">
<option value="1">1 story house</option>
<option value="2">2 story house</option>
<option value="3">3 story house +</option>
</select>
</div>
</div>
<div class="form-calc__item">
<label for="selectJobType" class="form-calc__label">Job Type?</label>
<div class="form-calc__select-container">
<select name="select3" id="selectJobType" class="form-calc__select">
<option value="-1">Complete tree removal</option>
<option value="1">Tree Removal</option>
<option value="2">Tree Prune</option>
<option value="3">Palm Removal</option>
<option value="4">Palm Prune</option>
<option value="5">Arborist Report</option>
</select>
</div>
</div>
<div class="form-calc__item">
<label for="selectLocationProperty" class="form-calc__label">Trees location on your property?</label>
<div class="form-calc__select-container">
<select name="select4" id="selectLocationProperty" class="form-calc__select">
<option selected>Front Yard</option>
<option value="1">Access via a driveway (wide)</option>
<option value="2">Access via a gate (narrow)</option>
<option value="3">Vacant land</option>
</select>
</div>
</div>
<div class="form-calc__item">
<div class="form-calc__result">$250 - $610</div>
<div class="form-calc__result-subtext">Expected price range in Australia</div>
</div>
<div class="form-calc__item">
<button type="submit" class="form-calc__submit">Request a quote</button>
</div>
</form>
Related
So I am trying to make a masked input element, that can have two styled drop down boxes as shown in the image. I have tried using vaadian-time-picker, combo boxes, select lists and datalists with an input element. The datalists has been the most successful but I am getting styling issues as shown in the second image.
I have tried using datalists-css libraries etc. I am at a blocker where it's a choice between having the correct functionality of the design, or have the design but not the functionality.
The element should also allow the user to type and have a drop down. Any help would be greatly appreciated!
Here is my datalists code(I am using svelte with typescript):
script and HTML
function timesArray():string[]{
for(let i=0; i<=24; i++){
if(i>=10){
times.push("<option value='"+i.toString()+":00'/>");
}
else{
times.push("<option value='"+"0"+i.toString()+":00'/>");
}
}
return times;
}
</script>
<span invalid={isInvalid ? '' : null} class="day-block">
<span class="time-range" class:error={isInvalid} >
<input
use:action={startMaskRef}
placeholder="00:00"
disabled={readonly}
bind:value={internalTimeRange.Start}
on:blur={valueChanged}
bind:this={startInput} list="startTimes"/>
<datalist id="startTimes" autocomplete="off">
{#each timesArray() as time, i}
{#if i>=10}
<option value="{i.toString()}:00"/>
{:else}
<option value="0{i.toString()}:00"/>
{/if}
{/each}
</datalist>
<div class="separator"> — </div>
<input
use:action={endMaskRef}
placeholder="00:00"
disabled={readonly}
bind:value={internalTimeRange.End}
bind:this={endInput}
on:blur={valueChanged} list="endTimes"/>
<datalist id="endTimes" autocomplete="off">
{#each timesArray() as time, i}
{#if i>=10}
<option value="{i.toString()}:00"/>
{:else}
<option value="0{i.toString()}:00"/>
{/if}
{/each}
</datalist>
</span>
CSS
display: inline-table;
border-radius: 0;
}
.time-range {
position: relative;
display: inline-flex;
padding: 0.5rem;
border-bottom: 1.5px solid var(--remundo-primary-color);
width: max-content;
}
datalist {
position: fixed;
border: 1 none;
overflow-x: hidden;
overflow-y: auto;
}
datalist option {
font-size: 0.8em;
padding: 0.3em 1em;
background-color: rgb(173, 172, 172);
cursor: pointer;
width: 20%;
left: 0%;
}
/* option active styles */
datalist option:hover, datalist option:focus {
color: #fff;
background-color: #036;
outline: 0 none;
}
.separator {
font-size: 8px;
margin-right: 1px;
margin-left: 0rem;
margin-top: 5px;
color: var(--remundo-shadow-color);
}
input {
width: auto;
box-sizing: border-box;
border: none;
padding: 0;
color: var(--remundo-primary-color);
}
input:focus {
outline: none;
}
I'm trying to create a GPA calculator (just to practice html, css, javascript) and am having an issue I can't seem to solve. Here's what's happening.
TL;DR: When I click on an input field, the corresponding object is erased.
For each course, there is a form with input fields for course name (text input), grade (select input), and credits earned (number input). When you want to add another course, you're adding another form. When a form is created, so is an object that's associated with it. I create this association by adding an id to the form with a unique number and also adding that id number to the object.
When I console.log the various steps of creating an object and setting its values and saving it to the local storage, everything works fine. However, when I was trying to create functionality to update the values of the objects, I started having troubles. I've pinpointed when they happen. Whenever I click on an input field, the object is erased. Specifically, only the object that's tied to that input field is erased. So if I create 5 forms and I click on the text input of the 3rd one, the 3rd object is erased. I can click on that same field multiple times and nothing else will happen. Then, if I click, say, the number input of the 5th form, then the 5th object is erased. I know it's not the delete function at work because that function would also remove the form from view.
If anyone could help me pinpoint what I can do to fix this, I would greatly appreciate it.
Javascript
// Theme
let lightMode = document.getElementById('light-mode');
let darkMode = document.getElementById('dark-mode');
lightMode.addEventListener('click', () => {themeTransition(); document.documentElement.setAttribute('data-theme', 'light');});
darkMode.addEventListener('click', () => {themeTransition(); document.documentElement.setAttribute('data-theme', 'dark');});
function themeTransition()
{
document.documentElement.classList.add('transition');
window.setTimeout(() => document.documentElement.classList.remove('transition'), 1000);
}
// GPA CALCULATION
// Object ID
var objId = 0;
// Grades class
class Grades
{
constructor(id, course, grade, credits)
{
this.id = id;
this.course = course;
this.grade = grade;
this.credits = credits;
}
}
// Storage class
class Store
{
static getGrades()
{
let grades;
if (localStorage.getItem('grades') == null)
{
grades = [];
}
else
{
grades = JSON.parse(localStorage.getItem('grades'));
objId = localStorage.getItem('objId');
}
return grades;
}
static addGrade(grade, newObjId)
{
const grades = Store.getGrades();
grades.push(grade);
localStorage.setItem('grades', JSON.stringify(grades));
localStorage.setItem('objId', JSON.stringify(newObjId));
console.log(grades);
}
static updateGrade(id, course, grade, credits)
{
const grades = Store.getGrades();
grades.forEach((oldGrade, index) =>
{
if (oldGrade.id == id)
{
oldGrade[index].course = course;
oldGrade[index].grade = grade;
oldGrade[index].credits = credits;
}
});
localStorage.setItem('grades', JSON.stringify(grades));
}
static removeGrade(id)
{
const grades = Store.getGrades();
grades.forEach((grade, index) =>
{
if (grade.id == id)
{
grades.splice(index, 1);
}
});
localStorage.setItem('grades', JSON.stringify(grades));
}
}
// UI class
class UI
{
static displayGrades()
{
const grades = Store.getGrades();
grades.forEach((grade) => UI.addCurrentGrade(grade));
}
static addCurrentGrade(grade)
{
const list = document.querySelector('.add-grades');
const row = document.createElement('form');
const addBefore = document.querySelector('.add');
row.classList.add('add-item');
row.setAttribute('id', `${grade.id}`)
row.innerHTML =
`
<div class="input-node course">
<label for="course">Course</label>
<input type="text" id="course">
</div>
<div class="input-node grade">
<label for="grade">Grade</label>
<select id="grade">
<option value="none"></option>
<option value="A">A</option>
<option value="A-">A-</option>
<option value="B+">B+</option>
<option value="B">B</option>
<option value="B-">B-</option>
<option value="C+">C+</option>
<option value="C">C</option>
<option value="C-">C-</option>
<option value="D+">D+</option>
<option value="D">D</option>
<option value="D-">D-</option>
<option value="F">F</option>
<option value="W">W</option>
<option value="I">I</option>
<option value="P">P</option>
<option value="NP">NP</option>
</select>
</div>
<div class="input-node credits">
<label for="credits">Credits</label>
<input type="number" id="credits">
</div>
<div class="input-node delete">
<i class="fas fa-times-circle"></i>
</div>
`;
list.insertBefore(row, addBefore);
document.querySelector('.delete').addEventListener('click', delGrade);
document.querySelector('.add-grades').addEventListener('input', updateGrades);
}
static addNewGrade(e)
{
if (e.parentElement.classList.contains('add-grade'))
{
objId++;
const currentId = objId;
const list = document.querySelector('.add-grades');
const row = document.createElement('form');
const addBefore = document.querySelector('.add');
row.classList.add('add-item');
row.setAttribute('id', `${currentId}`)
row.innerHTML =
`
<div class="input-node course">
<label for="course">Course</label>
<input type="text" id="course">
</div>
<div class="input-node grade">
<label for="grade">Grade</label>
<select id="grade">
<option value="none"></option>
<option value="A">A</option>
<option value="A-">A-</option>
<option value="B+">B+</option>
<option value="B">B</option>
<option value="B-">B-</option>
<option value="C+">C+</option>
<option value="C">C</option>
<option value="C-">C-</option>
<option value="D+">D+</option>
<option value="D">D</option>
<option value="D-">D-</option>
<option value="F">F</option>
<option value="W">W</option>
<option value="I">I</option>
<option value="P">P</option>
<option value="NP">NP</option>
</select>
</div>
<div class="input-node credits">
<label for="credits">Credits</label>
<input type="number" id="credits">
</div>
<div class="input-node delete">
<i class="fas fa-times-circle"></i>
</div>
`;
list.insertBefore(row, addBefore);
document.querySelector('.delete').addEventListener('click', delGrade);
document.querySelector('.add-grades').addEventListener('input', updateGrades);
const course = e.parentElement.parentElement.querySelector('#course').value;
const grade = e.parentElement.parentElement.querySelector('#grade').value;
const credits = e.parentElement.parentElement.querySelector('#course').value;
const grades = new Grades(currentId, course, grade, credits);
Store.addGrade(grades, currentId);
}
}
static deleteGrade(del)
{
if (del.parentElement.classList.contains('delete'))
{
del.parentElement.parentElement.remove();
}
}
}
// EVENTS
// Display Existing Grades
document.addEventListener('DOMContentLoaded', UI.displayGrades);
// Add Grade
document.querySelector('.add-grade').addEventListener('click', (e) =>
{
UI.addNewGrade(e.target);
});
// Update Grade
document.querySelector('.add-grades').addEventListener('input', updateGrades);
function updateGrades(e)
{
const id = e.target.parentElement.parentElement.getAttribute('id');
const course = e.target.parentElement.parentElement.querySelector('#course').value;
const grade = e.target.parentElement.parentElement.querySelector('#grade').value;
const credits = e.target.parentElement.parentElement.querySelector('#course').value;
Store.updateGrade(id, course, grade, credits);
}
// Remove Grade
document.querySelector('.add-grades').addEventListener('click', delGrade);
function delGrade(e)
{
UI.deleteGrade(e.target);
Store.removeGrade(e.target.parentElement.parentElement.getAttribute('id'));
}
document.body.addEventListener('click', testFun);
function testFun()
{
const grades = Store.getGrades();
console.log(grades);
}
note: function testFun() is to log the objects in the Grades class whenever I click on anything
HTML
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.13.1/css/all.css" integrity="sha384-xxzQGERXS00kBmZW/6qxqJPyxW3UR0BPsL4c8ILaIWXva5kFi7TxkIIaMiKtqV1Q" crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
<title>GPA Calculator</title>
</head>
<body>
<div class="container">
<div id="view-mode">
<button id="light-mode">Light</button> | <button id="dark-mode">Dark</button>
</div>
<header class="header">
<h1>GPA</h1>
<h2>Calculator</h2>
</header>
<section class="add-grades">
<div class="table-header">
<h1>Semester <span class="semester">–</span></h1>
<h2>Semester GPA: <span class="gpa-semester">–</span></h2>
</div>
<div class="add add-grade">
<i class="fas fa-plus-circle"></i>
</div>
</section>
<div class="add add-semester">
<i class="fas fa-plus-circle"></i>
</div>
<aside class="gpa-total">
<h2>GPA</h2>
<h1><span class="gpa-total">–</span></h1>
</aside>
</div>
<script src="main.js"></script>
</body>
</html>
If you want the full effect, here's the CSS as well
/* Global */
html[data-theme="light"]
{
--background: rgb(235, 235, 235);
--panel: rgb(245, 245, 245);
--panel-head: rgb(0, 80, 190);
--text: rgb(20, 20, 20);
--text-secondary: rgb(60, 60, 60);
--text-panel: rgb(20, 20, 20);
--text-panel-head: rgb(245, 245, 245);
--add: rgb(58, 180, 34);
--delete: rgb(255, 55, 55);
}
html[data-theme="dark"]
{
--background: rgb(40, 40, 40);
--panel: rgb(70, 70, 70);
--panel-head: rgb(0, 106, 255);
--text: rgb(245, 245, 245);
--text-secondary: rgb(120, 120, 120);
--text-panel: rgb(245, 245, 245);
--text-panel-head: rgb(245, 245, 245);
--add: rgb(58, 180, 34);
--delete: rgb(255, 55, 55);
}
*
{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body
{
background: var(--background);
font-family: Cochin, Georgia, Times, 'Times New Roman', serif;
font-size: 16px;
color: var(--text);
}
.container
{
width: 80%;
margin: auto;
}
button
{
background: none;
border: none;
outline: none;
}
/* Header */
#view-mode
{
text-align: right;
margin-top: 20px;
}
#view-mode button
{
font-size: 16px;
color: var(--text);
}
#view-mode button:hover
{
color: var(--panel-head);
text-decoration: underline;
cursor: pointer;
}
.header
{
margin: 20px 0 50px 0;
text-align: center;
text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
text-transform: uppercase;
}
.header h1
{
font-size: 6em;
}
.header h2
{
font-size: 1.77em;
color: var(--text-secondary);
}
/* User Input */
.add-grades
{
min-width: 400px;
max-width: 500px;
margin: auto;
margin-top: 20px;
background: var(--panel);
color: var(--text-panel);
border-radius: 20px;
display: flex;
flex-direction: column;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
.table-header
{
padding: 10px 15px;
display: flex;
justify-content: space-between;
align-items: baseline;
border-top-right-radius: 20px;
border-top-left-radius: 20px;
background: var(--panel-head);
color: var(--text-panel-head);
}
.table-header h1
{
font-size: 2em;
}
.table-header h2
{
font-size: 1.2em;
}
.add-item
{
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
.add-item .input-node
{
display: flex;
justify-content: space-between;
align-items: center;
}
.add-item .input-node *
{
margin: 0 3px;
}
.input-node #course
{
width: 75px;
padding: 5px;
border: none;
border-radius: 5px;
outline: none;
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5);
}
.input-node #grade
{
font-size: 1em;
outline: none;
}
.input-node #credits
{
width: 40px;
padding: 5px;
border: none;
border-radius: 5px;
outline: none;
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5);
}
.delete i
{
font-size: 1.4em;
padding: 0;
color: var(--text-panel);
}
.delete i:hover
{
color: var(--delete);
cursor: pointer;
}
.add-grades .add
{
margin: 13px;
margin-top: 10;
display: flex;
justify-content: flex-end;
}
.add i
{
font-size: 1.4em;
color: var(--text-panel);
}
.add i:hover
{
color: var(--panel-head);
cursor: pointer;
}
.container > .add
{
min-width: 400px;
max-width: 500px;
margin: auto;
margin-top: 20px;
}
/* GPA Calculation */
.gpa-total
{
margin-top: 50px;
text-align: center;
}
.gpa-total h2
{
font-size: 3em;
text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
.gpa-total h1
{
width: 250px;
margin: auto;
margin-top: 10px;
padding: 60px 0;
font-size: 6em;
border-radius: 100%;
background: var(--panel-head);
color: var(--text-panel-head);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
/* Transition */
html.transition,
html.transition body,
html.transition body:before,
html.transition body:after,
html.transition section,
html.transition section:before,
html.transition section:after
{
transition: all 750ms !important;
transition-delay: 0 !important;
}
on my website, there are 2 buttons. one button is to indent text to the left and the other button is to indent text to the right. what I am trying to achieve is that whenever I press the indent left or right button, currently selected (on focus) text should move left or right (depending on what button I press). at the same time, I want the font size of that text to go down by one level, so when compared to the text above, it's smaller to the text above.
// global variable
let onFocus = null;
// this function
function focusedText(event) {
onFocus = event.target;
}
function init() {
const newLineButton = document.querySelector('#newLine');
newLineButton.addEventListener("click", newLine);
newLine();
document.querySelector("#printButton").addEventListener("click", printPage)
}
function newLine() {
const newLine = document.createElement("p");
newLine.setAttribute("contenteditable", true);
newLine.addEventListener("keydown", handleKeyDown)
newLine.addEventListener("focus", focusedText)
newLine.classList.add("textLine")
const parent = document.querySelector('#textBox');
parent.appendChild(newLine);
newLine.focus();
}
function handleKeyDown(event) {
if (event.which === 13) {
event.preventDefault();
newLine();
}
}
// this runs the init(); function
init();
// this prints the page
function printPage() {
window.print();
}
// this fuction changes the text size
function textSize(selectTag) {
const listValue = selectTag.options[selectTag.selectedIndex].value;
onFocus.style.fontSize = listValue;
}
* {
padding-top: 0em;
padding-bottom: 0em;
margin-top: 0em;
margin-bottom: 0em;
}
*:focus {
outline: 0px solid transparent;
}
body {
margin: 0;
}
.title {
font-family: 'Assistant', sans-serif;
font-size: 2em;
text-align: center;
text-transform: uppercase;
color: white;
background: #6a0dad;
letter-spacing: 0.20em;
}
.navMenu {
display: flex;
align-items: stretch;
padding-top: 0.5em;
padding-bottom: 0.5em;
justify-content: center;
}
.navMenu button,
#dropDown {
padding: 0.3em 1.2em;
margin: 0 0.1em 0.1em 0;
border: 0.16em solid rgba(255, 255, 255, 0);
border-radius: 2em;
box-sizing: border-box;
font-family: 'Assistant', sans-serif;
font-weight: bold;
font-size: 1rem;
color: white;
text-shadow: 0 0.04em 0.04em rgba(0, 0, 0, 0.35);
text-align: center;
transition: all 0.2s;
background-color: #6a0dad;
cursor: pointer;
}
.navMenu button:hover,
#dropDown:hover {
border-color: white;
}
#dropDown option {
font-weight: bold;
}
#textBox {
display: flex;
justify-content: left;
width: auto;
flex-flow: column nowrap;
font-family: 'Assistant', sans-serif;
}
.textLine {
color: black;
width: 100%;
padding-left: 0.8em;
padding-right: 0.8em;
box-sizing: border-box;
transition: background-color 0.25s;
}
#media screen {
.textLine:hover {
background-color: #6a0dad;
color: white;
}
}
#media print {
.navMenu,
.title {
display: none;
}
}
.textLine:empty::before {
content: "Enter your text here";
color: grey;
font-family: 'Assistant', sans-serif;
pointer-events: none;
}
.textLine:hover:empty::before {
content: "Enter your text here";
color: white;
font-family: 'Assistant', sans-serif;
}
<!DOCTYPE html>
<html>
<head>
<title>Outline Editing</title>
<link rel="stylesheet" type="text/css" href="main-css.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<main>
<h1 class="title">Outline Editing</h1>
<nav class="navMenu">
<button type="button" id="indentLeft"><i class="material-icons">format_indent_decrease</i></button>
<select id="dropDown" onchange="textSize(this);" size="1">
<option value="" selected disabled hidden>Levels</option>
<option value="200%">Level 1</option>
<option value="170%">Level 2</option>
<option value="150%">Level 3</option>
<option value="130%">Level 4</option>
<option value="100%">Level 5</option>
</select>
<button type="button" id="newLine">New Line</button>
<button type="button" id="indentRight"><i class="material-icons">format_indent_increase</i></button>
<button type="button" id="printButton">Print</button>
</nav>
<div id="textBox">
</div>
<script src="main.js"></script>
</main>
</body>
</html>
You could just add "Horizontal Tab" as an HTML entity on your focused text.
First change the <p> to <pre>.
function newLine() {
const newLine = document.createElement("pre");
//...
}
Update your init function:
function init() {
var newLineButton = document.querySelector('#newLine');
newLineButton.addEventListener("click", newLine);
newLine();
document.querySelector("#printButton").addEventListener("click", printPage);
let indentRight = document.getElementById("indentRight");
indentRight.addEventListener("click", IndentRight_Click);
let indentLeft = document.getElementById("indentLeft");
indentLeft.addEventListener("click", IndentLeft_Click);
}
Then you can add the "Horizontal Tab" on the text that is focused, checking if you have already added:
function IndentRight_Click(event) {
let horizontalTab = " ";
let originalHtml = onFocus.innerHTML;
if (!originalHtml.includes("\t")) onFocus.innerHTML = horizontalTab + originalHtml;
onFocus.focus();
}
And finally, check for it again on your "Left Indentation":
function IndentLeft_Click(event) {
var originalHtml = onFocus.innerHTML;
if (originalHtml.includes("\t")) onFocus.innerHTML = originalHtml.replace("\t", "");
onFocus.focus();
}
i have a form that loads unique pages when submitted based on what the user selects on a particular drop-down. in a particular option in the drop-down i set the pop up screen to show when the form is submitted but this loads the page again and brings the pop up. i need to prevent the page from loading again, please help
<label>payment plan?</label>
<select id="mySelect" name="payment-plan">
<option value="plan.html">day</option>
<option value="plan1.html">night</option>
<option value="#msa-popup1">special</option>
<option value="plan3.html">day and night</option>
<option value="plan4.html">weekly</option>
<option value="plan5.html">monthly</option>
<option value="plan6.html">Yearly</option>
</select>
<!-- pop up -->
<div id="msa-popup1" class="msa-overlay">
<div class="msa-popup">
<h2>For Sale?</h2>
<a class="msa-close" href="#">×</a>
<div class="msa-content">
what plan suits you? <br>
</div>
</div>
</div>
<!-- pop up ending -->
.msa-overlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0,0,0,0.51);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
.msa-overlay:target {
visibility: visible;
opacity: 1;
}
.msa-popup {
margin: 70px auto;
padding: 20px;
background: #fff;
border-radius: 5px;
width: 65%;
position: relative;
transition: all 5s ease-in-out;
}
.msa-popup h2 {
margin-top: 0;
color: #333;
font-family: Josefin Sans, sans-serif;
}
.msa-popup .msa-close {
position: absolute;
top: 20px;
right: 30px;
transition: all 200ms;
font-weight: bold;
text-decoration: none;
color: #333;
}
.msa-popup .msa-close:hover {
color: #3462FA;
}
.msa-popup .msa-content {
max-height: 30%;
overflow: auto;
font-size:.9em;
text-align: center;
}
var form = document.getElementById('myForm');
var select = document.getElementById('mySelect')
select.onchange=function(e){
form.setAttribute('action', e.target.value);
}
Add a submit handler to the form, and if the action value starts with a #, set the window.location.hash manually, and return false; to keep the form from submitting and refreshing the page. Here's a codepen since this won't work within the code sandbox on SO - http://codepen.io/mcoker/pen/MpoYgJ
Seems like you're missing some code, too - there is no form#myForm or submit button, so added those. Please update your post with all of the relevant code.
var form = document.getElementById('myForm');
var select = document.getElementById('mySelect');
select.onchange = function(e) {
form.setAttribute('action', e.target.value);
}
form.onsubmit = function(e) {
var action = this.getAttribute('action');
if (action.substr(0,1) == '#') {
window.location.hash = this.getAttribute('action');
return false;
}
}
.msa-overlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.51);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
.msa-overlay:target {
visibility: visible;
opacity: 1;
}
.msa-popup {
margin: 70px auto;
padding: 20px;
background: #fff;
border-radius: 5px;
width: 65%;
position: relative;
transition: all 5s ease-in-out;
}
.msa-popup h2 {
margin-top: 0;
color: #333;
font-family: Josefin Sans, sans-serif;
}
.msa-popup .msa-close {
position: absolute;
top: 20px;
right: 30px;
transition: all 200ms;
font-weight: bold;
text-decoration: none;
color: #333;
}
.msa-popup .msa-close:hover {
color: #3462FA;
}
.msa-popup .msa-content {
max-height: 30%;
overflow: auto;
font-size: .9em;
text-align: center;
}
<form id="myForm">
<label>payment plan?</label>
<select id="mySelect" name="payment-plan">
<option value="plan.html">day</option>
<option value="plan1.html">night</option>
<option value="#msa-popup1">special</option>
<option value="plan3.html">day and night</option>
<option value="plan4.html">weekly</option>
<option value="plan5.html">monthly</option>
<option value="plan6.html">Yearly</option>
</select>
<input type="submit">
</form>
<!-- pop up -->
<div id="msa-popup1" class="msa-overlay">
<div class="msa-popup">
<h2>For Sale?</h2>
<a class="msa-close" href="#">×</a>
<div class="msa-content">
what plan suits you? <br>
</div>
</div>
</div>
<!-- pop up ending -->
You can try this here:
https://jsfiddle.net/mikeydouglas/7hr5qp3n/10/
<label>payment plan?</label>
<select id="mySelect" name="payment-plan">
<option value="">Select a Plan...</option>
<option value="plan.html">day</option>
<option value="plan1.html">night</option>
<option value="#msa-popup1">special</option>
<option value="plan3.html">day and night</option>
<option value="plan4.html">weekly</option>
<option value="plan5.html">monthly</option>
<option value="plan6.html">Yearly</option>
</select>
<!-- pop up -->
<div id="msa-popup1" class="msa-overlay">
<div class="msa-popup">
<h2>For Sale?</h2>
<a class="msa-close" href="#">×</a>
<div class="msa-content">
what plan suits you? <br>
</div>
</div>
</div>
<!-- pop up ending -->
<script>
var mSelect = document.getElementById("mySelect");
mSelect.addEventListener("change", function() {
// var strUser = e.options[e.selectedIndex].value;
var popPage = mSelect.options[mSelect.selectedIndex].value;
alert("The page " +popPage+ "should open next if popups are not disabled")
window.open(popPage);
});
</script>
I am facing one issue in my html code please check that out below in code:
HTML:
<div class="agent_select_wrap">
<select name="menu-114" class="wpcf7-form-control wpcf7-select" aria-invalid="false">
<option value="Select Category" selected="selected">Select Agent Name</option>
<option>Mr. abc</option>
<option>Mr. abc</option>
<option>Mr. abc</option>
</select>
</div>
<div class="agent_select_wrap02">
<div class="my_textarea"></div>
<button>Send</button>
</div>
CSS
.agent_select_wrap { width: 40%; margin: 30px auto 10px auto;}
.agent_select_wrap02 { width: 40%; margin: 0px auto 50px auto;}
.agent_select_wrap select{font-weight:100; font-family: 'Open Sans', sans-serif; font-size: 13px; color: #494949; background: #fff url('../images/selectbox-arrow02.png') right center no-repeat; outline: 0; margin-bottom: 0px; margin: auto; width: 100%; height: 40px; border: 1px solid #ccc; border-radius: 0; -webkit-appearance: none; -moz-appearance: none; appearance: none; -ms-appearance: none; /*box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.25);*/}
.agent_select_wrap select option { background: #fff; color: #000;}
.my_textarea textarea {font-weight:100; font-family: 'Open Sans', sans-serif; font-size: 13px; color: #494949; width:97.4%; display:block; height: 100px; border: 1px solid #ccc; padding: 6px 0 0 6px; margin: 0; border-radius: 0px; /*box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.25);*/}
.my_textarea p{padding: 0; margin: 0; text-align: center; font-size: 12px;font-family: 'Open Sans', sans-serif;}
.agent_select_wrap02 button { display: block; margin: 16px auto 0 auto; padding: 7px 30px; background: #494949; color: #fff; font-weight: 100; font-family: 'Open Sans', sans-serif; font-size: 18px; border: 0;}
.agent_select_wrap02 button:hover {cursor:pointer;}
JS
$(document).on('change', 'select[name=menu-114]', function () {
$("<textarea> Hello Mr. </textarea>").appendTo(".my_textarea")
$("<p>Please enter your message here..!</p>").appendTo(".my_textarea")
$(function () {
$('select').change(function () {
$that = $(this);
$('textarea').val(function () {
return $(this).prop('defaultValue') + ' ' + $that.val();
});
});
});
});
here is my working example
https://jsfiddle.net/7j623eho/
you just need to change one line of code in javascript code.
$(".my_textarea").html("<textarea> Hello Mr.</textarea><p>Please enter your message here..!</p>");
use above code Instead of yours ..
$("<textarea> Hello Mr. </textarea>").appendTo(".my_textarea")
$("<p>Please enter your message here..!</p>").appendTo(".my_textarea")
Probably your problem is that you don't remove just created textarea. Try to create it in <div id='temp'> element and then remove this element just before you create new one.
$('#temp').remove();
var container = $('<div id="temp">');
$("<textarea> Hello Mr. </textarea>").appendTo(container);
$("<p>Please enter your message here..!</p>").appendTo(container);
container.appendTo(".my_textarea");
I believe what you want is to create the textarea only once, and let the inline handler to handle further change, so the better way to achieve it is
var onMenuSelected = function () {
$("<textarea> Hello Mr. </textarea>").appendTo(".my_textarea")
$("<p>Please enter your message here..!</p>").appendTo(".my_textarea")
$(function () {
$('select').change(function () {
$that = $(this);
console.log('Select');
$('textarea').val(function () {
return $(this).prop('defaultValue') + ' ' + $that.val();
});
});
});
// Just unbind self
$(document).off('change', 'select[name=menu-114]', onMenuSelected);
}
$(document).on('change', 'select[name=menu-114]', onMenuSelected);
By define the function, you can directly remove the $(document).on without remove other possible exist handlers. And the select event will only be registered once.
jsFiddle here.
Here we go, use the following code:
HTML
<div class="agent_select_wrap">
<select name="menu-114" class="wpcf7-form-control wpcf7-select" aria-invalid="false">
<option value="Select Category" selected="selected">Select Agent Name</option>
<option>Mr. abc</option>
<option>Mr. abc</option>
<option>Mr. abc</option>
</select>
</div>
<div class="agent_select_wrap02">
<div id="my_textarea0">
</div>
<textarea id="my_textarea">
</textarea>
<button>Send</button>
</div>
JS
$(document).on('change', 'select[name=menu-114]', function () {
$("#my_textarea0").html("<textarea> Hello Mr. </textarea>")
$("#my_textarea").html("<p>Please enter your message here..!</p>")
$(function () {
$('select').change(function () {
$that = $(this);
$('textarea').val(function () {
return $(this).prop('defaultValue') + ' ' + $that.val();
});
});
});
});