Stop loop iterations of functions with setTimeout - javascript

My problem is when I hover over something really fast, it executes the first function and then the second function when the mouse leave the text. The two functions are executed completely. I would like something like, if the mouse leave before a specific time, do something. For instance, change the text to "Fr"
$( "#nav6" ).hover(
function() {
navsix(6);
}, function() {
<!-- clearTimeout(TO) -->
nav6out(6);
}
);
function navsix(i) {
if (window.matchMedia("(min-width: 600px)").matches) {
var elem = document.getElementById("nav6");
var str = "Français";
var len = str.length + 1 - i;
var TO = setTimeout(function () {
elem.innerHTML = str.substring(0, len);
if (--i) navsix(i);
}, 50)
}
}
function nav6out(i) {
if (window.matchMedia("(min-width: 600px)").matches) {
var elem = document.getElementById("nav6");
var str = "Français";
len = i + 1
var TO = setTimeout(function () {
elem.innerHTML = str.substring(0, len);
if (--i) nav6out(i);
}, 50)
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="topnav-right"><a id="nav6" href="#Francais">Fr</a></div>

You're on the right track with clearTimeout(). I added clearTimeout() right before each of your setTimeout() functions and declared TO at the top.
var TO = "";
var hoverTimeout = "";
$("#nav6").hover(
function() {
hoverTimeout = setTimeout(function() {
navsix(6);
}, 200)
},
function() {
clearTimeout(hoverTimeout);
nav6out(6);
}
);
function navsix(i) {
if (window.matchMedia("(min-width: 600px)").matches) {
var elem = document.getElementById("nav6");
var str = "Français";
var len = str.length + 1 - i;
clearTimeout(TO);
TO = setTimeout(function() {
elem.innerHTML = str.substring(0, len);
if (--i) navsix(i);
}, 50)
}
}
function nav6out(i) {
if (window.matchMedia("(min-width: 600px)").matches) {
var elem = document.getElementById("nav6");
var str = "Français";
if (elem.innerHTML.length > 2) {
len = i + 1;
clearTimeout(TO);
TO = setTimeout(function() {
elem.innerHTML = str.substring(0, len);
if (--i) nav6out(i);
}, 50)
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="topnav-right"><a id="nav6" href="#Francais">Fr</a></div>

Related

Combining two Javascript functions to one window.onload not working

I have two functions that I want to run on window.onload event but only the last function seems to work so far. One function is for an image slider and the other one retrieves data from a google spreadsheet cell.
function fun1() { //image slider
var ul;
var li_items;
var imageNumber;
var imageWidth;
var prev, next;
var currentPostion = 0;
var currentImage = 0;
function init() {
ul = document.getElementById('image_slider');
li_items = ul.children;
imageNumber = li_items.length;
imageWidth = li_items[0].children[0].clientWidth;
ul.style.width = parseInt(imageWidth * imageNumber) + 'px';
prev = document.getElementById("prev");
next = document.getElementById("next");
prev.onclick = function() {
onClickPrev();
};
next.onclick = function() {
onClickNext();
};
}
function animate(opts) {
var start = new Date;
var id = setInterval(function() {
var timePassed = new Date - start;
var progress = timePassed / opts.duration;
if (progress > 1) {
progress = 1;
}
var delta = opts.delta(progress);
opts.step(delta);
if (progress == 1) {
clearInterval(id);
opts.callback();
}
}, opts.delay || 17);
}
function slideTo(imageToGo) {
var direction;
var numOfImageToGo = Math.abs(imageToGo - currentImage);
direction = currentImage > imageToGo ? 1 : -1;
currentPostion = -1 * currentImage * imageWidth;
var opts = {
duration: 1000,
delta: function(p) {
return p;
},
step: function(delta) {
ul.style.left = parseInt(currentPostion + direction * delta * imageWidth * numOfImageToGo) + 'px';
},
callback: function() {
currentImage = imageToGo;
}
};
animate(opts);
}
function onClickPrev() {
if (currentImage == 0) {
slideTo(imageNumber - 1);
} else {
slideTo(currentImage - 1);
}
}
function onClickNext() {
if (currentImage == imageNumber - 1) {
slideTo(0);
} else {
slideTo(currentImage + 1);
}
}
}
function fun2() {
// Google spreadsheet js
google.load('visualization', '1', {
callback: function() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1sA7M5kG6Xo8YScD1Df38PIA_G0bvhGRdqoExXg0KJTs/gviz/tq?tqx=out:html&tq?gid=0&headers=0&range=A1:C');
query.send(displayData);
}
});
function displayData(response) {
numRows = response.getDataTable().getValue(0, 0);
document.getElementById('data').innerHTML = numRows;
}
}
var addFunctionOnWindowLoad = function(callback) {
if (window.addEventListener) {
window.addEventListener('load', callback, false);
} else {
window.attachEvent('onload', callback);
}
}
addFunctionOnWindowLoad(fun1);
addFunctionOnWindowLoad(fun2);
This is the answer I've tried link but I can't seem to figure out where I'm going wrong.
This is what I ended up doing, and now all the functions work.
var ul;
var li_items;
var imageNumber;
var imageWidth;
var prev, next;
var currentPostion = 0;
var currentImage = 0;
function init() {
ul = document.getElementById('image_slider');
li_items = ul.children;
imageNumber = li_items.length;
imageWidth = li_items[0].children[0].clientWidth;
ul.style.width = parseInt(imageWidth * imageNumber) + 'px';
prev = document.getElementById("prev");
next = document.getElementById("next");
prev.onclick = function() {
onClickPrev();
};
next.onclick = function() {
onClickNext();
};
}
function animate(opts) {
var start = (new Date());
var id = setInterval(function() {
var timePassed = (new Date()) - start;
var progress = timePassed / opts.duration;
if (progress > 1) {
progress = 1;
}
var delta = opts.delta(progress);
opts.step(delta);
if (progress == 1) {
clearInterval(id);
opts.callback();
}
}, opts.delay || 17);
//return id;
}
function slideTo(imageToGo) {
var direction;
var numOfImageToGo = Math.abs(imageToGo - currentImage);
// slide toward left
direction = currentImage > imageToGo ? 1 : -1;
currentPostion = -1 * currentImage * imageWidth;
var opts = {
duration: 1000,
delta: function(p) {
return p;
},
step: function(delta) {
ul.style.left = parseInt(currentPostion + direction * delta * imageWidth * numOfImageToGo) + 'px';
},
callback: function() {
currentImage = imageToGo;
}
};
animate(opts);
}
function onClickPrev() {
if (currentImage === 0) {
slideTo(imageNumber - 1);
} else {
slideTo(currentImage - 1);
}
}
function onClickNext() {
if (currentImage == imageNumber - 1) {
slideTo(0);
} else {
slideTo(currentImage + 1);
}
}
window.onload = init;
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
function fun2() {
// Google spreadsheet js
google.load('visualization', '1', {
callback: function() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1sA7M5kG6Xo8YScD1Df38PIA_G0bvhGRdqoExXg0KJTs/gviz/tq?tqx=out:html&tq?gid=0&headers=0&range=A1:C');
query.send(displayData);
}
});
function displayData(response) {
numRows = response.getDataTable().getValue(0, 0);
document.getElementById('data').innerHTML = numRows;
}
}
addLoadEvent(fun2);
addLoadEvent(function() {
});
I found this function a while ago and believe it or not, I still need to use it every so often. addEventLoad() Just call addEventLoad while passing the function to load.
"The way this works is relatively simple: if window.onload has not already been assigned a function, the function passed to addLoadEvent is simply assigned to window.onload. If window.onload has already been set, a brand new function is created which first calls the original onload handler, then calls the new handler afterwards."
This snippet will load 3 functions on window.onload
Snippet
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
function alert1() {
alert("First Function Loaded");
}
function alert2() {
alert("Second Function Loaded");
}
function alert3(str) {
alert("Third Function Loaded; Msg: " + str);
}
addLoadEvent(alert1);
addLoadEvent(alert2);
addLoadEvent(function() {
alert3("This works");
});
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

Jquery erase text with type effect

I write some script to add text with typing effect. I need to remove text like that effect but don't know how do that. If can please help.
JS Code :
var title = $(".form-title").attr("data-title");
$.each(title.split(''), function (i, letter) {
setTimeout(function () {
console.log(letter);
$('.form-title').html($('.form-title').html() + letter);
}, 500 * i);
});
JSFIDDLE
var title = $(".form-title").attr("data-title");
var interval = 200;
var wait = interval + (interval * title.length);
$.each(title.split(''), function (i, letter) {
setTimeout(function () {
$('.form-title').html($('.form-title').html() + letter);
}, interval * i);
});
var i = title.length;
while(i >= 0){
setTimeout(function () {
var text = $('.form-title').html();
var length = text.length - 1;
$('.form-title').html(text.substring(0, length));
}, wait + (interval * i) );
i--;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<h2 class="form-title" data-title="Dear Concept Studio,"></h2>
You can trim the last letter of the HTML content with each iteration.
For example:
$('.form-title').html($('.form-title').html().substring(0, title.length-1-i));
https://jsfiddle.net/ecvbL0f7/2/
If you already had the text:
<h2 class="form-title">Dear Concept Studio</h2>
Then you would remove it with this:
var H2 = $("h2");
var H2Length = H2.text().length;
$.each(H2.text().split(''), function (i, letter) {
setTimeout(function () {
console.log(H2.text().substring(0,H2Length-1));
H2.text(H2.text().substring(0,H2Length-1));
H2Length--;
}, 500 * i);
});
There you go, a snippet for you:
var
$title = $("h2");
var func = function() {
$title.text($title.text().substring(0, $title.text().length - 1));
if ($title.text().length > 0) {
setTimeout(func, 100);
};
};
func();
http://jsfiddle.net/ucvvegay/7/
on jsFiddle
use the following javascript. Check the demo also in the below
var title = $(".form-title").attr("data-title");
$.each(title.split(''), function (i, letter) {
setTimeout(function () {
if(title.length-i!=1) {
$('.form-title').html(title.substring(0,title.length-i));
} else {
$('.form-title').html(title.substring(0,title.length-i));
setTimeout(function() {
$('.form-title').html("");
},500);
}
}, 500 * i);
});
$('.form-title').html("")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h2 class="form-title" data-title="Dear Concept Studio,"></h2>
Try like this,
var title = $(".form-title").attr("data-title");
var leng = title.split('').length-1;
$.each(title.split(''), function (i, letter) {
setTimeout(function () {
// console.log(letter);
if(i===leng){deleting()}
$('.form-title').html($('.form-title').html() + letter);
}, 500 * i);
});
function deleting (){
var text = $('.form-title').html();
var length = text.length-1;
$.each(text.split(''),function(i,letter){
setTimeout(function () {
$('.form-title').html(text.substring(0,length-i));
},500*i);
});
}
https://jsfiddle.net/ucvvegay/9/
This is JS code to animate typing effect then erasing it and showing a blinking cursor. You may further tweak the code.
credits goes to original author Simon Shahriver.
Here's the Fiddle: https://codepen.io/jerrygoyal/pen/vRPpGO
var TxtType = function(el, toRotate, period) {
this.toRotate = toRotate;
this.el = el;
this.loopNum = 0;
this.period = parseInt(period, 10) || 2000;
this.txt = '';
this.tick();
this.isDeleting = false;
};
TxtType.prototype.tick = function() {
var i = this.loopNum % this.toRotate.length;
var fullTxt = this.toRotate[i];
if (this.isDeleting) {
this.txt = fullTxt.substring(0, this.txt.length - 1);
} else {
this.txt = fullTxt.substring(0, this.txt.length + 1);
}
this.el.innerHTML = '<span class="wrap">'+this.txt+'</span>';
var that = this;
var delta = 200 - Math.random() * 100;
if (this.isDeleting) { delta /= 2; }
if (!this.isDeleting && this.txt === fullTxt) {
delta = this.period;
this.isDeleting = true;
} else if (this.isDeleting && this.txt === '') {
this.isDeleting = false;
this.loopNum++;
delta = 500;
}
setTimeout(function() {
that.tick();
}, delta);
};
window.onload = function() {
var elements = document.getElementsByClassName('typewrite');
for (var i=0; i<elements.length; i++) {
var toRotate = elements[i].getAttribute('data-type');
var period = elements[i].getAttribute('data-period');
if (toRotate) {
new TxtType(elements[i], JSON.parse(toRotate), period);
}
}
};
body {
background-color:#ce6670;
text-align: center;
color:#fff;
padding-top:50px;
}
* { color:#fff; text-decoration: none;}
.wrap{
animation: caret 1s steps(1) infinite;
border-right: 0.08em solid #fff;
padding-right: 1px;
}
#keyframes caret {
50% {
border-color: transparent;
}
}
<h1>
<a href="" class="typewrite" data-period="2000" data-type='[ "Hi, I am Jerrygoyal.", "I am Creative.", "I Love Design.", "I Love to Develop." ]'>
<span class="wrap"></span>
</a>
</h1>

Toggle class on HTML element without jQuery

I have a section on my website which holds all the content, but I want a "sidebar" with hidden content to smoothly appear from the left at the push of an external button.
CSS transitions can handle the smoothness no problem, and jQuery toggle() can switch between classes to move the hidden div in and out of the screen.
How can I get the same effect without using jQuery?
You can toggle classes using the classList.toggle() function:
var element = document.getElementById('sidebar');
var trigger = document.getElementById('js-toggle-sidebar'); // or whatever triggers the toggle
trigger.addEventListener('click', function(e) {
e.preventDefault();
element.classList.toggle('sidebar-active'); // or whatever your active class is
});
That should do everything you need - if you have more than one trigger I'd recommend using document.querySelectorAll(selector) instead.
You can implement it only by CSS3:
<label for="showblock">Show Block</label>
<input type="checkbox" id="showblock" />
<div id="block">
Hello World
</div>
And the CSS part:
#block {
background: yellow;
height: 0;
overflow: hidden;
transition: height 300ms linear;
}
label {
cursor: pointer;
}
#showblock {
display: none;
}
#showblock:checked + #block {
height: 40px;
}
The magic is the hidden checkbox and the :checked selector in CSS.
Working jsFiddle Demo.
HTML ONLY
You can use <summary>. The following code doesn't have any dependency.
No JavaScript, CSS at all, HTML only.
<div class="bd-example">
<details open="">
<summary>Some details</summary>
<p>More info about the details.</p>
</details>
<details>
<summary>Even more details</summary>
<p>Here are even more details about the details.</p>
</details>
</div>
For more detail, go to MDN official docs.
you can get any element by id with javascript (no jquery) and the class is an attribute :
element.className
so have this as a function:
UPDATE:
since this is becoming a somewhat popular I updated the function to make it better.
function toggleClass(element, toggleClass){
var currentClass = element.className || '';
var newClass;
if(currentClass.split(' ').indexOf(toggleClass) > -1){ //has class
newClass = currentClass.replace(new RegExp('\\b'+toggleClass+'\\b','g'), '')
}else{
newClass = currentClass + ' ' + toggleClass;
}
element.className = newClass.trim();
}
function init() {
animateCSS(document.getElementById("slide"), 250, {
left: function (timePercent, frame) {
var endPoint = 128,
startPoint = 0,
pathLength = endPoint - startPoint,
base = 64, //slope of the curve
currentPos = Math.floor(startPoint + (Math.pow(base, timePercent) - 1) / (base - 1) * pathLength);
return currentPos + "px";
}
}, function (element) {
element.style.left = "128px";
});
};
var JobType = function () {
if (!(this instanceof JobType)) {
return new JobType(arguments[0]);
};
var arg = arguments[0];
this.fn = arg["fn"];
this.delay = arg["delay"];
this.startTime = arg["startTime"];
this.comment = arg["comment"];
this.elapsed = 0;
};
function JobManager() {
if (!(this instanceof JobManager)) {
return new JobManager();
};
var instance;
JobManager = function () {
return instance;
};
JobManager.prototype = this;
instance = new JobManager();
instance.constructor = JobManager;
var jobQueue = [];
var startedFlag = false;
var inProcess = false;
var currentJob = null;
var timerID = -1;
var start = function () {
if (jobQueue.length) {
startedFlag = true;
currentJob = jobQueue.shift();
var startOver = currentJob.delay - ((new Date()).getTime() - currentJob.startTime);
timerID = setTimeout(function () {
inProcess = true;
currentJob.fn();
if (jobQueue.length) {
try {
while ((jobQueue[0].delay - ((new Date()).getTime() - currentJob.startTime)) <= 0) {
currentJob = jobQueue.shift();
currentJob.fn();
};
}
catch (e) { };
}
inProcess = false;
start();
}, (startOver > 0 ? startOver : 0));
}
else {
startedFlag = false;
timerID = -1;
};
};
instance.add = function (newJob) {
if (newJob instanceof JobType) {
stopCurrent();
var jobQueueLength = jobQueue.length;
if (!jobQueueLength) {
jobQueue.push(newJob);
}
else {
var currentTime = (new Date()).getTime(),
insertedFlag = false;
for (var i = 0; i < jobQueueLength; i++) {
var tempJob = jobQueue[i],
tempJobElapsed = currentTime - tempJob["startTime"],
tempJobDelay = tempJob["delay"] - tempJobElapsed;
tempJob["elapsed"] = tempJobElapsed;
if (newJob["delay"] <= tempJobDelay) {
if (!insertedFlag) {
jobQueue.splice(i, 0, newJob);
insertedFlag = true;
}
};
if (i === (jobQueueLength - 1)) {
if (!insertedFlag) {
jobQueue.push(newJob);
insertedFlag = true;
}
}
};
};
if ((!startedFlag) && (!inProcess)) {
start();
};
return true;
}
else {
return false;
};
};
var stopCurrent = function () {
if (timerID >= 0) {
if (!inProcess) {
clearTimeout(timerID);
timerID = -1;
if (currentJob) {
jobQueue.unshift(currentJob);
};
};
startedFlag = false;
};
};
return instance;
};
function animateCSS(element, duration, animation, whendone) {
var frame = 0,
elapsedTime = 0,
timePercent = 0,
startTime = new Date().getTime(),
endTime = startTime + duration,
fps = 0,
averageRenderTime = 1000,
normalRenderTime = 1000 / 25,
myJobManager = JobManager();
var inQueue = myJobManager.add(JobType({
"fn": displayNextFrame,
"delay": 0,
"startTime": (new Date).getTime(),
"comment": "start new animation"
}));
function playFrame() {
for (var cssprop in animation) {
try {
element.style[cssprop] = animation[cssprop].call(element, timePercent, frame);
} catch (e) { }
};
};
function displayNextFrame() {
elapsedTime = (new Date().getTime()) - startTime;
timePercent = elapsedTime / duration;
if (elapsedTime >= duration) {
playFrame();
if (whendone) {
whendone(element);
};
return;
};
playFrame();
frame++;
averageRenderTime = elapsedTime / frame;
fps = 1000 / averageRenderTime;
inQueue = myJobManager.add(JobType({
"fn": displayNextFrame,
"delay": (fps < 15 ? 0 : normalRenderTime - averageRenderTime),
"startTime": (new Date).getTime(),
"comment": frame
}));
}
};
(function () {
if (this.addEventListener) {
this.addEventListener("load", init, false)
}
else {
window.onload = init;
}
}());
// By Plain Javascript
// this code will work on most of browsers.
function hasClass(ele, clsName) {
var el = ele.className;
el = el.split(' ');
if(el.indexOf(clsName) > -1){
var cIndex = el.indexOf(clsName);
el.splice(cIndex, 1);
ele.className = " ";
el.forEach(function(item, index){
ele.className += " " + item;
})
}
else {
el.push(clsName);
ele.className = " ";
el.forEach(function(item, index){
ele.className += " " + item;
})
}
}
var btn = document.getElementById('btn');
var ele = document.getElementById('temp');
btn.addEventListener('click', function(){
hasClass(ele, 'active')
})
I did not test but the code below should work.
<script>
function toggleClass(){
var element = document.getElementById("a");
element.classList.toggle("b");
}
document.getElementById("c").addEventListener('click', toggleClass )
</script>

Converting jquery to javascript progress bar

Please help me convert this JQuery to Javascript progress bar script
var generateButton = document.getElementById("generate");
if (generateButton.addEventListener) {
generateButton.addEventListener("click", random, false);
}
else if (generateButton.attachEvent) {
generateButton.attachEvent('onclick', random);
}
function random(e) {
setTimeout(function(){
$('.progress .bar').each(function() {
var me = $(this);
var perc = me.attr("data-percentage");
//TODO: left and right text handling
var current_perc = 0;
var progress = setInterval(function() {
if (current_perc>=perc) {
clearInterval(progress);
} else {
current_perc +=1;
me.css('width', (current_perc)+'%');
}
me.text((current_perc)+'%');
}, 50);
});
},300);
var num = Math.random();
var greetingString = num;
document.getElementById("rslt").innerText = greetingString;
}
Here is the Live version: http://jsfiddle.net/chjjK/9/
Pretty easy actually, use document.getElementsByClassName and a for loop to replace the each:
var bar = document.getElementsByClassName("bar");
for (var i = 0; i < bar.length; i++) {
var me = bar[i];
var perc = me.getAttribute("data-percentage");
var current_perc = 0;
var progress = setInterval(function() {
if (current_perc>=perc) {
clearInterval(progress);
} else {
current_perc +=1;
me.style.width = current_perc+'%';
}
me.innerHTML = ((current_perc)+'%');
}, 50);
}
}, 300);
Demo: http://jsfiddle.net/chjjK/13/

