Strange problem with JavaScript code - javascript

Hi Masters Of Web Development,
first I want to say that I did not believe in my eyes - I've got a piece of javascript that works just fine in IE7, and don't in Firefox!!! :)))) That was little joke. :)
So I already told you the problem (it wasn't joke), now I'm pasting the javascript:
<script type="text/javascript">
<!-- This script and many more are available free online at -->
<!-- The JavaScript Source!! http://javascript.internet.com -->
<!-- Begin
var ms;
ms = %%CONTENT_REFRESH%% - 5;
var stop;
stop = 0;
var myvalue;
function display() {
if (!stop) {
setTimeout("display();", 1000);
}
thetime.value = myvalue;
}
function recalc() {
var hours;
var minutes;
var seconds;
ms = ms - 1;
hours = Math.floor(ms / 3600);
minutes = Math.floor(ms / 60);
if (minutes < 10) {
minutes = "0"+minutes;
}
seconds = ms - (minutes*60) - (hours*3600);
if (seconds < 10) {
seconds = "0"+seconds;
}
myvalue = hours+":"+minutes+":"+seconds;
thetime.value = myvalue;
if (myvalue == "0:00:00") {
stop = 1;
}
if (!stop) {
setTimeout("recalc();", 1000);
}
}
// End -->
</SCRIPT>
This is very old script I know that. It takes my current remaining song time, from my winamp and countdowns in site. But as I said, it does not work in Firefox.
Body and code that calls countdown timer looks like this:
<body class="playlist_body" onLoad="recalc();display();">
Time Left In Song: <INPUT align="center" TYPE="text" Name="thetime" size=5 />
</body>
//Edit: I look at FireBug, and I saw the following error:
thetime is not defined
recalc()playlist.cgi (line 87)
function onload(event) { recalc(); display(); }(load )1 (line 2)
error source line: [Break on this error] thetime.value = myvalue;\n

The problem is that it's accessing DOM elements by name.
Add the following code to the top to declare a variable for the thetime element, add id="thetime" to the INPUT, and add a call to init(); in onload in the body element.
var thetime;
function init() {
thetime = document.getElementById('thetime');
}
By the way, you can replace the textbox with a regular DIV element by setting the div's ID to thetime, and replacing thetime.value with thetime.innerHTML.
Also, it's better to call setTimeout with a function instead of a string; you should replace "display();" and "recalc();" with display and recalc respectively.

IE has a "feature" where an element with a name attribute is placed in the window object, eg.
<div name=foo></div>
Will give you a variable "foo" -- this is non-standard, you should do
document.getElementByName("foo")
To get the timer output element.

var thetime = document.getElementById("thetime");
and add id="thetime" instead of just name="thetime" to the input

Related

How can I make my two JavaScripts work together?

Hello I am trying to have my clock and my countdown timer on the same page so people/users can see when I am done with my game and for them to have the correct time with the countdown timer also. Here is the code. They both work separately but when the are both put on a .php page only the bottom one (countdown timer) works and if I do JQuery.noconflict to the timer the clock works but the countdown doesn't.
<!-- Clock Part 1 - Holder for Display of Clock -->
<span id="tP"> </span>
<!-- Clock Part 1 - Ends Here -->
<!-- Clock Part 2 - Put Anywhere AFTER Part 1 -->
<script type="text/javascript">
// Clock Script Generated By Maxx Blade's Clock v2.0d
// http://www.maxxblade.co.uk/clock
function tS(){ x=new Date(); x.setTime(x.getTime()); return x; }
function lZ(x){ return (x>9)?x:'0'+x; }
function tH(x){ if(x==0){ x=12; } return (x>12)?x-=12:x; }
function dE(x){ if(x==1||x==21||x==31){ return 'st'; } if(x==2||x==22){ return 'nd'; } if(x==3||x==23){ return 'rd'; } return 'th'; }
function y2(x){ x=(x<500)?x+1900:x; return String(x).substring(2,4) }
function dT(){ window.status=''+eval(oT)+''; document.title=''+eval(oT)+''; document.getElementById('tP').innerHTML=eval(oT); setTimeout('dT()',1000); }
function aP(x){ return (x>11)?'pm':'am'; }
var dN=new Array('Sun','Mon','Tue','Wed','Thu','Fri','Sat'),mN=new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'),oT="dN[tS().getDay()]+' '+tS().getDate()+dE(tS().getDate())+' '+mN[tS().getMonth()]+' '+y2(tS().getYear())+' '+':'+':'+' '+tH(tS().getHours())+':'+lZ(tS().getMinutes())+':'+lZ(tS().getSeconds())+aP(tS().getHours())";
if(!document.all){ window.onload=dT; }else{ dT(); }
</script>
<!-- Clock Part 2 - Ends Here -->
<script type="text/javascript">
//###################################################################
// Author: ricocheting.com
// Version: v3.0
// Date: 2014-09-05
// Description: displays the amount of time until the "dateFuture" entered below.
var CDown = function() {
this.state=0;// if initialized
this.counts=[];// array holding countdown date objects and id to print to {d:new Date(2013,11,18,18,54,36), id:"countbox1"}
this.interval=null;// setInterval object
}
CDown.prototype = {
init: function(){
this.state=1;
var self=this;
this.interval=window.setInterval(function(){self.tick();}, 1000);
},
add: function(date,id){
this.counts.push({d:date,id:id});
this.tick();
if(this.state==0) this.init();
},
expire: function(idxs){
for(var x in idxs) {
this.display(this.counts[idxs[x]], "Sorry, hopfully we are open in a couple minutes");
this.counts.splice(idxs[x], 1);
}
},
format: function(r){
var out="";
if(r.d != 0){out += r.d +" "+((r.d==1)?"Day":"Days")+", ";}
if(r.h != 0){out += r.h +" "+((r.h==1)?"Hour":"Hours")+", ";}
out += r.m +" "+((r.m==1)?"Min":"Mins")+", ";
out += r.s +" "+((r.s==1)?"Sec":"Secs")+", ";
return out.substr(0,out.length-2);
},
math: function(work){
var y=w=d=h=m=s=ms=0;
ms=(""+((work%1000)+1000)).substr(1,3);
work=Math.floor(work/1000);//kill the "milliseconds" so just secs
y=Math.floor(work/31536000);//years (no leapyear support)
w=Math.floor(work/604800);//weeks
d=Math.floor(work/86400);//days
work=work%86400;
h=Math.floor(work/3600);//hours
work=work%3600;
m=Math.floor(work/60);//minutes
work=work%60;
s=Math.floor(work);//seconds
return {y:y,w:w,d:d,h:h,m:m,s:s,ms:ms};
},
tick: function(){
var now=(new Date()).getTime(),
expired=[],cnt=0,amount=0;
if(this.counts)
for(var idx=0,n=this.counts.length; idx<n; ++idx){
cnt=this.counts[idx];
amount=cnt.d.getTime()-now;//calc milliseconds between dates
// if time is already past
if(amount<0){
expired.push(idx);
}
// date is still good
else{
this.display(cnt, this.format(this.math(amount)));
}
}
// deal with any expired
if(expired.length>0) this.expire(expired);
// if no active counts, stop updating
if(this.counts.length==0) window.clearTimeout(this.interval);
},
display: function(cnt,msg){
document.getElementById(cnt.id).innerHTML=msg;
}
};
window.onload=function(){
var cdown = new CDown();
//Year,Month,Day,Hour,Min,Sec\\ (Jan - 0 Fed - 1 ++ Dec - 11, 12 is replaced with 0 for Jan)
cdown.add(new Date(2014,9,29,12,18,0), "countbox1");
};
</script>
<h2> Time until ^^<<>> opens!</h2>
<div id="countbox1"></div>
Fixed the problem
Thanks to #Scronide , #James Thorpe , and #Ultimater. I put all of your methods into place and kept them separate and used #Scronide final method. Thanks again.
They're both assigning to window.onload so the second is overwriting the function of the first.
If you are using jquery, instead of assigning to window.onload, you can instead use:
/* first component */
//initialisation for first component
$(function() {
dT();
});
/* second component */
//initialisation for second component
$(function() {
var cdown = new CDown();
//Year,Month,Day,Hour,Min,Sec\\ (Jan - 0 Fed - 1 ++ Dec - 11, 12 is replaced with 0 for Jan)
cdown.add(new Date(2014,9,29,12,18,0), "countbox1");
});
Both use window.onload. Simply join the two functions into one.
Neither of these scripts use any jQuery, so it isn't a jQuery conflict. The problem is that they are both setting a function to window.onload, so the last script will always override the one before it.
I suggest removing the if(!document.all){ window.onload=dT; }else{ dT(); } line from the end of the clock script and adding dT(); inside the window.onload assignment from the second script.
So you would have something like:
window.onload=function(){
dT();
var cdown = new CDown();
cdown.add(new Date(2014,9,29,12,18,0), "countbox1");
};

setTimeout executes itself right away/on clear

I'm making a webpage where user events are logged in.
To test the feature I made a small, independant webpage with a teaxtarea and a text input. The events logged are those performed on the input element.
I want to prevent the same event text to be shown multiple times in a row, but I can't seem to prevent them from showing up!
I also want to add a line to separate event groups 0.5 seconds after no other event happened, but the line seems to appear on every event trigger, evenif I use clearTimeout with the timeout ID.
Basically: I don't want any line to be repeated. If the last line is a separator line, then it must not add another one. Yet it doesn't see to work.
JSFiddle Demo
Here is my code:
JavaScript
var timerID = 0;
function addSeparateLine()
{
document.getElementById('listeEvenements').value += "--------------------\n";
}
function show(newEventText)
{
var eventListField = document.getElementById('listeEvenements');
var eventList = [];
if (eventListField.value.length > 0)
{
eventList = eventListField.value.split("\n");
}
var eventCounter = eventList.length;
if (eventList[eventCounter - 2] == newEventText)
{
clearTimeout(timerID);
newEventText = "";
}
timerID = setTimeout(addSeparateLine, 500);
if (newEventText !== "")
{
eventListField.value += newEventText + "\n";
}
return true;
}
HTML
<fieldset id="conteneurLogEvenements">
<legend>Events called from HTML attribute</legend>
<textarea id="listeEvenements" rows="25"></textarea>
<input id="controleEcoute" type="text" onBlur="show('Blur');" onchange="show('Change');" onclick="show('Click');" onfocus="show('Focus');" onMousedown="show('MouseDown');" onMousemove="show('MouseMove');" onMouseover="show('MouseOver');" onkeydown="show('KeyDown');"
onkeypress="show('KeyPress');" onkeyup="show('KeyUp');" />
</fieldset>
http://jsfiddle.net/z6kb4/2/
It sounds like what you want is a line that prints after 500 milliseconds of inactivity, but what your code currently says to do is "print a line 500 milliseconds after any action, unless it gets canceled". You can get better results by structuring the code more closely to your intended goal.
Specifically, instead of scheduling a new timeout every time an event occurs, simply start a loop when the first event occurs that checks the time that has elapsed since the most recent event received and then prints a line when the elapsed time exceeds the desired threshold (500 milliseconds). Something like:
function addSeparateLine() {
var elapsed = new Date().getTime() - lastEventTime;
if (elapsed >= 500) {
document.getElementById('listeEvenements').value += "--------------------\n";
clearInterval(timerID);
timerID = -1;
}
}
...and then you schedule it like:
if(newEventText !== "") {
lastEventTime = new Date().getTime();
eventListField.value += newEventText+"\n";
if (timerID == -1) {
timerID = setInterval(addSeparateLine,100);
}
}
Working example here: http://jsfiddle.net/z6kb4/4/
Because you are not actually stopping the show function in any way. The clearTimeout only applies to the separator add. I have updated your fiddle. You need to wrap your function with
if (+new Date() - lastfire < 500) return;
and
lastfire = +new Date();
(before the last return--see the updated fiddle). Also, make sure to stick the global definition var lastfire = -1; somewhere up top.

Simple countdown using minutes and seconds

I need a countdown that will refresh a page, and I think I've finally got it, except for one thing. I'd like the countdown to be in minutes and seconds, not just seconds (the countdown is for one hour). A simple MM:SS format would be fine, but also writing out minutes and seconds would work. Can anybody help?
<SCRIPT LANGUAGE="JavaScript">
<!--
var counterobj = document.all ? counter : document.getElementById("counter");
var countdownfrom = 3600; //countdown period in seconds
var currentsecond = counterobj.innerHTML = countdownfrom+1;
function countdown()
{
if (currentsecond!=1)
{
currentsecond-=1;
counterobj.innerHTML = currentsecond;
}
else
{
self.location.reload();
return;
}
setTimeout("countdown()",1000)
}
countdown()
//-->
</script>
Calculate minutes using a floor doing like
minute = Math.floor(currentsecond/60);
Then just output as normal.
edit -- fixed! Hopefully! (accidentally said to use mod -- you need to use Floor, I believe)

Javascript delete div Element

I am implementing a Stopwatch in JavaScript.
I want to delete additional div elements when pushing a clear button. I added function cc();, but function cc() doesn't work. What's wrong with my code?
Javascript:
a = 0;
myButton = 0;
function myWatch(flug) {
if(myButton == 0) {
Start = new Date();
myButton = 1;
document.myForm.myFormButton.value = "Stop!";
myInterval = setInterval("myWatch(1)", 1);
} else {
if(flug == 0) {
myButton = 0;
document.myForm.myFormButton.value = "Start";
clearInterval(myInterval);
}
Stop = new Date();
T = Stop.getTime() - Start.getTime();
H = Math.floor(T / (60 * 60 * 1000));
T = T - (H * 60 * 60 * 1000);
M = Math.floor(T / (60 * 1000));
T = T - (M * 60 * 1000);
S = Math.floor(T / 1000);
Ms = T % 1000;
document.myForm.myClick.value = H + ":" + M + ":" + S + ":" + Ms;
}
}
b = 0;
function stop() {
b++;
stopa();
}
function stopa() {
var element = document.createElement('div');
element.id = pos;
var objBody = document.getElementsByTagName("body")
.item(0);
objBody.appendChild(element);
rap = "";
rap = "rap" + b + "=" + H + ":" + M + ":" + S + ":" + Ms;
element.innerHTML = rap;
}
function cc() {
document.body.removeChild(element);
}
HTML:
<form name="myForm" action="#">
<input type="text" size="20" name="myClick">
<input type="button" value="Start" name="myFormButton" onclick="myWatch(0)" />
<input type="button" value="Rap" name="Rap" onclick="stop()">
<input type="button" value="clear" name="clear" onclick="cc()">
</form>
<h3>
<div id="pos">
</div>
</h3>
Try to pass the context explicitly as parameter on the cc() function.
js
function cc(el) {
el.parentNode.removeChild(el);
}
html
<input type="button" value="clear" name="clear" onclick="cc(this)">
Open up your Console. It's found in most major browsers and will help you loads with JS development.
For example, if you look at your code exactly as is, you get an error:
Uncaught ReferenceError: element is not defined
As several have said, it's a variable scope issue. There's a few easy fixes, the easiest being simply making element have a larger scope - that is, define it outside of your functions first.
var element = null;
and then in stopa, don't use var because it'll make a new, local variable instead of using the global one.
element = document.createElement('div');
The next problem you'll notice is that element in cc still doesn't refer to the correct element - this is because in the following line, pos is not defined.
element.id = pos;
Again, take a look at the Console (now more specifically at the HTML section than the JS, but it's in the same developer options). You'll notice the created element's ID is [object HTMLDivElement] - not "pos". I'd recommend not even worrying about giving them ids, you have a div with id pos already in your HTML, simply append your results to that instead of the body.
objBody = document.getElementById("pos");
Then when you clear, clear all children from pos (you'll also want to clear the text box I'm sure, so here ya go)
while (objBody.hasChildNodes()) {
objBody.removeChild(objBody.lastChild);
}
document.myForm.myClick.value = "";
Notice now we no longer need element to be global, because it's only referenced in one function - it can be local to that function. However, objBody is now referenced in stopa and cc, so we'll make it global as we did with element and simply ensure all future references to it don't include var.
var element = null;
Add some error checking (clearing before you click Start causes errors, for example) and you're good to go!
http://jsfiddle.net/daCrosby/MMywX/1/
The function cc has no idea what 'element' is. The easiest way to fix this is to use jquery. When you delete the div, do something like
$('#pos').remove()
This finds the div with id 'pos' and removes it. You may need to pass the id of the div to cc if it's not just 'pos'.
Modern browsers supports remove() method on the element. You don't need to use external libraries as jQuery or long code. It's simple as :
var x = document.getElementById("myElement");
x.remove();
Working exemple here -> https://jsfiddle.net/tmj3p7t5/

Javascript clearInterval is speeding up a timer instead of pausing it

I've got a ColdFusion application that I am developing that requires a timer that can start, pause, and clear. My problem is that although it works perfectly fine in IE9, Firefox, Opera, Chrome, and Safari, it will not work in IE8 (which is a huge chunk of my userbase). The issue is that when I click and try to stop the timer, instead of the timer stopping, it speeds up. It only does it in IE8 (the other browsers work fine).
-- CLOCK CODE --
function check_timer() {
if($('#timer').hasClass('start')) {
$('#timer').val("Stop Timer");
timer = setInterval ( "increaseCounter()", 1000 );
$('#timer').removeClass('start')
}
else {
if(typeof timer != "undefined") {
clearInterval(timer);
}
$('#timer').val("Start Timer");
$('#timer').addClass('start')
}
}
function increaseCounter() {
var secVal;
var minVal;
secVal = parseInt($('#counterSec').html(),10)
minVal = parseInt($('#counterMin').html(),10)
if(secVal != 59) {
secVal = secVal + 1;
if(secVal < 10) {
secVal = secVal.toString();
secVal = "0" + secVal;
}
$('#counterSec').html(secVal);
}
else {
if(minVal != 59){
minVal = minVal + 1;
if(minVal < 10) {
minVal = minVal.toString();
minVal = "0" + minVal;
}
$('#counterMin').html(minVal);
}
else {
$('#counterHour').html((parseInt($('#counterHour').html(),10)+1));
$('#counterMin').html("00");
}
$('#counterSec').html("00");
}
}
-- DIV CONTAINING CLOCK --
<div class="supportClock" style="width:150px; border-radius:20px;" align="center">
<span id="addZeroHour"></span>
<span id="counterHour">00</span>
:<span id="addZeroMin"></span>
<span id="counterMin">00</span>
:<span id="addZeroSec"></span>
<span id="counterSec">00</span>
</div>
-- BUTTON TO ACTIVATE CLOCK --
<input type="button" id="timer" class="start" value="Start Timer" onclick="check_timer()">
add this to the top of your script(outside the functions):
var timer;
Otherwise you will never run into this branch:
if(typeof timer != "undefined")
The reason: there is an element with the ID "timer", you may access it by using timer without the suggested modification and timer will never be of type "undefined"
Or simply use another name for the timeout-variable.
Have a look here: http://jsfiddle.net/qEATW/3/
Even if you set an interval to be, for example, one second, it won't necessarily be one second between calls.
For timeouts and intervals, always pass in the function, never a string: setInterval(increaseCounter, 1000)
There's no reason to parse values from the DOM. It's incredibly inefficient to do so. If you instead use Date differences, you can simply store one variable (start time), and get hours/mins/seconds since that time. You can update the view however often you like and it will always be accurate.
I personally prefer "recursive" timeouts as opposed to intervals. With intervals, you'll always need to take that extra step to clear the interval when you want it to stop. You can stop a timeout loop in several different ways, and it tends to be easier to understand what's going on. Timeouts also allow us the flexibility of changing the time between calls (not that that is relevant here).
It is considered a bad practice to bind event handlers inline (on the HTML element). If you are already using jQuery, there's really no excuse for this as jQuery makes the process so very simple.
I got rid of the "addZero" spans that you had. I'm not sure what you were doing with them, but they weren't necessary and only served to clutter the markup.
HTML:
<div class="supportClock" style="width:150px; border-radius:20px;" align="center">
<span id="counterHour">00</span>
: <span id="counterMin">00</span>
: <span id="counterSec">00</span>
</div>
<input type="button" id="timer" class="start" value="Start Timer">
JS:
(function(){
var clock = $(".supportClock"),
hr = $("#counterHour"),
min = $("#counterMin"),
sec = $("#counterSec"),
running = false,
startTime,
timeout;
function updateClock(){
var time = (new Date()) - startTime,
hrs = Math.floor(time / 1000 / 60 / 60),
mins = Math.floor(time / 1000 / 60 - hrs * 60),
secs = Math.floor(time / 1000 - mins * 60 - hrs * 60 * 60);
hr.text(hrs > 9 ? hrs : '0' + hrs);
min.text(mins > 9 ? mins: '0' + mins);
sec.text(secs > 9 ? secs : '0' + secs);
timeout = setTimeout(updateClock, 1000/2);
}
$("#timer").click(function(){
if (!running){
running = true;
this.value = "Stop Timer";
startTime = new Date();
updateClock();
}
else{
running = false;
this.value = "Start Timer";
clearTimeout(timeout);
}
});
})();

Categories