Skip to content

Instantly share code, notes, and snippets.

@jimsynz
Last active August 29, 2015 14:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jimsynz/8fa41dd9e9ab2c78e9f0 to your computer and use it in GitHub Desktop.
Save jimsynz/8fa41dd9e9ab2c78e9f0 to your computer and use it in GitHub Desktop.
An exercise in refactoring horrible procedural JavaScript. Please don't be this person.
/*
* This is a JS file from a library that our client wanted us to use. It included a dependency on a JS lib called `classie` which is
* used for adding and removing HTML classes to elements. The project already includes jQuery.
*/
(function() {
$(document).ready(function() {
var triggerBttn = $('.trigger-overlay'),
overlay = document.querySelector( 'div.overlay' ),
closeBttn = overlay.querySelector( 'button.overlay-close' );
transEndEventNames = {
'WebkitTransition': 'webkitTransitionEnd',
'MozTransition': 'transitionend',
'OTransition': 'oTransitionEnd',
'msTransition': 'MSTransitionEnd',
'transition': 'transitionend'
},
transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],
support = { transitions : Modernizr.csstransitions };
function toggleOverlay() {
if( classie.has( overlay, 'open' ) ) {
classie.remove( overlay, 'open' );
classie.add( overlay, 'close' );
var onEndTransitionFn = function( ev ) {
if( support.transitions ) {
if( ev.propertyName !== 'visibility' ) return;
this.removeEventListener( transEndEventName, onEndTransitionFn );
}
classie.remove( overlay, 'close' );
};
if( support.transitions ) {
overlay.addEventListener( transEndEventName, onEndTransitionFn );
}
else {
onEndTransitionFn();
}
}
else if( !classie.has( overlay, 'close' ) ) {
classie.add( overlay, 'open' );
}
}
triggerBttn.addEventListener( 'click', toggleOverlay );
closeBttn.addEventListener( 'click', toggleOverlay );
});
})();
# Rewritten as an Overlay object with methods, and a few private methods (hidden within the closure).
# Now, if you want to add behaviour, it's super easy to subclass it, override the methods you need to change
# and call super where necessary.
transitionEndEventName = ->
transEndEventNames =
WebkitTransition: "webkitTransitionEnd"
MozTransition: "transitionend"
OTransition: "oTransitionEnd"
msTransition: "MSTransitionEnd"
transition: "transitionend"
transEndEventNames[Modernizr.prefixed("transition")]
supportsTransitions = ->
Modernizr.csstransitions
onEndTransition = (ev)->
if supportsTransitions()
return if ev.propertyName isnt "visibility"
@overlay.off transitionEndEventName(), onEndTransition
@overlay.removeClass 'close'
class Overlay
constructor: (@overlay)->
closeButton = @overlay.find('button.overlay-close')
closeButton.click((e)=> @toggle e) if closeButton.length > 0
isOpen: ->
@overlay.hasClass 'open'
close: ->
@overlay.removeClass 'open'
@overlay.addClass 'close'
if supportsTransitions()
@overlay.on transitionEndEventName(), => onEndTransition.call(@)
else
onEndTransition.call(@)
open: ->
@overlay.addClass 'open'
toggle: (e)->
if @isOpen()
@close()
else
@open()
$(document).ready ->
overlay = new Overlay $('.overlay')
$('.trigger-overlay').click (e)-> overlay.toggle e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment