Unable to modify javascript within an HTML website - javascript

Hello I am relatively new and have never coded before a month ago but I am slowly teaching myself the structure and inner workings of a website though html, css, and javascript. I am trying to modify a specific script within a website. This website is
https://www.wizards.com/dnd/dice/dice.htm
My goal is to make it so that I can manipulate a dice roll to give me an altered range for example instead of 1-4, maybe 1-10 and to also perhaps give me a number I specify. I also want to leave the general aesthetic of the site as unchanged as possible.
So first off I put this handy piece of code within the URL
javascript:document.body.contentEditable='true'; document.designMode='on'; void 0
and it allowed me to make the content within the body editable.
I wanted to be simple and just change the D4 dice element https://gyazo.com/adf563827f63edd37264882e90fd5f85 so it would give give me numbers in a range of 1-20.
The HTML code for this element is
<img src="https://www.wizards.com/dnd/dice/images/d4a.jpg" alt="d4" name="d4" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage('document.d4','document.d4','images/d4b.jpg')" width="38" border="0" height="37">
I noticed the onclick="rolld4()" So I looked within the head of the website and noticed within <script language="JavaScript1.2"></script> these lines of code.
function rolld4() {
d4rolls = parseInt(document.form1.d4n.value);
d4mod = parseInt(document.form1.d4mo.value);
dtotal = "";
d4res = 0;
rtotal = document.form1.runningtotal.value;
for (i=0; i<2; i++) {
if (document.form1.d4m[i].checked) {
d4pm = i }
}
if (d4pm == 0) {
dtotal = dtotal + "Roll(" + d4rolls.toString() + "d4" + ")+" + d4mod.toString() + ":\n"
}
if (d4pm == 1) {
dtotal = dtotal + "Roll(" + d4rolls.toString() + "d4" + ")-" + d4mod.toString() + ":\n"
}
for (r=0; r<d4rolls; r++) {
var d4 = Math.floor((Math.random() * 4) + 1);
d4res = d4res + d4;
dtotal = dtotal + d4.toString() + ","
}
if (d4pm == 0) {
d4res = d4res + d4mod;
dtotal = dtotal + "+" + d4mod + "\n" + "Total:" + d4res
}
if (d4pm == 1) {
d4res = d4res - d4mod;
if (d4res <= minimumvalue) {
d4res = minimumvalue;
}
dtotal = dtotal + "-" + d4mod + "\n" + "Total:" + d4res
}
document.form1.d4r.value = d4res;
rtotal = dtotal + "\n\n" + rtotal;
document.form1.runningtotal.value = rtotal;
}
I altered above line Math.floor((Math.random() * 4) + 1) to Math.floor((Math.random() * 20) + 1)
I then created a new script with the modified code and placed it below the D4 dice element which should alter the output to give me my range from 1-20. I was able to achieve a bit of success and did in fact mimic a roll range of 1-20. However this has only worked for me once and I have been unable to replicate it even going through the exact same process.
I also saw that within the <script language="JavaScript1.2"></script>scripts that it was one large comment. This is what confuses me because if the javascript functions within the code are turned to comments where is the javascript being pulled from when the dice is clicked and "rolled". I cant seem to find the source.
I am a total novice when it comes to javascript I have mostly been delving into HTML and CSS for designing websites so I have practically zero knowledge of javascript beside the general format.

You cannot alter (change) or delete any javascript on a loaded website. It's not possible as web browsers first compile the javascript when website is loading and prepare it for execution.
Even if you delete a script tag, that piece of code exists somewhere in the memory.
BUT, you can add pieces of javascript code to a webpage (think of it as it is adding itself to the end of the page in a separate script tag) via web console or Scratchpad in Mozilla Firefox OR developer tools > console in Google Chrome.
With that and some clever thinking (depending on the existing code on the website) you can do the stuff you want.

Related

How to copy text to clipboard in Vaadin without addon

