I have this ugly chunk of code which is responsible for positioning some sub-navigation on a website and I want some opinion on how I could improve it, because even I admit it's ugly as hell :)
Maybe someone has a better structuring idea, because I don't due to the complex logic :
positionSubItems : function() {
var $that = $(this),
$parent = $that.parents().eq(1),
$elements = $parent.find(' > li'),
$activeElements = $parent.find(' > li.active'),
$container = $that.parent().find(".expandedViewContainer"),
highestBoundary = $($elements[0]).offset().top - $($elements[0]).outerHeight(true),
lowestBoundary = $($elements[$elements.length - 1]).offset().top + $($elements[$elements.length - 1]).outerHeight(true),
containerHeight = $container.outerHeight(true),
elementHeight = $that.outerHeight(true),
returnIndex = function(selector) {
return $(selector).parent().index();
};
if($that.data().subItemsPositioned !== true) {
$container.css({
'margin-top' : - ( containerHeight / 2 + (elementHeight / 2) )
});
if((lowestBoundary - highestBoundary) <= containerHeight) {
$container.css({
'margin-top' : - ((elementHeight * 2) + (elementHeight * returnIndex($that)) + ($activeElements.find(" > ul").outerHeight(true) || 0))
});
}
if($container.offset().top < highestBoundary) {
$container.css({
'margin-top' : - ((elementHeight * 2) + (elementHeight * returnIndex($that)))
});
if((lowestBoundary - highestBoundary) < containerHeight) {
$container.css({
'margin-top' : - ((elementHeight * 2) + (elementHeight * returnIndex($that)) + ($activeElements.find(" > ul").outerHeight(true) || 0))
});
}
}
if(($container.offset().top + containerHeight) >= lowestBoundary) {
$container.css({
'margin-top' : - ( containerHeight - (elementHeight * ($elements.length - returnIndex($that))) )
});
if((lowestBoundary - highestBoundary) <= containerHeight) {
$container.css({
'margin-top' : - ((elementHeight * 2) + (elementHeight * returnIndex($that)) + ($activeElements.find(" > ul").outerHeight(true) || 0))
});
}
}
$that.data().subItemsPositioned = true;
}
}
So just let me briefly explain what it does. Let's say we have a left vertical navigation ( a vertical list of li
). In those li
s we have a link and another div which also contains another list of items. So what this function need's to do it's position this sub level of li
s according to some rules :
- there are two boundaries, one upper which corresponds to the most upper 'li' item on the first level plus it's own height, and the other one lower which corresponds to the most low
li
on the first level plus it's own height - the first condition would be that always position the sub items, which are held by a container and displayed to the right of the parent
li
, so the parent it's shown in the middle of that container - based on the above rule, if the offset of the resulted positioning of the container exceeds the upper boundary, then reposition the container so the top offset of the container it's now at the same level as the upper boundary
- continuing to click on the rest of the items follow the first rule, apply the second one if it's the case, then if this following condition it's meet apply it : when the offset of the bottom of the container exceeds the lowest boundary, reposition it so the bottom of the container it's always at the same level as the lowest boundary
- after going through all of the above rules and conditions you also have to check if the height of the container is bigger than the height between the upper and lower boundary, in that case apply the first rule, position the container at the same level as the upper boundary
- there is also another scenario encountered, if there are to few parent
li
s and the height of the container now exceeds the height of the height between boundaries again, so we'll have to apply the just above mentioned rule - and there is another scenario which I won't describe as I'm already to deep into details
So stating the above, I hope someone has a better way of doing all the logic and maybe a more cleaner way too :)