I have the code below but I cannot call nextPromo because it is not a function. How can I make this work? I am trying to setup a rotator using object oriented style. I am new to it so i am very confused. I have tried many things but I jsut don't know and I am very frustrated with it, please help
function promoSlides(s){
this.index = 0;
this.prevIndex = 0;
this.currentVeh = "";
this.t;
this.slides = s;
this.len = this.slides.length;
this.sortWeight = function(){
($('body').hasClass('en')) ? this.slides.sort(SortByWeight) : this.slides.sort(SortByWeightFr);
};
function SortByWeight(a,b) { return b.weight - a.weight; }
function SortByWeightFr(a,b) { return a.frWeight - b.frWeight; }
this.startTimer = function(){ this.t = setTimeout("this.nextPromo()", 3000); }
this.nextPromo = function(){
if(this.index > 0 || this.prevIndex > 0) $(this.slides[this.prevIndex].el).css("display","none");
$(this.slides[this.index].el).css("display","block");
this.prevIndex = this.index;
this.index = (this.index < this.len-1) ? this.index+1 : 0;
this.startTimer();
}
return true;
} ;
Actually, nextPromo is a function. You can call it like:
this.nextPromo();
Or, if that doesn't work, you can just call it like a normal function:
nextPromo();
See this jsFiddle for an example of this kind of function.
Hope this helps.
EDIT: Here is a simplified example which I have tested. This uses setInterval to periodically advance the slide index. The "next" functionality is contained within an anonymous function.
function promoSlides(s) {
this.startTimer = function () {
setInterval(
function () {
alert("called");
// if (this.index > 0 || this.prevIndex > 0) {
// $(this.slides[this.prevIndex].el).css("display", "none");
// }
// $(this.slides[this.index].el).css("display", "block");
// this.prevIndex = this.index;
// this.index = (this.index < this.len - 1) ? this.index + 1 : 0;
}, 3000
);
}
return true;
};
var p = new promoSlides(null);
p.startTimer();
You're assigning a function to this.nextPromo, so calling this.nextPromo(); should work.
Related
I have a code that runs setInterval in a function. What I try to achive is to exit from that function after clearInterval occured. I set up a condition to check wheter the interval is cleared. I'm struggling to find a method to return from the main Start() function based on the current state of the code.
Code:
function Start() {
var elementX = document.getElementById('moveMeX')
var elementY = document.getElementById('moveMeY')
elementY.style.top = "0px"
var posX = 0
startPosX = 0
var posY = 0
startPosY = 0
var speed = 1
var xIsMoving = true
var yIsMoving = true
var myIntervalX = setInterval(function() {
if(startPosX == 0) {
posX+=speed
elementX.style.left = posX + 'px'
if(posX==100) {
startPosX = 100
}
}
else if (startPosX==100) {
posX-=speed
elementX.style.left = posX + 'px'
if(posX==0) {
startPosX = 0
}
}
}, 10);
function stopX() {
clearInterval(myIntervalX);
xIsMoving = false
}
elementX.addEventListener("mousedown", stopX);
elementX.addEventListener("mousedown", startY);
function startY() {
var myIntervalY = setInterval(function() {
if(startPosY == 0) {
posY+=speed
elementY.style.top = posY + 'px'
if(posY==100) {
startPosY = 100
}
}
else if (startPosY==100) {
posY-=speed
elementY.style.top = posY + 'px'
if(posY==0) {
startPosY = 0
}
}
}, 10);
function stopY() {
elementY.style.zIndex = "-1";
clearInterval(myIntervalY);
yIsMoving = false
}
elementY.addEventListener("mousedown", stopY);
}
if (xIsMoving === false && yIsMoving === false) {
console.log('stopped')
stopped = true
}
}
Start()
Codepen link: https://codepen.io/silentstorm902/pen/podNxVy
The part you state you have a problem with,
if (xIsMoving === false && yIsMoving === false) {
console.log('stopped')
stopped = true
}
currently only runs once: when Start() is first called. At that time, both conditions are false because the variables have their initial declared values of true.
You could create a new setInterval to run this if statement every so often, but it seems unnecessary because your current stopY function is really the place where you know that both xIsMoving and yIsMoving are both false -- because stopY only runs after stopX has run. So just move your statement of stopped=true at the end of the stopY function:
function stopY() {
elementY.style.zIndex = "-1";
clearInterval(myIntervalY);
yIsMoving = false;
console.log("stopped");
stopped = true;
}
Good day all, I'm trying to make a jquery game where a group of enemy will spawn after a group of enemy gets destroyed. I'm calling alien_cruiser() function & unbinding minion_roulette() function after minion_roulette_counter gets 0. But every time I run, function does not get unbind & after counter gets 0 both type of enemies show. I want to run them one by one. Here are the codes:
var sound = new Audio("sounds//dishoom.ogg");
var score = 0;
var minion_roulette_life = 10;
var cruiser_life = 20;
var minion_roulette_counter = 3;
var cruiser_counter = 3;
function processBullet() {
$(".projectile").each(function() {
var maxTop = $(this).offset().top;
var breakable1 = $(this).collision("#minion-roulette");
var breakable2 = $(this).collision("#cruiser");
$(this).css("top", maxTop - 25);
if (breakable1.length != 0 || breakable2.length != 0) {
$(this).remove();
}
if (maxTop <= 35) {
$(this).remove();
}
if (breakable1.length != 0) {
--minion_roulette_life;
if (minion_roulette_life == 0) {
sound.play();
breakable1.remove();
minion_roulette(true);
minion_roulette_counter--;
$("#score").html(++score);
minion_roulette_life = 10;
}
}
//This is the place where it checks if counter is 0 or not
if (minion_roulette_counter == 0) {
$('#content').unbind(function() {
minion_roulette(false)
});
alien_cruiser(false);
minion_roulette_counter = -1;
}
if (breakable2.length != 0) {
--cruiser_life;
if (cruiser_life == 0) {
sound.play();
breakable2.remove();
alien_cruiser(true);
$("#score").html(++score);
cruiser_life = 20;
}
}
});
}
Am I doing any wrong here? Please I need a solution badly. Tnx.
In this situation, you could use a conditional statement to determine which function to call.
For example:
if (minion_roulette_counter == 0) {
alien_cruiser();
}
else {
minion_roulette();
}
Binding and unbinding doesn't 'turn off' a function, unfortunately. To quote MDN:
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
– MDN: 'Bind'
I have a function for letting blink a OpenLayer marker three times. The simplified version which only shows console messages:
function blink_three_times(layername){
var x = 0;
setTimeout(function() {
blink_in = setInterval(function() {
x = x+1;
if ( x === 3) {clearInterval(blink_in)};
console.log(layername + ' is visible');
}, 500);
}, 250);
blink_out = setInterval(function() {
if (x === 2) {clearInterval(blink_out)};
console.log(layername + ' is invisible');
}, 500);
};
It works fine, but if it is started multiple times before one has finished, the counter (x) exceeds 3 and the interval does not stop. How can I avoid that?
That is because you have funcions blink_in & blink_out in global scope. When you are calling it second time it overwrites the definitions of functions.
Define them using var to make them local.
var blink_in = setInterval(function() {..})
and
var blink_out = setInterval(function() {..})
DEMO
Your variables blink_in and blink_out are global ones so if you call the function multiple times they will override it and therefore cannot stop the interval properly.
Use them in your function scope by definining them with "var" in order to avoid the problem (see http://jsfiddle.net/cb0h8tst/)
function blink_three_times(layername){
var x = 0;
var blink_in, blink_out;
setTimeout(function() {
blink_in = setInterval(function() {
x = x+1;
if ( x === 3) {clearInterval(blink_in)};
console.log(layername + ' is visible');
}, 500);
}, 250);
blink_out = setInterval(function() {
if (x === 2) {clearInterval(blink_out)};
console.log(layername + ' is invisible');
}, 500);
};
Based on your last update question,
you could also make a more dynamic to keep track of the layers that are actually being blinked, a possible example
function Blinker(opt) {
var ts = {};
this.elementId = opt ? opt.elementId : undefined;
this.runs = (opt ? opt.runs : 3) || 3;
this.completed = (opt ? opt.completed : function() { }) || function() { };
this.start = function(arg) {
var timestamp = arg || this.elementId, that = this;
if (typeof ts[timestamp] !== 'undefined') {
console.log('Cannot run multiple times on same layer');
return;
}
ts[timestamp] = {
timestamp: timestamp,
count: 0,
element: document.getElementById(arg || this.elementId),
controller: this
};
setTimeout(function() {
ts[timestamp].showInterval = setInterval(that.setVisibility.bind(ts[timestamp], true), 500);
}, 250);
ts[timestamp].hideInterval = setInterval(this.setVisibility.bind(ts[timestamp], false), 500);
};
this.setVisibility = function(visible) {
this.element.style.visibility = visible ? 'visible' : 'hidden';
this.element.style.display = visible ? 'inherit' : 'none';
if (visible) {
this.count++;
}
if (!visible && this.count === 2)
{
clearInterval(this.hideInterval);
}
if (visible && this.count === 3)
{
clearInterval(this.showInterval);
this.controller.completed.apply(this.controller, [this.element.id]);
delete ts[this.timestamp];
}
};
}
var blinker = new Blinker({
elementId: 'blinker',
runs: 3,
completed: function(elementId) {
var log = document.getElementById('log');
log.innerHTML += '<p><strong>' + elementId + '</strong> has finished blinking</p>';
}
});
you could find the fiddle here: http://jsfiddle.net/q70w0kpx/
I have a mootools code:
(function() {
var index = 0;
Element.implement({
toggle: function() {
var args = Array.slice(arguments, 0);
count = args.length - 1;
return this.addEvent("click", function() {
args[index].apply(this, arguments);
index = (count > index) ? index + 1 : 0;
});
},
resetToggle: function() {
index = 0;
}
});
})();
document.getElement(".toggle").toggle(
function() {
document.id("menu").setStyle("display", "block");
}, function() {
document.id("menu").setStyle("display", "none");
}
);
});
How to hide/show div.menu container with animation?
Thanks!
haha this looks like my old toggle code :) do:
document.id('menu').setStyles({
display: 'block',
opacity: 0
}).fade(1);
and the opposite.
update to:
(function(){
var Element = this.Element,
Elements = this.Elements;
[Element, Elements].invoke('implement', {
toggle: function(){
var args = Array.prototype.slice.call(arguments),
count = args.length-1,
// start at 0
index = 0;
return this.addEvent('click', function(){
var fn = args[index];
typeof fn === 'function' && fn.apply(this, arguments);
// loop args.
index = count > index ? index+1 : 0;
});
}
});
}());
If you want to make a animation you could use reveal() / dissolve() available in MooTools-More
document.getElement(".toggle").toggle(function () {
document.id("menu").reveal();
}, function () {
document.id("menu").dissolve();
});
Note you had a pair }); too much in your code (last line)
Example
But if you would use more, there is already a .toggle() method you can use, that would give you just show/hide like this.
What I'm after:
There are 5 counters on my page, they should all start from 0 and count upwards (increment) at the same time to different values that are set at different speeds. So for example I set 10, 25, 1500, 400, 500 in my variables I would like them all to reach these values.
• start at the same time
• all increment at different speeds
• stop at value set for each
My Problem
I can't figure out a good way to write some simple very efficient javascript to do this (going to be used on a mobile), currently I'm using setinterval which seems to start all the counters at different times and jerks/not smooth..
how far I've got so far
http://jsfiddle.net/95smH/
setInterval(f1,500);
setInterval(f2,1500);
setInterval(f3,500);
setInterval(f4,50);
var v1 = 0
, v2 = 0
, v3 = 0
, v4 = 0;
function f1() {
$('.count.v1').text(v1);
if ( v1 < 450 )
{
v1 ++;
}
}
function f2() {
$('.count.v2').text(v2);
if ( v2 < 50 )
{
v2 ++;
}
}
function f3() {
$('.count.v3').text(v3);
if ( v3 < 23 )
{
v3 ++;
}
}
function f4() {
$('.count.v4').text(v4);
if ( v4 < 4 )
{
v4 ++;
}
}
This would be my shot at a slightly more general way. It will also kill the setInterval once every counter has finished. Of course this will still have the typical inaccuracy of Javascript intervals.
var counter = new (function () {
'use strict';
var counters = [],
handler = null,
precision = 50;
this.addCounter = function (maxValue, interval, selector) {
counters.push({
maxValue: maxValue,
currentValue: 0,
interval: interval / precision,
intervalCounter: 0,
$output: $(selector)
});
return this;
};
this.start = function () {
handler = setInterval(function () {
var stillRunning = false;
for (var i = 0; i < counters.length; i++) {
var counter = counters[i];
counter.intervalCounter++;
if (counter.intervalCounter === counter.interval) {
counter.intervalCounter = 0;
counter.currentValue++;
if (counter.currentValue <= counter.maxValue) {
stillRunning = true;
counter.$output.val(counter.currentValue);
}
} else {
stillRunning = true;
}
}
if (!stillRunning) {
clearInterval(handler);
}
}, precision);
};
return this;
})();
counter
.addCounter(50, 250, '.v1')
.addCounter(25, 500, '.v2')
.start();
Demo fiddle: http://jsfiddle.net/s9AYz/1/
Note that precision must be set such that the interval of each counter is a multiple of it (Boris solution has the same requirement).
This is based on your own code style:
setInterval(tick,50);
var cusers = 0
, cawardshows = 0
, ccountries = 0
, cregions = 0;
var susers = 500
, sawardshows = 1500
, scountries = 500
, sregions = 50;
var i = 0;
function tick() {
$('.count.users').text(cusers);
if ( cusers < 450 && i % susers == 0)
{
cusers ++;
}
$('.count.awardshows').text(cawardshows);
if ( cawardshows < 50 && i % sawardshows == 0 )
{
cawardshows ++;
}
$('.count.countries').text(ccountries);
if ( ccountries < 23 && i % scountries == 0 )
{
ccountries ++;
}
$('.count.regions').text(cregions);
if ( cregions < 4 && i % sregions == 0)
{
cregions ++;
}
i += 50;
}
The idea is to have only one timer, so all updates will be synchronized to the same clock. Since values have different "speeds", you update some of them only every nth step.
Here is a solution quite cpu-friendly :
- you only have one setInterval using a base period that you decide.
- On each interval you iterate through your all counters doing very little work each time.
(i even avoided to use % ).
- The elements are cached.
jsbin is here :
http://jsbin.com/urUxojo/2/edit?html,js,console,output
window.onload=function() {
// this is the period of the base Interval in ms.
// The counters will be aligned on this base period
Counter.basePeriod = 50 ;
// constructor of a Counter
// ! initializes the counter display.
function Counter(id, period_ms, max, initialValue) {
this.element = document.getElementById(id);
this.period = Math.ceil(period_ms / Counter.basePeriod) || 1;
this.max = max ;
this.value = initialValue || 0 ;
this.last = 0;
this.element.value = (this.value);
return this;
};
// called on each basePeriod tick
// updates the element every period until it reaches its max value.
Counter.prototype.tick = function() {
this.last++;
if (this.last == this.period &&
this.value != this.max ) {
this.value++;
this.element.value = (this.value);
this.last=0;
}
};
Counter.counters = [];
Counter.start= function () {
function handleCounters() {
for (var i=0; i< Counter.counters.length; i++) { Counter.counters[i].tick(); }
}
Counter._interval = setInterval(handleCounters, Counter.basePeriod);
};
Counter.add = function() {
var newCounter = Object.create(Counter.prototype);
Counter.counters.push( Counter.apply(newCounter, arguments) );
}
// -------------------------------
Counter.add('cnt1' , 500 , 450 );
Counter.add('cnt2' , 400 , 40 );
Counter.add('topCounter', 1000 , 5 );
Counter.start();
}
Well, you always want to get rid of duplicity, so you can do:
function IntervalClass(selector, sleepTime, maxValue, startValue) {
var curValue = startValue;
this.tick = function () {
if (curValue < maxValue) {
curValue++;
}
$(selector).html(curValue);
};
this.start = function () {
setInterval(this.tick, sleepTime);
};
}
new IntervalClass(".count.users", 1000, 35, 0).start();
new IntervalClass(".count.awardshows", 500, 20, 0).start();
new IntervalClass(".count.countries", 1500, 15, 0).start();
new IntervalClass(".count.regions", 200, 100, 0).start();
JSFIDDLE