some errors with javascript objects - javascript

I am beginning to hate objects in javascript.
Every time I have error and I fix it, a new error appears, and so on.
Can you please take a look at the following code and tell me what's wrong ?
problem message:
"this.Images is undefined"
and more errors also
HTML File
<div id="SlideShow" >
<img id="img" src="images/img.jpg" alt="" /><span id="desc"></span>
</div>
<script type="text/javascript">
meToo.Images = ['images/img.jpg','images/img2.jpg','images/img3.jpg','images/img4.jpg','images/img5.jpg'];
meToo.Titles = ['Pic1','pic2','Pic3','Pic4','Pic5'];
meToo.Play('img');
</script>
Javascript Object
var meToo = {
Images: [],
Titles: [],
counter: 0,
Play: function(ElemID){
var element = document.getElementById(ElemID);
var ImgLen = this.Images.length;
if(this.counter < ImgLen){
this.counter++;
element.src = this.Images[this.counter];
element.nextSibling.innerHTML = this.Titles[this.counter];
}else{
this.counter = 0;
}
setTimeout(this.Play, 1000);
}
};
See the Example

See this question. Otherwise setTimeout sets this to the window object. Also, the counter should be incremented after setting the images or you will be reading outside the array bounds.
Finally, when resetting the counter to 0, there will be an additional one-second delay before the loop restarts, because the image is not being reset in that else block. You may wish to rewrite that part of the logic.
Updated Fiddle
if(this.counter < ImgLen){
element.src = this.Images[this.counter];
element.nextSibling.innerHTML = this.Titles[this.counter];
this.counter++;
}else{
this.counter = 0;
}
var _this = this;
setTimeout(function() { _this.Play('img') }, 1000);
This is what I would write to keep the loop going at one-second intervals:
Play: function(ElemID) {
var element = document.getElementById(ElemID);
var ImgLen = this.Images.length;
if (this.counter == ImgLen) {
this.counter = 0;
}
element.src = this.Images[this.counter];
element.nextSibling.innerHTML = this.Titles[this.counter];
this.counter++;
var _this = this;
setTimeout(function() {
_this.Play('img')
}, 1000);
}

if(this.counter < ImgLen)
is wrong.
What will happen here is that when you run
this.counter++;
the value of that variable will now be ImgLen.length
Arrays in javascript go from 0 to length -1.So now you'll be exceeding the array's length, when you run:
this.Images[this.counter];
and encounter an error.
The quick fix here is to change to
if(this.counter < ImgLen -1)
If you're encountering other problems, then post the exact error message. (Run in Chrome and press F12 (for example) to bring up the console so you can see the errors).

Here check this out.It should work perfectly for you.I have made it a singleton object and also I am doing a check if incase meToo.Play is called before the dom is loaded it will not crash.All the other mistakes that the guys above are pointing are also taken care of.
<script>
var meToo = function(){
var Images = ['http://www.image-upload.net/di/WMPI/img.jpg','http://www.image-upload.net/di/HPUQ/img2.jpg','http://www.image-upload.net/di/WQ9J/img3.jpg','http://www.image-upload.net/di/GIM6/img4.jpg','http://www.image-upload.net/di/0738/img5.jpg'];
var Titles = ['Pic1','pic2','Pic3','Pic4','Pic5'];
var counter = 0;
return {
Play: function(ElemID) {
var element = document.getElementById(ElemID);
if(element){
var ImgLen = Images.length;
if(counter < ImgLen) {
element.src = Images[counter];
element.nextSibling.innerHTML = Titles[this.counter];
counter++;
} else {
counter = 0;
}
}
setTimeout(callmeToo, 1000);
}
}
}();
function callmeToo(){
meToo.Play('img');
}
callmeToo();
</script>

Related

Show elements of array one by one - Jquery

