/*! sidr - v3.0.0 - 2017-12-10
http://www.berriart.com/sidr/
* Copyright (c) 2013-2017 Alberto Varela; Licensed MIT */
(function () {
'use strict';
var sidrStatus = {
moving: false,
opened: false
};
var store = {};
var store$1 = {
add: function add(key, value) {
store[key] = value;
},
get: function get(key) {
return store[key];
}
};
var getMethod = function getMethod(methodName) {
return function (name, callback) {
// Check arguments
if (typeof name === 'function') {
callback = name;
name = 'sidr';
} else if (!name) {
name = 'sidr';
}
var menu = store$1.get(name);
menu[methodName](callback);
};
};
var methods = {};
var publicMethods = ['open', 'close', 'toggle', 'reload'];
for (var i = 0; i < publicMethods.length; i++) {
var methodName = publicMethods[i];
methods[methodName] = getMethod(methodName);
}
function runner(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 {
console.error('Method ' + method + ' does not exist on sidr');
}
}
var utils = {
// 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;
}
},
extend: function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
},
fetch: function fetch(url, callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
callback(xmlhttp.responseText);
}
};
xmlhttp.open('GET', url, true);
xmlhttp.send();
}
};
function addPrefix(item, attribute) {
var toReplace = item.getAttribute(attribute);
if (typeof toReplace === 'string' && toReplace !== '' && toReplace !== 'sidr-inner') {
item.setAttribute(attribute, toReplace.replace(/([A-Za-z0-9_.-]+)/g, 'sidr-' + attribute + '-$1'));
}
}
function getTransitionPrefix(property, style) {
var prefix = void 0;
var prefixes = ['moz', 'webkit', 'o', 'ms'];
for (var i = 0; i < prefixes.length; i++) {
prefix = prefixes[i];
if (prefix + property in style) {
return prefix;
}
}
return false;
}
var dom = {
id: function id(elementId) {
return document.getElementById(elementId);
},
qs: function qs(selector) {
return document.querySelector(selector);
},
qsa: function qsa(selectors) {
return document.querySelectorAll(selectors);
},
createElement: function createElement(elementId) {
var elem = document.createElement('div');
elem.id = elementId;
document.body.appendChild(elem);
return elem;
},
getHTMLContent: function getHTMLContent(selectors) {
var htmlContent = '';
var items = this.qsa(selectors);
for (var i = 0; i < items.length; i++) {
htmlContent += '
' + items[i].innerHTML + '
';
}
return htmlContent;
},
addPrefixes: function addPrefixes(htmlContent) {
var elem = document.createElement('div');
elem.innerHTML = htmlContent;
var items = elem.querySelectorAll('*');
for (var i = 0; i < items.length; i++) {
addPrefix(items[i], 'id');
addPrefix(items[i], 'class');
items[i].removeAttribute('style');
}
return elem.innerHTML;
},
transitions: function () {
var body = document.body || document.documentElement;
var style = body.style;
var supported = false;
var property = 'transition';
var cssProperty = 'transition';
var event = 'transitionend';
if (property in style) {
supported = true;
} else {
property = property.charAt(0).toUpperCase() + property.substr(1);
var prefix = getTransitionPrefix(property, style);
supported = !!prefix;
cssProperty = supported ? prefix + property : null;
property = supported ? '-' + prefix + '-' + property.toLowerCase() : null;
if (prefix === 'webkit') {
event = 'webkitTransitionEnd';
} else if (prefix === '0') {
event = 'oTransitionEnd';
}
}
return { cssProperty: cssProperty, supported: supported, property: property, event: event };
}()
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var 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;
};
}();
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
function changeClasses(element, action, classes) {
var classesArray = classes.split(' ');
for (var i = 0; i < classesArray.length; i++) {
var newClass = classesArray[i].trim();
element.classList[action](newClass);
}
}
function setProperty(element, prop, value) {
element[prop] = value;
}
function getProperty(element, prop, value) {
return element[prop];
}
var BaseElement = function () {
function BaseElement(element) {
classCallCheck(this, BaseElement);
this.element = element;
}
createClass(BaseElement, [{
key: 'bind',
value: function bind(event, callback) {
this.element.addEventListener(event, callback, false);
}
}, {
key: 'unbind',
value: function unbind(event, callback) {
this.element.removeEventListener(event, callback, false);
}
}, {
key: 'style',
value: function style(property, value) {
if (typeof property === 'string') {
this.element.style[property] = value;
} else {
for (var key in property) {
if (property.hasOwnProperty(key)) {
this.element.style[key] = property[key];
}
}
}
}
}, {
key: 'addClass',
value: function addClass(classes) {
changeClasses(this.element, 'add', classes);
}
}, {
key: 'removeClass',
value: function removeClass(classes) {
changeClasses(this.element, 'remove', classes);
}
}, {
key: 'html',
value: function html(value) {
if (value) {
setProperty(this.element, 'innerHTML', value);
} else {
return getProperty(this.element, 'innerHTML');
}
}
}, {
key: 'scrollTop',
value: function scrollTop(value) {
if (value) {
setProperty(this.element, 'scrollTop', value);
} else {
return getProperty(this.element, 'scrollTop');
}
}
}, {
key: 'offsetWidth',
value: function offsetWidth() {
return this.element.offsetWidth;
}
}]);
return BaseElement;
}();
var bodyAnimationClass = 'sidr-animating';
var openAction = 'open';
function isBody(element) {
return element.tagName === 'BODY';
}
function openClasses(name) {
var classes = 'sidr-open';
if (name !== 'sidr') {
classes += ' ' + name + '-open';
}
return classes;
}
var Body = function (_BaseElement) {
inherits(Body, _BaseElement);
function Body(settings, menuWidth) {
classCallCheck(this, Body);
var _this = possibleConstructorReturn(this, (Body.__proto__ || Object.getPrototypeOf(Body)).call(this, dom.qs(settings.body)));
_this.name = settings.name;
_this.side = settings.side;
_this.speed = settings.speed;
_this.timing = settings.timing;
_this.displace = settings.displace;
_this.menuWidth = menuWidth;
return _this;
}
createClass(Body, [{
key: 'prepare',
value: function prepare(action) {
var prop = action === openAction ? 'hidden' : '';
// Prepare page if container is body
if (isBody(this.element)) {
var html = new BaseElement(dom.qs('html'));
var scrollTop = html.scrollTop();
html.style('overflowX', prop);
html.scrollTop(scrollTop);
}
}
}, {
key: 'unprepare',
value: function unprepare() {
if (isBody(this.element)) {
var html = new BaseElement(dom.qs('html'));
html.style('overflowX', '');
}
}
}, {
key: 'move',
value: function move(action) {
this.addClass(bodyAnimationClass);
if (action === openAction) {
this.open();
} else {
this.close();
}
}
}, {
key: 'open',
value: function open() {
var _this2 = this;
if (this.displace) {
var transitions = dom.transitions;
var styles = {
width: this.offsetWidth() + 'px',
position: 'absolute'
};
this.style(this.side, '0');
this.style(transitions.cssProperty, this.side + ' ' + this.speed / 1000 + 's ' + this.timing);
this.style(styles);
setTimeout(function () {
return _this2.style(_this2.side, _this2.menuWidth + 'px');
}, 1);
}
}
}, {
key: 'onClose',
value: function onClose() {
var transitions = dom.transitions;
var styles = {
width: '',
position: '',
right: '',
left: ''
};
styles[transitions.cssProperty] = '';
this.style(styles);
this.unbind(transitions.event, this.temporalCallback);
}
}, {
key: 'close',
value: function close() {
if (this.displace) {
var transitions = dom.transitions;
this.style(this.side, 0);
var self = this;
this.temporalCallback = function () {
self.onClose();
};
this.bind(transitions.event, this.temporalCallback);
}
}
}, {
key: 'removeAnimationClass',
value: function removeAnimationClass() {
this.removeClass(bodyAnimationClass);
}
}, {
key: 'removeOpenClass',
value: function removeOpenClass() {
this.removeClass(openClasses(this.name));
}
}, {
key: 'addOpenClass',
value: function addOpenClass() {
this.addClass(openClasses(this.name));
}
}]);
return Body;
}(BaseElement);
var Menu = function (_BaseElement) {
inherits(Menu, _BaseElement);
function Menu(settings) {
classCallCheck(this, Menu);
var _this = possibleConstructorReturn(this, (Menu.__proto__ || Object.getPrototypeOf(Menu)).call(this, dom.id(settings.name)));
_this.name = settings.name;
_this.speed = settings.speed;
_this.side = settings.side;
_this.displace = settings.displace;
_this.source = settings.source;
_this.timing = settings.timing;
_this.method = settings.method;
_this.renaming = settings.renaming;
_this.onOpenCallback = settings.onOpen;
_this.onCloseCallback = settings.onClose;
_this.onOpenEndCallback = settings.onOpenEnd;
_this.onCloseEndCallback = settings.onCloseEnd;
_this.init(settings);
return _this;
}
createClass(Menu, [{
key: 'init',
value: function init(settings) {
// If the side menu do not exist create it
if (!this.element) {
this.element = dom.createElement(this.name);
}
this.style(dom.transitions.cssProperty, this.side + ' ' + this.speed / 1000 + 's ' + this.timing);
this.addClass('sidr sidr-' + this.side);
this.body = new Body(settings, this.offsetWidth());
this.reload();
}
}, {
key: 'reload',
value: function reload() {
var _this2 = this;
if (typeof this.source === 'function') {
var newContent = this.source(name);
this.html(newContent);
} else if (typeof this.source === 'string' && utils.isUrl(this.source)) {
utils.fetch(this.source, function (newContent) {
_this2.html(newContent);
});
} else if (typeof this.source === 'string') {
var htmlContent = dom.getHTMLContent(this.source);
if (this.renaming) {
htmlContent = dom.addPrefixes(htmlContent);
}
this.html(htmlContent);
} else if (this.source !== null) {
console.error('Invalid Sidr Source');
}
}
}, {
key: 'move',
value: function move(action, callback) {
// Lock sidr
sidrStatus.moving = true;
this.body.prepare(action);
this.body.move(action);
this.moveMenu(action, callback);
}
}, {
key: 'open',
value: function open(callback) {
var _this3 = 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 = store$1.get(sidrStatus.opened);
alreadyOpenedMenu.close(function () {
_this3.open(callback);
});
return;
}
this.move('open', 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);
this.onCloseCallback();
}
}, {
key: 'toggle',
value: function toggle(callback) {
if (sidrStatus.opened === this.name) {
this.close(callback);
} else {
this.open(callback);
}
}
}, {
key: 'onOpenMenu',
value: function onOpenMenu(callback) {
var name = this.name;
sidrStatus.moving = false;
sidrStatus.opened = name;
this.unbind(dom.transitions.event, this.temporalOpenMenuCallback);
this.body.removeAnimationClass();
this.body.addOpenClass();
this.onOpenEndCallback();
if (typeof callback === 'function') {
callback(name);
}
}
}, {
key: 'openMenu',
value: function openMenu(callback) {
var self = this;
this.style(this.side, 0);
this.temporalOpenMenuCallback = function () {
self.onOpenMenu(callback);
};
this.bind(dom.transitions.event, this.temporalOpenMenuCallback);
}
}, {
key: 'onCloseMenu',
value: function onCloseMenu(callback) {
this.unbind(dom.transitions.event, this.temporalCloseMenuCallback);
this.style({
left: '',
right: ''
});
this.body.unprepare();
sidrStatus.moving = false;
sidrStatus.opened = false;
this.body.removeAnimationClass();
this.body.removeOpenClass();
this.onCloseEndCallback();
if (typeof callback === 'function') {
callback(name);
}
}
}, {
key: 'closeMenu',
value: function closeMenu(callback) {
var self = this;
this.style(this.side, '');
this.temporalCloseMenuCallback = function () {
self.onCloseMenu(callback);
};
this.bind(dom.transitions.event, this.temporalCloseMenuCallback);
}
}, {
key: 'moveMenu',
value: function moveMenu(action, callback) {
if (action === 'open') {
this.openMenu(callback);
} else {
this.closeMenu(callback);
}
}
}]);
return Menu;
}(BaseElement);
var Button = function (_BaseElement) {
inherits(Button, _BaseElement);
function Button(element, settings) {
classCallCheck(this, Button);
var _this = possibleConstructorReturn(this, (Button.__proto__ || Object.getPrototypeOf(Button)).call(this, element));
_this.init(settings);
return _this;
}
createClass(Button, [{
key: 'init',
value: function init(settings) {
var data = this.element.getAttribute('data-sidr');
// If the plugin hasn't been initialized yet
if (!data) {
var name = settings.name;
var method = settings.method;
var bind = settings.bind;
this.element.setAttribute('data-sidr', name);
this.bind(bind, function (event) {
event.preventDefault();
runner(method, name);
});
}
}
}]);
return Button;
}(BaseElement);
var defaultOptions = {
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: 'click', // The event 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
};
function fnSidr(options) {
var settings = utils.extend(defaultOptions, options);
store$1.add(settings.name, new Menu(settings));
return this.each(function () {
new Button(this, settings);
});
}
/*
* Sidr
* https://github.com/artberri/sidr
*
* Copyright (c) 2013-2017 Alberto Varela
* Licensed under the MIT license.
*/
jQuery.sidr = runner;
jQuery.fn.sidr = fnSidr;
}());