I have created a page where I have multiple functionality done but stuck with timing of it, if you see the page example here in JSFiddle.
When you open the page, it will first run a loader and when the loader is complete there are multiple boxes, which is showing one by one but in currently its not happening, Loader is loading fine and then in the next step where centered columns has to appear one by one, the first four columns loads by default and then other div loads one by one.
My question is, how can I execute a function and execute another another function once the previous is complete.
For loader I have the following:
//--------- process bar animation
var showText = function (target, message, index, interval) {
if (index < message.length) {
$(target).append(message[index++]);
setTimeout(function () { showText(target, message, index, interval); }, interval);
}
}
var width = 100,
perfData = window.performance.timing, // The PerformanceTiming interface represents timing-related performance information for the given page.
EstimatedTime = -(perfData.loadEventEnd - perfData.navigationStart),
time = parseInt((EstimatedTime/1000)%60)*100;
showText("#msg", "Welcome to the Company Group", 0, width);
// Loadbar Animation
$(".loadbar").animate({
width: width + "%"
}, time);
// Loadbar Glow Animation
$(".glow").animate({
width: width + "%"
}, time);
// Percentage Increment Animation
var PercentageID = $("#precent"),
start = 0,
end = 100,
durataion = time;
animateValue(PercentageID, start, end, durataion);
function animateValue(id, start, end, duration) {
var range = end - start,
current = start,
increment = end > start? 1 : -1,
stepTime = Math.abs(Math.floor(duration / range)),
obj = $(id);
var timer = setInterval(function() {
current += increment;
$(obj).text(current + "%");
//obj.innerHTML = current;
if (current == end) {
clearInterval(timer);
}
}, stepTime);
}
// Fading Out Loadbar on Finised
setTimeout(function(){
$('.preloader-wrap').fadeOut(300);
$('.loader-wrap').fadeOut(300);
$('.main-wrapper').fadeIn(300);
$('body').addClass('bg');
}, time);
For showing div one by one in next step I have the following code:
$(".column-wrapper").each(function(index) {
var $this = $(this);
setTimeout(function () { $this.addClass("show"); }, index * 1000);
});
I use trigger and on for those kind of things. You had a lot of code, so sorry, I didn't want to read all of that but this is a simplified example.
https://jsfiddle.net/2d6p4L6k/1/
$(document).ready(function(){
var action = function(){
$('div.one').css('background-color', 'green');
/* do whatever you want to do */
/* then trigger(call) another function */
$(document).trigger('hello-action');
};
var hello = function() {
$('div.two').css('background-color', 'fuchsia');
};
/* just listen if anything triggers/calls "hello-action" */
/* if so call function named hello */
$(document).on('hello-action', hello);
setTimeout(action, 1500);
});
div {
width: 50px;
height: 50px;
background-color: orange;
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="one">one</div>
<div class="two">two</div>
Note: To keep it simple we trigger and listen on $(document) which is really just to keep it simple. A better approach would be to have a wrapper element, and then you can do exactly the same (trigger and listen) just on that element and not on the entire document. You can find more details on the jQuery API .trigger()
Related
First let me describe the project I'm stuggeling with. English is not my foreign language so I do not know the exact name of the effect I am looking for.
Basicly I am creating a bingo type of game where the host can press on a button to start the bingo wheel. Eventually the wheel will stop and the word it has landed on is the chosen word for that round. After that, this word get removed from the game and the game starts over and over untill someone calls a bingo.
I started playing a bit around with some JSON data and how to remove the items from the array etc which is pretty easy to do. But now comes the part where I am struggeling the most. I have to create a kind of function that scrolls through all options like a wheel at a certain speed that eventually decreased in speed so it will land on the chosen word for this round. I created a fiddle with the code I currently have. Note that it's purely created for functionality instead of looks!
var json = {
"titles": [
"PLACEHOLDER_1",
"PLACEHOLDER_2",
"PLACEHOLDER_3",
"PLACEHOLDER_4",
"PLACEHOLDER_5",
"PLACEHOLDER_6",
"PLACEHOLDER_7",
"PLACEHOLDER_8",
"PLACEHOLDER_9",
"PLACEHOLDER_10",
"PLACEHOLDER_11",
"PLACEHOLDER_12",
"PLACEHOLDER_13",
"PLACEHOLDER_14",
"PLACEHOLDER_15"
]
}
$(document).ready(function() {
var app = new Bingo.init();
})
var Bingo = {
viewport: {
isMobile: 0,
isTablet: 0,
isDesktop: 1,
device: 'desktop',
browser: null
}
}
Bingo.init = function() {
Bingo.gameController.init();
};
Bingo.gameController = {
gameNames: {},
init: function() {
Bingo.gameController.general.saveJson();
$('.test').on('click', Bingo.gameController.array.pickRandomNumber)
},
general: {
saveJson: function() {
Bingo.gameController.gameNames = json.titles;
},
//General reset function
resetGame: function() {
Bingo.gameController.general.saveJson;
}
},
array: {
pickRandomNumber: function() {
//reset gamefield
Bingo.gameController.game.buildGame();
var gameNames = Bingo.gameController.gameNames;
var totalNames = gameNames.length;
//Pick a random number
var chosenNumber = Math.floor(Math.random() * totalNames);
Bingo.gameController.array.remove(chosenNumber)
},
remove: function(id) {
//remove chosen name from array
var gameNames = Bingo.gameController.gameNames;
var check = gameNames.indexOf(gameNames[id]);
Bingo.gameController.game.highlightName(id);
if (check != -1) {
gameNames.splice(check, 1);
Bingo.gameController.gameNames = gameNames;
}
}
},
game: {
buildGame: function() {
//build all the array entry's into the div
$('.page.main-game').empty();
var gameNames = Bingo.gameController.gameNames;
for (var i = 0; i < gameNames.length; i++) {
var item = '<div class="name-item" data-id="' + i + '">' + gameNames[i] + '</div>';
$('.page.main-game').append(item);
}
},
highlightName: function(id) {
//highlight the chosen number red
$('.name-item[data-id="' + id + '"]').css('color', 'red');
}
}
}
Fiddle link here
(I hope the link is correct, not using fiddle that much)
So now when you click on the 'play again' button you see that it wil highlight a word. What has to happen is when I press the play again button the red highlight has to go from the first div to the last and so forth untill it eventually stops at a div (which is chosen with the random number or something).
If someone can help me with this or could give me a hint in the right direction please let me know!
EXTRA: The app will eventually get a look like a scrollwheel that the iphone gets when you open a select box (hope you know what I am referring to). So thats why its a wheel of fortune-ish effect. If someone could provide me with the correct name for this let me know so I can adjust the title!
If any information is missing please let me know, i'd be happy to provide it! Thanks in regard!!
The basic ideas are (1) to keep the current index, so you can start the spin every time from that index, where 'spining' is just increasing that index or set to zero when reaching the maximal index; and (2) set a timeout for the next painting, and reduce that timeout everytime, until it's low enough.
JsFiddle Demo
HTML
<p><button onclick="w.spin(w.randomNext(), 8)">SPIN</button></p>
<ul id='wheel'>
<li>$100</li>
<li>$250,000</li>
<li>$25,000</li>
<li>$10,000</li>
<li>$1,000</li>
<li>$5</li>
<li>$2,000</li>
<li>30,000</li>
<li>$40</li>
</ul>
JavaScript
var wheelEl = document.getElementById('wheel');
function Wheel () {
this.current = 4;
}
Wheel.prototype.init = function () {
this.onItem();
}
Wheel.prototype.randomNext = function () {
return Math.floor(Math.random() * wheelEl.children.length);
}
Wheel.prototype.spin = function (next, itemsPerSecond) {
var timeout = setTimeout(onItem.bind(this), (1 / itemsPerSecond) * 1000);
function onItem () {
// stop if speed is low enough
if (itemsPerSecond < 1)
return;
// spin to next item
this.current ++;
if (this.current >= wheelEl.children.length)
this.current = 0;
// paint text
this.onItem();
// reduce speed
clearTimeout(timeout);
itemsPerSecond--;
timeout = setTimeout(onItem.bind(this), (1 / itemsPerSecond) * 1000);
}
}
// paints the index of this.current
Wheel.prototype.onItem = function () {
for (var i = 0 ; i < wheelEl.children.length ; i++)
wheelEl.children[i].style.color = (i == this.current) ? '#6d4321' : '#000000';
}
var w = new Wheel();
w.init();
Basically I'm trying to toggle a function that gradually change background color of div. There's a separate script.js file that is responsible for function gradientify() to run.
I'm just not sure what is the logic to toggle a function...
index.html
<body>
<button type="button" id="btn"></button>
<div style="width: 100px; height: 100px;"></div>
</body>
script.js
$('#btn').click(function() {
$('div').toggle(function() {
$(this).gradientify({
gradients: [
{ start: [49,76,172], stop: [242,159,191] },
{ start: [255,103,69], stop: [240,154,241] },
{ start: [33,229,241], stop: [235,236,117] }
]
});
});
});
The Jquery toggle function toggles the visibility of an element. It basically sets the css property display to display: none. If you want the content inside the "gradientifyied" element to still be visible when you toggle the gradients then you can't use Jquery.toggle.
Sadly the gradientify API doesn't provide any way to cancel the gradients once they are set on an element so the only way to toggle the gradients on an element is to remove it from the DOM all together.
We can create a copy of the clean element before the gradiants are applied and when we want to remove the gradients, we remove the old element from the DOM and insert the copy we kept.
function toggleGradients() {
var gradientTargetCopy = $( ".gradientTarget" ).clone()
var gradientsOff = true;
return function() {
if (gradientsOff) {
$('.gradientTarget').gradientify({
gradients: [
{ start: [49,76,172], stop: [242,159,191] },
{ start: [255,103,69], stop: [240,154,241] },
{ start: [33,229,241], stop: [235,236,117] }
]
});
} else {
$('.gradientTarget').remove()
$('body').append(gradientTargetCopy)
gradientTargetCopy = $( ".gradientTarget" ).clone()
}
gradientsOff = !gradientsOff
}
}
$('#btn').click(toggleGradients());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://codefog.github.io/jquery-gradientify/jquery.gradientify.min.js"></script>
<body>
<button type="button" id="btn">Toggle gradients</button>
<div class="gradientTarget" style="width: 100px; height: 100px;">Hello!</div>
</body>
Just use plain JavaScript.
var x = 3; //Length of amount of color options you want
var bgcolor_num = Math.floor((Math.random() * x) + 1);
setInterval(function () {
if (bgcolor_num === 1) {
bgcolor = "#FF0000";
bgcolor_num = 2;
} else if (bgcolor_num === 2) {
bgcolor = "#00FF00";
bgcolor_num = 3;
} else {
bgcolor = "#0000FF";
bgcolor_num = 1;
}
document.getElementById('whatever').style.backgroundColor = bg_color;
}, 12000);
What happens is that it defines a variable, x, and randomizes a number from 1 to x. Then, an interval (which runs every 12 seconds; 12,000 milliseconds) determines whether the number, bgcolor_num, is 1, 2, 3, or something else. Remember, the amount of options you have has to equal x. If it doesn't, it will run as "else" and will start back at color option #1.
Make sure you have an ID set for your div and reconfigure the part that actually triggers the change!
If you want an example of this happening, you can always go to my website typrograms.com/RGB.html and right-click, view-source! I use a similar method, and it slowly changes the color.
I have list of projects with images that have hover effect. Hover effect shows project description. I made a loop that shows for 3 seconds every project description.
The problem is when you mouse enter some element it shows text, but when loop catches it hides project text. And you need leave and enter the element to show text again. I want to prevent from text to hide if element is already hovered.
var index = 0;
var duration = 3000;
function loopProjects() {
$('.port-hov').each(function(index,item) {
index = index + 1;
//console.log(index);
setTimeout(function(){
$(item).mouseenter();},duration);
duration = duration + 3000;
setTimeout(function(){
$(item).mouseleave();},duration);
});
}
setInterval(loopProjects, index * 4000);
Solution!
function loopProjects() {
$('.port-hov').each(function(index,item) {
index = index + 1;
setTimeout(function(){
$(item).mouseenter();},duration);
duration = duration + 3000;
setTimeout(function(){
if (!$(item).is(":hover")){
$(item).mouseleave();}},duration);
});
}
I'm making a site that has an area that it's content disappear and re-appears. So when the user clicks certain button, the <div>'s content fades out and fades in the content relative to the clicked icon.
First time the function getabout is clicked it works OK, but whenever I click on clear() and then again on getabout it starts blinking. I've discovered that it does the clean to the div but it happens that the content re-appears again from nothing and becomes intermittent.
Here is my JavaScript code, it's commented so you could give me a hand here:
var check = null; //this will be checking the instance of div's content
const wait_time = 50; //the time it will take to fade
function getabout(id) {
/* prevent second call to the same function to bug */
if (check == id) return;
var titleOpacity = 0,
textOpacity = 0;
/* this changes the title first */
document.getElementById("title").style.opacity = 0;
document.getElementById("title").innerHTML = "this is the title";
// recursive call to the opacity changer, it
// increases opacity by 0.1 each time until it's 1
setInterval(function () {
titleOpacity = fadeIn(titleOpacity, 'title');
}, wait_time);
/* changes the content next to the title */
window.setTimeout(function () {
document.getElementById("dialog").style.opacity = 0;
document.getElementById("dialog").innerHTML = "this is the content";
setInterval(function () {
textOpacity = fadeIn(textOpacity, 'dialog');
}, wait_time);
}, 500);
check = id; // defines the instance "about" at the moment
}
function fadeIn(opacity, id) {
opacity += 0.1;
document.getElementById(id).style.opacity = opacity;
document.getElementById(id).style.MozOpacity = opacity;
if (opacity >= 1.0) clearInterval(listener);
return opacity;
}
function clear() {
var opacity = document.getElementById("title").style.opacity;
// supposed to decrease the opacity by 0.1 but it's not doing that
setInterval(function () {
opacity = fadeout(opacity);
}, wait_time);
//cleans the title and dialog to fill with the next button user clicked
document.getElementById("title").innerHTML = "";
document.getElementById("dialog").innerHTML = "";
}
function fadeout(opacity) {
opacity -= 0.1;
document.getElementById("title").style.opacity = opacity;
document.getElementById("dialog").style.MozOpacity = opacity;
if (opacity <= 0.0) clearInterval(listener);
return opacity;
}
function getregister(id) {
if (check == id) return;
clear(); // proceed to fade out the content and clean it
check = id;
}
I don't understand what is the error of the code. with the clear() function it should smoothly fade out the content and then clean it. But it just cleans the div. And next time I use getabout() function, instead of smoothly fade in again as it does the first time, it starts to blink.
I'm relatively new to web programming and I refuse JQuery for now. I want to understand deeply javascript before go to JQuery and this is why I would just like to know pure JavaScript solutions and considerations about this.
Ive managed to cock up my comment so trying again!
I think your problem is that you're not clearing the setInterval correctly - ensure you use listener = setInterval(...)
As it stands your clearInterval(listener); is doing nothing as 'listener' is not defined. So your fade out function continues to run.
I have this simple slider JScript that hovers thumbnails to the left or the right depending on what button you click.
<script>
$(document).ready(function()
{
$(".right-arrow").click(function(){
$(".box1").animate({right:"1100px"},800);
$(".box2").animate({right:"1100px"},1000);
$(".box3").animate({right:"1100px"},1200);
$(".box4").animate({right:"1100px"},1400);
$(".box5").animate({right:"1100px"},1600);
$(".box6").animate({right:"1100px"},1800);
$(".box7").animate({right:"1100px"},2000);
$(".box8").animate({right:"1100px"},2200);
$(".box9").animate({right:"1100px"},2400);
$(".box10").animate({right:"1100px"},2600);
$(".box11").animate({right:"1100px"},2800);
$(".box12").animate({right:"1100px"},3000);
});
$(".left-arrow").click(function(){
$(".box12").animate({right:"0px"},800);
$(".box11").animate({right:"0px"},1000);
$(".box10").animate({right:"0px"},1200);
$(".box9").animate({right:"0px"},1400);
$(".box8").animate({right:"0px"},1600);
$(".box7").animate({right:"0px"},1800);
$(".box6").animate({right:"0px"},2000);
$(".box5").animate({right:"0px"},2200);
$(".box4").animate({right:"0px"},2400);
$(".box3").animate({right:"0px"},2600);
$(".box2").animate({right:"0px"},2800);
$(".box1").animate({right:"0px"},3000);
});
});
</script>
However if i click the right button and then quickly click the left one i get a congestion of thumbnails 'colliding' with one another.
How do i insert a nice callback function so as to wait that the animation to one side is finished and then proceed with the other way ?
First of all, when you see patterns in your code, it is a good indication that you should start refactoring:
$(document).ready(function() {
$(".right-arrow").click(function(){
for (i = 1; i < 13; i++){
$('.box' + i).stop().animate({
right: 1000
}, {
duration: 600 + (i * 200),
queue: true
});
}
});
$(".left-arrow").click(function(){
for (i = 1; i < 13; i++){
$('.box' + i).stop().animate({
right: 0
}, {
duration: 3200 - (i * 200),
queue: true
});
}
});
}
Regarding the timing conflict, all you need is to pass true for the queue option, which will ensure ensuing animations start after previous ones have completed.
Take a look at here JQuery Animate
var domArray = [$(".box1"), $(".box2"), $(".box3")....];
var runningIndex = 0;
function runAnimate(){
domArray[runningIndex].animate({right:"0px"},800 + runningIndex*200, function(){
if(domArray.length > runningIndex){
runningIndex ++;
runAnimate();
}
});
}
$(".right-arrow").click(function(){
runningIndex = 0;
runAnimate();
});
Try this :D Hope can help you