Replacing Document.write Problems(I did some research but still failed) - javascript

I got a great answer to this but have more questions. :) I was told that having javascript declared in two different places was bad and messy(you can see in the answer below), but I'm learning from a book right now and it told me to put my variables, arrays, functions etc. in the head of the html and the rest in the body.(that's why I have javascript declared in two different places) Is that wrong and why? He also recommended using a developer tool. I'm very new to coding in general and don't know much about these could anyone recommend a developer tool for chrome? Also what would a developer tool do? Thanks!
This was fixed:
Hi I was converting the card war game so it worked on a page instead of in the console and here was my original code http://pastebin.com/AgLgy97F. I was trying to use document.write to write out the code on a web, but I found out that document.write rewrote the whole page and removed the button I put there to progress to the next turn.
I looked on the forums and I looked online and came to the conclusion that I shoud replace it using this<div id="play"></div> and document.getElementById("play").innerHTML="I'm a string!". So I made this http://pastebin.com/29mVqp67. I tried it out and nothing happened -_-. What did I do wrong replacing document.write?
The new code I made is here too:
<html>
<head>
<script language="JavaScript">
<!--
var disp = function() {
document.getElementByID("play").innerHTML="You drew a "+user_disp+".";
document.getElementByID("play").innerHTML="Your opponent drew a "+cpu_disp+".";
document.getElementByID("play").innerHTML=statement;
};
var war = function() {
document.getElementByID("play").innerHTML="W-A-R spells WAR!";
disp();
};
var full = [1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13];
var user = [];
var cpu = [];
var rand = 0;
//Shuffles and deals the deck
var shuffled = [];
for (var i=0;i<52;i++) {
rand=Math.floor(Math.random()*full.length);
shuffled.push(full[rand]);
full.splice(rand,1);
}
for (var j=0;j<52;j++) {
if (j%2===0) {
user[user.length]=shuffled.pop();
} else {
cpu[cpu.length]=shuffled.pop();
}
}
//Creates a bunch of variables and functions that will be needed in the game
var cpu_card=0;
var cpu_warcard=0;
var cpu_war1=0;
var cpu_war2=0;
var cpu_war3=0;
var cpu_disp=0;
var user_card=0;
var user_warcard=0;
var user_war1=0;
var user_war2=0;
var user_war3=0;
var user_disp=0;
var statement=0;
var card_name = function(cpuc,userc) {
switch (cpuc) {
case 13:
cpu_disp="K";
break;
case 12:
cpu_disp="Q";
break;
case 11:
cpu_disp="J";
break;
case 1:
cpu_disp="A";
break;
default:
cpu_disp=cpuc;
break;
}
switch (userc) {
case 13:
user_disp="K";
break;
case 12:
user_disp="Q";
break;
case 11:
user_disp="J";
break;
case 1:
user_disp="A";
break;
default:
user_disp=userc;
break;
}
};
//Lets play the game!
//-->
</script>
</head>
<body>
<form>
<input type="Button" value="Click to Take Your Turn" onClick="playWar()"></input>
</form>
<p>
<h1>This Is War Lets Play!!!!</h1>
<br>
<div id="play"></div>
<script language="JavaScript">
<!--
function playWar(){
if(user.length<52 && user.length>1) {
//Picks out the cards that are used
cpu_card=cpu.shift();
user_card=user.shift();
card_name(cpu_card,user_card);
//Figures out if you win, lose, or go to war
if (user_card<cpu_card) {
statement="You lost!";
cpu[cpu.length]=cpu_card;
cpu[cpu.length]=user_card;
} else {
if (user_card>cpu_card) {
statement="You won!";
user[user.length]=user_card;
user[user.length]=cpu_card;
} else {
if(cpu.length<3 || user.length<3){
user[user.length]=user_card;
cpu[cpu.length]=cpu_card;
}
else{
statement="You tied! TO WAR!";
}
}
}
disp();
//This is what happens when you go to war
if (statement==="You tied! TO WAR!") {
cpu_war1=cpu.shift();
cpu_war2=cpu.shift();
cpu_war3=cpu.shift();
cpu_warcard=cpu.shift();
user_war1=user.shift();
user_war2=user.shift();
user_war3=user.shift();
user_warcard=user.shift();
card_name(cpu_warcard,user_warcard);
if (user_warcard<cpu_warcard) {
statement="You lost the war to your opponent!";
cpu[cpu.length]=cpu_war1;
cpu[cpu.length]=cpu_war2;
cpu[cpu.length]=cpu_war3;
cpu[cpu.length]=cpu_warcard;
cpu[cpu.length]=cpu_card;
cpu[cpu.length]=user_war1;
cpu[cpu.length]=user_war2;
cpu[cpu.length]=user_war3;
cpu[cpu.length]=user_warcard;
cpu[cpu.length]=cpu_card;
} else {
if(user_warcard>cpu_warcard) {
statement="You crushed your opponent in war!";
user[user.length]=user_war1;
user[user.length]=user_war2;
user[user.length]=user_war3;
user[user.length]=user_warcard;
user[user.length]=user_card;
user[user.length]=cpu_war1;
user[user.length]=cpu_war2;
user[user.length]=cpu_war3;
user[user.length]=cpu_warcard;
user[user.length]=cpu_card;
} else {
statement="The war resulted in a stalemate!";
user[user.length]=user_war1;
user[user.length]=user_war2;
user[user.length]=user_war3;
user[user.length]=user_warcard;
user[user.length]=user_card;
cpu[cpu.length]=cpu_war1;
cpu[cpu.length]=cpu_war2;
cpu[cpu.length]=cpu_war3;
cpu[cpu.length]=cpu_warcard;
cpu[cpu.length]=cpu_card;
}
}
war();
}
}
//When you are done, here it finds if you win or lose this game
else if (user.length===52) {
document.getElementByID("play").innerHTML="You have crushed your opponent. Feel free to steal all of his belongings!";
} else {
document.getElementByID("play").innerHTML="Unfortunatly, you have fallen victim to your opponent's wrath and have been conquered.;
}
}
//-->
</script>
</body>

