Javascript, program not entering function with button clicks - javascript

I'm having problems with a startGame function in my code and am seeking help. Originally, I have some HTML code like so:
`
<div id="startScreen">
<h1>Spell and Blade</h1>
<button id="startButton">Start</button>
<!-- Pop-up window -->
<div id="popUpWindow" class="popUpWindow">
<!-- Pop-up window content -->
<div class="popUpWindow-content">
<span class="close">×</span>
<p>
Please select a character type that best fits your play style.
The character type you choose will be the character you control!
</p>
<div id="characterButtons">
<button class="tank" onclick="startGame(1)">Tank</button>
<button class="wizard" onclick="startGame(2)">Wizard</button>
<button class="elf" onclick="startGame(3)">Elf</button>
</div>
</div>
</div>
`
^^This code is embedded in the body tag and the script tags are at the button. This is the main contents of the HTML page.
Calling this function in my javascript labels it undefined when the user clicks any of the characterButtons.
Javascript, name of file Canvas.js:
`function startGame(characterType){
//Code that starts the game.
}`
Other solutions I have tried are in another file called, ButtonProperties.js:
characterButtons.onclick = function () {
console.log("Here in characterButton function");
var characterType = 0;
var tankButton = document.getElementsByClassName("tank");
var wizardButton = document.getElementsByClassName("wizard");
var elfButton = document.getElementsByClassName("elf");
if (tankButton.onclick) {
console.log("Here in tankButton if statement");
characterType = 1;
startGame(characterType);
}
if (wizardButton.onclick) {
characterType = 2;
startGame(characterType);
}
if (elfButton.onclick) {
characterType = 3;
startGame(characterType);
}`enter code here`
}
The above file also has code relating to a pop up window, but I don't think that is where the problem is, also
var characterButtons = document.getElementById("characterButtons"); is near the top of the file, just not listed above.
I'm clueless as to why the function is not getting called. The console.log function counts the number of times a character button is clicked just fine, but the program won't go into any of the if statements. Any help anyone can provide is much appreciated!

You are using getElementsByClassName which returns array, so your buttons tankButton, wizardButton etc are arrays. I would suggest you change your code like below
<div id="characterButtons">
<button id="tank" onclick="startGame(1)">Tank</button>
<button id="wizard" onclick="startGame(2)">Wizard</button>
<button id="elf" onclick="startGame(3)">Elf</button>
</div>
and use
var tankButton = document.getElementById("tank");
var wizardButton = document.getElementById("wizard");
var elfButton = document.getElementById("elf");
then it should work. This is better performance wise as well.

Related

Iterate through buttons by class and display data from parent div of the selected button in a modal

