重构JS函数

时间:2012-11-22 15:36:20

标签: javascript jquery

我有这个丑陋的代码块,它负责在网站上定位一些子导航,我想对如何改进它有一些看法,因为即使我承认它是丑陋的地狱:)

也许有人有更好的结构理念,因为我不是因为复杂的逻辑:

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

    }

让我简单解释它的作用。我们假设我们有一个左垂直导航(li的垂直列表)。在那些li中,我们有一个链接和另一个div,它还包含另一个项目列表。那么这个函数需要根据一些规则来定位li的子级别:

  • 有两个边界,一个上面对应最上面的&#39; li&#39;第一级上的项目加上它自己的高度,另一个下级对应于第一级别中最低li加上它自己的高度
  • 第一个条件是始终定位子容器,这些子容器由容器保持并显示在父li的右侧,因此父容器显示在容器的中间
  • 根据上述规则,如果容器的最终定位的偏移超过上边界,则重新定位容器,使容器的顶部偏移现在与上边界处于同一水平< / LI>
  • 继续点击其余项目遵循第一条规则,如果是这样,则应用第二条规则,然后如果符合以下条件则应用它:当底部的偏移量时容器超过最低边界,重新定位容器底部,它始终与最低边界处于同一水平
  • 在完成上述所有规则和条件后,您还必须检查容器的高度是否大于上边界和下边界之间的高度,在这种情况下应用第一个规则,将容器放在同一位置作为上边界的水平
  • 还遇到另一个场景,如果父li个很少,并且容器的高度现在再次超过边界之间的高度,那么我们必须应用刚才上述规则
  • 还有另一个场景,我不会描述,因为我已经深入细节

如上所述,我希望有人有更好的方法来做所有的逻辑,也许更清洁的方式:)

3 个答案:

答案 0 :(得分:1)

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

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

我认为这应该是一个很好的开始。寻找重复的代码行

答案 1 :(得分: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;
}

}

答案 2 :(得分: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;
}