JS Constructor Function Can't Find Global Variable - javascript

The crux of this problem is that assigning a variable to an html element is not working within a constructor function.
There must be a way around this right?
The most effective way I have found is to create a method within the constructor function that returns the element.
The problematic variable is "box".
I commented out the section at the start where I tried to make box a global variable, but the constructor couldn't find the box variable. That is the weirdest part to me.
Below is my sample code:
window.onload = function()
{
document.getElementById("sub_button").onclick = adder;
document.getElementById("scrap_it").onclick = remover;
}
//var box = document.getElementById("contact_list");
//refers to the select tag containing contact names as options
var Contacts = function()
{
this.box = function (){ return document.getElementById("contact_list");}
this.list = [];
this.contact_info = document.getElementById("contact_info");
this.find = function(personName){
var found = "missing";
for(var i = 0; i < this.list.length; i++)
{
if(this.list[i].personName == personName)
{
found = i;
}
}
return found;
}
this.addPerson = function(personName, phone)
{
if (this.find(personName) == "missing")
{
personName = personName;
contact =
{
personName: personName,
phone: phone
}
this.list.push(contact);
this.update();
}
else
{
alert("Sorry, this contact name is already in use. Please choose another.");
}
}
this.update = function()
{
this.box().innerHTML = "";
for (var i = 0; i <this.list.length; i++)
{
option_element = document.createElement("OPTION");
option_node = document.createTextNode(this.list[i].personName);
option_element.appendChild(option_node);
this.box().appendChild(option_element);
}
}
this.remove = function(name_to_delete)
{
var index_to_remove = name_to_delete;
this.list.splice(index_to_remove, 1);
this.update();
}
this.postInfo = function(contact_to_display)
{
var index_to_display = contact_to_display;
alert(this.list[index_to_display].personName);
alert(this.list[index_to_display].phone);
}
}
var myList = new Contacts();
function adder()
{
myList.addPerson(document.getElementById("contact_name").value, document.getElementById("contact_phone").value);
}
function remover()
{
myList.remove(myList.box().selectedIndex);
}
function showInfo()
{
myList.postInfo(myList.box().selectedIndex);
}
And the HTML:
<html>
<head>
<title>Address Book</title>
<script type="text/javascript" src="beta3.js"></script>
</head>
<body>
<form id="contact_form">
<label for="contact_name">Name: </label>
<input type="text" id="contact_name" /><br />
<label for="contact_phone">Phone: </label>
<input type="text" id="contact_phone" /><br />
<input type="button" name="submit" value="submit" id="sub_button" />
</form>
<br />
<div>
Delete
</div>
<br />
<div>
<select name="contact_list" id="contact_list" size="10" multiple="multiple" style="width: 450px">
</select>
</div>
<div>
<textarea id="contact_info">
</textarea>
</div>
</body>
</html>

try something like this
var box;
window.onload = function()
{
document.getElementById("sub_button").onclick = adder;
document.getElementById("scrap_it").onclick = remover;
//refers to the select tag containing contact names as options
box = document.getElementById("contact_list");
}
Your code is not working because your script is executed before our element is render in dom so your box variable get nothing.

Related

Update URL’s based on Input text