I have been trying for days now to figure out what I am doing wrong here. I have buttons for items that are located on different pages and they all use the same modal that contains a form and item details, depending on which button is selected.
The buttons have the same class and when clicked I need to get the attributes from the button's parent div (several divs above the button) and display the data from parent div in the modal. I am using Wordpress and I cannot add the attributes to the buttons, so I had to add them to a parent div.
I can get the code to work perfectly in visual studio but when I add it to Wordpress I keep getting errors in the console stating "Can't create duplicate variable that shadows a global property: 'l'" and "Can't create duplicate variable: 'modalBtns'". I cannot use button onclick for the buttons as Wordpress restricts that from what I have read, so I have to do it another way.
I have scoured Google and tried every suggestion I have found on this site and many others. I renamed 'modalBtns', broke code down into functions and put the functions outside the loop, added the functions inside the loop, changed modalBtns to var, constant..nothing is working. I don't know how to clear the errors.
I am also having issue with the modal not getting the data as the code has already ran prior to the modal loading so the id's for the modal divs I am putting the data in are not even present when code runs. I have to add item name to a hidden field of the form and add image, price, description. I tried delaying the code in the section where it is looking for modal divs but it still doesn't work.
This is what I have that works in Visual Studio but not on Wordpress. I don't know what I am doing wrong.
<div class="modalBtn" data-pkg="Package #1" data-price="124" data-duration="month" data-desc="This + that" data-img="main">
<div id="otherDiv">
<button id="Package1" class="premium-price-pricing-button">Package 1</button>
</div>
</div>
<div class="modalBtn" data-pkg="Package #2" data-price="234" data-duration="month" data-desc="Another descrpition" data-img="thumbnail">
<div id="otherDiv">
<button id="Package2" class="premium-price-pricing-button">Package 2</button>
</div>
</div>
<div class="modalBtn" data-pkg="Package #3" data-price="345" data-duration="each" data-desc="" data-img="custom">
<div id="otherDiv"></div>
<button id="Package3" class="premium-price-pricing-button" >Package 3</button>
</div>
<div id="modal">
<h1 id="modalTitle">This is the title</h1>
<img id="modalImg" src="defaultImg.png"/>
<p><span id="modalPrice">100</span><span id="modalDuration">month</span><span id="modalDesc">Description here</span></p>
<form action="/action_page.php">
<label for="name">First name:</label><br>
<input type="text" id="name" name="name" value="John"><br>
<label for="pkg">Package:</label><br>
<input type="text" id="pkg" class="pkgFormField" name="pkg" value="Doe"><br><br>
<input type="submit" value="Submit">
</form>
</div>
This is the code
//Get all buttons with classname premium-price-pricing-button
let modalBtns = document.getElementsByClassName('premium-price-pricing-button');
//Iterate through buttons & add event listener, when clicked run updateModal function
for (var i = 0; i < modalBtns.length; i++) {
modalBtns[i].addEventListener('click', updateModal);
}
function updateModal() {
//Get parent div which has data attributes
let parentDiv = this.closest('.modalBtn');
//Get/set attribute data-pkg from parent and set as pkg
let pkg = parentDiv.getAttribute("data-pkg");
//Get/set variables from parent attributes
let price= parentDiv.getAttribute("data-price");
let duration = parentDiv.getAttribute("data-duration");
let desc = parentDiv.getAttribute("data-desc");
let btnImg = parentDiv.getAttribute("data-img");
let modalImg = document.getElementById("modalImg");
//Find hidden form field & name field
let pkgField = document.getElementById("pkg");
let nameField = document.getElementById("name");
//Set default image for modal
let img = "image1.png";
//Find modal ids and replace innerHTML with parent attributes
document.getElementById("modalTitle").innerHTML = pkg;
document.getElementById("modalPrice").innerHTML = price;
document.getElementById("modalDuration").innerHTML = duration;
document.getElementById("modalDesc").innerHTML = desc;
//If img attribute is 'custom' or 'thumbnail' replace it with alternate image
if (btnImg == "custom"){
img = "image2.png";
}
if (btnImg == "thumbnail") {
img = "image3.png";
}
//Set img for modal
modalImg.src = img;
//Set pkg value in form to pkg
pkgField.value = pkg;
}
Wrap your JS Code within function like this:
(function () {
/**
* Put your code here.
*/
})();

HTML onclick function not working for a button