Stop jQuery Typewriter animation onclick

I'm wondering how I might stop the following typewriter script when I - for instance - click a link. I don't want to do anything fancy, simply stop the animation as soon as the link is clicked.
$(function () {
var ch = 0;
var item = 0;
var items = $('.headline_origin li').length;
var time = 1000;
var delay = 40;
var wait = 6000;
var tagOpen = false;
function tickInterval() {
if(item < items) {
var text = $('.headline_origin li:eq('+item+')').html();
type(text);
text = null;
var tick = setTimeout(tickInterval, time);
} else {
clearTimeout(tick);
}
}
function type(text) {
time = delay;
ch++;
if(text.substr((ch - 1), 1) == '<') {
if(text.substr(ch, 1) == '/') {
tagOpen = false;
}
var tag = '';
while(text.substr((ch - 1), 1) != '>') {
tag += text.substr((ch - 1), 1);
ch++;
}
ch++;
tag += '>';
var html = /\<[a-z]+/i.exec(tag);
if(html !== null) {
html = html[0].replace('<', '</') + '>';
tagOpen = html;
}
}
if(tagOpen !== false) {
var t = text.substr(0, ch);
} else {
var t = text.substr(0, ch);
}
$('h1 span.origin').html(t);
if(ch > text.length) {
item++;
ch = 0;
time = wait;
}
}
var tick = setTimeout(tickInterval, time);
});
Thanks in advance!
#rrfive
Inside your tickInterval function, remove the var declaration from the setTimeout - we can reuse the global tick variable.
Then you just need to have a clearInterval(tick); on your click handler for whichever button you like.

Categories

Resources