The following code is meant to change the color of one field:
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
</head>
<body>
<form></form>
<form>
<input name="thisone" />
</form>
<script language="javascript">
var bkColor = "red";
function getEvent(e){
if(window.event != null) {
return event;
}
return e;
}
function setBKColor(e){
e = getEvent(e);
var src = e.srcElement || e.target;
window.status="t";
if(src != null) {
src.style.bkColor = src.style.backgroundColor;
src.style.backgroundColor = bkColor;
}
}
function reSetBKColor(e){
e = getEvent(e);
var src = e.srcElement || e.target;
if(src != null) {
src.style.backgroundColor = src.style.bkColor;
}
}
function attachEvent(name,element,callBack) {
if (element.addEventListener) {
element.addEventListener(name, callBack,false);
} else if (element.attachEvent) {
element.attachEvent('on' + name, callBack);
}
}
function setListner(eve,func) {
var ele = document.forms[0].elements;
for(var i = 0; i <ele.length;i++) {
element = ele[i];
if (element.name) {
switch (element.name) {
case 'thisone':
attachEvent(eve,element,func);
}
}
}
}
setListner("focus",setBKColor);
setListner("blur",reSetBKColor);
</script>
However, when before the field which changes color there is another form, the code stops working. So at present the HTML code could look like this, to match the inconvenience:
<name="thisone">
<form></form>
<form></form>
Now this code works.
But how to make the JS part independent from <form>, and only dependent on the <Name> of the text field?
Add an id to your form and use that to refence it
function setListner(eve,func) {
var ele = document.getElementById("#formID").elements;
Using a forms index in the DOM is an unreliable way of accessing its elements
Related
I have the following index.html. The objective of the javascript below is to reload the #obj element's data tag, so that it can display multiple images. However, it is possible that one of the images I link the buttons to doesn't exist (in this case, #2).
function updateObject(evt) {
var id = evt.currentTarget.id;
var object = document.getElementById("obj");
if (id == "1") {
object.setAttribute("data","https://upload.wikimedia.org/wikipedia/commons/f/fa/Apple_logo_black.svg")
}
else {
object.setAttribute("data", "file/that/doesnt/exist")
}
}
for (var i = 0; i < document.getElementsByTagName("button").length; i++) {
document.getElementsByTagName("button")[i].addEventListener("click", updateObject, false);
}
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
</head>
<body>
<button id="1">button1</button>
<button id="2">button2</button>
<object id="obj" style='width: 100px'></object>
</body>
</html>
What I expect to happen in the following script is this:
The user presses button1, sees apple
User presses button2, sees nothing
User presses button1, sees apple
However, the third step in that doesn't happen - when I try to reload the object's data after linking to a nonexistent file, it stays blank.
As far as I've been able to gather, this happens in Chrome, and for me works in Safari. I must use the object tag, or some other method that allows for interactive SVG.
One solution you could possibily do is to remove and add the node itself to force a hard reset
var clone = object.cloneNode();
var parent = object.parentNode;
parent.removeChild(object);
parent.appendChild(clone);
function updateObject(evt) {
var id = evt.currentTarget.id;
var object = document.getElementById("obj");
if (id == "1") {
object.setAttribute("data", "https://upload.wikimedia.org/wikipedia/commons/f/fa/Apple_logo_black.svg")
var clone = object.cloneNode();
var parent = object.parentNode;
parent.removeChild(object);
parent.appendChild(clone);
} else {
object.setAttribute("data", "file/that/doesnt/exist")
}
}
for (var i = 0; i < document.getElementsByTagName("button").length; i++) {
document.getElementsByTagName("button")[i].addEventListener("click", updateObject, false);
}
<button id="1">button1</button>
<button id="2">button2</button>
<object id="obj" style='width: 100px'></object>
Try changing the tag to an <img> and setting the "src" attribute.
function updateObject(evt) {
var id = evt.currentTarget.id;
var object = document.getElementById("obj");
if (id == "1") {
object.setAttribute("src","https://upload.wikimedia.org/wikipedia/commons/f/fa/Apple_logo_black.svg")
}
else {
object.setAttribute("src", "file/that/doesnt/exist")
}
}
for (var i = 0; i < document.getElementsByTagName("button").length; i++) {
document.getElementsByTagName("button")[i].addEventListener("click", updateObject, false);
}
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
</head>
<body>
<button id="1">button1</button>
<button id="2">button2</button>
<img id="obj" style='width: 100px'></img>
</body>
</html>
I provide a sample which helps you to solve your problem by making a fake request to that URL.
Chrome does it to inform. Even if you handle onerror correctly with correct error handling with try-catch and every trick with a void or ( ) that is told to prevent error - you can not fix it. It is out of Javascript control.
function updateObject(evt) {
var id = evt.currentTarget.id;
var object = document.getElementById("obj");
if (id == "1") {
object.setAttribute("data","https://upload.wikimedia.org/wikipedia/commons/f/fa/Apple_logo_black.svg");
}
else {
var request;
if(window.XMLHttpRequest)
request = new XMLHttpRequest();
else
request = new ActiveXObject("Microsoft.XMLHTTP");
request.open('GET', 'file/that/doesnt/exist', false);
request.send();
// the object request will be actually modified
if (request.status === 404) {
alert("The file you are trying to reach is not available.");
}
else
{
object.setAttribute("data", "file/that/doesnt/exist");
}
}
}
for (var i = 0; i < document.getElementsByTagName("button").length; i++) {
document.getElementsByTagName("button")[i].addEventListener("click", updateObject, false);
}
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
</head>
<body>
<button id="1">button1</button>
<button id="2">button2</button>
<object id="obj" style='width: 100px'></object>
</body>
</html>
But notice that it will only work on the same origin. For another host, you will have to use a server-side language to do that, which you will have to figure it out by yourself.
I am trying to check if the input name is already in a Google Sheet. However, I am getting this error:
Uncaught TypeError: google.script.run.doSomething is not a function.
Here is my Index.html file.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<meta charset="UTF-8">
</head>
<body>
<input type="text" id="meetingTitle" value=""> // Getting value here
<button onclick="checkName()">Check if available</button> //Calling function is is causing the error.
<p id=nameVerification><i>Click the button above to check availability.</i></p>
<script>
function checkName() {
var toPass = document.getElementById("meetingTitle").value;
prompt("toPass " + toPass);
google.script.run.doSomething();
}
function checkNameCS(checkNameSSReturn) {
if (checkNameSSReturn == "") {
document.getElementById('nameVerification').innerHTML = "Already in Use: Please try with another name."
document.getElementById("meetingTitle").value = "";
} else {
document.getElementById("meetingTitle").value = checkNameSSReturn;
document.getElementById('nameVerification').innerHTML = "Meeting name available. Procced."
}
}
function doSomething () {
var nameGiven = document.getElementById("meetingTitle").value;
var nameExists = false;
var nameVerified = false;
var name = nameGiven.toLowerCase();
name = strip(name);
prompt("name " + name);
var spreadsheetId = ''; //Sheet id entered
var rangeName = 'Sheet1';
var values = Sheets.Spreadsheets.Values.get(spreadsheetId, rangeName).values;
if (!values) {} else {
for (var row = 0; row < values.length; row++) {
if (name == values[row][0]) {
nameExists = true;
}
}
}
if (nameExists) {
checkNameCS("");
prompt("name2 " + " ");
return;
}
nameVerified = true;
prompt("name2 " + name);
checkNameCS(name);
return;
}
function strip(str) {
return str.replace(/^\s+|\s+$/g, '');
}
</script>
</body>
</html>
I tried debuging it with prompts but with no success. It seems like the function do something is properly called. But the code stops working aftergoogle.script.run.doSomething();.
I have looked at the documentation for successhandlers but they dont solve the issue either.
How about this modification?
Issue of your script:
doSomething() of google.script.run.doSomething() is required to be Google Apps Script.
In your script, doSomething() is put in HTML (index.html), and a method for using Google Apps Script is included. When google.script.run.doSomething() is run, doSomething() cannot be found at Google Apps Script (code.gs). By this, such error occurs. And if doSomething() is run at HTML side, also an error occurs at Sheets.Spreadsheets.Values.get(), because Sheets.Spreadsheets.Values.get() is the method of Advanced Google Services with Google Apps Script.
If you put it to Google Apps Script (code.gs), Javascript which is used at the script of doSomething() is required to be modified.
Modified script:
In this modification, your script was separated to Google Apps Script (code.gs) and HTML (index.html). var nameGiven = document.getElementById("meetingTitle").value; and checkNameCS(name); are used in index.html.
By the way, before you run this script, please enable Sheets API at Advanced Google Services.
Google Apps Script: code.gs
function strip(str) {
return str.replace(/^\s+|\s+$/g, '');
}
function doSomething (nameGiven) {
var nameExists = false;
var nameVerified = false;
var name = nameGiven.toLowerCase();
name = strip(name);
var spreadsheetId = '###'; //Sheet id entered
var rangeName = 'Sheet1';
var values = Sheets.Spreadsheets.Values.get(spreadsheetId, rangeName).values;
if (values) {
for (var row = 0; row < values.length; row++) {
if (name == values[row][0]) {
nameExists = true;
}
}
}
if (nameExists) {
return "";
}
nameVerified = true;
return name;
}
HTML: index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<meta charset="UTF-8">
</head>
<body>
<input type="text" id="meetingTitle" value="">
<button onclick="checkName()">Check if available</button>
<p id=nameVerification><i>Click the button above to check availability.</i></p>
<script>
function checkName() {
var toPass = document.getElementById("meetingTitle").value;
prompt("toPass " + toPass);
var nameGiven = document.getElementById("meetingTitle").value; // Added
google.script.run.withSuccessHandler(checkNameCS).doSomething(nameGiven); // Modified
}
function checkNameCS(checkNameSSReturn) {
console.log(checkNameSSReturn)
if (checkNameSSReturn == "") {
document.getElementById('nameVerification').innerHTML = "Already in Use: Please try with another name."
document.getElementById("meetingTitle").value = "";
} else {
document.getElementById("meetingTitle").value = checkNameSSReturn;
document.getElementById('nameVerification').innerHTML = "Meeting name available. Procced."
}
}
</script>
</body>
</html>
Reference:
Class google.script.run
Here is an example from the book "DOM Scripting: Web Design with JavaScript and the Document Object Model." I don't know why it's not working. When I click on the list, the pictures should be changed in the placeholder. But now they only open in the window.
Thank you!
window.onload = prepareGallery;
function prepareGallery() {
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
if (!document.getElementById("imagegallery")) return false;
var gallery = document.getElementById("imagegallery");
var links = gallery.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
links[i].onclick = function() {
return showPic(this) ? false : true;
}
}
}
function showPic(whichpic) {
if (!document.getElementById("placeholder")) return false;
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
if (placeholder.nodeNae != "IMG") return false;
placeholder.setAttribute("src", source);
if (document.getElementById("description")) {
var text = whichpic.getAttribute("title") ? whichpic.getAttribute("title") : "";
if (description.firstChild.nodeType == 3) {
description.firstChild.nodeValue = text;
}
}
return true;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Image Gallery</title>
</head>
<body>
<h1>Snapshots</h1>
<ul id="imagegallery">
<li>Flower</li>
<li>Building</li>
<li>Cold Day</li>
<li>Sunset</li>
</ul>
<p id="description">Choose an Image.</p>
<img src="images/placeholder.png" alt="my image gallery" id="placeholder" style="border: 2px solid #eaeaea">
</body>
</html>
So I looked up the ebook. didn't want to buy it to answer a question, but I took a look at the source code and couldn't find what chapter you'd be on to be using just this code. from what it looks like it, I can only guess you're on chapter 6, so take a look at the example JS script for that chapter, it works fine. also, you have a syntax error on line 38 of your code "documnet" should probably be document. Would have made this a comment but couldn't.
The issue is if (placeholder.nodeNae != "IMG") return false; nodeNae should be nodeName. Not sure why the snippet wasn't throwing an error.
window.onload = prepareGallery;
function prepareGallery() {
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
if (!document.getElementById("imagegallery")) return false;
var gallery = document.getElementById("imagegallery");
var links = gallery.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
links[i].onclick = function() {
return showPic(this) ? false : true;
}
}
}
function showPic(whichpic) {
if (!document.getElementById("placeholder")) return false;
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
if (placeholder.nodeName != "IMG") return false;
placeholder.setAttribute("src", source);
if (document.getElementById("description")) {
var text = whichpic.getAttribute("title") ? whichpic.getAttribute("title") : "";
if (description.firstChild.nodeType == 3) {
description.firstChild.nodeValue = text;
}
}
return true;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Image Gallery</title>
</head>
<body>
<h1>Snapshots</h1>
<ul id="imagegallery">
<li>Flower</li>
<li>Building</li>
<li>Cold Day</li>
<li>Sunset</li>
</ul>
<p id="description">Choose an Image.</p>
<img src="images/placeholder.png" alt="my image gallery" id="placeholder" style="border: 2px solid #eaeaea">
</body>
</html>
This code seems pretty outdated so I'm going to write a newer one.
const is a block scoped variable that cannot have the value altered and cannot be redeclared. Docs
.querySelector and .querySelectorAll return either a DOM object or a NodeList of matching nodes respectively. Docs
Since gallery_images is a NodeList that means we can iterate over it with .forEach. In the forEach I am using an Arrow Function as shorthand for assigning the event listener to the a element.
.forEach(image => image.addEventListener('click', showImage)) is the same as .forEach(function() { this.addEventListener('click', showImage); }.
If anything is confusing I can try and clarify it some more. I've linked to the docs for additional information.
const gallery = document.querySelector('#imagegallery');
const gallery_images = document.querySelectorAll('#imagegallery a');
const placeholder = document.querySelector('#placeholder');
gallery_images.forEach(image => image.addEventListener('click', showImage));
function showImage(event) {
event.preventDefault(); // Stop the link from opening
const source = this.href;
const title = this.title;
placeholder.src = source;
placeholder.alt = title;
}
<h1>Snapshots</h1>
<ul id="imagegallery">
<li>Flower</li>
<li>Building</li>
<li>Cold Day</li>
<li>Sunset</li>
</ul>
<p id="description">Choose an Image.</p>
<img src="images/placeholder.png" alt="my image gallery" id="placeholder" style="border: 2px solid #eaeaea">
Good afternoon, apologies if this more obvious than it appears to myself,
I am having a difficult time adding classes to some input zones, is there a way to add another class to an input and then from this action continue to do more, in one streamlined section of code.
This is a diluted version of the issue I am having as I can't seem to get it to work, I still very am much a novice with JavaScript and any advice would be greatly appreciated.
<!DOCTYPE HTML>
<html>
<head>
<script src="jquery-1.12.4.min.js"></script>
<script type="text/javascript">
function checkSubmission(){
var inputVal = document.getelementbyclassName("compulsory").value;
if (inputVal == "") {
$('this').addClass('redborder');
window.location = "";
};
else if (inputVal != "" && document.getelementbyclassName('redborder')) {
$('this').removeClass('redborder');
window.location.href('');
};
else {
window.location.href('');
};
};
function checkFilled(){
var inputFill = document.getelementbyclassName('redborder').value;
if (inputFill != "") {
document.getelementbyclassName('redborder').style.border-color = "green";
};
};
</script>
<style type="text/css">
.redborder{
border-color: red;
}
</style>
</head>
<body>
<button onclick="checkSubmission()">Change</button>
<input class="compulsory">
</body>
</html>
Thank you very much in advanced if you are able to assist.
Here is a "cleaned up" version I doubt it will work but if you compare it to what you have you can see all the changes mentioned above.
function checkSubmission() {
var inputVal = document.getElementsByClassName("compulsory").value;
if (inputVal == "") {
$("this").addClass("redborder");
window.location = "";
} else if (inputVal !== "" && document.getElementsByClassName("redborder")) {
$("this").removeClass("redborder");
window.location.href("");
} else {
window.location.href("");
}
}
function checkFilled() {
var inputFill = document.getElementsByClassName("redborder").value;
if (inputFill !== "") {
document.getElementsByClassName("redborder").style.border = "thin solid green";
}
}
I'm trying to create a palindrome checker. And now it seems that my lengthChecker() is no longer being called, nor is the condition whenever a word isn't a palindrome, then say it's not a palindrome. What could be the issue?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Lesson #6 Homework</title>
<script type="text/javascript" src="./js/palindrome.js"></script>
</head>
<body>
<h1>Is it a Palindrome?</h1>
<div id="mainCont">
<p>Hello. Please enter a word, and I'll see if it is a palindrome.</p>
<p>Word:
<input type="text" id="str" name="string" />
<button id="checkInput">Submit</button>
</p>
</div>
</body>
</html>
Here is the JS as of now:
function lengthChecker() {
var str = document.getElementById("str").value;
if (str.length > 10 ) {
alert("Sorry. Your input surpasses the 10 characters maximum. Please try again.")
return false;
} else if (str.length == 0) {
alert ("Sorry. Your input is too short, and doesn't meet the 10 characters maximum. Please try again.")
return false;
}
palindrome();
}
function palindrome() {
var revStr = "";
var str = document.getElementById("str").value;
var i = str.length;
for (var j = i; j >= 0; j--) {
revStr = revStr + str.charAt(j);
}
if (str == revStr) {
isPalindrome();
} else {
alert(str + " -is not a Palindrome");
}
}
function isPalindrome() {
alert(str + " is a Palindrome.");
}
document.addEventListener("DOMContentLoaded" , function(e){
var el = document.getElementById("checkInput");
el.addEventListener("click", isPalindrome);
});
You have your Javascript linked in the head element, so it is executed before the <button id="checkInput"> gets into the DOM. Move it to the end of body or make it deferred.
Because you are tying to access your button, before your page is properly loaded.
You need to get your button and bind your event handler, when DOM is loaded.
document.addEventListener("DOMContentLoaded", function(e) {
var el = document.getElementById("checkInput");
el.addEventListener("click", isPalindrome);
});