So I'm making a website, and I have some buttons that scroll to certain parts of a page. I have 5 buttons, and all of them have the exact same code except for their names. One of the buttons is broken and doesn't do anything, even though its code is the same as the working ones.
Here is my HTML:
About Us
<div class = "OurMethodsBar">
<button class = "OurMethodsButton" onclick = "ScrollTo(OurMethodsAnchor)">
Our Methods
</button>
</div>
<div class = "InvestBar">
<button class = "InvestButton" onclick = "ScrollTo(InvestAnchor)">
Invest
</button>
</div>
<div class = "ContactUsBar">
<button class = "ContactUsButton" onlclick = "ScrollTo(ContactUsAnchor)">
Contact Us
</button>
</div>
<div class = "MoreInformationBar">
<button class = "MoreInformationButton" onclick = "ScrollTo(MoreInfoAnchor)">
More Info
</button>
</div>
Here is my JS:
var AboutUsAnchor = document.getElementById("AboutUsAnchor");
var OurMethodsAnchor = document.getElementById("OurMethodsAnchor");
var InvestAnchor = document.getElementById("InvestAnchor");
var ContactUsAnchor = document.getElementById("ContactUsAnchor");
var MoreInfoAnchor = document.getElementById("MoreInfoAnchor");
function ScrollTo(Element) {
Element.scrollIntoView(true);
}
ScrollTo(AboutUsAnchor);
The broken button is the ContactUsButton which is supposed to scroll to the ContactUsAnchor.
If I manually use my ScrollTo function and input the ContactUsAnchor, it still works, but when I try to hit the button, it doesn't work.
I'd rather change approach and rewrite your function to get a string and get the element by ID later.
function ScrollTo(element) {
document.getElementById(element).scrollIntoView(true);
}
And then in your buttons just pass the string containing the ID in single quotes '
<button class = "ContactUsButton" onclick = "ScrollTo('ContactUsAnchor')">
Contact Us
</button>
And as others have pointed out, fix that onlclick :P

How can I pass a variable from a JS input to HTML?

I'm taking an input from a user in javascript and using it to display that number of pages. Basically, I ask the user how many items they have. If they say, for example, 4, I need to ask them the name of each item on the next page. Then, on the next 4 pages, they are to input the value of each item one per page and finally, I will display a table of the items, values, and final sum. My question is:
After obtaining the number of items in my javascript file, how do I pass it back to my HTML file? Should I even be passing it back to my HTML file?
When I have the number of items, how do I open that many new files/pages for javascript and HTML based on it? Or can I do it all on one js file? I know it's quite redundant to open a new HTML and JS file for each item but I don't know how to clear the page each time after a button click and display a new input box on the same file.
Sorry if this is a really stupid question, just a confused begginer here. Thank you!
Here's what I have so far:
index.html:
<body>
<h1>Welcome!</h1>
<h2>Ready to track your items?</h2>
<p><button>Start</button></p>
</body>
items.html:
<body>
<h3>How many items do you have?</h3>
<p><input id="numItems"></p>
<script src="main.js"></script>
</body>
main.js:
var numIt = document.getElementById("numItems");
numIt.addEventListener("input", display);
function display(){
var item = parseFloat(numIt.value);
alert("you have " + item+" items");
}
I am not 100% sure, but guess You need to dynamically generate N number of inputs to have users fill in names of each item. As mentioned opening new or creating new html files would not be the best solution, also it can't be done with browser javascript.
So instead why not generate input elements and append them to the DOM, for more info please see DOM w3schools
Small example.
function display(){
var item = parseFloat(numIt.value);
for(var i =0; i<item;i++){
var inpElem = document.createElement("input");
inpElem.setAttribute("name", "item"+i);
inpElem.setAttribute("placeholder", "Input name of the item #"+i);
document.body.appendChild(inpElem);
}
}
Let's say user inputs 2. It will generate
<input placeholder="Input name of the item #1" name="item1" >
<input placeholder="Input name of the item #2" name="item2" >
Also to empty the body - document.body.innerHTML = ""
Probably you can use "pages" (hide all elements except one)
There is an example, you can check it out
const pages = ["page1", "page2", "page3"]
showPage(0)
function hidePages() {
for(const page of pages)
changeElementVisibility(page, false)
}
function showPage(num) {
hidePages()
const pageId = pages[num]
changeElementVisibility(pageId, true)
}
function changeElementVisibility(id, visible) {
document.getElementById(id).style.display = visible ? "" : "none"
}
function secondPageSumbit() {
const itemsCount = document.getElementById("itemsCount").value
document.getElementById("result").innerText = "Items Count: " + itemsCount
}
<head>
<script src="main.js"></script>
</head>
<body>
<div id="page1">
<h1>Welcome!</h1>
<h2>Ready to track your items?</h2>
<p><button onclick="showPage(1)">Start</button></p>
</div>
<div id="page2">
<h3>How many items do you have?</h3>
<p><input id="itemsCount"></p>
<p><button onclick="secondPageSumbit();showPage(2)">Next</button></p>
</div>
<div id="page3">
<h3>Result</h3>
<p id="result"></p>
</div>
</body>