So I have a button on which I want to display each element of my array for a few seconds. This is my html code:
<button class="btn" id="random">Start</button>
I have made an array with jQuery that I want to use to change the buttons text:
$(document).ready(function() {
$("#random").on("click", loop);
});
var array = ["el1","el2","el3"];
function loop() {
for (i = 0; i < array.length; i++) {
$("#random").html(array[i]);
}
var random = Math.floor(Math.random() * array.length) + 1;
$("#random").html(array[random]);
}
The for loop is supposed to do what I want but I can't find a way to delay the speed, it always just shows the last line of code. When I try setTimeout or something it just looks like it skips the for loop.
My proposal is to use IIFE and delay:
var array = ["el1","el2","el3", "Start"];
function loop(){
for (i = 0; i < array.length; i++){
(function(i) {
$("#random").delay(1000).queue(function () {
$(this).html(array[i]);
$(this).dequeue();
});
})(i);
}
}
$(function () {
$("#random").on("click", loop);
});
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<button class="btn" id="random">Start</button>
Basically, a for loop will not help you. It runs with the max speed it can. And delaying it would do no good in js (you would just freeze the browser). Instead, you can just make a function that will execute itself with a delay. Kinda recursion, but not entirely. Below would make the trick.
https://jsfiddle.net/7dryshay/
$(document).ready(function() {
$("#random").on("click", function (event) {
// texts to cycle
var arr = ["el1","el2","el3"];
// get the button elem (we need it in this scope)
var $el = $(event.target);
// iteation function (kinda recursive)
var iter = function () {
// no more stuff to display
if (arr.length === 0) return;
// get top of the array and set it on button
$el.text(arr.shift());
// proceed to next iteration
setTimeout(iter, 500);
}
// start first iteration
iter();
});
});
Use setInterval() and clearInterval()
$(document).ready(
function() {
$("#random").on("click", loop);
}
);
var array = ["el1", "el2", "el3"];
var int;
function loop() {
var i = 0; // variable for array index
int && clearInterval(int); // clear any previous interval
int = setInterval(function() { //store interval reference for clearing
if (i == array.length) clearInterval(int); // clear interval if reached the last index
$("#random").text(i == array.length ? 'Start' : array[i++]); // update text with array element atlast set back to button text
}, 1000);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button class="btn" id="random">Start</button>
UPDATE : If you need to implement it using for loop and setTimeout() then do something like this
var array = ["el1", "el2", "el3", "Start"];
function loop() {
for (i = 0; i < array.length; i++) {
(function(i) {
setTimeout(function() {
$("#random").html(array[i]);
}, i * 1000);
})(i);
}
}
$(function() {
$("#random").on("click", loop);
});
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<button class="btn" id="random">Start</button>

setInterval won't get out of loop

The following javascript code takes randomly selected value from a array and types it in the input box. I've used jquery. I want to end setInterval "zaman2", so after It ends I can retype the next random string to the input box. But the loop doesn't end and gets stuck. How can I solve this?
Link to jsFiddle: http://jsfiddle.net/AQbq4/4/
var dersler = [...very long list...];
var zaman = setTimeout(function() {
var yeniDers = dersler[Math.floor(Math.random()*dersler.length)];
sayac = 0;
var zaman2 = setInterval(function() {
var harf = yeniDers.slice(0,(sayac+1));
sayac++;
$('#main-search').attr('placeholder', harf).typeahead({source: dersler});
if (sayac == yeniDers.length) {
clearInterval(zaman2);
}
},450);
},2000);
Don't you mean
DEMO
var tId, tId2;
function show() {
var ran = arr[Math.floor(Math.random()*arr.length)];
cnt = 0;
tId = setInterval(function() {
var char = ran.slice(0,(cnt+1));
cnt++;
$( '#main-search' ).attr('placeholder', char);
if (cnt == ran.length) {
clearInterval(tId);
tId2=setTimeout(show,2000);
}
},450);
}
show();

Jquery: Infinite loop and pause

I have this code
var timeout = 0;
$('#container td').each(function(){
var td = this;
setTimeout(function() {
var new_text = $(td).find(text).html();
popup_text.html(new_text);
popup.fadeIn('fast').delay(1000).fadeOut('slow');
}, timeout);
timeout += 1000 + 1000;
});
I get text from table cells and is displayed in the layer with a delay.
1 question: How do I make this code to run in an endless loop?
2 question: How to do that when you hover the mouse over popop cycle temporarily stopped and then continue?
Thanks a lot!
One way is to put the code to be repeated in a function, and have the function repeat itself at the end:
var timeout = 1000;
var action = function() {
// Do stuff here
setTimeout(action, timeout);
};
action();
However, as ahren suggested, setInterval might be better:
var timeout = 1000;
var action = function() {
// Do stuff here
};
setInterval(action, timeout);
The difference is slight, but if the machine is running slowly for some reason, the setInterval version will run the code every second on average, whereas the setTimeout version will run the code once each second at most.
Neither of those methods really work well with each(), however, so you'll need to store the sequence of popups somewhere and step through them:
var timeout = 1000;
var tds = $('#container td');
var index = 0;
var action = function() {
var td = tds[index];
var new_text = $(td).html();
popup.html(new_text);
popup.fadeIn('fast').delay(1000).fadeOut('slow');
if(++index >= tds.length)
index = 0;
};
setInterval(action, timeout);
action();
Finally, to avoid moving to the next popup while the popup is hovered, you can add a check for that at the start of the function. It's also necessary to rearrange the animations so that they go "check for hover - fade out - change text - fade in".
var timeout = 1000;
var tds = $('#container td');
var index = 0;
var action = function() {
if(popup.is(':hover'))
return;
var td = tds[index];
var new_text = $(td).html();
popup.fadeOut('slow', function() {
popup.html(new_text);
}).fadeIn('fast');
if(++index >= tds.length)
index = 0;
};
setInterval(action, timeout);
action();
jsFiddle: http://jsfiddle.net/qWkYE/2/
If you like the short clean way, then use the jquery-timing plugin and write:
$.fn.waitNoHover = function(){
return this.is(':hover') ? this.wait('mouseleave') : this;
};
$('#popups div').repeat().each($).fadeIn('fast',$)
.wait(200).waitNoHover().fadeOut('slow',$).all()
​
See this on http://jsfiddle.net/creativecouple/fPQdU/3/

Clear a non-global timeout launched in jQuery plug-in

I try to set a timeout on an element, fired with a jQuery plugin. This timeout is set again in the function depending on conditions. But, I want to clear this element's timeout before set another (if I relaunch the plug-in), or clear this manually.
<div id="aaa" style="top: 0; width: 100px; height: 100px; background-color: #ff0000;"></div>
Here's my code (now on http://jsfiddle.net/Ppvf9/)
$(function() {
$('#aaa').myPlugin(0);
});
(function($) {
$.fn.myPlugin = function(loops) {
loops = loops === undefined ? 0 : loops;
this.each(function() {
var el = $(this),
loop = loops,
i = 0;
if (loops === false) {
clearTimeout(el.timer);
return;
}
var animate = function() {
var hPos = 0;
hPos = (i * 10) + 'px';
el.css('margin-top', hPos);
if (i < 25) {
i++;
} else {
if (loops === 0) {
i = 0;
} else {
loop--;
if (loop === 0) {
return;
} else {
i = 0;
}
}
}
el.timer = window.setTimeout(function () {
animate();
}, 1000/25);
};
clearTimeout(el.timer);
//$('<img/>').load(function() {
// there's more here but it's not very important
animate();
//});
});
return this;
};
})(jQuery);
If I make $('#element').myPlugin();, it's launched. If I make it a second time, there's two timeout on it (see it by doing $('#aaa').myPlugin(0);
in console). And I want to be able to clear this with $('#element').myPlugin(false);.
What am I doing wrong?
EDIT :
SOLVED by setting two var to access this and $(this) here : http://jsfiddle.net/Ppvf9/2/
try saving the timeout handle as a property of the element. Or maintain a static lookup table that maps elements to their timeout handles.
Something like this:
el.timer = window.setTimeout(...);
I assume you need one timer per element. Not a single timer for all elements.

How to stop my javascript countdown?

How can I stop my javascript function when countdown = 0?
JS:
var settimmer = 0;
$(function(){
window.setInterval(function() {
var timeCounter = $("b[id=show-time]").html();
var updateTime = eval(timeCounter)- eval(1);
$("b[id=show-time]").html(updateTime);
}, 1000);
});
HTML:
<b id="show-time">20</b>
For one thing remove those evals. They don't do anything.
Then all you have to do is clear the timer when it reaches zero.
$(function(){
var timer = setInterval(function() {
var timeCounter = parseInt($("b[id=show-time]").text());
$("b[id=show-time]").text(--timeCounter); // remove one
if(!timeCounter) clearInterval(timer);
}, 1000);
});
It is easy! When you call setInterval it return an ID, so you can destroy the interval later. To destroy it you must use clearInterval(id), and voilà!
It works like this:
// Activate timer
var iv = window.setInterval(...);
// Deactive timer
window.clearInterval(iv);
Also you should use parseInt() instead of eval():
$(function() {
// Read the start value once and store it in a variable
var timeCounter = parseInt( $("b[id=show-time]").text() );
// Active the counter
var iv = window.setInterval(function() {
// Decrement by one and write back into the document
$("b[id=show-time]").text(--timeCounter);
// Check if counter == 0 -> stop counting
if (0 == timeCounter) {
window.clearInterval(iv);
// ...do whatever else needs to be done when counter == 0 ..
}
}, 1000);
});
Example:
var i = 0,
pid = setInterval(function() {
if (++i > 10)
clearInterval(pid);
}, 1000);
Based on what you wanted for your code ...
$(function() {
var el = document.getElementById('show-time'),
pid = setInterval(function() {
// (s - i) coerces s to Number
var t = el.innerHTML - 1;
el.innerHTML = t;
if (t < 1)
clearInterval(pid);
}, 1000);
});
Keep in mind that JS won't be 100% accurate with its timing.
Pasted code below or see the fiddle: http://jsfiddle.net/raHrm/
<script type="text/javascript">
$(function(){
var settimmer = 0,
timeCounter = $("#show-time").html(),
updateTime = timeCounter;
(function countDown() {
timeCounter = $("#show-time").html();
updateTime = parseInt(timeCounter)-1;
$("#show-time").html(updateTime);
if ( updateTime ) {
setTimeout(countDown, 1000);
}
})();
});​
</script>
Set the timer to a variable, then use clearInterval in-order to stop the loop. As for catching the end, use a simple conditional:
$(function(){
var elem=$('strong[id="show-time"]'),settimmer=0,updateTime,t;
t=window.setInterval(function() {
updateTime=parseFloat(elem.html(),10)-1;
if(updateTime==0) {
window.clearInterval(t);
elem.html('Done!');
} else {
elem.html(updateTime);
}
},1000);
});
Then in the HTML:
<strong id="show-time">20</strong>
The <b> tag is depreciated, try to avoid using it. Also, there is no reason to eval() the HTML you are getting from the element; a simple parseFloat() works just fine.

Categories