I’m trying to make an animated radar based on the location specified on the input text field. What I’m trying to achieve is when a user enters a location in the input text field, I want the specified location to be placed in the {location} part of each url. How can I achieve this?
Here is what I have:
<html>
<head>
</head>
<body>
<img class="slide" width="1080" height="1080" style="background-image:url('https://maps.aerisapi.com/{api-key}/flat,counties,admin-lg/1080x1080/{location},9/0.png32')">
<br>
<br>
<form>
<label>Location:</label>
<input type="text" id="location" />
<br>
<br>
<input type="submit" value="submit" onclick="goToPage();" />
</form>
<script>
var currentImage = 0,
images = [
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/-50minutes.png",
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/-40minutes.png",
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/-30minutes.png",
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/-20minutes.png",
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/-10minutes.png",
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/current.png"
];
function initSlideshow() {
setImage(0);
setInterval(function() {
nextImage();
}, 700);
}
function nextImage() {
if (images.length === currentImage + 1) {
currentImage = 0;
} else {
}
setImage(currentImage);
}
function setImage(image) {
document.querySelectorAll('.slide')[0].src = images[image];
}
window.onload = initSlideshow();
</script>
</body>
</html>
This form will reload the page. If you want to execute a script that updates a variable in the page when you click the submit button, that's probably not desirable. So, change:
<input type="submit" value="submit" onclick="goToPage();" />
to
<input type="submit" value="submit" onclick="event.preventDefault();goToPage();" />
Then, if goToPage() is the function you want to update the image urls in, that function should look like this:
function goToPage(){
images.map((image) => image.replace("{location}", document.getElementById("location").value));
}
NOTE: this function will replace the "{location}" part of the image url strings, so you won't be able to do this action twice. If you want to be able to do this twice, I'd suggest not actually updating the image url strings, but rather making a getter that will build you a new images array with custom locations on the fly whenever you want, like so:
var locationValue = "";
function goToPage(){
locationValue = document.getElementById("location").value;
}
function getImages(){
var imagesCopy = [];
for(var i = 0; i < images.length; i++) imagesCopy[i] = images[i].replace("{location}", locationValue);
return imagesCopy;
}
Here that all is together:
<html>
<head>
</head>
<body>
<img class="slide" width="1080" height="1080" style="background-image:url('https://maps.aerisapi.com/{api-key}/flat,counties,admin-lg/1080x1080/{location},9/0.png32')">
<br>
<br>
<form>
<label>Location:</label>
<input type="text" id="location" />
<br>
<br>
<input type="submit" value="submit" onclick="event.preventDefault();goToPage();console.log(getImages());" />
</form>
<script>
var currentImage = 0,
images = [
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/-50minutes.png",
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/-40minutes.png",
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/-30minutes.png",
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/-20minutes.png",
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/-10minutes.png",
"https://maps.aerisapi.com/{api-key}/radar:75/1080x1080/{location},9/current.png"
];
var locationValue = "";
function goToPage(){
locationValue = document.getElementById("location").value;
}
function getImages(){
var imagesCopy = [];
for(var i = 0; i < images.length; i++) imagesCopy[i] = images[i].replace("{location}", locationValue);
return imagesCopy;
}
function initSlideshow() {
setImage(0);
setInterval(function() {
nextImage();
}, 700);
}
function nextImage() {
if (getImages().length === currentImage + 1) {
currentImage = 0;
} else {
}
setImage(currentImage);
}
function setImage(image) {
document.querySelectorAll('.slide')[0].src = getImages()[image];
}
window.onload = initSlideshow();
</script>
</body>
</html>

How to add reset button in the dialog in Google Sheets