I have spent long, too long, trying to make all of the directory components work. They took something that could have been super simple and made it complex and difficult.
I finally buckled and tried to copy a javascript function into my project and it worked with a simple method. The method, like all others need to be initiated by some other component. But do that in any way you want it.
All I'll leave here is the code. And the hope that somebody else will find this and use less time than I did.
void copyText(String text){
Page page = UI.getCurrent().getPage();
page.executeJavaScript(
"var el = document.createElement('textarea');" +
"el.value = $0;" +
"el.setAttribute('readonly', '');" +
"el.style = {" +
" position: 'absolute'," +
" left: '-9999px'" +
"};" +
"document.body.appendChild(el);" +
"el.select();" +
"document.execCommand('copy');" +
"document.body.removeChild(el);",
text);
}
void copyText(String text){
Page page = UI.getCurrent().getPage();
page.executeJavaScript(
"var el = document.createElement('textarea');" +
"el.value = $0;" +
"el.setAttribute('readonly', '');" +
"el.style = {" +
" position: 'absolute'," +
" left: '-9999px'" +
"};" +
"document.body.appendChild(el);" +
"el.select();" +
"document.execCommand('copy');" +
"document.body.removeChild(el);",
text);
}
Just to further explain the code. We need to initialize the page and then execute plain javascript-code. In this code, I pass the String text as a parameter and the utilize it in the code as "$0".
The code creates a textarea, which most of the addons in the directory also does. It then sets the text-string, it hide it from the ui with some styling. Then the textarea gets added to our file, because you are only allowed to copy a value that is visible. Then the text is selected, copied, and lastly the textarea is removed. Fast and clean.
You can also add the following line:
el.setSelectionRange(0, 99999);
Add it after the el.select(); line. According to W3, it should work better on phones with this line, but I have not tested it.

Why does my JavaScript code not work on refresh?