You have a few problems here to start with.
you have your javascript declared in two different places and in both cases you are polluting the global namespace. That should be cleaned up and may help identify some problems.
you have an unterminated string literal at the end of this line:
you have fallen victim to your opponent's wrath and have been conquered. <===
getElementByID NEEDS to be getElementById
Your disp() function is incorrect. As it is written, each successive line is replacing the previous text.
var disp = function() {
document.getElementByID("play").innerHTML="You drew a "+user_disp+".";
document.getElementByID("play").innerHTML="Your opponent drew a "+cpu_disp+".";
document.getElementByID("play").innerHTML=statement;
};
This can be fixed by concatenating the strings together prior to setting innerHtml, or, to have more control over the output you can use separate elements. Pseudo code:
else.innerHTML = string1 + string2 + string3;
I'd recommend making some heavy use of the developer tools for whichever browser you are using for development. It will help you catch many of these problems either by watching the console output or by stepping through the code.
I've put your code in a jsFiddle as well.
That should get you started. Good luck!

Related

How to change document.write into a function for ASCII art

I am fairly new in development so I am going to try my best in phrasing my question accurately. Well, it is pretty simple, I have written a script below which draws a Christmass Tree as ASCII art on the webpage. I have used document.write. I want to however:
Check if my code can be made simpler
Convert it into a function and still make it display on to the webpage
I am not very familiar with using the DOM yet and tried console.log but I am sure I am doing something wrong there considering my relatively low experience. Would be great if someone could guide me and show me how this can be made into a solid function which still displays the christmas tree on the browser.
Thanks!
<!DOCTYPE html>
<html>
<body>
<p></p>
<script>
//define height and star parameter
var height=5;
var star=true;
//add or remove star
if(star===true){
for (u=0;u<1;u++) {
for (r=0;r<height-1;r++) {
document.write("&nbsp");
}
document.write("*</br>");
}
} else {
document.write("");
};
//create a loop for the pyramid in the tree
for (i=0; i<height; i++) {
for(r=height-1; r>i; r--) {
document.write("&nbsp");
}
for (k=0; k<=(i*1); k++) {
document.write("x");
}
document.write("</br>");
};
//create trunk of tree
for (u=0;u<1;u++) {
for (r=0;r<height-1;r++) {
document.write("&nbsp");
}
document.write("I</br>");
}
</script>
</body>
</html>

if/else statement confusion

I'm thinking about making a small semi-game where you respond to a mysterious void about things. The user sees a question on-screen, types a response in the textbox and clicks the reply button, and the script replies.
My main problem is to understand the logic behind all this.
For example:
Do you like apples?
A1:Yes
A2:No
if(yes){
say this
} else if(no){
say that
}
What would be the appropriate syntax in this case? Because i'm really really confused right now, it may seem like a very noob-question, but jQuery is getting on my nerves.
var input = document.querySelector('input'),
output = document.getElementById('output');
input.onkeyup = function(event) {
switch (this.value.toLowerCase()) {
case 'chicken':
output.innerText = "I like chicken too";
break;
case 'meat':
output.innerText = "mmmmm, meat!!";
break;
default:
break;
}
};
<form>
<input type="text" />
<div id="output">Huh?</div>
</form>
You could also just do this
var isYes = true;
(isYes) ? /* Do this */ : /* Do this */ ;
Saves you lines of code
Edit: As you had requested I have created a snippet. Try it out, type in chicken/meat
Since you are using a Boolean (true,false) type of scenario you can can just use an if/else type of statement:
var is_yes = true;
if(is_yes){
// Do this
} else {
// Do that
}

JavaScript Countdown with argument passing in

You are given an integer called start_num. Write a code that will countdown from start_num to 1, and when the countdown is finished, will print out "Liftoff!".
I am unsure how to do this and keep getting stuck.
This is the code I am provided with at the beginning of the problem:
function liftoff_countdown(start_num) {
// My code goes here!
}
And then they want me to pass in a value such as the 5:
liftoff_countdown(5);
And then this will be my output:
6
5
4
3
2
1
"Liftoff!"
Thanks!
Look at this maybe help you to create your own code
make two file in a same folder (script.js and index.html)
index.html
<!doctype html>
<head>
<title>Countdown</title>
</head>
<body>
<div id="container">
<div id="inputArea">
</div>
<h1 id="time">0</h1>
</div>
<script src="script.js"></script>
</body>
</html>
script.js
var valueRemaining;
var intervalHandle;
function resetPage() {
document.getElementById("inputArea").style.display = "block";
}
function tick() {
var valueDisplay = document.getElementById("time");
valueDisplay.innerHTML = valueRemaining;
if (valueRemaining === 0) {
valueDisplay.innerHTML = "Liftoff!";
clearInterval(intervalHandle);
resetPage();
}
valueRemaining--;
}
function startCountdown() {
var count = document.getElementById("count").value;
if (isNaN(count)) {
alert("Please enter a number!");
return;
}
valueRemaining = count;
intervalHandle = setInterval(tick, 1000);
document.getElementById("inputArea").style.display = "none";
}
// as soon as the page is loaded...
window.onload = function () {
var inputValue = document.createElement("input");
inputValue.setAttribute("id", "count");
inputValue.setAttribute("type", "text");
// create a button
var startButton = document.createElement("input");
startButton.setAttribute("type", "button");
startButton.setAttribute("value", "Start Countdown");
startButton.onclick = function () {
startCountdown();
};
// add to the DOM, to the div called "inputArea"
document.getElementById("inputArea").appendChild(inputValue);
document.getElementById("inputArea").appendChild(startButton);
};
in this example you have many things to understand how javascript works behind scenes.
How about this...
function liftoff_countdown()
{
var span=document.getElementById('num');
var i=document.getElementById('num').innerText;
i=i-1;
span.innerText=i;
if (i==0){
span.innerText='Liftoff!';
clearInterval(count_down)
}
}
var count_down=setInterval(liftoff_countdown,1000);
<span id="num">5</span>
You can achieve this with a simple recursive function and the use of setTimeout to recursively call the function after a time lapse of 1 second.
function lift_off(seconds) {
if(seconds == 0) {
console.log('liftoff');
} else {
console.log(seconds--);
setTimeout(function(){lift_off(seconds);},1000);
}
}
lift_off(10);
Here is a working JSFiddle
Preface
A lot of these answers seem to be focused on doing things with timers and recursion. I do not believe that is your intent. If your only goal is to print those values to the console, you could simply do the following (see the comments for an explanation).
The Answer
function liftoff_countdown(start_num) {
// Loops through all values between 0 and start_num
for(int i = 0; i < start_num; i++) {
// Prints the appropriate value by subtracting from start_num
console.log( start_num - i );
}
// Upon exiting the loop, prints "Liftoff!"
console.log("Liftoff!");
}
Additional Thoughts
You could just as easily loop backwards through the numbers instead of forward like so:
for(int i = start_num; i > 0; i--){
console.log( i );
}
I tend to lean towards iterating forwards just because it's more common, and it's often easy to confuse readers of your code if they gloss over the loop initialization.
Additionally, I am working with the assumption that when you say "print" you mean "console.log()". If this is untrue, you could of course use any other function in its place (e.g. alert( "Liftoff!" );).

Passing variable between functions in Javascript (Titanium Studio Desktop)

Hopefully I can articulate this problem well. I'm working on a simple audio player in Titanium Desktop. The primary code I'm focused on right now is the following:
function pickMusicFolder (){
var win = Titanium.UI.getCurrentWindow();
win.openFolderChooserDialog(function(folderResponse) {
var file = Titanium.Filesystem.getFile(folderResponse[0]);
var listing = file.getDirectoryListing();
for (var i = 0; i < listing.length; i++) {
if (listing[i].isDirectory()) {
// if the listing is a directory, skip over it
$('#main').append('DIRECTORY: ' + listing[i].nativePath() +
'<br />');
// continue;
}
else {
// otherwise, print the filename of the file to the #main content window
var songOnList = listing[i].nativePath();
var songURL = songOnList.replace(/\\/g,"/");
$('#main ul').append('<li>' + songURL + '</li>');
}
}
});
};
function playSong(songURL){
var currentSong = Titanium.Media.createSound(songURL);
currentSong.play();
this.stopPlayback = stopPlayback;
function stopPlayback(currentSong){
currentSong.stop();
}
}
And then related HTML:
<input type="image" src="img/player_stop.png" name="stopPlayback" onClick="playSong.stopPlayback(songURL)" />
<input type="image" src="img/folder_add.png" name="pickMusicFolder" onClick="pickMusicFolder()" />
Now, both pickMusicFolder and playSong itself work properly. However, stopPlayback isn't working, I'm having a really hard time grasping how to deal with different functions for playing and stopping audio, since the code that's generating the clickable links is completely compartmentalized within the pickMusicFolder function, while the code for stopping playback is only attached to the one separate interface button.
I simply need access to the songURL variable between multiple functions in order to be able to perform operations on one solitary song while it's playing (or not). I'm avoiding resorting to global variables, as I find that to be sort of a cop out.
Anyone have any ideas? Any tips are much appreciated! (Oh, and please ignore my ugly code; was trying a bunch of hack-y solutions before posting.)
Very quickly solution is to store currentSong as property of function playSong:
function playSong(songURL){
var currentSong = Titanium.Media.createSound(songURL);
playSong.currentSong = currentSong; // store curernt playing song as property of function
currentSong.play();
}
playSong.stopPlayback = function() {
if (playSong.currentSong) {
playSong.currentSong.stop();
delete playSong.currentSong;
}
};
when song will be stopped just remove this property that would mean no song are playing now
You should use a closure. See below
var stopPlayback = function() { /* Placeholder, defined later */ };
var playSong = function(songURL){
var currentSong = Titanium.Media.createSound(songURL);
currentSong.play();
// Redefine stopSong in the parent scope
stopPlayback = function(){
// currentSong is available to this function via closure
currentSong.stop();
}
}
HTML Edit
<input type="image" src="img/player_stop.png" name="stopPlayback" onClick="stopPlayback()" />
As a side note, you should not be using HTML attributes to attach JavaScript events. This is a great series on event attachment, but what you really should read is this part. Also, every JS library provides methods for attaching events to make your life easier.

