How to call a function in external script file from HTML - javascript

I'm trying to call a javascript function in my HTML index file and I can't get it to work.
This is my html file that I'm trying to call a function from.
<div class="main">
<h1 class="header-main" onload="HeaderTyper('Welcome', this)">
<noscript>no javascript</noscript>
</h1>
</div>
<script type="text/javascript" src="script.js"></script>
And this is the script.
function HeaderTyper(message, element){
var i = 0;
var speed = 50;
if (i < message.length) {
element.innerHTML += message.charAt(i);
//play keystroke sound
i++;
setTimeout(HeaderTyper, speed);
}
}
I'm trying to get a typewriter effect style header. I'm planning to add some keystroke sounds, but first I need to figure out how to actually type it out in the header tag. The code won't type out the message I'm passing in argument. What did I do wrong ? Thank you for any help.

After the HTML page ends (As #johannchopin explained), import the file and then add an event listener (as #aaronburrows explained).
<body>
<div class="main">
<h1 class="header-main">
<noscript>no javascript</noscript>
</h1>
</div>
</body>
</html>
<script type="text/javascript" src="script.js"></script>
<script>
let h1 = document.querySelector('.header-main');
h1.addEventListener('load', HeaderTyper("Welcome", h1, false));
</script>
Also, I fixed the function, it was missing the parameters.
function HeaderTyper(message, element, i) {
var speed = 50;
if (i < message.length) {
console.log(message.charAt(i))
element.innerHTML += message.charAt(i);
//play keystroke sound
setTimeout(function(){ HeaderTyper(message,element,++i)}, speed);
}
}

You're attempting to bind a function call before it is loaded into the browser. Remove the onload from the HTML and add an event listener to the script.

According to this solution, The onload event can only be used on the document(body) itself. Best way to achieve this is to call the function in a <script> tag just before the </body> closing tag:
<div class="main">
<h1 class="header-main">
<noscript>no javascript</noscript>
</h1>
</div>
<script>
function HeaderTyper(message) {
var i = 0;
var speed = 50;
var element = document.querySelector('.header-main');
if (i < message.length) {
element.innerHTML += message.charAt(i);
//play keystroke sound
i++;
setTimeout(HeaderTyper, speed);
}
}
HeaderTyper('Welcome');
</script>

Ok, hi there.
function HeaderTyper(message, element){
alert('script loaded') //<---
var i = 0;
I put this line at the beginning of the script to make sure it works. And it's not.
Why?
Because you just made your function but doesn't call it.
First way to solve this - put ur function in the "script" of HTML doc. And call it after, like
<script>
function HeaderTyper(message) {
let i = 0
let speed = 50
let element = document.querySelector('.header-main')
if (i < message.length) {
element.innerHTML += message.charAt(i)
i += 1
setTimeout(HeaderTyper, speed)
}
}
HeaderTyper('Welcome') //<---
</script>
Second way - put HeaderTyper() at the end of script.js file, so the function start, but you need to make a link for "message" and "element".
setTimeout(HeaderTyper, speed);
}
}
HeaderTyper(someMessage, someElement) //<---

Related

How to make a typing animation, that can restart half way through

