/*!
* mobileMenu Plugin v1.0
* http://blog.net21.cz
*
* Copyright (c) 2016 Tomas Tulka
* Released under the MIT license
*
* Date: 2016-01-03
*/
/**
* @param dataJsonUrl required the url of a JSON file with the menu data
* @param yOffset optional the offset in the position Y (for a shadow)
*/
$.fn.mobileMenu = function(dataJsonUrl, yOffset) {
if (!yOffset) yOffset = 5;
openedMenus = [];
function openMenu(menuId, mainContainer, parentBlock, level, title, menu) {
var div = $('
');
div.css('position', 'absolute');
openedMenus[menuId][level] = false;
// title to get back to the old menu only for the child menus
if (level > 0) {
var titleItem = $('');
titleItem.click(function() {
// the actual menu goes to the left away
div.animate({left: '100%'}, function() {
div.remove();
});
// the old menu comes from the left
var h = parentBlock.outerHeight(true) + 10;
if (h > mainContainer.height()) { // we need to keep the biggest from old and new blocks during the animation
mainContainer.height(h);
}
parentBlock.animate({left: '0'}, function(){
mainContainer.height(h);
openedMenus[menuId][level - 1] = false;
});
});
div.append(titleItem);
}
// fill the menu items
$.each(menu, function(i, el) {
var itemClass = 'mobileMenuItem';
if (level == 0 && i == 0) {
itemClass += ' first';
}
var itemText = el.name;
if (el.link) {
itemClass += ' link';
itemText = '' + itemText + '';
}
var item = $('' + itemText + '
');
if (el.menu) {
item.click(function() {
if (!openedMenus[menuId][level]) {
openedMenus[menuId][level] = true;
openMenu(menuId, mainContainer, div, level + 1, el.name, el.menu);
}
});
}
div.append(item);
});
if (parentBlock == null) {
// in this context is the mainContainer the real main container
// the main menu comes from the top to the bottom
div.css('visibility', 'hidden'); // we need to render the block to get its height, but not to show it
mainContainer.append(div);
var h = div.outerHeight(true);
if (h > mainContainer.height()) { // we need to keep the biggest from old and new blocks during the animation
mainContainer.height(h);
}
div.height(0); // show the block with the zero height
div.css('visibility', 'visible')
div.animate({height: h}, function(){ // animate the block to the original height
mainContainer.height(h + 10);
});
} else {
// the child menu comes to the right
div.css('left', '100%');
parentBlock.after(div);
var h = div.outerHeight(true) + 10;
if (h > mainContainer.height()) { // we need to keep the biggest from old and new blocks during the animation
mainContainer.height(h);
}
parentBlock.animate({left: '-100%'});
div.animate({left: '0'}, function(){
mainContainer.height(h);
});
}
}
return this.each(function(index) {
var mainButton = $(this);
mainButton.addClass('mobileMenuButton');
openedMenus[index] = [];
var docWidth = $(document).width();
$.getJSON(dataJsonUrl, function(data) {
if (data.menu) {
var main = $('');
var leftOffset = mainButton.offset().left;
main.width((docWidth - leftOffset) + 'px');
main.css('top', mainButton.offset().top + mainButton.outerHeight(true));
main.css('left', leftOffset);
var mainContainer = $('');
mainContainer.css('position', 'relative');
mainContainer.css('overflow', 'hidden');
mainButton.after(main);
main.append(mainContainer);
var menuShown = false;
mainButton.click(function() {
if (!menuShown) {
menuShown = true;
openMenu(index, mainContainer, null, 0, null, data.menu);
mainButton.addClass('expanded');
} else {
// hide to whole menu by the animation to the top
mainContainer.children().animate({height: '0'}, function(){
mainContainer.height('auto');
$(this).remove();
});
mainButton.removeClass('expanded');
menuShown = false;
}
});
}
else {
console.log('menu data not valid');
}
});
});
}