I'm taking a Udemy course and one of the exercises is to build a Dice game.
Basically it's just two dice (for each player/stakeholder) on screen both showing the value of 6. On refresh, it should 'roll' the dice (generate a random side for each dice, which are all images), and the header text should change to state the outcome of the game.
But my code doesn't work on refresh. I'm trying to find out why. Here's a comparison of my code VS the instructor's code:
This is my code, which doesn't work on refresh (but I've tested it and it works when I run it as a function).
//Generating Random Numbers for Dice 1 & Dice 2
var RandomNo1 = (Math.floor(Math.random() * 6) + 1)
var RandomNo2 = (Math.floor(Math.random() * 6) + 1)
//Making a var for image sources Dice 1-6 (images/dice#.png)
var imageSource1 = ("images/dice" + RandomNo1 + ".png")
var imageSource2 = ("images/dice" + RandomNo2 + ".png")
//set.Attribute function to change the img source for the dice
document.querySelector('.player1').setAttribute("src", imageSource1);
document.querySelector('.player2').setAttribute("src", imageSource2);
//Setting conditional statements to change the header depending on results of the dice roll.
if (RandomNo1 > RandomNo2) {
document.querySelector("h1").innerText="Player 1 Wins!";
}
else if (RandomNo2 > RandomNo1) {
document.querySelector("h1").innerText="Player 2 Wins!";
}
else {
document.querySelector("h1").innerText="It's a draw!";
}
This is the instructor's code, which does work on refresh.
var randomNumber1 = Math.floor(Math.random() * 6) + 1; //1-6
var randomDiceImage = "dice" + randomNumber1 + ".png"; //dice1.png - dice6.png
var randomImageSource = "images/" + randomDiceImage; //images/dice1.png - images/dice6.png
var image1 = document.querySelectorAll("img")[0];
image1.setAttribute("src", randomImageSource);
var randomNumber2 = Math.floor(Math.random() * 6) + 1;
var randomImageSource2 = "images/dice" + randomNumber2 + ".png";
document.querySelectorAll("img")[1].setAttribute("src", randomImageSource2);
//If player 1 wins
if (randomNumber1 > randomNumber2) {
document.querySelector("h1").innerHTML = "🚩 Play 1 Wins!";
}
else if (randomNumber2 > randomNumber1) {
document.querySelector("h1").innerHTML = "Player 2 Wins! 🚩";
}
else {
document.querySelector("h1").innerHTML = "Draw!";
}
How does her page change on refresh? Why doesn't it change immediately upon loading? Why doesn't my code, like hers, work on refresh?
Your script is fine. In essence it does the same as the script your teacher provided. To be honest, your script is better on several aspects, not in the least because you have added explanatory comments throughout, and I really like to see someone using .innerText, and not .innerHTML. The latter is really intended to inject HTML, so you did right to opt for .innerText. Personally, I would use .textContent, but that is just a detail.
The only explanation that is left, is that your script runs too soon, when the DOM is not ready yet, and so the querySelector() calls return undefined.
Move your <script> element towards the end of your HTML document, after the other elements you need to address in your script. A good place to put it, is right before the closing </body> tag.
welcome to stackoverflow!
There are a few mistakes in your code:
Do not begin your variable names with capital lettes, these are for naming constructors. (It's some sort of unspoken law to make your code better readable for other developers as well)
I don't think this is a problem in your code you showed us. I think you should
paste the script tag on the end of the html file, so document.querySelector() can select the html elements.
I made a pen here where I took your code and show you that it works. (I just changed the $element.setAttribute("src") to $element.innerText)
You can also use $element.src = instead of $element.setAttribute("src")

How to run a specific javascript code before page load (first of all)?

I have a js code that adds margin-top to a row with a specific class name (page with id=3) . I would like this code runs before page load because now it instantly displays the row without margin-top and then add it. The row should be displayed with the margin-top already be added.
My site is on wordpress and i added the js script on head.
I have tried
window.onpaint = checkMargin();
but it did not work. Any idea?
This is my js code
<script type="text/javascript">
//sets margin-top in serv-col --- IF not mobile version
function addServMargin() {
containers = document.getElementsByClassName('serv-cont');
titles = document.getElementsByClassName('serv-col-title');
texts = document.getElementsByClassName('serv-col-text');
links = document.getElementsByClassName('serv-col-link');
col_pad = '0px';
if ( window.innerHeight > 800) { col_pad = '8.3vh'; }
for (var i = 0; i < titles.length; i++) {
title_height = titles[i].offsetHeight;
text_height = texts[i].offsetHeight;
style = window.getComputedStyle(containers[i], '');
cont_height = style.getPropertyValue('height');
cont_padd = style.getPropertyValue('padding-top');
links[i].style.marginTop = 'calc(' + cont_height + ' - ' +
cont_padd + ' - ' + col_pad + ' - ' + title_height + 'px - 1.48vh - ' +
text_height + 'px - 127px - 5vh)';
}
}
function checkMargin() {
if (document.getElementsByClassName('page-id-13')[0] && window.innerWidth > 900) { addServMargin(); }
}
window.onresize = checkMargin;
</script>
I don't think making it run first will solve anything. The first thing the code does is get the containers, titles, texts, and links... which it does by searching the DOM. It then loops through the titles array and does the adjusting as needed. If the script runs before any rendering is done, the DOM elements won't exist. It 1) won't be able to find them, and 2) can't loop through them because the array will be empty.
Actually even before that, it checks for the existence of the elements it's looking for, and the screen size. I think the only way to get it to work w/o making it look like an after thought adjustment, would be to use CSS and media sizing to set the styles in the first place.
As I know JS is executed as the script tag is reached by Browser html interpreter. So putting it in the head tag on the first position may guarantee that it strats first, but can't guarantee that it ends execution before page loads, because the page loads asynchroniously.

Javascript slideshow with interval

I have a JavaScript Slideshow that only changes image when you refresh the page. I've tried adding
setInterval("printImage1()", 4000);
But then I get multiple images underneath eachother.
JavaScript
NumberOfImagesToRotate1 = 10;
FirstPart1 = '<a href="';
MiddlePart1 = '.htm"><img src="img/';
LastPart1 = '.jpg" border="0" height=”450” width="800"></a>';
function printImage1() {
var r = Math.ceil(Math.random() * NumberOfImagesToRotate1);
document.write(FirstPart1 + r + MiddlePart1 + r + LastPart1);
}
HTML
<script>printImage1()</script;
If I understand "But then I get multiple images underneath eachother" correctly, then every 4 seconds, you get another image printed under the previous.
in your HTML you should add something like:
<div id="spaceForImage"><div>
Then, in your javascript, include jQuery and replace the document.write(...) line with:
$('#spaceForImage').html(FirstPart1 + r + MiddlePart1 + r + LastPart1);
That should do what you want.
EDIT:
Using Mijago's idea, you'll need to have something like
<a id="slideLink" href="1.htm"><img id="slideImage" src="img/q1.jpg"></img></a>
in your HTML by default, then in your javascript, change document.write() to
$('#slideLink').attr('href',r + '.htm');
$('#slideImage').attr('src','img/' + r + '.jpg');
This is fine too. Changes the DOM less, but has an extra line of code.