How to refresh a separate page to get PHP session variables?

Before I start, I need you to know that my methods aren't the best. I'm a beginner to JavaScript and php and I'm sure that what I'm trying to accomplish can be accomplished by much better and simpler means.
I think my problem lies with session variables and printing pages. I have a page where a user creates tables from dropdown lists. I need to print the tables but on three different pages and in three different formats. I have the three pages linked to print using an the "frames["iframe].print" function.
Here are my frames:
<iframe src="customer_detail.php" style="display:none;"name="framed"></iframe>
<iframe src="advisor_copy.php" style="display:none;" name="framez"></iframe>
<iframe src="customer_copy.php" style="display:none;" name="frame"></iframe>
And my buttons:
<span id = "cCopy"><button class = "button" onclick= "frames['frame'].print();"/> Customer Copy</button></span>
<span id = "aCopy"><button class = "button" onclick="frames['framez'].print();" value="Advisor_Copy">Advisor Copy</button> </span>
<span id = "cCopy"><button class ="button" onclick= "frames['framed'].print();" value="customer_copy">Customer Detail </button></span>
From what I understand, the page needs to be refreshed in order for the session variables to update. My hack solution which works is to refresh the 3 pages I'm printing(customer_detail, customer_copy and advisor_copy) every 1 second. What I'd much rather have is the ability to refresh the page I'm printing when I click one of the three buttons so I can update the session variables being called on those pages.
I've tried refreshing the iframe with an onclick event but it doesn't do exactly what I need it to. I've searched around for various solutions and none of them have really worked. If I need to restructure my code then I will. I think what I really should do is pass the variables I need to the other pages via an AJAX call. I'd like to know if there's a solution which will allow my code to function without having to more or less start from scratch.
Ok. This is a ugly workaround without rewrite all.
<span id = "cCopy"><button class = "button">Customer Copy</button> </span>
<span id = "aCopy"><button class = "button" value="Advisor_Copy">Advisor Copy</button> </span>
<span id = "cCopy"><button class ="button" value="customer_copy">Customer Detail </button></span>
<br>
<iframe name="framed"></iframe>
<iframe name="framez"></iframe>
<iframe name="frame"></iframe>
WORKING EXAMPLE
UPDATE
...and on single PHP pages, on body tag put... <body onload="window.print()">
UPDATE 2
and if you want to remove underline button text add
style="text-decoration:none;"
on each <a tag
UPDATE 3 (it is necessary to carry some tests, due to the browsers security locks)
Your index.html:
<span id = "cCopy"><button onclick="printIframe('framed')" class = "button">Customer Copy</button></span>
<span id = "aCopy"><button onclick="printIframe('framez')" class = "button" value="Advisor_Copy">
Advisor Copy</button></span>
<span id = "cCopy"><button onclick="printIframe('frame')" class ="button" value="customer_copy">Customer Detail</button></span>
<br>
<div id='frames'>
</div>
<script>
var iframes = {}; //create a 'container' for iframe
iframes['framed'] = 'customer_detail.php'; // your link
iframes['framez'] = 'advisor_copy.php'; // your link
iframes['frame'] = 'customer_copy.php'; // your link
// if you want to add another iframe create a new line with iframes['myIframeName'] = 'MyIframeUrlLink'; // your link
for (var k in iframes){
createIframe(k, iframes[k]);
}
function printIframe(id) //this call a javascript print function inside your PHP - need for security reason
{
var iframe = document.frames ? document.frames[id] : document.getElementById(id);
var ifWin = iframe.contentWindow || iframe;
iframe.focus();
ifWin.printPage();
return false;
}
//this create iframes
function createIframe(name, src) {
var i = document.createElement("iframe");
i.name = name;
i.id = name;
i.src = src;
i.style= "display: none";
document.getElementById("frames").appendChild(i);
};
</script>
In your PHP Pages, remove my onload="window.print()" and at the end of body tag, just before </body> to be clear, add:
<script>
function printPage() { print(); }
</script>
like this:
</body>
<script>
function printPage() { print(); }
</script>
function refreshPage() {
$("#widgetbox").fadeOut(750, function() {
<!-- empty the current content and then fetch new data -->
$("#widgetbox").empty
<!-- load the getPage.php file which will replace all the
$("#widgetbox").load("getPage.php", function() {
$("#widgetbox").fadeIn();
});
});
};
<!-- initiate the function above -->
$(function(){
refreshPage();
<!-- set the interval for refreshing, default set to 1.0 seconds -->
var int = setInterval("refreshPage()", 1000);
});
study this
http://websitetutorials.net/jquery/rotate-product-listings-php-and-jquery
and modify it