Disappearing Menu Commands After User Input in Tampermonkey

Tampermonkey is an extension for Google Chrome that attempts to emulate the functionality of Greasemonkey. To be clear, I got my script to work in Chrome and the default JavaScript changes to show up. I wanted to test the menu commands, however, and entered a 6-digit hex color code after clicking on the command in the Tampermonkey menu. I reloaded the page, and the commands disappeared from the menu! My script was still there (and the checkbox was ticked).
No matter what I did or what code I changed, I could never emulate this initial functionality after that user-defined input was set. This leads me to believe that there's some persistent data that I can't delete that's causing my script to fail prematurely. NOTE: This exact script works perfectly and without errors in Firefox.
This is obviously not a Tampermonkey forum, but people here seem very knowledgeable about cross-platform compatility. I didn't hear a single peep from the Chrome console after all of the changes below, and I'm really just out of ideas at this point. Here are some things I've tried (with no success). Any console errors are listed:
Changing jQuery version from 1.5.1 to 1.3.2
Calling localStorage.getItem('prevoColor') from console after page load (both values null)
Changing client-side storage from localStorage to get/setValue
Calling GM_getValue from the console = ReferenceError: GM_getValue is not defined
Deleting localStorage entries for veekun.com in Chrome options
Refreshing, Re-installing the script, and restarting the browser more times than I can count
Repeating all of the above commands using Firebug Lite (bookmarklet)
Here's the code I was using:
// ==UserScript==
// #name Veekun Comparison Highlighter
// #namespace tag://veekun
// #description Highlights moves exclusive to pre-evolutions on veekun.com's family comparison pages (user-defined colors available)
// #include http://veekun.com/dex/gadgets/*
// #author Matthew Ammann
// #version 1.0.3
// #date 3/11/11
// #require http://sizzlemctwizzle.com/updater.php?id=98824
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
// ==/UserScript==
/*
Goal: Change checkmark color & move name to user-specified color on family comparison pages if
[DONE] Baby poke has a LEVEL-UP move unlearned by any evolutions
[DONE] a) Make sure move is not a TM or tutor move
[DONE] Any other mid-evolution has a move unlearnable by a final evo (Caterpie, Weedle families)
[DONE] a) Make sure move is not a TM or tutor move
[DONE] Any pre-evo has a TUTOR move unlearned by any evo (Murkrow in HG/SS)
[] Implement auto-update after uploading to userscripts.org
Credits: Brock Adams, for helping with Chrome compatibility
Metalkid, for the jQuery consult
*/
var isLevelupMove = false;
var isTutorMove = false;
var isTM = false;
var TMhead = $('#moves\\:machine');
var hasSecondEvo = false;
var hasFinalEvo1 = false;
var hasFinalEvo2 = false;
var header = $('.header-row').eq(1);
var TMmoves = new Array();
//This section deals with the user-defined colors
GM_registerMenuCommand("Color for pre-evolutionary-only moves", prevoColorPrompt)
GM_registerMenuCommand("Color for first evolution-only moves", evoColorPrompt)
var prevoColor = GM_getValue('prevoColor', '#FF0000');
var evoColor = GM_getValue('evoColor', '#339900');
function prevoColorPrompt()
{
var input = prompt("Please enter a desired 6-digit hex color-code for pre-evolutionary pokemon:")
GM_setValue('prevoColor', '#'+input);
}
function evoColorPrompt()
{
var input = prompt("Please enter the desired 6-digit hex color-code for first-evolution pokemon:")
GM_setValue('evoColor', '#'+input);
}
//This loop tests each 'th' element in a sample header row, determining how many Evos are currently present in the chart.
$('.header-row').eq(1).find('th').each(function(index)
{
if($(this).find('a').length != 0)
{
switch(index)
{
case 2:
hasSecondEvo = true;
break;
case 3:
hasFinalEvo1 = true;
break;
case 4:
hasFinalEvo2 = true;
break;
}
}
});
//All 'tr' siblings are TM moves, since it's the last section on the page
//This array puts only the names of the available TMs into the TMmoves array
TMhead.nextAll().each(function(index)
{
TMmoves.push($(this).children(":first").find('a').eq(0).html());
});
$('tr').each(function(index)
{
var moveName = $(this).children(":first").find('a').eq(0).html();
moveName = $.trim(moveName);
switch($(this).attr('id'))
{
case 'moves:level-up':
isLevelupMove = true;
break;
case 'moves:egg':
isLevelupMove = false;
break;
case 'moves:tutor':
isTutorMove = true;
case 'moves:machine':
isTM = true;
}
if(isLevelupMove || isTutorMove)
{
var babyMoveCell = $(this).find('td').eq(0);
babyMoveText = $.trim(babyMoveCell.html());
secondEvoCell = babyMoveCell.next();
secondEvoText = $.trim(secondEvoCell.html());
finalEvo1Cell = secondEvoCell.next();
finalEvo1Text = $.trim(finalEvo1Cell.html());
finalEvo2Cell = finalEvo1Cell.next();
finalEvo2Text = $.trim(finalEvo2Cell.html());
//This checks if evolutions have checkmarks
if(babyMoveText.length > 0)
{
if(hasSecondEvo && secondEvoText.length == 0 || hasFinalEvo1 && finalEvo1Text.length == 0 ||
hasFinalEvo2 && finalEvo2Text.length == 0)
{
//See if the move is a TM before proceeding
var tm = tmCheck(moveName);
if(!tm)
{
if(secondEvoText.length > 0)
{
babyMoveCell.css("color", evoColor);
secondEvoCell.css("color", evoColor);
babyMoveCell.prev().find('a').eq(0).css("color", evoColor); //highlights move name
}
else
{
babyMoveCell.css("color", prevoColor);
babyMoveCell.prev().find('a').eq(0).css("color", prevoColor);
}
}
}
}
else if(secondEvoText.length > 0)
{
if(hasFinalEvo1 && finalEvo1Text.length == 0 || hasFinalEvo2 && finalEvo2Text.length == 0)
{
var tm = tmCheck(moveName);
if(!tm)
{
secondEvoCell.css("color", evoColor);
babyMoveCell.prev().find('a').eq(0).css("color", evoColor);
}
}
}
}
});
function tmCheck(input)
{
var isTM = false;
//Iterate through TMmoves array to see if the input matches any entries
for(var i = 0; i < TMmoves.length; i++)
{
if(input == TMmoves[i])
{
isTM = true;
break;
}
}
if(isTM == true)
return true;
else
return false;
}
//alert("evoColor: " + localStorage.getItem('evoColor') + ". prevoColor: " + localStorage.getItem('prevoColor'));
Any ideas as to why this is happening?
EDIT: I messaged sizzlemctwizzle about this problem, and this was his reply: "Tampermonkey’s #require implementation is incorrect. It downloads my updater far too often so I have banned it from using my updater via browser sniffing. My server just can’t handle the traffic it brings. The script it is downloading from my server shouldn’t have any actual code in it. Since it is causing errors with in your script I would guess Tampermonkey isn’t passing the User Agent header when it does these requests. I’m never tested my updater in Chrome so I have no idea why it breaks. Perhaps you could try and install NinjaKit instead."
What URL are you testing this on? I tested on http://veekun.com/dex/gadgets/stat_calculator.
Anyway, the script behavior, vis à vis the menu commands did seem erratic with Tampermonkey. I couldn't really tell / didn't really check if the rest of the script was working as it should.
The culprit seems to be the sizzlemctwizzle.com update check. Removing its // #require made the menu stable. Putting that directive back, broke the script again.
I've never been a fan of that update checker, so I'm not going to dive into why it appears to be breaking the Tampermonkey instance of this script. (That would be another question -- and one probably best directed at the 2 responsible developers.)
For now, suggest you just delete it. Your users will check for updates as needed :) .

Categories

Resources