0

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 lis 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 lis 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 lis 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 :)

4

3 回答 3

1

这是某种示例(没有完全阅读您的函数的作用,只是进行了一些重构以使该函数干燥一点

这仍然有些丑陋,但我希望它有助于将您推向正确的方向

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();
    },

    containerCSS = function(marginTop) {
        $container.css({
            'margin-top' : - marginTop
        });
    },

    doTheMarginTop = function() {
        containerCSS((elementHeight * 2) + (elementHeight * returnIndex($that)) + ($activeElements.find(" > ul").outerHeight(true) || 0));
    };

if($that.data().subItemsPositioned !== true) {

    containerCSS(containerHeight / 2 + (elementHeight / 2));

    if((lowestBoundary - highestBoundary) <= containerHeight) {
        doTheMarginTop();
    }

    if($container.offset().top < highestBoundary) {
        containerCSS(((elementHeight * 2) + (elementHeight * returnIndex($that))));

        if((lowestBoundary - highestBoundary) < containerHeight) {
            doTheMarginTop();
        }
    }

    if(($container.offset().top + containerHeight) >= lowestBoundary) {
        containerCSS( containerHeight - (elementHeight * ($elements.length - returnIndex($that))) );
        if((lowestBoundary - highestBoundary) <= containerHeight) { doTheMarginTop(); }
    }

    $that.data().subItemsPositioned = true;
}

}

于 2012-11-22T15:53:24.743 回答
1

在不测试底层逻辑是否有意义的情况下,我认为这更容易阅读

if(!$that.data().subItemsPositioned)  {
  var  offset=0;
  var ulOuterHeight = (elementHeight * 2) + (elementHeight * returnIndex($that)) + ($activeElements.find("  >  ul").outerHeight(true) ||  0);
  switch(true)  {
    case (lowestBoundary - highestBoundary)  <=  containerHeight  :
      offset = ulOuterHeight;  
      break;
    case $container.offset().top  <  highestBoundary  :
      if((lowestBoundary - highestBoundary)  <  containerHeight)  {
        offset = ulOuterHeight; 
      }
      else offset = (elementHeight * 2) + (elementHeight * returnIndex($that))
      break;
    case ($container.offset().top + containerHeight)  >=  lowestBoundary  :
      if((lowestBoundary - highestBoundary)  <=  containerHeight)  {
        offset = ulOuterHeight; 
      }
      else offset = containerHeight - (elementHeight * ($elements.length - returnIndex($that)));  
      break;
    default: offset = containerHeight/2 + (elementHeight/2);
  }
  $container.css({'margin-top'  : - offset  });
  $that.data().subItemsPositioned = true;
}
于 2012-11-23T07:49:52.990 回答
1

这段代码似乎总是一样的,试着把它放在 if 条件之外(可能是一个函数):

$container.css({
    'margin-top' : - ((elementHeight * 2) + (elementHeight *     returnIndex($that)) + ($activeElements.find(" > ul").outerHeight(true) || 0))
});

我认为这应该是一个很好的起点。查找重复的代码行

于 2012-11-22T15:44:07.073 回答