简体   繁体   English

重构JS功能

[英]Refactor JS Function

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 ). 假设我们有一个左垂直导航( li的垂直列表)。 In those li s we have a link and another div which also contains another list of items. 在这些li一个值得我们一个链接,另一个DIV其中还包含项目的另一份名单。 So what this function need's to do it's position this sub level of li s according to some rules : 因此,此功能需要执行的操作是根据一些规则将li的此子级别定位:

  • 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 有两个边界,一个上限对应于第一层上最高的“ li”项加上它自己的高度,另一个边界下限对应于第一层上最低的li加上它自己的高度
  • 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 第一个条件是始终将子项放置在一个容器中,并显示在父级li的右侧,因此将父项显示在该容器的中间
  • 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 还有另一种情况,如果父li很少,并且容器的高度现在再次超过边界之间的高度,那么我们就必须应用上述规则
  • 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 :) 因此,如上所述,我希望有人有更好的方法来执行所有逻辑,也许还有更清洁的方法:)

this piece of code seems to be always the same, try to put that out of the if conditions (probably into a function): 这段代码似乎总是相同的,请尝试将其排除在if条件之外(可能放在函数中):

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

i think that should be a good point to start. 我认为这应该是一个很好的起点。 look for lines of code which are duplicate 寻找重复的代码行

here is some kind of example (without exactly reading what your function does, just some refactorings to dry this function a little bit up 这是一个示例(没有完全阅读您的功能做什么,只是进行一些重构以使此功能变干一点)

this is still some kind of ugly but i hope it helps to push you into the right direction 这仍然有些丑陋,但我希望它有助于将您推向正确的方向

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;
}

} }

Without testing if the underlying logic makes sense, this is slightly easier to read in my opinion 在我看来,如果不测试基础逻辑是否有意义,这会更容易阅读

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM