Friday, March 30, 2012

scaling wordpress on the cheap

How to handle 10 million hits a day. He claims to handle ~7000 hits per minute. Doesn't necessarily handle spikes though.

Thursday, March 29, 2012

jQuery Trigger custom parameters

So I just found out that you can pass custom parameters to jQuery's trigger(), which greatly simplifies automating UI actions.

Say you're building a really basic carousel:

<ul class="carousel">
  <li><img src="slide1.jpg" /></li>
  <li><img src="slide2.jpg" /></li>
  <li><img src="slide3.jpg" /></li>
</ul>
<button id="next">Next</button>

$.fn.carousel = function(options) {

  //hide all the slides, except the first one
  this.children().hide().first().show()
  
  var self = this
  $(options.next).click(function(e) {
    e.preventDefault()

    //move first slide to end of list and hide it
    self.children().first().appendTo(self).hide()

    //show new first slide
    self.children().first().show()
  })
  
}

$(".carousel").carousel({next: "#next"})

And say you want to make it rotate automatically every 10 seconds.

var animation = setInterval(function() {
  $("#next").trigger("click")
}, 10000)

BUT, you want to make it stop once a user clicks the button to go next. What now?

Custom parameters

You basically just want to differentiate between a real user clicking, and the click event that is fired programmatically from the setInterval. We can use custom parameters to do this fairly elegantly:

var animation = setInterval(function() {
  $("#next").trigger("click", [true])
}, 10000)

$.fn.carousel = function(options) {

  //hide all the slides, except the first one
  this.children().hide().first().show()
  
  var self = this
  $(options.next).click(function(e, continueAnimation) {

    if (!continueAnimation) clearInterval(animation)

    e.preventDefault()

    //move first slide to end of list and hide it
    self.children().first().appendTo(self).hide()

    //show new first slide
    self.children().first().show()
  })
  
}

$(".carousel").carousel({next: "#next"})

A regular click event only passes the event object as a parameter to the callback function, so the continueAnimation variable is undefined in that case. When triggering the event programmatically, we can pass the value true and run code conditionally based on that.

So that's it.

Monday, March 5, 2012

Using jQuery custom events to organize code better

One problem when creating complex user interfaces comes when you have lots of plugins interacting asynchronously. For example, you might have a modal popup that ajaxes an image carousel in. And maybe you use the same modal code to play videos (probably using HTML5 with Flash fallback.) Or maybe you're using collapsible side panels and cool eye-catching widgets like Isotope side-by-side.

The naive way to structure code like that would typically go along these lines:

//let's suppose we're loading a carousel
$("#carousel").load("/carousel/", function() {
  
  //but we have an Isotope panel
  //on the page and we need to hide it
  hideIsotopePanel()

  //and we also need to hide modal popups
  killModals()

  //and make sure videos/audio
  //aren't playing in the background
  killVideos()

  //get the idea?
})

The problem, of course, is that hiding the Isotope panel, killing videos, modal popups and God knows what else are not part of the carousel logic. It just so happens that when including this carousel on the page, you need to de-clutter your page so that your user isn't overwhelmed.

The headache starts when you have to worry about the permutations of what needs to hide when: now there's a carousel on the page. When is it supposed to hide? Where do I put the code for that? What else exists in the page that needs to hide when the carousel loads?

Ideally, we'd like to organize the code for doing all of this showing and hiding in their own modules: Isotope hiding code goes where the rest of the Isotope code is, modal hiding code goes where the rest of modal code is, and so on. But how can we do that?

jQuery custom events

One way is to use jQuery custom events. We could rewrite the carousel loading function above like this:

$("#carousel").load("/carousel/", function() {

  //fire a custom event we just made up
  $(document).trigger("carousel-loaded")

})

This is basically the same thing the browser does behind the scenes when you click on an element, and an event handler magically fires. The difference here is that you can define when the event gets fired, and what it's called.

Now we can go into the Isotope module and define there when it's appropriate to hide the component:

//in the file where we're doing all
//the Isotope heavy-lifting

$(document).on("carousel-loaded", function() {

  hideIsotopePanel()

})

What's the advantage of refactoring code around like that?

The main advantage is that now it's easier to manage orthogonality (i.e. hiding something on one corner case, but forgetting to on another):

$("#isotope").load("/isotope/", function() {

  $(document).trigger("isotope-loaded")

})


$(document).on("carousel-loaded modal-loaded", function() {

  hideIsotopePanel()

})

The snippet above is just an extension of the refactoring idea above. It allows me to fire Isotope-specific events, and ensures the Isotope panel hides when modal popups load (in addition to hiding when the carousel loads). By refactoring all my code to use custom event like this, I can set the groundwork to make other permutations also easy to maintain (e.g. I would be able to go into the code dealing with modals, and, without plowing through thousands of lines of code, I could easily make the modal hide on video load, on carousel load, and so on and so on.)

Github hacked

Oh, the drama.