Pausable typewriter effect in jQuery - javascript

I'm using the typewriter plugin from Jason Frame's Grab Bag.
However, I now find myself in a situation where I need to be able to pause and resume this typewriter at any point during its run.
Ideally, I'd have .typewriter("pause") to pause it, and .typewriter("resume") to resume the animation from where it left off.
I've tried setting a paused variable within the plugin, and leaving the interval running with a check for the variable each iteration -- if true, do nothing.
However, due to my lack of skills in making jQuery plug-ins, each time I call the function to pause the typewriter, it just starts all over again. I suspect the paused variable gets reset.
How would I go about making this plugin pausable?

jsBin demo
Add this 2 lines here:
(function($) {
$.fn.typewriter = function() {
this.each(function() {
var $ele = $(this), str = $ele.text(), progress = 0;
$ele.text('');
timer = setInterval(function() {
if(pause===false){ // ADD THIS LINE ////////////////////////
$ele.text(str.substring(0, progress++) + (progress & 1 ? '_' : ''));
if (progress >= str.length) clearInterval(timer);
} // ADD THIS LINE ////////////////////////
}, 100);
});
return this;
};
})(jQuery);
$("#typewriter").typewriter(); // run your plugin
and I created this:
var pause = false;
$('#play_pause').click(function(){
pause= !pause ? true : false; // toggle true/false pause states
});
EDIT: find a better plugin-like solution in the comment below!

Related

clearInterval function not clearing setInterval function

I utilized this resource to structure my code: http://www.w3schools.com/jsref/met_win_clearinterval.asp
var intervalID = setInterval(function(){ ogpeWrapper() }, 10);
function ogpeWrapper() {
$("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper").wrapAll('<div id="colWrapperContainer"></div>');
}(jQuery);
function myStopFunction() {
if (document.getElementById('colWrapperContainer')) {
clearInterval(intervalID);
setIntervalID = undefined;
}
}
My ogpeWrapper function is running, but the clearInterval function is not.
Basically, once $("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper").wrapAll(''); runs, I want the interval to stop running it.
Edit - 12:24pm CST:
This is the base code I utilize to wrap the listed elements -
(function($) {
$("#breadcrumbAds, #breadcrumbWrapper, #containerTopParsys, #leftColWrapper, #rightColWrapper").wrapAll('<div id="colWrapperContainer"></div>');
})(jQuery);
This code works, but it doesn't process the change until after the DOM has completely loaded. I need the function to work as soon as those elementals are all available. So I need to use a setInterval to process the function, then clear the interval once the function is processed.
If anyone knows of another way to do this, besides a setIterval, please let me know.
You need to create a definite if else condition within the variable so you know exactly when it will start and when it will stop. Also, because the minimum millisecond interval timing is not consistent across browsers, although you want it to detect really fast, I would recommend a "safer" number and use 100 as the minimum instead. The .length method is a handy little way for you to check if an element is on a page; You can use it as a pseudo dynamic true/false conditional. Lastly, in your .wrapAll() tag, I swapped your single and double quotes, as it is best practice to do such.
var colWrapper = setInterval(function(){
if ($('div#colWrapperContainer').length > 0) {
var doNothing = "";
clearInterval(colWrapper);
} else {
$("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper").wrapAll("<div id='colWrapperContainer'></div>");
}
}, 100);
Here is a working example for your reference Wrap Example
Update:
Example for putting the script inside the <body> tag (no window.load/document.ready) so that it runs independently as soon as it is loaded.
<script type="text/javascript">//<![CDATA[
//http://stackoverflow.com/questions/33483000/clearinterval-function-not-clearing-setinterval-function/33483267#33483267
//Auto Wrap Solution
//Alexander Dixon [11-02-2015]
var wrapThese = $("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper");
var colWrapper = setInterval(function () {
if ($('div#colWrapperContainer').length > 0) {
var doNothing = "";
clearInterval(colWrapper);
} else {
wrapThese.wrapAll('<div id="colWrapperContainer"></div>').addClass('success');
}
}, 100);
//]]>
</script>

need to set a timer for in javascript , then clear

I want to create a timer in JavaScript. I see the setTimeout(fn, 100) but unclear how to wrap this so it will clear itself at the end.
I tried doing
var buttonTimer = null;
$scope.backButton = function() {
if(buttonTimer === null){
$history.back();
}
buttonTimer = setTimeout(function(buttonTimer){
buttonTimer = null;
}, 100);
}
The whole point is to prevent the user from hitting this function too quickly.. and ignoring all subsequent clicks within that 100ms window, at the end of the window, clear the timer and resume accepting clicks
Since you are doing angular, I prepared a plnkr for demonstration:
http://plnkr.co/edit/5qrslKpmkglXTvEyYgBr?p=preview
Your code is almost Ok, the only problem is that you start a new timeout on every click. The effect is, that the callback fires multiple times and resets buttonTimer.
So the only change is:
var blocker = null;
$scope.backButton = function() {
if(blocker == null) {
blocker = setTimeout(function(){
blocker = null;
}, 1500);
// DO YOUR STUFF HERE
}
};
You can use throttle from lodash/underscore or Ramdajs.
for example
$scope.backButton=_.throttle(100,function(){/* do something here */});

Wait for keypress with timeout

