Created
February 5, 2015 20:37
-
-
Save niedermyer/de52531b898152610781 to your computer and use it in GitHub Desktop.
Modified JQuery Sidr Plugin for use with Turbolinks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Sidr | |
* https://github.com/artberri/sidr | |
* | |
* Modified for use with Rails 4/Turbolinks | |
* by West Arete on February 5, 2015 | |
* | |
* Copyright (c) 2013 Alberto Varela | |
* Licensed under the MIT license. | |
*/ | |
;(function( $ ){ | |
var sidrMoving = false, | |
sidrOpened = false; | |
// Private methods | |
var privateMethods = { | |
// Check for valids urls | |
// From : http://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-an-url | |
isUrl: function (str) { | |
var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol | |
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name | |
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address | |
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path | |
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string | |
'(\\#[-a-z\\d_]*)?$','i'); // fragment locator | |
if(!pattern.test(str)) { | |
return false; | |
} else { | |
return true; | |
} | |
}, | |
// Loads the content into the menu bar | |
loadContent: function($menu, content) { | |
$menu.html(content); | |
}, | |
// Add sidr prefixes | |
addPrefix: function($element) { | |
var elementId = $element.attr('id'), | |
elementClass = $element.attr('class'); | |
if(typeof elementId === 'string' && '' !== elementId) { | |
$element.attr('id', elementId.replace(/([A-Za-z0-9_.\-]+)/g, 'sidr-id-$1')); | |
} | |
if(typeof elementClass === 'string' && '' !== elementClass && 'sidr-inner' !== elementClass) { | |
$element.attr('class', elementClass.replace(/([A-Za-z0-9_.\-]+)/g, 'sidr-class-$1')); | |
} | |
$element.removeAttr('style'); | |
}, | |
execute: function(action, name, callback) { | |
// Check arguments | |
if(typeof name === 'function') { | |
callback = name; | |
name = 'sidr'; | |
} | |
else if(!name) { | |
name = 'sidr'; | |
} | |
// Declaring | |
var $menu = $('#' + name), | |
$body = $($menu.data('body')), | |
$html = $('html'), | |
menuWidth = $menu.outerWidth(true), | |
speed = $menu.data('speed'), | |
side = $menu.data('side'), | |
displace = $menu.data('displace'), | |
onOpen = $menu.data('onOpen'), | |
onClose = $menu.data('onClose'), | |
bodyAnimation, | |
menuAnimation, | |
scrollTop, | |
bodyClass = (name === 'sidr' ? 'sidr-open' : 'sidr-open ' + name + '-open'); | |
// Open Sidr | |
if('open' === action || ('toggle' === action && !$menu.is(':visible'))) { | |
// Check if we can open it | |
if( $menu.is(':visible') || sidrMoving ) { | |
return; | |
} | |
// If another menu is opened, close it first | |
if(sidrOpened !== false) { | |
methods.close(sidrOpened, function() { | |
methods.open(name); | |
}); | |
return; | |
} | |
// Lock sidr | |
sidrMoving = true; | |
// Left or right? | |
if(side === 'left') { | |
bodyAnimation = {left: menuWidth + 'px'}; | |
menuAnimation = {left: '0px'}; | |
} | |
else { | |
bodyAnimation = {right: menuWidth + 'px'}; | |
menuAnimation = {right: '0px'}; | |
} | |
// Prepare page if container is body & should be displaced | |
if($body.is('body') && displace){ | |
scrollTop = $html.scrollTop(); | |
$html.css('overflow-x', 'hidden').scrollTop(scrollTop); | |
} | |
// Open menu | |
if(displace){ | |
$body.addClass('sidr-animating').css({ | |
width: $body.width(), | |
position: 'absolute' | |
}).animate(bodyAnimation, speed, function() { | |
$(this).addClass(bodyClass); | |
}); | |
} | |
else { | |
setTimeout(function() { | |
$(this).addClass(bodyClass); | |
}, speed); | |
} | |
$menu.css('display', 'block').animate(menuAnimation, speed, function() { | |
sidrMoving = false; | |
sidrOpened = name; | |
// Callback | |
if(typeof callback === 'function') { | |
callback(name); | |
} | |
$body.removeClass('sidr-animating'); | |
}); | |
// onOpen callback | |
onOpen(); | |
} | |
// Close Sidr | |
else { | |
// Check if we can close it | |
if( !$menu.is(':visible') || sidrMoving ) { | |
return; | |
} | |
// Lock sidr | |
sidrMoving = true; | |
// Right or left menu? | |
if(side === 'left') { | |
bodyAnimation = {left: 0}; | |
menuAnimation = {left: '-' + menuWidth + 'px'}; | |
} | |
else { | |
bodyAnimation = {right: 0}; | |
menuAnimation = {right: '-' + menuWidth + 'px'}; | |
} | |
// Close menu | |
if($body.is('body')){ | |
scrollTop = $html.scrollTop(); | |
$html.removeAttr('style').scrollTop(scrollTop); | |
} | |
$body.addClass('sidr-animating').animate(bodyAnimation, speed).removeClass(bodyClass); | |
$menu.animate(menuAnimation, speed, function() { | |
$menu.removeAttr('style').hide(); | |
$body.removeAttr('style'); | |
$('html').removeAttr('style'); | |
sidrMoving = false; | |
sidrOpened = false; | |
// Callback | |
if(typeof callback === 'function') { | |
callback(name); | |
} | |
$body.removeClass('sidr-animating'); | |
}); | |
// onClose callback | |
onClose(); | |
} | |
} | |
}; | |
// Sidr public methods | |
var methods = { | |
open: function(name, callback) { | |
privateMethods.execute('open', name, callback); | |
}, | |
close: function(name, callback) { | |
privateMethods.execute('close', name, callback); | |
}, | |
toggle: function(name, callback) { | |
privateMethods.execute('toggle', name, callback); | |
}, | |
// I made a typo, so I mantain this method to keep backward compatibilty with 1.1.1v and previous | |
toogle: function(name, callback) { | |
privateMethods.execute('toggle', name, callback); | |
} | |
}; | |
$.sidr = function( method ) { | |
if ( methods[method] ) { | |
return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); | |
} | |
else if ( typeof method === 'function' || typeof method === 'string' || ! method ) { | |
return methods.toggle.apply( this, arguments ); | |
} | |
else { | |
$.error( 'Method ' + method + ' does not exist on jQuery.sidr' ); | |
} | |
}; | |
$.fn.sidr = function( options ) { | |
var settings = $.extend( { | |
name : 'sidr', // Name for the 'sidr' | |
speed : 200, // Accepts standard jQuery effects speeds (i.e. fast, normal or milliseconds) | |
side : 'left', // Accepts 'left' or 'right' | |
source : null, // Override the source of the content. | |
renaming : true, // The ids and classes will be prepended with a prefix when loading existent content | |
body : 'body', // Page container selector, | |
displace : true, // Displace the body content or not | |
onOpen : function() {}, // Callback when sidr opened | |
onClose : function() {} // Callback when sidr closed | |
}, options); | |
var name = settings.name, | |
$sideMenu = $('#' + name); | |
// If the side menu do not exist create it | |
if( $sideMenu.length === 0 ) { | |
$sideMenu = $('<div />') | |
.attr('id', name) | |
.appendTo($('body')); | |
} | |
// Adding styles and options | |
$sideMenu | |
.addClass('sidr') | |
.addClass(settings.side) | |
.data({ | |
speed : settings.speed, | |
side : settings.side, | |
body : settings.body, | |
displace : settings.displace, | |
onOpen : settings.onOpen, | |
onClose : settings.onClose | |
}); | |
// The menu content | |
if(typeof settings.source === 'function') { | |
var newContent = settings.source(name); | |
privateMethods.loadContent($sideMenu, newContent); | |
} | |
else if(typeof settings.source === 'string' && privateMethods.isUrl(settings.source)) { | |
$.get(settings.source, function(data) { | |
privateMethods.loadContent($sideMenu, data); | |
}); | |
} | |
else if(typeof settings.source === 'string') { | |
var htmlContent = '', | |
selectors = settings.source.split(','); | |
$.each(selectors, function(index, element) { | |
htmlContent += '<div class="sidr-inner">' + $(element).html() + '</div>'; | |
}); | |
// Renaming ids and classes | |
if(settings.renaming) { | |
var $htmlContent = $('<div />').html(htmlContent); | |
$htmlContent.find('*').each(function(index, element) { | |
var $element = $(element); | |
privateMethods.addPrefix($element); | |
}); | |
htmlContent = $htmlContent.html(); | |
} | |
privateMethods.loadContent($sideMenu, htmlContent); | |
} | |
else if(settings.source !== null) { | |
$.error('Invalid Sidr Source'); | |
} | |
return this.each(function(){ | |
var $this = $(this), | |
data = $this.data('sidr'); | |
// If the plugin hasn't been initialized yet | |
if ( ! data ) { | |
$this.data('sidr', name); | |
if('ontouchstart' in document.documentElement) { | |
$this.bind('touchstart', function(e) { | |
var theEvent = e.originalEvent.touches[0]; | |
this.touched = e.timeStamp; | |
}); | |
$this.bind('touchend', function(e) { | |
var delta = Math.abs(e.timeStamp - this.touched); | |
if(delta < 200) { | |
e.preventDefault(); | |
methods.toggle(name); | |
} | |
}); | |
} | |
else { | |
$('html').removeAttr('style'); | |
sidrMoving = false; | |
sidrOpened = false; | |
$this.on('click', function(e) { | |
e.preventDefault(); | |
methods.toggle(name); | |
}); | |
} | |
} | |
}); | |
}; | |
})( jQuery ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment