Javascript and HTML onclick event- how to disable and add - javascript

As an experiment for a larger project, I am trying to make a text battle (it's in progress). What I need is when I press the button, it prints the text into a <p> tag. Also, it makes two buttons, one that says ATTACK and the other says SPARE. How would I
disable the initial onclick event from the button so I don't keep on making new buttons
add an onclick event to the new ones so I could run a different function.
This is my code:
HTML:
<button id = 'button' onclick='enemy()'>button</button>
And my JavaScript:
// PLAYER
var playerHP = 100;
var playerAt = 10;
var playerDef = 0;
//ENEMY
var enemyHP = 50;
var enemyAt = 5;
//FIGHT
function enemy() {
document.getElementById("test").innerHTML = "You encounter a wild MONSTER(AT:5 ¦ HP:50). Will you attack?";
for (var i = 0; i < 1; i++) {
var btnAt = document.createElement('BUTTON');
var t = document.createTextNode('Attack!');
btnAt.appendChild(t);
document.body.appendChild(btnAt);
var btnSp = document.createElement('BUTTON');
var d = document.createTextNode('Spare!');
btnSp.appendChild(d);
document.body.appendChild(btnSp);
}
}
Ignore some of the stuff- its for future use.
P.S. No jQuery, please, unless it is unavoidable.

something like this using .Disabled to disable the button, so you dont have to clear out the onclick for later use. and just set .onclick to whatever function you want on the button you built. I also recommend not trying to avoid jquery... Once you start using it, you can relize how much easier it can make your life. Also, why the loop?
// PLAYER
var playerHP = 100;
var playerAt = 10;
var playerDef = 0;
//ENEMY
var enemyHP = 50;
var enemyAt = 5;
//FIGHT
function enemy() {
document.getElementById("test").innerHTML = "You encounter a wild MONSTER(AT:5 ¦ HP:50). Will you attack?";
var btnAt = document.createElement('BUTTON');
//set onlick for button
btnAt.onclick = function()
{
//do stuff here
}
var t = document.createTextNode('Attack!');
btnAt.appendChild(t);
document.body.appendChild(btnAt);
var btnSp = document.createElement('BUTTON');
var d = document.createTextNode('Spare!');
btnSp.appendChild(d);
document.body.appendChild(btnSp);
//disable button
var originalbtn = document.getElementById("button").disabled = true;
}

Related

HTML & Javascript - Using a loop to create buttons doesn't "individualize" .onclick = {} [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 3 years ago.
I feel like this question has already been answered, but I couldn't find it, so I'll ask it anyways.
I was playing with Javascript in HTML, and I decided to make a whole bunch of buttons using a loop. I wanted to assign a function to each one based on which it was. Here, I'll show you the script:
for (var i = 0; i < 6; i++) {
var button = document.createElement("button");
button.innerHTML = i;
button.className = "buttonclass";
button.onclick = function() {alert(i)};
var buttonDiv = document.getElementById("buttons");
buttonDiv.appendChild(button);
}
But when I click on any of the buttons, it returns a "6". I know where the problem is; I can't use simply {alert(i)}. But what should I use instead?
If you are restricted to using var for browser support purposes, you can use functions to properly encapsulate some of these values so that the result isn't hoisted and set to the last value of i.
function generateButtons() {
var i;
var buttonDiv = document.getElementById("buttons");
for (var i = 0; i < 6; i++) {
generateButton(i, buttonDiv);
}
}
function generateButton(iteration, container) {
var button = document.createElement("button");
button.innerHTML = iteration;
button.className = "buttonclass";
button.onclick = function() { alert(iteration); }
container.appendChild(button);
}
generateButtons();
<div id="buttons"></div>
However, if you are able to use more modern containers like let and const, then you can keep the simpler structure and leverage the magic of block scoped containers:
for (let i = 0; i < 6; i++) {
let button = document.createElement("button");
button.innerHTML = i;
button.className = "buttonclass";
button.onclick = function() {alert(i)};
let buttonDiv = document.getElementById("buttons");
buttonDiv.appendChild(button);
}
<div id="buttons"></div>
The problem is that when you call alert(i), it is after the loop. After the loop, i is 6. You need to save the value of i, so you can call it later.
for (var i = 0; i < 6; i++) {
var button = document.createElement("button");
button.innerHTML = i;
button.className = "buttonclass";
var buttonDiv = document.getElementById("buttons");
buttonDiv.appendChild(button);
let a = i
button.onclick = function () { alert(a) };
}

Illustrator Script All Text Properties

Currently working a script to make ALL the texts of a document with some specifics. Glad to say it's already functioning but not completely because it's just working on some of the textframes and not all of them.
The intention is to make the changes on every texts on the active document (point, area, frames, etc) and unfortunately, even when it works on some text frame, not all characters are affected because some special ones like - or + don't get the properties of the other normal characters.
Made some research and do believe I should be working with parentStory maybe? But I didn't figure out how to implement.
Here is my code:
var document = app.activeDocument;
var allTexts = document.textFrames[0];
for (i=0; i<allTexts.words.length; i++) {
allTexts.words[i].characterAttributes.autoLeading = true;
allTexts.words[i].characterAttributes.tracking = 250;
allTexts.words[i].characterAttributes.kerningMethod = AutoKernType.AUTO;
allTexts.words[i].characterAttributes.underline = false;
allTexts.words[i].characterAttributes.strikeThrough = false;
allTexts.words[i].characterAttributes.capitalization = FontCapsOption.NORMALCAPS;
allTexts.words[i].characterAttributes.language = LanguageType.UKENGLISH;
allTexts.words[i].characterAttributes.horizontalScale = 100;
allTexts.words[i].characterAttributes.verticalScale = 100;
allTexts.words[i].characterAttributes.baselineShift = 0;
allTexts.words[i].characterAttributes.rotation = 0;
allTexts.words[i].characterAttributes.baselinePosition = FontBaselineOption.NORMALBASELINE;
allTexts.words[i].characterAttributes.baselineDirection = BaselineDirectionType.Standard;
allTexts.words[i].characterAttributes.alternateGlyphs = AlternateGlyphsForm.DEFAULTFORM;
allTexts.words[i].characterAttributes.antialias = TextAntialias.SHARP;
}
already got helped in a different source by adding textRange to it.
var thisTextFrame;
for(var i = 0; i < app.activeDocument.textFrames.length; i++){
thisTextFrame = app.activeDocument.textFrames[i]
thisTextFrame.textRange.characterAttributes.tracking = 250;
// ...
}

Looping through divs and highlighting text

I am creating a mock blog where I will be appending the posts via the JavaScript file. I currently have it set up so that a search button will work to only show posts with the same text in the search bar. Now, I want the posts to have the found word highlighted.
HTML:
<div id= "custom_blog_div"></div>
JS:
if (document.getElementById("custom_blog_div")) {
//Blog Post 2
var post_2_div = document.createElement("div");
post_2_div.setAttribute("id", "post_2_div");
post_2_div.setAttribute("class", "post_div");
custom_blog_div.appendChild(post_2_div);
// Header
var post_2_Header = document.createElement("h2");
var post_2_Header_Text = document.createTextNode("Welcome, and Pardon the Construction!");
post_2_Header.setAttribute("class", "blog_post_header");
post_2_Header.appendChild(post_2_Header_Text);
post_2_div.appendChild(post_2_Header);
// Date
var post_2_Date = document.createElement("p");
var post_2_Date_Text = document.createTextNode("January 2, 2018 12:00 am");
post_2_Date.setAttribute("class", "blog_post_date");
post_2_Date.appendChild(post_2_Date_Text);
post_2_div.appendChild(post_2_Date);
// Blog
var post_2_Blog = document.createElement("p");
var post_2_Blog_Text = document.createTextNode("This is a Left Image:");
var post_2_Blog_Image_1 = document.createElement("img");
post_2_Blog.setAttribute("class", "blog_post_text");
post_2_Blog_Image_1.setAttribute("class", "Left_Image");
post_2_Blog_Image_1.setAttribute("width", "100px");
post_2_Blog_Image_1.setAttribute("src", "./series images/main series/spirit legends issue 5/Spirit Legends 5 - Cover.jpg")
post_2_Blog.appendChild(post_2_Blog_Text);
post_2_Blog.appendChild(post_2_Blog_Image_1);
post_2_div.appendChild(post_2_Blog);
// Blog Post 1
var post_1_div = document.createElement("div");
post_1_div.setAttribute("id", "post_1_div");
post_1_div.setAttribute("class", "post_div");
custom_blog_div.appendChild(post_1_div);
// Header
var post_1_Header = document.createElement("h2");
var post_1_Header_Text = document.createTextNode("Welcome, and Pardon the Construction!");
post_1_Header.setAttribute("class", "blog_post_header");
post_1_Header.appendChild(post_1_Header_Text);
post_1_div.appendChild(post_1_Header);
// Date
var post_1_Date = document.createElement("p");
var post_1_Date_Text = document.createTextNode("January 2, 2018 12:00 am");
post_1_Date.setAttribute("class", "blog_post_date");
post_1_Date.appendChild(post_1_Date_Text);
post_1_div.appendChild(post_1_Date);
// Blog
var post_1_Blog = document.createElement("p");
var post_1_Blog_Text = document.createTextNode("Hi, and welcome to the official Spirit Legends website! The site is live in order to test out certain things, but as you can see, it is very much incomplete. Please look forward to the complete site in the future!");
post_1_Blog.setAttribute("class", "blog_post_text");
post_1_Blog.appendChild(post_1_Blog_Text);
post_1_div.appendChild(post_1_Blog);
}
// Search Bar button
document.getElementById("search_news_button").onclick = function() {
var all_blogs = document.getElementById("custom_blog_div").querySelectorAll(".post_div");
var text_field = document.getElementById("search_news_button_text").value.toLowerCase();
var custom_blog = document.getElementById("custom_blog_div");
// Restore all Blog Posts before searching
for (i = 0; i < all_blogs.length; i++) {
if (all_blogs[i].style.display === "none") {
all_blogs[i].style.display = "inline";
}
}
// Loop through all Blog posts
for (i = 0; i < all_blogs.length; i++) {
// Display all Blog posts containing the text in the Search Bar
if (all_blogs[i].innerText.toLowerCase().includes(text_field) === true) {
all_blogs[i].style.display = "inline";
var x = "";
for (x = 0; x < custom_blog.innerText.length; x++) {
if (custom_blog[x].innerText.toLowerCase().includes(text_field) === true) {
x = custom_blog[x].innerText.toLowerCase();
x.style.backgroundColor = "yellow";
}
}
// Highlight the found text in each blog post
var x = "";
for (x = 0; x < custom_blog.innerText.length; x++) {
if (custom_blog[x].innerText.toLowerCase().includes(text_field) === true) {
x = custom_blog[x].innerText.toLowerCase();
x.style.backgroundColor = "yellow";
}
}
// Otherwise, if no Blog posts contain the text in the Search Bar or if Search Bar is empty, display the default
} else {
all_blogs[i].style.display = "none";
}
}
}
So, like I said, the blog is working, and the search button is working, but I cannot figure out how to get the searched word highlighted. Currently, this code results in the console telling me "TypeError: custom_blog[x] is undefined".
And, if it helps, the website is http://spiritlegendsofficial.com/ but this feature hasn't been added yet. Although you can look at the rest of the site's code on there and get some context for this mock blog.
Thanks!
Assuming custom_blog is an HTMLElement type, custom_blog[0] would represent the first child node of that HTMLElement. If you check that your variable custom_blog is defined in a javascript console, but custom_blog[x] isn't defined, it basically means your <div id= "custom_blog_div"></div> has no child elements.
I think your issue is somewhere in the loop that's grabbing your text for highlighting. You're checking the length of the string, but inside the loop you're attempting to target a child node in a case where there may not be one. You might want to change the for loop's condition for continuing to be based on the number of nodes instead:
if (custom_blog.hasChildNodes()) {
var children = custom_blog.childNodes;
for (x = 0; x < children.length; x++) {
if (children[x].innerText.toLowerCase().includes(text_field) === true) {
x = children[x].innerText.toLowerCase();
x.style.backgroundColor = "yellow";
}
}
}
For more info on childNodes: https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes

Why is my variable not incrementing?

I'm trying to build a very basic slider. I managed to create something but I am stuck when I try to change from one slide to another. I was thinking my code would work but it does not and I don't understand why.
Here's a link to a codepen of it
Here's the relevant part of my problem:
I have defined a slider like so:
var carrousel = document.getElementById('carrouselcontainer');
var slide1 = document.createElement('div');
slide1.className = 'slide1';
var slide2 = document.createElement('div');
slide2.className = 'slide2';
var slide3 = document.createElement('div');
slide3.className = 'slide3';
var slider = [slide1, slide2, slide3]
carrousel.appendChild(slider[0]);
And this does work. Now I am trying to add a function that will increment or decrement the slider variable when clicked.
var backButton = document.getElementById('backButton');
var forwardButton = document.getElementById('forwardButton')
function forward() {
slider++
}
forwardButton.addEventListener('click', forward)
But when I click on the forwardButton element, nothing happens. I know that the eventListener is working since I tried a window.alert() message on it and it works when I click it. What is it that I am doing wrong here?
Incrementing an array will not work but only generate error.
forward() should remove the actual child of the carrousel and
add a new child that has as value the next element of the slider array:
Introduce a currentSlide number variable to indicate the current index displayed and increment it in forward().
var currentSlide = 0;
...
carrousel.appendChild(slider[currentSlide]);
...
function forward() {
carrousel.removeChild(slider[currentSlide++]);
if (currentSlide >= slider.length){
currentSlide = 0;
}
carrousel.appendChild(slider[currentSlide]);
}
You need some kind of index which you use to get something out of your array:
var forwardButton = document.getElementById('forwardButton');
var result = document.getElementById('carrouselcontainer');
var sliderIndex = 0;
var slider1 = document.createElement("div");
slider1.innerHTML = "item 1";
var slider2 = document.createElement("div");
slider2.innerHTML = "item 2";
var slider3 = document.createElement("div");
slider3.innerHTML = "item 3";
var slider = [slider1, slider2, slider3];
result.appendChild(slider[sliderIndex]);
function forward() {
result.removeChild(slider[sliderIndex]);
sliderIndex = (sliderIndex + 1) % slider.length;
result.appendChild(slider[sliderIndex]);
}
forwardButton.addEventListener('click', forward);
<button id="forwardButton">Increment</button>
<div id="carrouselcontainer"></div>
You have to replace the element only incrementing the element does not work:
I added a counter "silderPos" to your script, so you can increment it by one on every click.
If it larger then 2 it will go back to 0 by a modulo action.
I made the carrouselElement global, so that your click script can access the element directly.
With this changes i can now go throu all of your element.
Please find the modified source code here:
var carrouselElement;
var sliderPos = 0;
function carrousel()
{
carrouselElement = document.getElementById('carrouselcontainer');
var slide1 = document.createElement('div');
slide1.className = 'slide1';
var slide2 = document.createElement('div');
slide2.className = 'slide2';
var slide3 = document.createElement('div');
slide3.className = 'slide3';
var slider = [slide1, slide2, slide3]
carrouselElement.appendChild(slider[0]);
var backButton = document.getElementById('backButton');
var forwardButton = document.getElementById('forwardButton')
function forward() {
carrouselElement.lastChild.remove();
sliderPos++;
sliderPos = sliderPos % 3;
carrouselElement.appendChild(slider[sliderPos]);
}
/*backButton.addEventListener('click', back)*/
forwardButton.addEventListener('click', forward)
}
window.addEventListener('load', carrousel);

running a while loop alongside jQuery without crashing the website

I need a constantly running while loop to check alot of if (value < otherValue || value === otherValue) without making the website crash and still be able to accept click events, etc...
Here is some of my code:
$(document).ready(function(){
var value = 0;
var otherValue = 25;
var otherValue2 = 75;
var otherValue3 = 100;
var otherValue4 = 125;
var otherValue5 = 175;
var otherValue6 = 200;
var otherValue7 = 300;
$('#button').click(function(){
value += 5;
// Here i make the value show on the page like fancy, but It's not essential for this question
});
});
So, how do I include a constantly running while loop that makes that code still functional, and doesn't crash the website?
I would take a look at setInterval it will allow you to execute a function every set amount of time.
var interval = null;
var value = 0;
var otherValue = 25;
var intervalTimer = 100; // 100ms
$('input').val(value);
$('button').on('click', function(){
interval = setInterval(function(){
$('input').val(value += 5);
}, intervalTimer);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input>
<button>
Start Updating Value
</button>

Categories