How do I dynamically add different elements for when the user clicks a button

Here is the link to the site.
The layout of the page consists of a "fixed" sidebar (left), in which buttons are created when a user clicks the "Add" button, accompanied by their chosen title and amount of points the button is worth. Then, when the button is clicked, the button disappears and the points are added on to the "Points" value, which is in the middle "div" of the page.
On the far right there is an empty div, I tried to make the same kind of thing, except I could never get it to work. What I wanted was to create another similar dynamically created button or "span" of some sort, where when the user clicks it, the points allocated to said button/span are the deducted from the total number of points. I was thinking of it as a redeeming system if that makes sense. Using coins, which I would just assign to be half the number of points.
Also, I was able to simply store the number of points and the level in localStorage, but I wasn't sure how to store the created buttons, so they disappear after every refresh, and I can't figure out how to do it, since they're not specifically coded in?
Also, if possible, how would I go about a notification div that creates an alert for each button that is clicked. The alert would say something along the lines of "You have completed task name", and it would store it in localStorage, so the user can see the buttons that were clicked in notification form.
One more thing, upon creating the button, there is a title and a number of points the user has to assign, under the second input text box, there are 5 different coloured "spans", each representing a different "field" you might say, in this case it's different subject, how would I make it so that when the user clicks one of the "Spans", the button created will be the same colour as the span they clicked?
I know I'm asking for a lot, but I have tried to do all of which I've asked for and have had massive troubles. If anyone thinks they can help me out It would be greatly appreciated. Thank you in advance.
Here is the code, html and javascript. The CSS is bootstrap.
HTML
<div >
<div id='header'>
<h2 style='font-size:71px'>Reward System</h2>
<div>
<ol class="breadcrumb" style="width:58%">
<li class="active">
<center> Home
</li>
<li>
About
</li>
<li>
Refresh </center>
</li>
</ol>
</div></div><center>
<div id='main'>
<div id='rightSide' class='well'>
</div>
<div class='well' id="addc" style='width:520px'>
<div id="addc">
<input class='form-control' maxlength="15" id="btnName" placeholder="New Task"
style='width:480px' type="text"><br>
<input maxlength="3" class='form-control' id="btnPoints" placeholder="Points"
style='width:480px' type="text"><br>
<span class="label label-danger">Mathematics EX1</span>
<span class="label label-primary">Mathematics EX2</span>
<span class="label label-success">Physics</span>
<span class="label label-info">Chemistry</span>
<span class=
"label label-warning">English Advanced</span><br>
<br>
<button id="addBtn" >Add</button>
</div>
</div>
<div class='panel panel-default' style='width:520px;height:100px'>
<h3><Strike>z</strike> Points</span></h3>
<div class='badge' id="result">
0
</div>
</div>
<hr style="width:520px;">
<div class='panel panel-default' style="width:520px;">
<h3>Level</h3>
<p class='badge' style='width:50px' id='lvl'>0</p>
<div class="progress" style='width:300px'>
<div class="progress-bar progress-bar-success" id='perce'
style="width;"></div>
</div>
</div><br>
</div>
<div id='leftSide' class='well'>
<center> <h3> Tasks </h3> </center>
<div class='well' id="container" style='width:260px;height:85%'>
</div>
<div id='reset'>
<button class='btn btn-warning' onclick='clearme()'>Reset</button>
</center>
</div>
</div>
JavaScript
var resDiv = document.getElementById('result');
resDiv.innerText = localStorage.getItem('myResult');
var levelDiv = document.getElementById('lvl');
levelDiv.textContent = localStorage.getItem('myLevel');
var btns = document.querySelectorAll('.btn');
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
this.parentNode.removeChild(this.nextElementSibling);
this.parentNode.removeChild(this);
});
}
var addBtn = document.getElementById('addBtn');
addBtn.className = "btn btn-default";
addBtn.addEventListener('click', function() {
var container = document.getElementById('container');
var objDiv = document.getElementById("container");
objDiv.scrollTop = objDiv.scrollHeight;
var btnName = document.getElementById('btnName').value;
var btnPoints = parseInt(document.getElementById('btnPoints').value);
if (!btnName)
btnName = "Button ?";
if (!btnPoints)
btnPoints = 50;
var newBtn = document.createElement('button');
var newPnt = document.createElement('span');
newBtn.className = 'btn btn-info';
newBtn.innerText = btnName;
newBtn.setAttribute('data-points', btnPoints);
newBtn.addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
this.parentNode.removeChild(this.nextElementSibling);
this.parentNode.removeChild(this);
});
newPnt.className = 'label label-default';
newPnt.innerText = "+" + btnPoints;
container.appendChild(newBtn);
container.appendChild(newPnt);
});
function addToResult(pts) {
// NaN is falsy, so you can just use || to make a fall-back to 0
var result = parseInt(resDiv.innerText, 10) || 0,
lvl = 0,
a = 100;
result = result + parseInt(pts, 10) || 0;
var pen = (result/500)*100;
while (result > (5 * a)) {
lvl += 1;
a += 100;
pen -= 100;
}
document.getElementById('perce').style.width = pen +"%";
resDiv.innerText = result;
levelDiv.innerText = lvl;
localStorage.setItem("myResult", result);
localStorage.setItem("myLevel", levelDiv.textContent);
}
function clearme() {
localStorage.clear();
}
To keep your buttons in localStorage you will need to create your own object that holds the button's name and points, then use JSON.stringify to turn an array of these objects into a string. That string can then be used with localStorage.setItem
function MyButtonObject(name,points){
this.name=name;
this.points=points;
}
var list=[new MyButtonObject('example',100)];
localStorage.setItem( 'btnList' , JSON.stringify(list) );
Next I would procede by seperating the code that makes a new buttons into its own function so it can be called when the page loads and you want to rebuild your button elements.
var listJSON=localStorage.setItem( 'btnList' );
var list= listJSON?JSON.parse(listJSON ):[];
list.forEach(function(btn){
makeButtonElements(btn);
});
function makeButtonElements(btn){
var btnName=btn.name, btnPoints=btn.points;
var newBtn = document.createElement('button');
var newPnt = document.createElement('span');
....etc....
Your existing function that creates buttons would call this one as well as creating a new MyButtonObject adding it to the array of said objects and storing that array with localStorage.setItem. The function that removes buttons will need updating to remove the correct object from the array and calling localStorage.setItem as well as adding your planned notification messages (and storing them).
You should probably take some time to plan what other features you might want (such as deleting buttons without scoring their points, displaying notifications etc) and think about how you can break those processes down into functions that can be reused at different points in your program (eg new button/notification created, existing button/notification loaded from storage)
Here is a handy function that copies a style property from one element to another that should help you set the buttons colours the way you want.
function copyStyle(prop,fromEl,toEl){
toEl.style[prop]=window.getComputedStyle(fromEl)[prop];
}
Note: I haven't check or tested any of this code so make sure you read through it and understand what it is meant to do before you start copying and pasting into your own program.

Categories

Resources