579 lines
16 KiB
JavaScript
Executable File
579 lines
16 KiB
JavaScript
Executable File
/*! sidr - v2.2.1 - 2016-02-17
|
|
* http://www.berriart.com/sidr/
|
|
* Copyright (c) 2013-2016 Alberto Varela; Licensed MIT */
|
|
|
|
(function () {
|
|
'use strict';
|
|
|
|
var babelHelpers = {};
|
|
|
|
babelHelpers.classCallCheck = function (instance, Constructor) {
|
|
if (!(instance instanceof Constructor)) {
|
|
throw new TypeError("Cannot call a class as a function");
|
|
}
|
|
};
|
|
|
|
babelHelpers.createClass = function () {
|
|
function defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
if ("value" in descriptor) descriptor.writable = true;
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
|
|
return function (Constructor, protoProps, staticProps) {
|
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
if (staticProps) defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
};
|
|
}();
|
|
|
|
babelHelpers;
|
|
|
|
var sidrStatus = {
|
|
moving: false,
|
|
opened: false
|
|
};
|
|
|
|
var helper = {
|
|
// Check for valids urls
|
|
// From : http://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-an-url
|
|
|
|
isUrl: function isUrl(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 true;
|
|
} else {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
|
|
// Add sidr prefixes
|
|
addPrefixes: function addPrefixes($element) {
|
|
this.addPrefix($element, 'id');
|
|
this.addPrefix($element, 'class');
|
|
$element.removeAttr('style');
|
|
},
|
|
addPrefix: function addPrefix($element, attribute) {
|
|
var toReplace = $element.attr(attribute);
|
|
|
|
if (typeof toReplace === 'string' && toReplace !== '' && toReplace !== 'sidr-inner') {
|
|
$element.attr(attribute, toReplace.replace(/([A-Za-z0-9_.\-]+)/g, 'sidr-' + attribute + '-$1'));
|
|
}
|
|
},
|
|
|
|
|
|
// Check if transitions is supported
|
|
transitions: function () {
|
|
var body = document.body || document.documentElement,
|
|
style = body.style,
|
|
supported = false,
|
|
property = 'transition';
|
|
|
|
if (property in style) {
|
|
supported = true;
|
|
} else {
|
|
(function () {
|
|
var prefixes = ['moz', 'webkit', 'o', 'ms'],
|
|
prefix = undefined,
|
|
i = undefined;
|
|
|
|
property = property.charAt(0).toUpperCase() + property.substr(1);
|
|
supported = function () {
|
|
for (i = 0; i < prefixes.length; i++) {
|
|
prefix = prefixes[i];
|
|
if (prefix + property in style) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}();
|
|
property = supported ? '-' + prefix.toLowerCase() + '-' + property.toLowerCase() : null;
|
|
})();
|
|
}
|
|
|
|
return {
|
|
supported: supported,
|
|
property: property
|
|
};
|
|
}()
|
|
};
|
|
|
|
var $$2 = jQuery;
|
|
|
|
var bodyAnimationClass = 'sidr-animating';
|
|
var openAction = 'open';
|
|
var closeAction = 'close';
|
|
var transitionEndEvent = 'webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend';
|
|
var Menu = function () {
|
|
function Menu(name) {
|
|
babelHelpers.classCallCheck(this, Menu);
|
|
|
|
this.name = name;
|
|
this.item = $$2('#' + name);
|
|
this.openClass = name === 'sidr' ? 'sidr-open' : 'sidr-open ' + name + '-open';
|
|
this.menuWidth = this.item.outerWidth(true);
|
|
this.speed = this.item.data('speed');
|
|
this.side = this.item.data('side');
|
|
this.displace = this.item.data('displace');
|
|
this.timing = this.item.data('timing');
|
|
this.method = this.item.data('method');
|
|
this.onOpenCallback = this.item.data('onOpen');
|
|
this.onCloseCallback = this.item.data('onClose');
|
|
this.onOpenEndCallback = this.item.data('onOpenEnd');
|
|
this.onCloseEndCallback = this.item.data('onCloseEnd');
|
|
this.body = $$2(this.item.data('body'));
|
|
}
|
|
|
|
babelHelpers.createClass(Menu, [{
|
|
key: 'getAnimation',
|
|
value: function getAnimation(action, element) {
|
|
var animation = {},
|
|
prop = this.side;
|
|
|
|
if (action === 'open' && element === 'body') {
|
|
animation[prop] = this.menuWidth + 'px';
|
|
} else if (action === 'close' && element === 'menu') {
|
|
animation[prop] = '-' + this.menuWidth + 'px';
|
|
} else {
|
|
animation[prop] = 0;
|
|
}
|
|
|
|
return animation;
|
|
}
|
|
}, {
|
|
key: 'prepareBody',
|
|
value: function prepareBody(action) {
|
|
var prop = action === 'open' ? 'hidden' : '';
|
|
|
|
// Prepare page if container is body
|
|
if (this.body.is('body')) {
|
|
var $html = $$2('html'),
|
|
scrollTop = $html.scrollTop();
|
|
|
|
$html.css('overflow-x', prop).scrollTop(scrollTop);
|
|
}
|
|
}
|
|
}, {
|
|
key: 'openBody',
|
|
value: function openBody() {
|
|
if (this.displace) {
|
|
var transitions = helper.transitions,
|
|
$body = this.body;
|
|
|
|
if (transitions.supported) {
|
|
$body.css(transitions.property, this.side + ' ' + this.speed / 1000 + 's ' + this.timing).css(this.side, 0).css({
|
|
width: $body.width(),
|
|
position: 'absolute'
|
|
});
|
|
$body.css(this.side, this.menuWidth + 'px');
|
|
} else {
|
|
var bodyAnimation = this.getAnimation(openAction, 'body');
|
|
|
|
$body.css({
|
|
width: $body.width(),
|
|
position: 'absolute'
|
|
}).animate(bodyAnimation, {
|
|
queue: false,
|
|
duration: this.speed
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
key: 'onCloseBody',
|
|
value: function onCloseBody() {
|
|
var transitions = helper.transitions,
|
|
resetStyles = {
|
|
width: '',
|
|
position: '',
|
|
right: '',
|
|
left: ''
|
|
};
|
|
|
|
if (transitions.supported) {
|
|
resetStyles[transitions.property] = '';
|
|
}
|
|
|
|
this.body.css(resetStyles).unbind(transitionEndEvent);
|
|
}
|
|
}, {
|
|
key: 'closeBody',
|
|
value: function closeBody() {
|
|
var _this = this;
|
|
|
|
if (this.displace) {
|
|
if (helper.transitions.supported) {
|
|
this.body.css(this.side, 0).one(transitionEndEvent, function () {
|
|
_this.onCloseBody();
|
|
});
|
|
} else {
|
|
var bodyAnimation = this.getAnimation(closeAction, 'body');
|
|
|
|
this.body.animate(bodyAnimation, {
|
|
queue: false,
|
|
duration: this.speed,
|
|
complete: function complete() {
|
|
_this.onCloseBody();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
key: 'moveBody',
|
|
value: function moveBody(action) {
|
|
if (action === openAction) {
|
|
this.openBody();
|
|
} else {
|
|
this.closeBody();
|
|
}
|
|
}
|
|
}, {
|
|
key: 'onOpenMenu',
|
|
value: function onOpenMenu(callback) {
|
|
var name = this.name;
|
|
|
|
sidrStatus.moving = false;
|
|
sidrStatus.opened = name;
|
|
|
|
this.item.unbind(transitionEndEvent);
|
|
|
|
this.body.removeClass(bodyAnimationClass).addClass(this.openClass);
|
|
|
|
this.onOpenEndCallback();
|
|
|
|
if (typeof callback === 'function') {
|
|
callback(name);
|
|
}
|
|
}
|
|
}, {
|
|
key: 'openMenu',
|
|
value: function openMenu(callback) {
|
|
var _this2 = this;
|
|
|
|
var $item = this.item;
|
|
|
|
if (helper.transitions.supported) {
|
|
$item.css(this.side, 0).one(transitionEndEvent, function () {
|
|
_this2.onOpenMenu(callback);
|
|
});
|
|
} else {
|
|
var menuAnimation = this.getAnimation(openAction, 'menu');
|
|
|
|
$item.css('display', 'block').animate(menuAnimation, {
|
|
queue: false,
|
|
duration: this.speed,
|
|
complete: function complete() {
|
|
_this2.onOpenMenu(callback);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}, {
|
|
key: 'onCloseMenu',
|
|
value: function onCloseMenu(callback) {
|
|
this.item.css({
|
|
left: '',
|
|
right: ''
|
|
}).unbind(transitionEndEvent);
|
|
$$2('html').css('overflow-x', '');
|
|
|
|
sidrStatus.moving = false;
|
|
sidrStatus.opened = false;
|
|
|
|
this.body.removeClass(bodyAnimationClass).removeClass(this.openClass);
|
|
|
|
this.onCloseEndCallback();
|
|
|
|
// Callback
|
|
if (typeof callback === 'function') {
|
|
callback(name);
|
|
}
|
|
}
|
|
}, {
|
|
key: 'closeMenu',
|
|
value: function closeMenu(callback) {
|
|
var _this3 = this;
|
|
|
|
var item = this.item;
|
|
|
|
if (helper.transitions.supported) {
|
|
item.css(this.side, '').one(transitionEndEvent, function () {
|
|
_this3.onCloseMenu(callback);
|
|
});
|
|
} else {
|
|
var menuAnimation = this.getAnimation(closeAction, 'menu');
|
|
|
|
item.animate(menuAnimation, {
|
|
queue: false,
|
|
duration: this.speed,
|
|
complete: function complete() {
|
|
_this3.onCloseMenu();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}, {
|
|
key: 'moveMenu',
|
|
value: function moveMenu(action, callback) {
|
|
this.body.addClass(bodyAnimationClass);
|
|
|
|
if (action === openAction) {
|
|
this.openMenu(callback);
|
|
} else {
|
|
this.closeMenu(callback);
|
|
}
|
|
}
|
|
}, {
|
|
key: 'move',
|
|
value: function move(action, callback) {
|
|
// Lock sidr
|
|
sidrStatus.moving = true;
|
|
|
|
this.prepareBody(action);
|
|
this.moveBody(action);
|
|
this.moveMenu(action, callback);
|
|
}
|
|
}, {
|
|
key: 'open',
|
|
value: function open(callback) {
|
|
var _this4 = this;
|
|
|
|
// Check if is already opened or moving
|
|
if (sidrStatus.opened === this.name || sidrStatus.moving) {
|
|
return;
|
|
}
|
|
|
|
// If another menu opened close first
|
|
if (sidrStatus.opened !== false) {
|
|
var alreadyOpenedMenu = new Menu(sidrStatus.opened);
|
|
|
|
alreadyOpenedMenu.close(function () {
|
|
_this4.open(callback);
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
this.move('open', callback);
|
|
|
|
// onOpen callback
|
|
this.onOpenCallback();
|
|
}
|
|
}, {
|
|
key: 'close',
|
|
value: function close(callback) {
|
|
// Check if is already closed or moving
|
|
if (sidrStatus.opened !== this.name || sidrStatus.moving) {
|
|
return;
|
|
}
|
|
|
|
this.move('close', callback);
|
|
|
|
// onClose callback
|
|
this.onCloseCallback();
|
|
}
|
|
}, {
|
|
key: 'toggle',
|
|
value: function toggle(callback) {
|
|
if (sidrStatus.opened === this.name) {
|
|
this.close(callback);
|
|
} else {
|
|
this.open(callback);
|
|
}
|
|
}
|
|
}]);
|
|
return Menu;
|
|
}();
|
|
|
|
var $$1 = jQuery;
|
|
|
|
function execute(action, name, callback) {
|
|
var sidr = new Menu(name);
|
|
|
|
switch (action) {
|
|
case 'open':
|
|
sidr.open(callback);
|
|
break;
|
|
case 'close':
|
|
sidr.close(callback);
|
|
break;
|
|
case 'toggle':
|
|
sidr.toggle(callback);
|
|
break;
|
|
default:
|
|
$$1.error('Method ' + action + ' does not exist on jQuery.sidr');
|
|
break;
|
|
}
|
|
}
|
|
|
|
var i;
|
|
var $ = jQuery;
|
|
var publicMethods = ['open', 'close', 'toggle'];
|
|
var methodName;
|
|
var methods = {};
|
|
var getMethod = function getMethod(methodName) {
|
|
return function (name, callback) {
|
|
// Check arguments
|
|
if (typeof name === 'function') {
|
|
callback = name;
|
|
name = 'sidr';
|
|
} else if (!name) {
|
|
name = 'sidr';
|
|
}
|
|
|
|
execute(methodName, name, callback);
|
|
};
|
|
};
|
|
for (i = 0; i < publicMethods.length; i++) {
|
|
methodName = publicMethods[i];
|
|
methods[methodName] = getMethod(methodName);
|
|
}
|
|
|
|
function sidr(method) {
|
|
if (method === 'status') {
|
|
return sidrStatus;
|
|
} else 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');
|
|
}
|
|
}
|
|
|
|
var $$3 = jQuery;
|
|
|
|
function fillContent($sideMenu, settings) {
|
|
// The menu content
|
|
if (typeof settings.source === 'function') {
|
|
var newContent = settings.source(name);
|
|
|
|
$sideMenu.html(newContent);
|
|
} else if (typeof settings.source === 'string' && helper.isUrl(settings.source)) {
|
|
$$3.get(settings.source, function (data) {
|
|
$sideMenu.html(data);
|
|
});
|
|
} else if (typeof settings.source === 'string') {
|
|
var htmlContent = '',
|
|
selectors = settings.source.split(',');
|
|
|
|
$$3.each(selectors, function (index, element) {
|
|
htmlContent += '<div class="sidr-inner">' + $$3(element).html() + '</div>';
|
|
});
|
|
|
|
// Renaming ids and classes
|
|
if (settings.renaming) {
|
|
var $htmlContent = $$3('<div />').html(htmlContent);
|
|
|
|
$htmlContent.find('*').each(function (index, element) {
|
|
var $element = $$3(element);
|
|
|
|
helper.addPrefixes($element);
|
|
});
|
|
htmlContent = $htmlContent.html();
|
|
}
|
|
|
|
$sideMenu.html(htmlContent);
|
|
} else if (settings.source !== null) {
|
|
$$3.error('Invalid Sidr Source');
|
|
}
|
|
|
|
return $sideMenu;
|
|
}
|
|
|
|
function fnSidr(options) {
|
|
var transitions = helper.transitions,
|
|
settings = $$3.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
|
|
timing: 'ease', // Timing function for CSS transitions
|
|
method: 'toggle', // The method to call when element is clicked
|
|
bind: 'touchstart click', // The event(s) to trigger the menu
|
|
onOpen: function onOpen() {},
|
|
// Callback when sidr start opening
|
|
onClose: function onClose() {},
|
|
// Callback when sidr start closing
|
|
onOpenEnd: function onOpenEnd() {},
|
|
// Callback when sidr end opening
|
|
onCloseEnd: function onCloseEnd() {} // Callback when sidr end closing
|
|
|
|
}, options),
|
|
name = settings.name,
|
|
$sideMenu = $$3('#' + name);
|
|
|
|
// If the side menu do not exist create it
|
|
if ($sideMenu.length === 0) {
|
|
$sideMenu = $$3('<div />').attr('id', name).appendTo($$3('body'));
|
|
}
|
|
|
|
// Add transition to menu if are supported
|
|
if (transitions.supported) {
|
|
$sideMenu.css(transitions.property, settings.side + ' ' + settings.speed / 1000 + 's ' + settings.timing);
|
|
}
|
|
|
|
// Adding styles and options
|
|
$sideMenu.addClass('sidr').addClass(settings.side).data({
|
|
speed: settings.speed,
|
|
side: settings.side,
|
|
body: settings.body,
|
|
displace: settings.displace,
|
|
timing: settings.timing,
|
|
method: settings.method,
|
|
onOpen: settings.onOpen,
|
|
onClose: settings.onClose,
|
|
onOpenEnd: settings.onOpenEnd,
|
|
onCloseEnd: settings.onCloseEnd
|
|
});
|
|
|
|
$sideMenu = fillContent($sideMenu, settings);
|
|
|
|
return this.each(function () {
|
|
var $this = $$3(this),
|
|
data = $this.data('sidr'),
|
|
flag = false;
|
|
|
|
// If the plugin hasn't been initialized yet
|
|
if (!data) {
|
|
sidrStatus.moving = false;
|
|
sidrStatus.opened = false;
|
|
|
|
$this.data('sidr', name);
|
|
|
|
$this.bind(settings.bind, function (event) {
|
|
event.preventDefault();
|
|
|
|
if (!flag) {
|
|
flag = true;
|
|
sidr(settings.method, name);
|
|
|
|
setTimeout(function () {
|
|
flag = false;
|
|
}, 100);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
jQuery.sidr = sidr;
|
|
jQuery.fn.sidr = fnSidr;
|
|
|
|
}()); |