I'm new to the scripting, but from what I have learned from this website, I have put together a check book balancesheet in google sheets.
I have a function "AddCheck" attached to the button on one of the cell. What it does is - opens a dialog box where I enter check details, like Date, Invoice number, amount and vendor's name. Then I click the submit button and Google sheets creates a row and adds those values.
My Question is how do I add a button next to the submit button that will allow me to add the New check details without leaving the dialog box. So that it will add the values to the cells and will clear the dialog box for another Entry.
This is my AddCheck function
function AddCheck() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('3:3').activate();
spreadsheet.getActiveSheet().insertRowsBefore(spreadsheet.getActiveRange().getRow(), 1);
spreadsheet.getActiveRange().offset(0, 0, 1, spreadsheet.getActiveRange().getNumColumns()).activate();
spreadsheet.getRange('A3').activate();
spreadsheet.getCurrentCell().setFormula('=A4+1');
spreadsheet.getRange('G3').activate();
spreadsheet.getCurrentCell().setValue('Pending');
spreadsheet.getRange('B3').activate();
fncOpenMyDialog()
};
This is my HTML dialog file
<!DOCTYPE html>
<html>
<body>
<form>
<label for="Date">Date :</label>
<input type='date' name='Date' id="Date" required="required"/>
<br>
<label for="Invoice">Invoice</label>
<input type='text' name='Invoice' id="Invoice" required="required"/>
<label for="Amount">Amount</label>
<input type='text' name='Amount' id="Amount" required="required"/>
<label for="Company">Company</label>
<select name="Class" id="vendor-selector" autofocus="autofocus" autocorrect="off" autocomplete="off">
<script>
(function () {
google.script.run.withSuccessHandler(
function (selectList) {
var select = document.getElementById("vendor-selector");
for( var i=0; i<selectList.length; i++ ) {
var option = document.createElement("option");
option.text = selectList[i][0];
select.add(option);
}
}
).getSelectList();
}());
</script>
</select>
<input type="submit" value="Submit" onclick="myFunction(this.parentNode)">
</form>
<p id="CompanyName"></p>
<script>
function myFunction(obj) {
var x = document.getElementById("vendor-selector").value;
document.getElementById("CompanyName").innerHTML = x;
google.script.run
.withSuccessHandler(() => google.script.host.close())
.functionToRunOnFormSubmit(obj);
}
</script>
</body>
</html>
This Function calls the Dialog
function fncOpenMyDialog() {
//Open a dialog
var htmlDlg = HtmlService.createHtmlOutputFromFile('CheckDetails')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(200)
.setHeight(250);
SpreadsheetApp.getUi()
.showModalDialog(htmlDlg, 'Check Details');
};
function functionToRunOnFormSubmit(fromInputForm) {
Logger.log(fromInputForm);
var ss = SpreadsheetApp.getActive();
ss.getSheetByName("Checks").getRange(3,3).setValues([[fromInputForm.Class]]);
ss.getSheetByName("Checks").getRange(3,2).setValues([[fromInputForm.Date]]);
ss.getSheetByName("Checks").getRange(3,4).setValues([[fromInputForm.Invoice]]);
ss.getSheetByName("Checks").getRange(3,6).setValues([[fromInputForm.Amount]]);
};
and this Function gets the List of vendors from Sheet2
function getSelectList()
{
var sheet = SpreadsheetApp.openById("141mlnxJBjepKxYCGXHFhz5IIEVnp6T2DDsb_uRgnZzY").getSheetByName('Sheet2');
var lastRow = sheet.getLastRow();
var myRange = sheet.getRange("A2:A" + lastRow);
var data = myRange.getValues();
Logger.log("Data = " + data);
return data;
};
function doGet()
{
return HtmlService.createHtmlOutputFromFile('CheckDetails');
}
Thank you for your help.
In order to implement this "Submit & Continue" feature, you only need to change the front-end code so that:
There is a new button.
Upon clicking the new button, the same back-end (GAS) code gets executed.
The dialog does not get closed after the GAS code execution, but the input elements are reset.
Code modifications
Add an id to the form tag so that it may be easily selected.
<form id="CheckDetailsForm">
Create a "Submit & Continue" button in your HTML. Assign an id to it so that it may be easily selected.
<input type="submit" value="Submit and continue" id="SubmitAndContinueInput" />
Within the script tag, add an event listener to the newly created button.
document.getElementById("SubmitAndContinueInput").addEventListener("click", myFunctionContinue);
Add the handler function for the newly created button's onclick event. This function will be very similar as the one you are using but: It will use the preventDefault to avoid the form being incorrectly sent and will clear the form data upon submission.
function clearForm() {
document.getElementById('Date').value = "";
document.getElementById('Invoice').value = "";
document.getElementById('Amount').value = "";
}
function myFunctionContinue(e) {
e.preventDefault();
var obj = document.getElementById("CheckDetailsForm");
var x = document.getElementById("vendor-selector").value;
document.getElementById("CompanyName").innerHTML = x;
google.script.run
.withSuccessHandler(clearForm)
.functionToRunOnFormSubmit(obj);
}
Example dialog:
Edit
Handling "submit and continue" new rows:
Remove the row-insertion functionality from AddCheck(). We will handle this logic afterwards:
function AddCheck() {
fncOpenMyDialog();
}
Modify the functionToRunOnFormSubmit() function so that it handles the row-insertion logic. I have also cleaned up the code a little bit. It would look like the following:
function functionToRunOnFormSubmit(fromInputForm) {
Logger.log(fromInputForm);
var sheet = SpreadsheetApp.getActive().getSheetByName("Checks");
sheet.insertRowBefore(3);
sheet.getRange("A3").setFormula("=A4+1");
sheet.getRange("B3").setValue(fromInputForm.Date);
sheet.getRange("C3").setValue(fromInputForm.Class);
sheet.getRange("D3").setValue(fromInputForm.Invoice);
sheet.getRange("F3").setValue(fromInputForm.Amount);
sheet.getRange("G3").setValue("Pending");
}
Full code
CheckDetails.html
<!DOCTYPE html>
<html>
<body>
<form id="CheckDetailsForm">
<label for="Date">Date :</label>
<input type='date' name='Date' id="Date" required="required"/>
<br>
<label for="Invoice">Invoice</label>
<input type='text' name='Invoice' id="Invoice" required="required"/>
<label for="Amount">Amount</label>
<input type='text' name='Amount' id="Amount" required="required"/>
<label for="Company">Company</label>
<select name="Class" id="vendor-selector" autofocus="autofocus" autocorrect="off" autocomplete="off">
<script>
(function () {
google.script.run.withSuccessHandler(
function (selectList) {
var select = document.getElementById("vendor-selector");
for( var i=0; i<selectList.length; i++ ) {
var option = document.createElement("option");
option.text = selectList[i][0];
select.add(option);
}
}
).getSelectList();
}());
</script>
</select>
<input type="submit" value="Submit" id="SubmitInput" />
<input type="submit" value="Submit and continue" id="SubmitAndContinueInput" />
</form>
<p id="CompanyName"></p>
<script>
document.getElementById("SubmitInput").addEventListener("click", myFunction);
document.getElementById("SubmitAndContinueInput").addEventListener("click", myFunctionContinue);
function clearForm() {
document.getElementById('Date').value = "";
document.getElementById('Invoice').value = "";
document.getElementById('Amount').value = "";
}
function myFunction(e) {
e.preventDefault();
var obj = document.getElementById("CheckDetailsForm");
var x = document.getElementById("vendor-selector").value;
document.getElementById("CompanyName").innerHTML = x;
google.script.run
.withSuccessHandler(() => google.script.host.close())
.functionToRunOnFormSubmit(obj);
}
function myFunctionContinue(e) {
e.preventDefault();
var obj = document.getElementById("CheckDetailsForm");
var x = document.getElementById("vendor-selector").value;
document.getElementById("CompanyName").innerHTML = x;
google.script.run
.withSuccessHandler(clearForm)
.functionToRunOnFormSubmit(obj);
}
</script>
</body>
</html>
Code.gs
function AddCheck() {
fncOpenMyDialog()
}
function fncOpenMyDialog() {
//Open a dialog
var htmlDlg = HtmlService.createHtmlOutputFromFile('CheckDetails')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(200)
.setHeight(250);
SpreadsheetApp.getUi()
.showModalDialog(htmlDlg, 'Check Details');
}
function functionToRunOnFormSubmit(fromInputForm) {
Logger.log(fromInputForm);
var sheet = SpreadsheetApp.getActive().getSheetByName("Checks");
sheet.insertRowBefore(3);
sheet.getRange("A3").setFormula("=A4+1");
sheet.getRange("B3").setValue(fromInputForm.Date);
sheet.getRange("C3").setValue(fromInputForm.Class);
sheet.getRange("D3").setValue(fromInputForm.Invoice);
sheet.getRange("F3").setValue(fromInputForm.Amount);
sheet.getRange("G3").setValue("Pending");
}
function getSelectList() {
var sheet = SpreadsheetApp.openById("141mlnxJBjepKxYCGXHFhz5IIEVnp6T2DDsb_uRgnZzY").getSheetByName('Sheet2');
var lastRow = sheet.getLastRow();
var myRange = sheet.getRange("A2:A" + lastRow);
var data = myRange.getValues();
Logger.log("Data = " + data);
return data;
}
function doGet() {
return HtmlService.createHtmlOutputFromFile('CheckDetails');
}

Trying to save all generated 'li' elements to local storage using JavaScript

This code successfully takes the contents of the form and saves it to an ordered list, 2 more functions do the same thing but instead create a timestamp. I'm trying to take every li element that gets generated and save it to localStorage when you push the save button and then repopulate it again from the local storage when you push the "load" button. I can't get it to work come hell or high water. The load button does nothing, and oddly enough the "save" button acts as a clear all and actually removes everything rather then saving it. Console log shows no errors. I have the JavaScript below and the corresponding HTML.
let item;
let text;
let newItem;
function todoList() {
item = document.getElementById("todoInput").value
text = document.createTextNode(item)
newItem = document.createElement("li")
newItem.onclick = function() {
this.parentNode.removeChild(this);
}
newItem.onmousemove = function() {
this.style.backgroundColor = "orange";
}
newItem.onmouseout = function() {
this.style.backgroundColor = "lightblue";
}
todoInput.onclick = function() {
this.value = ""
}
newItem.appendChild(text)
document.getElementById("todoList").appendChild(newItem)
};
function save() {
const fieldvalue = querySelectorAll('li').value;
localStorage.setItem('item', JSON.stringify(item));
}
function load() {
const storedvalue = JSON.parse(localStorage.getItem(item));
if (storedvalue) {
document.querySelectorAll('li').value = storedvalue;
}
}
<form id="todoForm">
<input id="todoInput" value="" size="15" placeholder="enter task here">
<button id="button" type="button" onClick="todoList()">Add task</button>
<button id="save" onclick="save()">Save</button>
<button id="load" onclick="load()">Load</button>
</form>
As #Phil and #Gary explained part of your problem is trying to use querySelectorAll('li') as if it would return a single value. You have to cycle through the array it returns.
Check the below code to give yourself a starting point. I had to rename some of your functions since they were causing me some errors.
<form id="todoForm">
<input id="todoInput" value="" size="15" placeholder="enter task here">
<button id="button" type="button" onClick="todoList()">Add task</button>
<button id="save" onclick="saveAll()" type="button">Save</button>
<button id="load" onclick="loadAll()" type="button">Load</button>
</form>
<div id="todoList"></div>
<script>
let item;
let text;
let newItem;
function todoList() {
item = document.getElementById("todoInput").value
text = document.createTextNode(item)
newItem = document.createElement("li")
newItem.onclick = function() {
this.parentNode.removeChild(this);
}
newItem.onmousemove = function() {
this.style.backgroundColor = "orange";
}
newItem.onmouseout = function() {
this.style.backgroundColor = "lightblue";
}
todoInput.onclick = function() {
this.value = ""
}
newItem.appendChild(text)
//Had to add the element
document.getElementById("todoList").appendChild(newItem);
}
function saveAll() {
//Create an array to store the li values
var toStorage = [];
var values = document.querySelectorAll('li');
//Cycle through the li array
for (var i = 0; i < values.length; i++) {
toStorage.push(values[i].innerHTML);
}
console.log(toStorage);
//Can´t test this on stackoverflow se the jsFiddle link
localStorage.setItem('items', JSON.stringify(toStorage));
console.log(localStorage);
}
function loadAll() {
const storedvalue = JSON.parse(localStorage.getItem('items'));
console.log(storedvalue);
//Load your list here
}
</script>
Check https://jsfiddle.net/nbe18k2u/ to see it working

How to connect JS functions to checkbox

Hello,
I am making a simple text changer website where I want the user to be able to select what options to use. Right now I have two options; myConvertOption which capitalizes every odd letter in a word and I have myScrambleOption which randomly mixes up each word a bit.
Right now whenever you click on Caps (checkbox_1) it already executes the function where I only want it to execute whenever the user clicks on the "Convert" button + it also puts spaces in between each letter now.
The Scramble button (checkbox_2) doesn't do anything for some reason, except for console logging the change.
JSfiddle: https://jsfiddle.net/MysteriousDuck/hLjytr2p/1/
Any help and suggestions will be greatly appreciated!
P.S I am new to Javascript.
Checkbox event listeners:
checkbox_1.addEventListener('change', function () {
console.log("checkbox_1 changed");
if (this.checked) {
myConvertFunction();
} else {
//Do nothing
}
})
checkbox_2.addEventListener('change', function () {
console.log("checkbox_2 changed");
if (this.checked) {
myScrambleFunction(text);
} else {
//Do nothing
}
})
Checkbox HTML:
<div class="checkbox">
<input type="checkbox" id="checkbox_1" >
<label for="checkbox_1">Caps</label>
</div>
<div class="checkbox">
<input type="checkbox" id="checkbox_2" >
<label for="checkbox_2">Scramble</label>
</div>
this works properly..
You just had to add the event on the button and then test which check box was checked, and other little things
<!doctype html>
<html>
<head>
</head>
<body>
<div class="container">
<h1> Text Changer </h1>
<h2> CAPS + randomize letters text changer</h2>
<div class="checkbox">
<input type="checkbox" id="checkbox_1">
<label for="checkbox_1">Caps</label>
</div>
<div class="checkbox">
<input type="checkbox" id="checkbox_2">
<label for="checkbox_2">Scramble</label>
</div>
<textarea type="text" autofocus="true" placeholder="input text" id="inputText" value="Input Value" spellcheck="false" style="width: 300px;"></textarea>
<button class="button button1" id="convertText">Convert</button>
<textarea type="text" placeholder="converted text" id="convertedText" value="Clear" readonly="true" spellcheck="false" style="width: 300px;"></textarea>
<button class="button button1" id="copyText">Copy</button>
</div>
<script>
var text = document.getElementById("inputText").value;
var convertText = document.getElementById("convertText");
var checkbox_2 = document.getElementById("checkbox_2");
var checkbox_1 = document.getElementById("checkbox_1");
//Capitalize every odd letter
function myConvertFunction() {
var x = document.getElementById("inputText").value;
var string = "";
for (let i = 0; i < x.length; i++) {
if (i % 2 == 0) {
string = string + x[i].toUpperCase();
} else {
string = string + x[i];;
}
}
return string;
}
//Scramble words
function myScrambleFunction(text) {
let words = text.split(" ");
words = words.map(word => {
if (word.length >= 3) {
return word.split('').sort(() => 0.7 - Math.random()).join('');
}
return word;
});
return words.join(' ');
}
document.getElementById("copyText").addEventListener("click", myCopyFunction);
//Copy textarea output
function myCopyFunction() {
var copyText = document.getElementById("convertedText");
copyText.select();
document.execCommand("copy");
alert("Copied the text: " + copyText.value);
eraseText();
}
//Delete textarea output
function eraseText() {
document.getElementById("convertedText").value = "";
document.getElementById("inputText").value = "";
document.getElementById("inputText").focus();
}
//don't add the event to the radio buttons (previously checkboxes), add it to the convert button, and in its function test which radio button has been checked
convertText.addEventListener('click', function() {
if (checkbox_1.checked && checkbox_2.checked) {
console.log("doing both options");
document.getElementById("convertedText").value = myScrambleFunction(myConvertFunction());
} else if (checkbox_2.checked) {
console.log("proceeding scrumble");
document.getElementById("convertedText").value = myScrambleFunction(text);
} else if (checkbox_1.checked) {
console.log("proceeding cap");
document.getElementById("convertedText").value = myConvertFunction();
}
})
</script>
</body>
</html>
You're never updating var text.
You need to update it before using it if you want the value to be something other than an empty string.
checkbox_2.addEventListener('change', function () {
console.log("checkbox_2 changed");
if (this.checked) {
text = document.getElementById("inputText").value;
myScrambleFunction(text);
} else {
//Do nothing
}

Inline form Validation

I'm trying to get my form to validate inline but can't seem to get the right syntax, at the moment I have this, which does nothing yet. The first function, formhandler is meant to change the span elements text if the element gets blured and take away the error text once the field is focused at the moment it does neither of these.
<html>
<script type = "text/javascript">
document.getElementById("form").onfocus = function formHandler() {
for(var i = 0; i < document.getElementById("form").length; i+=1){
if(document.getElementById("form").elements[i].type == 'text') {
if(document.getElementById("form").elements[i].focus()) {
var onode = document.getElementById("form").elements[i].nextSibling;
onode.innerHTML = "";
valid = true;
}
else if(document.getElementById("form").elements[i].blur()) {
var onode = document.getElementById("form").elements[i].nextSibling;
onode.innerHTML = "Please Fill in Field";
valid = false;
}
}
}
}
function validate() {
var valid = false;
for(var i = 0; i < document.getElementById("form").length; i+=1){
if(document.getElementById("form").elements[i].type == 'text') {
if(document.getElementById("form").elements[i].value == "") {
var onode = document.getElementById("form").elements[i].nextSibling;
onode.innerHTML = "Please Fill in Field";
valid = true;
}
else{
var onode = document.getElementById("form").elements[i].nextSibling;
onode.innerHTML = "";
valid = false;
}
}
}
}
document.getElementById("form").onsubmit = validate;
</script>
<head>
<title>Question 1 / Vraag 1 - Basic JavaScript Validaton / Basiese JavaScript validasie
</title>
<link rel="Stylesheet" type="text/css" href="style.css" />
</head>
<body>
<form method="get" action="" id = "form">
<table>
<tr>
<td> Firstname:</td>
<td> <input type="text" name="firstname" id="firstname" /><span id="fnError">
</span></td>
</tr>
<tr>
<td> Surname:</td>
<td> <input type="text" name="surname" id="surname" /><span id="snError">
</span></td>
</tr>
<tr>
<td> Age:</td>
<td> <input type="text" name="age" id="age" /><span id="aError">
</span></td>
</tr>
<tr>
<td> Email:</td>
<td><input type="text" name="email" id="email" /><span id="eError">
</span></td>
</tr>
<tr><td colspan="2"><input type="button" value="Validate" onclick = "validate()"/></td></tr>
</table>
</form>
</body>
</html>
I'm trying to achieve this without the use of jquery, so please don't suggest it, thanks in advance.
These are problems I found in your code:
Line 1: Forms don't have a .focus method. What did you mean for that to do?
Line 2: Change .length to .elements:
for (var i = 0; i < document.getElementById("form").elements.length; i++ ) {
var node = document.getElementById("form").elements[i];
...
The elements in the form are now aliased as node.
Lines 4: The .focus/.blur method doesn't return true if the element is out of focus. We're going to have to do it ourselves:
node.onfocus = function() { this.isInFocus = true; };
node.onblur = function() { this.isBlurred = !this.isInFocus; };
The resulting code is as follows:
if ( node.isInfocus ) { ... }
else if ( node.isBlurred ) { ... }
Line 9: Refer to above.
Wrap the code in a window.onload to be able to use the DOM elements when the DOM has loaded.
This is your revised code; let me know if it works for you:
var nodes = document.getElementById('form').elements, node;
for ( var i = 0; i < nodes.length; i++ ) (function(i) {
nodes[i].onfocus = function() { this.isInFocus = true; };
nodes[i].onblur = function() { this.isBlurred = !this.isInFocus; };
})(i);
for (var i = 0; i < nodes.length; i++) {
node = nodes[i];
if (node.type == 'text') {
if (node.isInFocus) {
var onode = node.nextSibling;
onode.innerHTML = "";
valid = true;
} else if (node.isBlurred) {
var onode = node.nextSibling;
onode.innerHTML = "Please Fill in Field";
valid = false;
}
}
}
First major problem: you are trying to do all of this in the initial script load. The main DOM is not yet loaded at that time so document.getElementById("form") won't find anything. Do the function definitions in an onload handler.
Also, not sure what you are expecting "valid" to bind to in the first function. Finally, once you have determined validity or not, you need to do something with the result.
You are referencing dom elements which don't exist yet. One solution would be to move all your <script> tag before </body>, so elements exist when the script is executed.
Another way, with pure javascript would be to do this:
<script>
window.onload = function(){
//All your code here
}
</script>
(The validate function could be outside if you want)
Cheers

Categories