How do I make a jQuery animation work across major browsers?

I have a bit of code that works in all major browsers save internet explorer and a animation effect that works only in Firefox. I am not real sure on how to even begin fixing this problem as it is fairly basic code. I will post the code snippets, first the html in the original rendering and then the jquery code used to modify the html dynamically.
The html on load starts with visibility hidden.
<h3 class="infobox" name="infobox"><p>text</p><p>text</p></h3>
These next 2 pieces of jquery from hover (enter and leave) for mouse related behavior.
Enter:
$(".infobox").css("visibility", "initial");
$(".infobox").html("<p>Location: " +
"<span style=\"color: " + (possiblemove[x] ? "green" : "red") + "\">" + indexcoords[x] + "</span></p>" +
"<p>Number of possible moves: " + possiblemoves + " Move count: " + nummoves + "</p>");
Leave:
$(".infobox").html("<p>text</p><p>text</p>");
$(".infobox").css("visibility", "hidden");
Animate:
for (var x = 0; x < 8; x++)
if (x % 2 == 0)
$(square).animate({backgroundColor: color}, 50);
else
$(square).animate({backgroundColor: 'red'}, 50);
$(square).animate({backgroundColor: color}, 50);
The web page with the questionable behavior:
http://freethecube.com/kt/
As you can see the highlighting effect of the board bits works in all major browsers. The info box at the top works in all but internet explorer. And the animate flashing for bad moves only works in firefox (have not tested this specifically in safari).
The general thing in common between these elements are the css modifications explicitly. The full css and jquery being used can be easily viewed by viewing the source of the page and clicking on the css file at the top and the js file at the bottom.
So what do I need to do to get these seemingly small css issues to work across all major browsers?
p.s.
I wrote this specifically simple in html for 2 reasons:
It is trust worthy code that anyone can see. It is actually a game and nothing else.
And easy portability into my wordpress site.
Jquery files being used:
jquery.js
jquery-animate.js
If there is a newer version of the animate, please let me know.
Thx
Addendum
The problems that I was having above did not stem from the CSS manipulation as I originally thought. It was indeed the CSS hook I was using. It was an older hack to fix the various versions of backgroundcolor there were. Such as: var bg = elem.currentStyle["backgroundColor"]; and var bg = document.defaultView.getComputedStyle(elem, null).getPropertyValue("background-color");. My whole issue was simply the difference in different browsers handly of RGB and RGBA color formats. My function would have been fine before RGBA, but not after.
The full css hook function I was using:
$.cssHooks.backgroundColor =
{
get: function(elem)
{
if (elem.currentStyle)
var bg = elem.currentStyle["backgroundColor"];
else if (window.getComputedStyle)
var bg = document.defaultView.getComputedStyle(elem, null).getPropertyValue("background-color");
if (bg.search("rgb") === -1)
return bg;
else
{
bg = bg.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x)
{
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(bg[1]) + hex(bg[2]) + hex(bg[3]);
}
}
};
The new and improved version: May still not be perfect but it is a lot closer.
$.cssHooks.backgroundColor =
{
get: function(elem)
{
if (elem.currentStyle)
var bg = elem.currentStyle["backgroundColor"];
else if (window.getComputedStyle)
var bg = document.defaultView.getComputedStyle(elem, null).getPropertyValue("background-color");
if (bg.search("rgb") === -1)
return bg;
else
{
bg = bg.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
return (bg && bg.length === 4) ? "#" +
("0" + parseInt(bg[1],10).toString(16)).slice(-2) +
("0" + parseInt(bg[2],10).toString(16)).slice(-2) +
("0" + parseInt(bg[3],10).toString(16)).slice(-2) : '';
}
}
};
Please up vote Strelok's answer because he hit the nail on the head. :)
A couple of things:
include jQuery before bootstrap
IE (any version) does not support initial value for the visibility css property. Just use visible.
At least in Chrome you have a problem in line 209 of game.js where the regex doesn't match anything and bg is null, so you need to handle this case and return the color or handle the case properly. It happens when the property value is rgba(0, 0, 0, 0) you need to handle rgba.

Categories