I'm running the below script on a WordPress powered site. It's very heavy on the animations and uses AJAX to fetch posts and load them into a div
.
Three things I wanted to address:
Cleaning up the code so that it runs faster/better
Sometimes the AJAX request doesn't get the next post and either keeps showing the same post, or briefly shows the next post then disappears
The animation
bubbles()
animates in some divs from off screen, and is closed with thecloseAggregator()
function. Sometimes thecloseAggregator()
function doesn't trigger the animations to slide thediv
s out of view, and instead just fades out. Which is problematic because the next time thebubbles()
function is triggered, the divs are already in view, thus: no pretty animation.
I imagine a lot of this is due to the lack of cleanliness/organization in the script. Just hoping someone can help clean this bit up!
//resize feeling font-size if word count is too high
function resizeFeeling(){
var $quote = $(".feeling");
var $numWords = $quote.text().split(" ").length;
if (($numWords >= 12) && ($numWords < 40)) {
$quote.find('h1').css({
'font-size' : '46px',
'line-height' : '48px'
});
$quote.find('h2').css({
'font-size' : '40px',
'line-height' : '50px'
});
}
};
//binding for key navigation
var pressedKeys = {};
var wtf = {
'keydown': function (e) {
if (pressedKeys[e.which])
return;
pressedKeys[e.which] = true;
var keyCode = e.keyCode || e.which,
key = {left: 37, right: 39, random: 83};
switch (keyCode) {
case key.left:
if ($('#post-nav .post-next a').length != 0) {
$('#keys .left-arrow').toggleClass('pressed');
$('#post-nav .post-next a').click();
} else { //if reach the beginning
$('#keys .left-arrow').toggleClass('pressed');
$('.boots').jrumble({rangeX: 5,rangeY: 0, rangeRot: 0, rumbleEvent: 'custom'});$('.boots').trigger('start_rumble');
}
break;
case key.right:
if ($('#post-nav .post-previous a').length != 0) {
$('#keys .right-arrow').toggleClass('pressed');
$('#post-nav .post-previous a').click();
} else { //if reach the end
$('#keys .right-arrow').toggleClass('pressed');
$('.boots').jrumble({rangeX: 5,rangeY: 0, rangeRot: 0, rumbleEvent: 'custom'});$('.boots').trigger('start_rumble');
}
break;
//load a random feeling by pressing the 's' key (ie. shuffle)
case key.random:
$('#keys .shuffle').toggleClass('pressed');
randomizeFeelings();
break;
}
},
'keyup': function (e) {
delete pressedKeys[e.which];
var keyCode = e.keyCode || e.which,
key = {left: 37, right: 39, random: 83 };
switch (keyCode) {
case key.left:
$('#keys .left-arrow').toggleClass('pressed');
$('.boots').trigger('stop_rumble');
break;
case key.right:
$('#keys .right-arrow').toggleClass('pressed');
$('.boots').trigger('stop_rumble');
break;
case key.random:
$('#keys .shuffle').toggleClass('pressed');
break;
}
}
};
//load up the welcome modal with the appropriate welcome message
function welcome() {
//Get the time of day
var currentTime = new Date().getHours();
//late
if (0 <= currentTime&¤tTime < 5) {
$('#heavyBoots h2').append("Hello my restless insomniac,");
}
//morning
if (5 <= currentTime&¤tTime < 12) {
$('#heavyBoots h2').append("Yawnnnn; good morning baby,");
}
//afternoon
if (12 <= currentTime&¤tTime < 16) {
$('#heavyBoots h2').append("Whatcha doin' dear?,");
}
//evening
if (16 <= currentTime&¤tTime < 22) {
$('#heavyBoots h2').append("Hello there,");
}
//late
if (23 <= currentTime&¤tTime <= 24) {
$('#heavyBoots h2').append("Hey, isn't it your bedtime?");
}
//Get the Day
var day=new Date().getDay();
switch (day)
{
case 0: //Sunday
$('#heavyBoots p').append("It's a lazy Sunday.");
break;
case 1: //Monday
$('#heavyBoots h2').html("Fuck Mondays.");
break;
case 5: //Friday
$('#heavyBoots p').append("Also, it's Friday!");
break;
default: //Any other day
$('#heavyBoots h2').append("");
}
//fade-in the background & then the welcome modal
$('#home-bg').fadeIn(500, function(){
$('#heavyBoots').animate({
bottom: '50%'
}, 500, 'easeInOutQuint');
});
//click to hide the welcome modal and load the first post (resize text if needed)
$('#heavyBoots a').live('click', function(){
$(this).parent().parent().animate({
bottom: '-150%'
}, 500, 'easeInOutQuint', function(){
$('#home-bg').fadeOut(200);
});
resizeFeeling();
$('#content').delay(1500).fadeIn(600);
$('.heavy h1').delay(1500).animate({
left: '0%'
},200, 'easeOutSine');
$('.heavy h2').delay(1500).animate({
right: '0%'
},200, 'easeOutSine', function() {
// fade-in bg if there
$('#custom-bg').fadeIn(500);
});
//slide-down date
setTimeout(function() {
$('#logo').delay(1000).animate({
top: '20px'}, 300, 'easeInOutElastic', function(){
$('.heavy h3 span').animate({
top: '0px'
},200, 'easeOutSine', function() {
// Animation complete.
$('#keys').animate({bottom: '20px'},300, 'easeInOutElastic');
});
});
}, 1000);
//call first post, activate feelings & bind keys
$(document).bind(wtf);
cycleFeelings();
});
};
function relationshipAggregator() {
//Remove current feeling from the view & slide out the keyboard legend
$('.heavy h1').animate({
left: '-150%'
},200, 'easeInBack');
$('.heavy h2').animate({
right: '-150%'
},200, 'easeInBack');
$('#custom-bg').fadeOut(100);
$('#content').fadeOut(600, function(){
$('.heavy h3 span').animate({top: '-40px'});
});
$('#keys').animate({bottom: '-55px'},300, 'easeInOutElastic');
//remove key binding to prevent user from accidentally changing the current feeling
bubbles();
$(document).unbind(wtf);
//close the aggregator, bring back the feeling & rebind the keys
};
function closeAggregator() {
$('#aggregator-close').animate({
top: '-100px'
}, 500, 'easeInOutElastic', function() {
$('#bubble1').animate({
left: '-150%'
}, 1000, 'easeOutBack');
$('#bubble2').animate({
top: '-150%'
}, 1000, 'easeOutBack');
$('#bubble3').animate({
bottom: '-150%'
}, 1000, 'easeOutBack');
$('#bubble4').animate({
bottom: '-150%'
}, 1000, 'easeOutBack');
$('#bubble5').animate({
right: '-150%'
}, 1000, 'easeOutBack');
$('#bubble6').animate({
top: '-150%'
}, 1000, 'easeOutBack');
$('#reddit').animate({
bottom: '-150%'
}, 1000, 'easeOutBack');
});
setTimeout( function() {
$('#aggregator').fadeOut(200);
$('.heavy h1').animate({
left: '0%'
},200, 'easeInBack');
$('.heavy h2').animate({
right: '0%'
},200, 'easeInBack');
$('#custom-bg').fadeIn(100);
$('#content').fadeIn(600, function(){
$('.heavy h3 span').animate({top: '0px'});
});
$('#keys').animate({bottom: '20px'},300, 'easeInOutElastic');
}, 800);
$(document).bind(wtf);
};
//NUMBERS & STUFF
function relationshipCount() {
var visitTime = $('#visit_time').val();
var relationshipTime = $('#relationship_time').val();
var nextDate = new Date(visitTime+':00:00');
var totalTime = new Date(relationshipTime);
$("#visit").countdown({
date: nextDate, //Counting down to a date
offset: 1,
hoursOnly: true,
onChange: function(e,settings) {
},
onComplete: function( event ) {
$(this).html('Right now');
},
leadingZero: true
});
$("#relationship").countdown({
date: totalTime, //Counting up to a date
offset: 1,
htmlTemplate: "%{o} %{d}",
hoursOnly: false,
onChange: function(e,settings) {
},
onComplete: function( event ) {
$(this).html('this should never complete');
},
leadingZero: true,
direction: 'up'
});
};
function bubbles(){
$('#aggregator').fadeIn(200);
comicScroll();
$('#bubble1').animate({
left: '50%'
}, 1000, 'easeInBack');
$('#bubble2').animate({
top: '50%'
}, 1000, 'easeInBack');
$('#bubble3').animate({
bottom: '50%'
}, 1000, 'easeInBack');
$('#bubble4').animate({
bottom: '50%'
}, 1000, 'easeInBack');
$('#bubble5').animate({
right: '50%'
}, 1000, 'easeInBack');
$('#bubble6').animate({
top: '50%'
}, 1000, 'easeInBack', function() {
$('#aggregator-close').animate({
top: '70px'
}, 500, 'easeInOutElastic');
});
$('#reddit').animate({
bottom: '50%'
}, 1000, 'easeInBack');
relationshipCount();
};
//the feeling is requested and loaded via AJAX
function cycleFeelings() {
//grab the next post link and replace default action with ajax load
$('#post-nav a').stop().live('click', function(e){
e.preventDefault();
//remove the current feeling from the view
$('.heavy h1').animate({
left: '-150%'
},200, 'easeInBack');
$('.heavy h2').animate({
right: '-150%'
},200, 'easeInBack');
var link = $(this).attr('href');
$('#custom-bg').fadeOut(100);
$('#content').fadeOut(600, loadContent);
//bring in the loading modal
$('#load').remove();
$('body').append('<div id="load"><span><h4>Loading</h4><h5>feelings...</h5></span></div>').fadeIn(100);
$('#load').animate({
top: '50%'
}, 500, 'easeInOutElastic').fadeIn(400);
//load up the feeling div with the new feeling content
function loadContent() {
$('#content').load(link+' .heavy','',showNewContent())
}
//animate in the newly loaded feeling
function showNewContent() {
setTimeout(function() {$('#content').fadeIn(600,hideLoader());
resizeFeeling();
$('.heavy h1').animate({
left: '0%'
},200, 'easeOutSine');
$('.heavy h2').animate({
right: '0%'
},200, 'easeOutSine', function() {
// fade-in bg if there
$('#custom-bg').fadeIn(500);
//slide-down date
setTimeout(function() {
$('.heavy h3 span').animate({
top: '0px'
},200, 'easeOutSine');
}, 500);
});
}, 1000);
}
//function to hide the loading modal
function hideLoader() {
$('#load').animate({
top: '-150%'
}, 200, 'easeInBack').fadeOut(200);
}
return false;
}).stop();
};
//random feeling is requested and loaded via AJAX
//TODO: merge with cycleFeelings() to remove redundancy in ajax request function
function randomizeFeelings(){
//remove the current feeling from the view
$('.heavy h1').animate({
left: '-150%'
},200, 'easeInBack');
$('.heavy h2').animate({
right: '-150%'
},200, 'easeInBack');
var toLoad = "/random-feeling/?cachebuster=" + Math.floor(Math.random()*10001);
$('#custom-bg').fadeOut(100);
$('#content').fadeOut(600, loadContent);
//bring in the loading modal
$('#load').remove();
$('body').append('<div id="load"><span><h4>Loading</h4><h5>feelings...</h5></span></div>').fadeIn(100);
$('#load').animate({
top: '50%'
}, 500, 'easeInOutElastic').fadeIn(400);
//load up the random feeling div with the new feeling content
function loadContent() {
$('#content').load(toLoad,'',showNewContent())
}
//animate in the newly loaded random feeling
function showNewContent() {
setTimeout(function() {$('#content').fadeIn(600,hideLoader());
resizeFeeling();
$('.heavy h1').animate({
left: '0%'
},200, 'easeOutSine');
$('.heavy h2').animate({
right: '0%'
},200, 'easeOutSine', function() {
// Animation complete.
$('#custom-bg').fadeIn(500);
//slide-down date
setTimeout(function() {
$('.heavy h3 span').animate({
top: '0px'
},200, 'easeOutSine');
}, 500);
});
}, 1000);
}
//function to hide the loading modal
function hideLoader() {
$('#load').animate({
top: '-150%'
}, 200, 'easeInBack').fadeOut(200);
}
return false;
};
//future option to have a physical button run the random feeling function
$('.feelings').click(randomizeFeelings);
//bind relationship aggregator to the click of the logo
$('#logo a').click(relationshipAggregator);
//close the aggregator
$('#aggregator-close a').click(closeAggregator);
/* --------------------------
RAGE COMIC MODAL
--------------------------
TODO: add/remove the div so it doesn't have to be hard-coded in header
*/
$('#reddit a').click(rageComics);
//bringing in the reddit rage comics modal
function rageComics() {
//unbinding the key nav for the feelings
$('#ragebox').fadeIn(200);
//binding the new key nav for the comics
$(document).bind(wtf2);
//initializing the first rage comic from reddit
nextRage();
};
function closeRage() {
//reset the count so that the first rage comic is loaded on next opening of the reddit modal
i = -1;
//unbind the key nav for the comics
$(document).unbind(wtf2);
//fadeout the current rage comic so it's not shown on next opening of the reddit modal
$('.rage-wrap').fadeOut(400);
//fadout the reddit rage comic modal completely
$('#ragebox').fadeOut(200);
//rebind the key nav for the feelings
}
//binding for rage comics key navigation
var pressedKeys2 = {};
var wtf2 = {
'keydown': function (e) {
if (pressedKeys2[e.which])
return;
pressedKeys2[e.which] = true;
var keyCode = e.keyCode || e.which,
key = {left: 37, right: 39};
switch (keyCode) {
case key.left:
prevRage();
break;
case key.right:
nextRage();
break;
}
},
'keyup': function (e) {
delete pressedKeys2[e.which];
var keyCode = e.keyCode || e.which,
key = {left: 37, right: 39};
switch (keyCode) {
case key.left:
//stuff
break;
case key.right:
//stuff
break;
}
}
};
/* --------------------------
REDDIT JSON REQUEST
--------------------------
TODO: get the image url even if url is to imgur page
*/
//set the count
var i = -1;
//parse the json data
function rage(data) {
var rageURL = data['data']['children'][i]['data']['url']; //the url
var rageTitle = data['data']['children'][i]['data']['title']; //the title of the rage comic
//the error variable
var rageErr = '<div><h5>Whoops!</h5><h6>'+rageTitle+'</h6><a href="'+rageURL+'" target="_blank">try again in a new tab</a></div>';
//append the image to the modal window
$('#comic .rage-wrap').html('<img src="'+rageURL+'" />');
//if the image loads, fade it in
$('img').load(function() {
$('.rage-wrap').fadeIn(400); comicScroll();
});
//if the image fails to load, show the error message of the link & title
$('img').error(function() {
$('#comic').removeClass('comic-loader');
$('.rage-wrap').html(rageErr).fadeIn(400);
});
};
//JSON request of the next rage comic
function nextRage() {
if (i>=-1) {
//increase the count by 1
i++;
//fadeout the current comic
$('.rage-wrap').fadeOut(400);
$('#comic').addClass('comic-loader');
$.ajax({
type: "GET",
url: "http://www.reddit.com/r/fffffffuuuuuuuuuuuu/.json",
dataType: "jsonp",
jsonp: "jsonp",
cache: true,
success: rage //run the data^
});
}
};
function prevRage() {
if (i>0) {
//decrease the count by 1
i--;
//fadeout the current comic
$('#comic').addClass('comic-loader');
$('.rage-wrap').fadeOut(400);
$.ajax({
type: "GET",
url: "http://www.reddit.com/r/fffffffuuuuuuuuuuuu/.json",
dataType: "jsonp",
jsonp: "jsonp",
cache: true,
success: rage //run the data^
});
}
};
//binding the previous rage comic button
$('.prev-rage a').click(prevRage);
//binding the next rage comic button
$('.next-rage a').click(nextRage);
//bind closing the modal to the close button
$('#closerage').click(closeRage);
/* --------------------------
LOGO & LOVE HOVER STATES
--------------------------
*/
function hoverStates() {
//Main Logo
$('#logo').hover( function () {
$(this).stop().animate({opacity : 1}, 100);
}, function () {
$(this).stop().animate({opacity : .6}, 100);
});
//Love Icon (fill up)
$('#love a').hover( function () {
$(this).find('span').stop().animate({height:'0'},400, 'easeInSine');
}, function () {
$(this).find('span').stop().animate({height:'44px'},400, 'easeOutSine');
});
//Aggregator Close
$('#aggregator-close').hover( function () {
$(this).stop().animate({opacity : 1}, 100);
}, function () {
$(this).stop().animate({opacity : .6}, 100);
});
};
// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function(){
log.history = log.history || []; // store logs to an array for reference
log.history.push(arguments);
if(this.console) {
arguments.callee = arguments.callee.caller;
var newarr = [].slice.call(arguments);
(typeof console.log === 'object' ? log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr));
}
};
// make it safe to use console.log always
(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,timeStamp,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try
{console.log();return window.console;}catch(err){return window.console={};}})());
(function($) {
$.fn.prettynumber = function(options) {
var opts = $.extend({}, $.fn.prettynumber.defaults, options);
return this.each(function() {
$this = $(this);
var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
var str = $this.html();
$this.html($this.html().toString().replace(new RegExp("(^\\d{"+($this.html().toString().length%3||-1)+"})(?=\\d{3})"),"1ドル"+o.delimiter).replace(/(\d{3})(?=\d)/g,"1ドル"+o.delimiter));
});
};
$.fn.prettynumber.defaults = {
delimiter : ','
};
})(jQuery);
-
\$\begingroup\$ This would be much easier to review if it was broken down into bite-sized chunks. Just put an important part of the code here and link to the rest. Or make multiple questions with different parts of the code in it. Hopefully that will help you get some great answers \$\endgroup\$James Khoury– James Khoury2011年12月04日 23:47:52 +00:00Commented Dec 4, 2011 at 23:47
2 Answers 2
You should always cache your selectors, even if they're used only once.
For example: var $visit = $("#visit");
etc.
-
\$\begingroup\$ so for example, just like in the first example, which has:
var $quote = $(".feeling");
I should do the same thing inside the rest of my functions? \$\endgroup\$ndimatteo– ndimatteo2011年10月27日 16:39:34 +00:00Commented Oct 27, 2011 at 16:39 -
\$\begingroup\$ Yes, for example, with a quick glance I see you're using $("#heavyBoots h2") seven times. Everytime jQuery has to scan your whole DOM to find that specific selector. If you cache it, that process happens only once. It can give a pretty good performance boost, especially in complex/long DOMs. \$\endgroup\$vmasto– vmasto2011年10月27日 20:58:06 +00:00Commented Oct 27, 2011 at 20:58
-
1\$\begingroup\$ Why must he cache it even if they're used only once? \$\endgroup\$Some Guy– Some Guy2011年11月29日 13:24:41 +00:00Commented Nov 29, 2011 at 13:24
-
\$\begingroup\$ why prefix it with
$
though? I don't get why people do that.. I imagine it's just an indicator that it's a jQuery object. But I'm not sure on that. \$\endgroup\$Yes Barry– Yes Barry2011年12月05日 05:39:31 +00:00Commented Dec 5, 2011 at 5:39 -
\$\begingroup\$ @mmmshuddup That's pretty much why. It's a convention that works for me. \$\endgroup\$kojiro– kojiro2011年12月05日 15:16:54 +00:00Commented Dec 5, 2011 at 15:16
I looked at just the first part of your welcome()
function:
Firstly You have multiple $('#heavyBoots p').append(
type calls, If you need to change it you will have multiple places to alter. I put the greeting /comment in a variable and +=
(for .append()
) or =
(for .html()
). This is cleaner IMHO.
Also I'd have to ask where you put your else if tool. You had multiple "if" statements that can be combined into one else if. This means when it finds one it doesn't have to evaluate any more of them and it has the added benefit of only needing one test.
There was a redundant default:
case in your switch which seemed to append nothing (""
)to the page.
function welcome() {
//Get the time of day
var currentTime = new Date().getHours();
var greeting = "";
var comment = "";
if (currentTime < 0) {
greeting = "Current Time is Negative. The World doesn't exist yet.";
}
else if (currentTime < 5) {
//late
greeting = "Hello my restless insomniac,";
}
else if (currentTime < 12) {
//morning
greeting = "Yawnnnn; good morning baby,";
}
else if (currentTime < 16) {
//afternoon
greeting = "Whatcha doin' dear?,";
}
else if (currentTime < 22) {
//evening
greeting = "Hello there,";
}
else if (currentTime <= 24) {
//late
greeting = "Hey, isn't it your bedtime?";
}
else
{
greeting = "The World has ended or someone added more hours in the day.";
}
//Get the Day
var day = new Date().getDay();
switch (day) {
case 0:
//Sunday
comment = "It's a lazy Sunday.";
break;
case 1:
//Monday
greeting = "Fuck Mondays.";
break;
case 5:
//Friday
comment = "Also, it's Friday!";
break;
}
$('#heavyBoots p').append(comment);
$('#heavyBoots h2').append(greeting);