Magic Eight Ball - Webpage

Hello! I’m just learning JavaScript and have completed the Magic Eight Ball Project. I want to find a simple way to trigger the JavaScript from a webpage. I created a basic page and cut and pasted the JavaScript into my HTML. (I trimmed off some of it to make it simpler). I have searched and found some code that "almost " makes it do what I want, but not quite. This code came from the w3schools page – How TO - Trigger Button Click on Enter. The code I added was:

        <button id="myBtn" onclick="javascript:alert(eightBall)">Button</button>
            var input = document.getElementById("myInput");
            input.addEventListener("keyup", function(event) {
                if (event.keyCode === 13) {
                event.preventDefault();
                document.getElementById("myBtn").click();
  }
}); ```
This will come up with a random answer to the question once, but unless I refresh the page, the same answer always comes up instead of a new random one each time. I really have no idea how to make this happen. Any help is appreciated! Here's the code for the entire webpage:
```<! DOCTYPE html>
<html>
    <body>
        <h1>Magic Eight Ball</h1>
        <h2>Ask the Magic Eight Ball a "yes/no" question!</h2>
        <input id="myInput" placeholder="Type a question">
        <button id="myBtn" onclick="javascript:alert(eightBall)">Button</button>
        <script>

            let randomNumber = Math.floor(Math.random() * 8);

            let eightBall = '';

            switch (randomNumber) {
            case 0:
            eightBall = 'It is certain';
            break;
            case 1:
            eightBall = 'What the???';
            break;
            case 2:
            eightBall = 'Reply hazy try again';
            break;
            case 3:
            eightBall = 'Cannot predict now';
            break;
            case 4:
            eightBall = 'Do not count on it';
            break;
            case 5:
            eightBall = 'My sources say no';
            break;
            case 6:
            eightBall = 'Outlook not so good';
            break;
            case 7:
            eightBall = 'Signs point to yes';
            break;
            }

            var input = document.getElementById("myInput");
            input.addEventListener("keyup", function(event) {
                if (event.keyCode === 13) {
                event.preventDefault();
                document.getElementById("myBtn").click();
  }
});
        </script>
    </body>