In an experiment I'm coding, on every trial, I need to display a stimulus (search array) and then wait for a maximum of 5 seconds for the subject to respond with a keypress. If a key is pressed, the next trial begins immediately or else after 5 seconds.
I just want to know if I can code up something like this in JavaScript, and if so, how should I code up the experiment? Also, I should be able to store the identity and timestamp of the key pressed.
The flow of your experiment, as I understood them, are this:
Show Stimulus
Check for keypresses repeatedly
If 5 seconds have passed, show next stimulus
If key was pressed, store keypress in array, then show next stimulus.
To do this, I would use Keypress, a JS library for catching input.
You would first want to define your stimuli
E.g.:
var stimuli = ["Apple","Orange","Keira Knightley","Banana"];
You would then want to set up your event listeners. These will log your keypresses for you.
var listener = new window.keypress.Listener();
var results = [];
listener.simple_combo("shift s", function() {
results.push("You pressed shift and s");
});
Then you want to set up the timing system. I would use a setInterval() function to increment the position in the array that the subject is in.
var pos = -1; //Arrays start at 0, and you want to run this function to start.
function nextStim() {
pos = pos + 1;
myDiv.innerHTML = stimuli[pos]
}
var results = [];
listener.simple_combo("shift s", function() {
results.push("The stimulus was: " + stimuli[pos] + "And you pressed Shift + S" );
});
setInterval(nextStim,5000);
<script>
var timeout;
timeout = setTimeout(next, 5000); //execute function "next" after 5000 miliseconds
//With jQuery
//$("#element").on("keypress", function(){ clearTimeout(timeout); next();} );
//Without jQuery
function elementOnKeypress()
{
clearTimeout(timeout); //don't execute "next" after 5000 (or less) ms
next(); //run "next"
}
function next()
{
//your code ..
}
</script>
<element onkeypress="elementOnKeypress();"></element><!-- element is your html-element to be keypressed -->

BigVideo.js .on("ended") fires multiple times

I'm using BigVideo.js jQuery plugin to show full screen background videos. I have links that load different background videos on click. At the end of each video (3-5 sec long) I'm loading an animation. Each video has its own animation on top.
Right now I'm fading in the animations with a time out that corresponds to the video length but it's not full proof. What I really need is for #anim03 to fade in when video-03.mp4 ends. But I can't figure out exactly how the BigVideo.js .on("ended") event really works. In the code I have below (simplified):
// init plugin
var BV = new $.BigVideo({useFlashForFirefox:false});
BV.init();
function setupVideo(url) {
if (Modernizr.touch) {
BV.show(url + '.jpg');
} else {
BV.show(url + '.mp4',{
altSource: url + '.webm',
ambient: false
});
}
}
function setupAnimation(num) {
BV.getPlayer().on("ended", function () { // event from video.js API - when video ends playing
$('#anim0' + num).animate({ opacity: 1 });
});
}
$('a').on('click', function(e) {
e.preventDefault();
// we remove .ext cause we got to setup .webm and .jpg versions
var url = $(this).attr('href').replace('.mp4', '');
setupVideo(url);
var current = $(this).parent().index()+1;
setupAnimation(current);
});
The event is triggered but it seems to go through some sort of queue and fire multiple times. If I console.log num like that:
function setupAnimation(num) {
console.log(num);
BV.getPlayer().on("ended", function () {
$('#anim0' + num).animate({ opacity: 1 });
});
}
I get a single expected value. But if I do it like that:
function setupAnimation(num) {
BV.getPlayer().on("ended", function () {
console.log(num);
$('#anim0' + num).animate({ opacity: 1 });
});
}
Then I get multiple values for num and each time I click and this function is called, I get more and moreā€¦ I'm guessing this .on("ended") loops through some array or something? I can't figure out that part from looking at the plugin's code.
Any help or pointer much appreciated!
When you use the player's "on" function you register a new listener function (This gives you the possibility to trigger multiple functions when something happens).
The reason your on "ended" function fires multiple times, is because each time setupAnimation executed it adds a new instance of the listener-function:
function () {
console.log(num);
$('#anim0' + num).animate({ opacity: 1 });
}
check the API documentation of Video.JS
https://github.com/videojs/video.js/blob/master/docs/api/vjs.Player.md#on-type-fn-
If I get right what you're trying to accomplish, the solution is to run 'setupAnimation' outside the on 'click' function.

how can I rearrange this code so my setInterval stops looping infinitely?

I'm trying to make a simple flip-card/memory match (like from super mario brothers 3) game in HTML/Javascript and am having a slight issue with the setInterval command.
Here is a link to the full code: http://jsfiddle.net/msfZj/
Here is the main issue/main logic of it:
if(click == 2) //denotes two cards being clicked
{
if(flippedArray[1].src === flippedArray[0].src) // if click 1 == click 2 then refer to function 'delayMatch' which sets click 1 and 2 cards to not be displayed
{
window.setInterval(function() { delayMatch() }, 500);
console.log("EQUAL");
}
else
{
window.setInterval(function() { delayNoMatch() }, 500); // if click 1 != click 2 then display card.png
console.log("NOT EQUAL");
}
function delayMatch() //function for matching pairs
{
flippedArray[0].style = "display:none;";
flippedArray[1].style = "display:none;";
}
function delayNoMatch() //function for non-matching pairs
{
flippedArray[0].src = "card.png";
flippedArray[1].src = "card.png";
}
click = 0; // when clicked two cards set click back to zero
}
The first two cards I click on always work: but from that point onward the setInterval keeps running the function over and over again in an endless loop every 500ms.
I'd be extremely appreciative if anybody can point my in the right direction on how I can do this properly.
Thank you very much for your time.
It looks like you need setTimeout, which only runs once?
window.setTimeout(function() { delayMatch() }, 500);
Otherwise, you need to clear the interval with clearInterval(i), but first set "i" using the return value of setInterval:
var i = window.setInterval(function() { delayMatch() }, 500);
Here's a demo (I JQuerified it a bit for JSFiddle).
You're going to want to go with setTimeout() instead of setInterval()
A handy function when you use setTimeout is clearTimeout. Say you want to set a timer, but maybe want a button to cancel
var timer = setTimeout(fn,1000);
//later maybe
clearTimeout(timer);

Categories