So I was making a simple text animation and decided to make it so once its done, you can restart it. Problem being, im not sure of a way to force it to restart onclick once done. The way im doing it, it can and will restart in the middle if you click the screen, which is fine, but it continues to print some text from before. Anyway heres my code
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1 id=typing-style></h1>
<script>
var i=0,text="Mitchell";
setInterval(()=>{
document.getElementById("typing-style").innerHTML += text.charAt(i);
i++;
},300)
function rerun() {
document.getElementById("typing-style").innerHTML = " ";
var i=0,text="Mitchell";
setInterval(()=>{
document.getElementById("typing-style").innerHTML += text.charAt(i);
i++;
},300)
}
</script>
<canvas id="screen" onclick="rerun()" width=1000% height=1000%></canvas>
</body>
</html>
So what I've been trying to do is get it to be able to restart when you click the screen, but stop the current process. Hope someone can figure it out.
This code never calls clearInterval, so both timers will run at the same time, cross-talking each other's text manipulations. The code is repeated unnecessarily--it's easier to write it once in a function, then call the function each time you need to run the logic.
For this sort of thing, I'd create a closure that encapsulates the data needed to create a timer: an interval and index. You can return a timer start function that handles resetting timer state and can be invoked in an event listener (preferred to onclick because it keeps behavior out of the markup; read more).
Lastly, prefer textContent or innerText to innerHTML. They're faster, safer and more semantically appropriate if the content is purely text-based.
const makeTextTyper = (el, text, speed) => {
let i;
let interval;
return () => {
clearInterval(interval);
el.innerText = "";
i = 0;
interval = setInterval(() => {
if (i < text.length) {
el.innerText += text[i++];
}
else {
clearInterval(interval);
}
}, speed)
};
};
const buttonEl = document.querySelector("button");
const typerEl = document.querySelector("h3");
const runTyper = makeTextTyper(typerEl, "Mitchell", 300);
buttonEl.addEventListener("click", runTyper);
runTyper();
<button>restart</button>
<h3></h3>
When the rerun function is invoked the existing interval needs to be cancelled, this can be achieved using the clearInterval method.
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1 id="typing-style"></h1>
<script>
var i = 0, text = "Mitchell";
var interval;
interval = setInterval(()=>{
document.getElementById("typing-style").innerHTML += text.charAt(i);
i++;
},300)
function rerun() {
clearInterval(interval);
document.getElementById("typing-style").innerHTML = " ";
var i=0,text="Mitchell";
interval = setInterval(()=>{
document.getElementById("typing-style").innerHTML += text.charAt(i);
i++;
},300)
}
</script>
<canvas height="1000%" id="screen" onclick="rerun()" width="1000%"></canvas>
</body>
</html>
I would write a if statement inside the rerun function to determine whether the animation is done or not. You can determine whether the text is done by using the .length method.
var typingText = document.getElementById("typing-style")
if(typingText.length === 8) //length of Mitchell {
document.getElementById("typing-style").innerHTML = " ";
var i=0,text="Mitchell";
setInterval(()=>{
document.getElementById("typing-style").innerHTML += text.charAt(i);
i++;
}
},300)
} ```

Problem with local progress bar code while it works properly on CodePen? [duplicate]

I'm trying to run a simple few lines of code using an index.html file and a script.js file, nothing else.
In the HTML file, I have doctype html:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="javascript/script.js"></script>
</head>
<body>
<div id="content1">This is content 1 </div>
<div id="content2">This is content 2 </div>
<div id="content3">This is content 3 </div>
</body>
</html>
And for my javascript section i have:
var elems = $("div");
if (elems.length) {
var keep = Math.floor(Math.random() * elems.length);
for (var i = 0; i < elems.length; ++i) {
if (i !== keep) {
$(elems[i]).hide();
}
}
}
When I run this in CodePen, or even on the code editor on this website, it works fine. But it doesn't work when I use the files on my desktop (index.html, script.js I do believe the folder structure is correct (script.js is in the javascript folder.)
Thank you all
Move your script tag just before the closing of the body tag:
<script src="javascript/script.js"></script>
</body>
This way the DOM will be available when your script runs.
If you prefer to keep your script in the head part, then wrap your code in a DOMContentLoaded event handler:
document.addEventListener("DOMContentLoaded", function() {
var elems = $("div");
if (elems.length) {
var keep = Math.floor(Math.random() * elems.length);
for (var i = 0; i < elems.length; ++i) {
if (i !== keep) {
$(elems[i]).hide();
}
}
}
});
... so to have your code run when the DOM is ready.
You did not tag your question with jquery, but as you seem to use it, you can use this shorter code for doing essentially the same as above:
$(function() {
var $elems = $("div").hide(),
$elems.eq(Math.floor(Math.random() * $elems.length)).show();
});
wrap your code in this function to execute it if the document is ready.
$(document).ready(function (){
// your code goes here
});

Code works in Codepen, but not with my desktop files

I'm trying to run a simple few lines of code using an index.html file and a script.js file, nothing else.
In the HTML file, I have doctype html:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="javascript/script.js"></script>
</head>
<body>
<div id="content1">This is content 1 </div>
<div id="content2">This is content 2 </div>
<div id="content3">This is content 3 </div>
</body>
</html>
And for my javascript section i have:
var elems = $("div");
if (elems.length) {
var keep = Math.floor(Math.random() * elems.length);
for (var i = 0; i < elems.length; ++i) {
if (i !== keep) {
$(elems[i]).hide();
}
}
}
When I run this in CodePen, or even on the code editor on this website, it works fine. But it doesn't work when I use the files on my desktop (index.html, script.js I do believe the folder structure is correct (script.js is in the javascript folder.)
Thank you all
Move your script tag just before the closing of the body tag:
<script src="javascript/script.js"></script>
</body>
This way the DOM will be available when your script runs.
If you prefer to keep your script in the head part, then wrap your code in a DOMContentLoaded event handler:
document.addEventListener("DOMContentLoaded", function() {
var elems = $("div");
if (elems.length) {
var keep = Math.floor(Math.random() * elems.length);
for (var i = 0; i < elems.length; ++i) {
if (i !== keep) {
$(elems[i]).hide();
}
}
}
});
... so to have your code run when the DOM is ready.
You did not tag your question with jquery, but as you seem to use it, you can use this shorter code for doing essentially the same as above:
$(function() {
var $elems = $("div").hide(),
$elems.eq(Math.floor(Math.random() * $elems.length)).show();
});
wrap your code in this function to execute it if the document is ready.
$(document).ready(function (){
// your code goes here
});

Execute javascript after page load is complete [duplicate]

This question already has answers here:
How to make JavaScript execute after page load?
(25 answers)
Closed 2 years ago.
I have an html page with some pre-rendered content and some yet un-rendered content. I want to display the pre-rendered content immediately, and then begin rendering the rest of the content. I am not using jQuery.
See the following snippet. I have tried this various ways, including injecting my script before the closing body tag and providing my script to populate the DOM as a callback to window.onload, document.body.onload, and document.addEventListener('DOMContentLoaded'). In every case, the page does not display the pre-rendered content until the rest of the content is rendered.
<html><head></head>
<body>
<header>What it is, my doge?</header>
<div id="main"></div>
<script>
var main = document.getElementById('main');
for (var i = 0; i < 500; i++)
main.innerText += new Date();
</script>
</body>
</html>
<html><head></head>
<body>
<header>What it is, my doge?</header>
<div id="main"></div>
<script>
var main = document.getElementById('main');
document.body.onload = function() {
for (var i = 0; i < 500; i++)
main.innerText += new Date();
};
</script>
</body>
</html>
<html><head></head>
<body>
<header>What it is, my doge?</header>
<div id="main"></div>
<script>
var main = document.getElementById('main');
window.onload = function() {
for (var i = 0; i < 500; i++)
main.innerText += new Date();
};
</script>
</body>
</html>
<html><head></head>
<body>
<header>What it is, my doge?</header>
<div id="main"></div>
<script>
var main = document.getElementById('main');
document.addEventListener('DOMContentLoaded', function() {
for (var i = 0; i < 500; i++)
main.innerText += new Date();
});
</script>
</body>
</html>
One case that has worked is window.setTimeout with 0 timeout. However, this simply defers the function until there is nothing left to do. Is this the best practice, here?
<html><head></head>
<body>
<header>What it is, my doge?</header>
<div id="main"></div>
<script>
var main = document.getElementById('main');
window.setTimeout(function() {
for (var i = 0; i < 500; i++)
main.innerText += new Date();
}, 0);
</script>
</body>
</html>
In terms of a best practice, there isn't one. In terms of a good, common, and acceptable practices, there are a handful. You've hit one:
setTimeout(function() { }, 1);
In this case, the function is executed within the browser's minimum timeout period after all other in-line processing ends.
Similarly, if you want to ensure your function runs shortly after some condition is true, use an interval:
var readyCheck = setInterval(function() {
if (readyCondition) {
/* do stuff */
clearInterval(readyCheck);
}
}, 1);
I've been using a similar, but more generalized solution in my own work. I define a helper function in the header:
var upon = function(test, fn) {
if (typeof(test) == 'function' && test()) {
fn();
} else if (typeof(test) == 'string' && window[test]) {
fn();
} else {
setTimeout(function() { upon(test, fn); }, 50);
}
}; // upon()
... and I trigger other functionality when dependencies are resolved:
upon(function() { return MyNS.Thingy; }, function() {
// stuff that depends on MyNS.Thingy
});
upon(function() { return document.readyState == 'complete';}, function() {
// stuff that depends on a fully rendered document
});
Or, if you want a more authoritative good practice, follow Google's example. Create an external async script and inject it before your first header script:
var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true;
s.src = '/path/to/script.js';
var header_scripts = document.getElementsByTagName('script')[0];
header_scripts.parentNode.insertBefore(s, header_scripts);
Google's solution theoretically works on all browsers (IE < 10?) to get an external script executing as soon as possible without interfering with document loading.
If you want an authoritative common practice, check the source for jQuery's onready solution.
Depending on your browser requirements you can use the async tag and import your script after content loads. This probably accomplishes the same thing as setTimeout(func, 0), but perhaps it's a little less hacky.
See http://plnkr.co/edit/7DlNWNHnyX5s6UE8AFiU?p=preview
html:
...
<body>
<h1 id="main">Hello Plunker!</h1>
<script async src="script.js"></script>
</body>
...
script.js:
for(var i=0; i<500; ++i) {
document.getElementById('main').innerText += new Date();
}
I've used this to effect before:
var everythingLoaded = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
clearInterval(everythingLoaded);
init(); // this is the function that gets called when everything is loaded
}
}, 10);
I think what you want to do is use an onload event on the tag.
This way first the "What it is, my doge?" message will appear while the javascript is processed.
I also set a timeout inside the loop, so you can see better the lines being added.
<html>
<head>
<script>
myFunction = function() {
for (var i = 1000; i > 0; i--) {
setTimeout(function() {
main.innerText += new Date();
}, 100);
}
};
</script>
</head>
<body onload="myFunction()">
<header>What it is, my doge?</header>
<div id="main"></div>
</body>
</html>

Simple Javascript Gallery

So I'm trying to loop through this array and change an image source every few seconds. Right now I have an onload event calling a setTimeOut method which should change the image 5 seconds after the page has loaded I would think, but it is doing it instantly. What is the problem? Here is my code:
<html>
<head>
<title>Ad Rotaror</title>
<script type="text/javascript">
var i = 0;
var ads = new Array(4);
ads[0]='promo1.gif';
ads[1]='promo2.gif';
ads[2]='promo3.gif';
ads[3]='promo4.gif';
ads[4]='promo5.gif';
function change()
{
if(i > 4)
i = 0;
document.images[0].src = ads[i];
i++;
}
</script>
</head>
<body>
<img src="promo1.gif" onload="setInterval(change(), 5000)" />
</body>
</html>
Change 'change()' to 'change'. You are calling the function immediately.

Categories

Resources