</html> ```

Thanks in advance!
Jason

Much as it may be a good challenge, it would appear you are jumping way ahead of things. There is much to learn after Magic Eight Ball before we get into DOM events, especially working with borrowed code the member likely doesn’t understand fully.

First rule of programming: Don’t use somebody else’s code unless you can write it yourself from scratch.

1 Like

Thanks for the advice Roy. Will the rest of the JavaScript course I’m taking get me to a point where I can do something like this? What does “Topic unlisted” at the bottom of your response mean? This is my first post to the forums, did I not list a topic? Thanks, J

Yes, but don’t rush ahead. Be sure you understand HTML completely and have covered the unit on DOM events and have a full understanding of that, too. We are authors, not borrowers. If we cannot do what it is we want, then it means we have more learning to do. Be the architect of your own code.

Unlisted means it will not appear in the main index of latest topics so don’t expect any more replies. Resume your studies and when you are ready to attempt this again, without borrowed code, we can pick it up then.

This was just for fun to show friends what I learned when a console wasn’t available. Haha. Looks like I’ll have to wait. Is the DOM events unit later in this same course? I see the very last section is on Requests, but I’m not sure if that is what you mean. Thanks again.

Yes, as far as I know the DOM events come up and there are some neat projects to go with it. Put your effort in the course and don’t let yourself veer off. There is nothing to show if we didn’t write it ourselves.

Fair enough. Thanks.

1 Like

Hey Roy,

We had this conversation about 4 months ago. Since then, I’ve enrolled in the Front End Engineer Path. I’ve been going through new content and reviewing the old content that I’ve already done in the standalone HTML, CSS and JavaScript courses I’ve completed. I just wanted to show you, I mostly figured out how to do what I was trying to do with the Magic Eight Ball Project. I know it could be improved upon. If you have time, would you take a look and see if you have any suggestions of better ways I could do this, please? I’m proud that I got this far, so be gentle hahaha!

website: Magic Eight Ball
github code: GitHub - JCode777/magic-eight-ball

Thanks again!

Jason

Well done! My only concern is using the prompt() function of the JavaScript console. You’ve got an HTML document, so why not use the FORM elements that it enables? Anyway, that’s for later exploration, as is replacing the switch with an object (optional, of course). Good work; keep at it, as in, cycle back periodically to your old projects and see if they cannot be improved upon in some way as you learn new concepts and grow your toolkit.

1 Like

Thank you so much for the positive feedback and constructive ideas Roy! I will go back at some point and try to change
the prompt idea to take advantage of the FORM elements instead. I’ll also look into the option of using an object in place of the switch statement.

I’m curious, in general, are the prompts likely to be avoided due to the “annoying pop-up” factor? Or is it just the least elegant way to achieve what I was going for here? Or does it cause a safety/security concern like when a malicious pop-up occurs?

Then, as far as using an object versus the switch statement? Would it likely end up being less code? Is less always more? (I’m assuming it is most of the time). I’m trying to picture how that would play out:

var randomFortunes = {
    fortune: ['It is certain', 'It is decidedly so', 'Reply hazy try again']
}

Though, an array technically is an object as well right? So maybe something like:

var randomFortunes = ['It is certain', 'It is decidedly so', 'Reply hazy try again'];

I’ll have to look into this further and see what option is best. I definitely have a lot more to learn. 51% finished the Front End Engineer Path feels like I’ve barely scratched the surface haha! Thanks again for taking a look and offering me some good feedback!

Jason

1 Like

The prompt() function is not asynchronous so if the prompt is waiting for the user’s response, everything else is waiting, too. Nothing can happen in the DOM during this time. It can also be disabled by the user if they so choose to, which could affect the overall experience.

Forms can be supported by the back end, as well as the front end which permits server-side validation, but that is a topic for down the road. Ultimately, they offer a better user experience and cannot be circumvented as easily as JS dialogs can be.

As for an object, yes, an array can do the job given a random number from 0 to 7, inclusive. An object literal will also work if we enumerate the array. The advantage would be that the data can be imported, not hard coded. We never have to touch the code to swap out the data. I haven’t done this, but your data could easily be stored in a module for export, and then imported by any number of other applications giving it re-usability. That would be something worth looking into when the time comes.

On the security question, I’m afraid that cannot be answered given my scant knowledge of the security side of things. One thing that may be possible is the injection of code through the dialog, though that too will need further research. Make it a weekend reading topic… Why NOT to use JS dialogs in a web facing page.

1 Like

Thanks again Roy!! I will definitely revisit this project again and see how much better I can make it! I think going back through all the material in my JavaScript courses a second time (as I go through the Front End Engineer Path) will help it sink in and make a lot more sense than it did the first time. I already felt much more confident in re-attempting the Magic Eight Ball Project today. I’ll look into the option of using forms. I was originally attempting that, but was way beyond my capabilities at that time as you noted a few months ago haha!

I’ll look into my weekend reading topic you’ve provided and try to get to the bottom of it! Thanks again and have a great weekend!

1 Like

Just had to explore, now that the question came up, nudge, nudge; maybe my bad for diverting you, but this can always be bookmarked and NB’d.

const eightBall = {
  0: 'It is certain',
  1: 'It is decidedly so',
  2: 'Reply hazy try again',
  3: 'Cannot predict now',
  4: 'Do not count on it',
  5: 'My sources say no',
  6: 'Outlook not so good',
  7: 'Signs point to yes',
  8: function () {
    return this[Math.floor(Math.random() * 8)]
  }
}
console.log("Will I be more positive in my outlook, today?")
console.log(eightBall['8']())
Will I be more positive in my outlook, today?
Signs point to yes

Perhaps a little more ES2015+…

const eightBall = {
  0: 'It is certain',
  1: 'It is decidedly so',
  2: 'Reply hazy try again',
  3: 'Cannot predict now',
  4: 'Do not count on it',
  5: 'My sources say no',
  6: 'Outlook not so good',
  7: 'Signs point to yes',
  '8' () {
    return this[Math.floor(Math.random() * 8)]
  }
}
console.log("Will I be more positive in my outlook, tomorrow?")
console.log(eightBall['8']())
Will I be more positive in my outlook, tomorrow?
Cannot predict now
1 Like

Thanks Roy! This way of doing it looks way more elegant!! Just from a “number of lines of code” perspective, not to mention visually much easier to follow!! My switch statement alone was 25 lines of code, plus another line for my random number generation. This accomplishes the same in about 12 or so!!!

In the project, they suggested either if/else statements or a switch statement. I thought the switch was much better than an 8 part if/else, but this idea is much more concise! Great suggestion, I’ll play with these ideas and see if I can incorporate them. I still have a lot to learn!

Thanks again! Have a good night and weekend!

1 Like

Just don’t look for black and white reasoning between any of the available, and yet to be explored techniques. It’s case by case, and never a certain choice until we thoroughly narrow it down; and even then, …? Keep an open mind, always.


const question = `Will there be clouds in the sky, tomorrow?`
console.log(`${question}\n${eightBall['8']()}`)
Will there be clouds in the sky, tomorrow?
It is decidedly so

Now in more practical terms…

const eightBall = {
  0: 'It is certain',
  1: 'It is decidedly so',
  2: 'Reply hazy try again',
  3: 'Cannot predict now',
  4: 'Do not count on it',
  5: 'My sources say no',
  6: 'Outlook not so good',
  7: 'Signs point to yes',
  answer () {
    return this[Math.floor(Math.random() * 8)]
  }
}
const question = `Will there be clouds in the sky, tomorrow?`
console.log(`${question}\n${eightBall.answer()}`)
Will there be clouds in the sky, tomorrow?
Cannot predict now

Now, how do we make eightBall an exported module, and have the module with the question and output display import that module?

I’m definitely keeping an open mind, but maybe getting in over my head haha! I’ve experimented with changing the switch statement over to an object literal (hopefully I’m using the right term there vs. just an object). I tried it briefly last night before going to bed and got “object Object” in the middle of my eight ball – but realized that since I was trying to
access the method in the object that I needed something more like eightBall.answer().

This morning, I did that and applied the question constant which works perfectly to the console (though I left the rest of my code to interact with my page that I’ve already setup.

But, I’ll admit, I’m not too clear with making an exported module. I went back to my Learn JavaScript Syntax: Modules section to review (and realized that none of that information stuck from the first time haha). I attempted using:

export {eightBall};

and then made a second JavaScript file and used:

import { eightBall } from './eightBall';

I also tried another method, using:

export default eightBall;

and in the second JS file:

import eightBall from './eightBall';

both result in – Uncaught SyntaxError: Cannot use import statement outside a module

Other than that one lesson on exporting modules (that didn’t really stick with me), I haven’t really come across any exporting of modules yet. That lesson also showed an option using Node.js, but that might be even farther from anything I’m familiar with. I’m not sure where to go from here on that idea.

Also curious, you said before “there’s nothing to show if we didn’t write it ourselves”…Which I have been trying to live by since then (and I know when we started this conversation 4 months ago, I originally attempted pasting in code I didn’t fully understand which resulted in something that didn’t really work as I intended). But, isn’t the whole purpose of exporting a module – making a chunk of code that you (or someone else) could just plug in and use? Again, I have a lot to learn, so pardon if I don’t know the right questions to ask to find the answers I didn’t yet know I was seeking hahaha!

I’m also taking some web design courses from the University of Michigan through Coursera and the teacher there talks about using a block of code someone else has written and not needing to know exactly how it works. I don’t know that I agree with that, as I’d rather know how something works from just being curious if nothing else. I find the Codecademy courses a lot more thorough than those classes. Sorry if this all got long-winded…But, what are your thoughts?

1 Like

Yeah, we’re in the same boat. I haven’t played around with modules and need to do some reading up on it. It’s not critical right now, just something to challenge yourself with when you have the time. Will see if I can come up with a working example over the weekend. For now, just embed the object in your code.

The question can come from the input control (text) of your form. Clear the form after you echo the text to the display. Poll the method in the object and echo that to the display, as well.

Your HTML will need some elements:

<section class="container">
  <label for="q">Magic 8-Ball</label>
  <input id="q" placeholder="Your question">
  <button id="ask">Ask away...</button>
  <p id="question"></p>
  <p id="answer"></p>
</section>

And your script will need to cache those elements…

// cached nodes
const q = document.querySelector('#q');
const question = document.querySelector('#question');
const answer = document.querySelector('#answer');
const ask = document.querySelector('#ask');
// handler
const handler = () => {
  question.textContent = q.value;
  q.value = ""
  answer.textContent = eightBall.answer();
}
//listener
ask.onclick = handler;

This isn’t tested but shouldn’t need too much fixing.


Node.js is another can of worms that can wait until you are really comfortable with JS.

Modular code is shareable, and makes collaborating a lot easier. We still have a part in the writing, though. Not everything can be out of the box. What would we learn from that? From adversity comes ingenuity and creative solutions. It’s okay to reverse engineer, but easier if we can forward engineer, first.


Tested and working as expected.

https://repl.it/@mtf/Magic-8-Ball-object-method

If you do use the above code in your web page, be sure to give attribution in the JS source file by including a link to either this topic or to my repl above.

1 Like

Thanks again Roy!! Using the form definitely looks and works a lot better than my original use of the prompt() function. Everything is up and running. I gave you credit at the bottom of my JS source file and included a link to this topic. I really appreciate all the help!!

website: Magic Eight Ball
code: GitHub - JCode777/magic-eight-ball

Onward to more JavaScript!! Talk to you again soon!

1 Like