jQuery大师,这段代码可以简化吗?

时间:2011-11-01 01:10:35

标签: jquery html css

现场演示: http://jsfiddle.net/stapiagutierrez/KKdsb/29/


我只是想为网站创建自己的星级评分用户界面,到目前为止,它的工作方式正如我所希望的那样,但我想看看我是否可以在不牺牲易读性的情况下减少代码。

由于我是jQuery的新手,也许我正在以迂回的方式做事。

有关改进的建议吗?

ul {
    list-style-type:none;
    margin-top:10px;
    margin-left:10px;
    border:1px solid #333;
    border-radius:8px;
    overflow:hidden;
    width:111px;
    cursor:pointer;
}

li {
    float:left;
    margin-left:5px;
    padding-top:2px;
}

<ul>
    <li>
        <img class="onestar rating" src="http://i.imgur.com/8LA1i.png" alt="no-star" />
    </li>

    <li>
        <img class="twostar rating" src="http://i.imgur.com/8LA1i.png" alt="no-star" />
    </li>

    <li>
        <img class="threestar rating" src="http://i.imgur.com/8LA1i.png" alt="no-star" />
    </li>

    <li>
        <img class="fourstar rating" src="http://i.imgur.com/8LA1i.png" alt="no-star" />
    </li>

    <li>
        <img class="fivestar rating" src="http://i.imgur.com/8LA1i.png" alt="no-star" />
    </li>
</ul>

$(document).ready(function() {
    $(".rating").click(function() {
        if ($(this).hasClass("onestar")) {
            alert("Clicked on 1 star!");
        }
        else if ($(this).hasClass("twostar")) {
            alert("Clicked on 2 stars!");
        }
        else if ($(this).hasClass("threestar")) {
            alert("Clicked on 3 stars!");
        }
        else if ($(this).hasClass("fourstar")) {
            alert("Clicked on 4 stars!");
        }
        else if ($(this).hasClass("fivestar")) {
            alert("Clicked on 5 stars!");
        }
    });

    $(".rating").mouseleave(function() {
        $(".rating").each(function() {
            $(this).attr("src", "http://i.imgur.com/8LA1i.png");
        });
    });

    $(".rating").mouseover(function() {
        if ($(this).hasClass("onestar")) {
            $(".onestar").attr('src', 'http://i.imgur.com/X68bI.png');
        }
        else if ($(this).hasClass("twostar")) {
            $(".onestar").attr('src', 'http://i.imgur.com/X68bI.png');
            $(".twostar").attr('src', 'http://i.imgur.com/X68bI.png');
        }
        else if ($(this).hasClass("threestar")) {
            $(".onestar").attr('src', 'http://i.imgur.com/X68bI.png');
            $(".twostar").attr('src', 'http://i.imgur.com/X68bI.png');
            $(".threestar").attr('src', 'http://i.imgur.com/X68bI.png');
        }
        else if ($(this).hasClass("fourstar")) {
            $(".onestar").attr('src', 'http://i.imgur.com/X68bI.png');
            $(".twostar").attr('src', 'http://i.imgur.com/X68bI.png');
            $(".threestar").attr('src', 'http://i.imgur.com/X68bI.png');
            $(".fourstar").attr('src', 'http://i.imgur.com/X68bI.png');
        }
        else if ($(this).hasClass("fivestar")) {
            $(".onestar").attr('src', 'http://i.imgur.com/X68bI.png');
            $(".twostar").attr('src', 'http://i.imgur.com/X68bI.png');
            $(".threestar").attr('src', 'http://i.imgur.com/X68bI.png');
            $(".fourstar").attr('src', 'http://i.imgur.com/X68bI.png');
            $(".fivestar").attr('src', 'http://i.imgur.com/X68bI.png');
        }
    });
});

3 个答案:

答案 0 :(得分:5)

这很有趣,这里是jsFiddle:http://jsfiddle.net/KKdsb/30/

注意parent()处理程序中两个mouseover函数的使用取决于您的html结构。我建议使用<ul>直接访问父$(this).closest('.classname')元素的类或类似内容。

jQuery代码:

$(document).ready(function() {
    $(".rating").click(function() {
        var position = $(this).parent().index();
    });

    $(".rating").mouseleave(function() {
        $(".rating").each(function() {
            $(this).attr("src", "http://i.imgur.com/8LA1i.png");
        });
    });

    $(".rating").mouseover(function() {
        var position = $(this).parent().index() + 1;
        $(this).parent().parent().find("li:lt("+position+") > img").each(function (i, e) {
            $(e).attr('src', 'http://i.imgur.com/X68bI.png');
        });
    });
});

参考:

答案 1 :(得分:3)

这是使用图像精灵的绝佳选择。基本上,您将所有星级评分放入单个图像文件中,并使用“background-position”CSS移动该文件。这样做的主要优点是你只需要对星形图像提出一个请求 - 你不会反复改变起始图像的路径(这可能会使事情变得有点笨拙和缓慢,具体取决于浏览器。 / p>

以下是使用图像精灵的示例: http://www.spookandpuff.com/examples/starRatings/starRatings.html

这是我使用的图像精灵:

5 star image sprite

这是HTML,CSS和Javascript:

HTML非常简单:

<div class="starRating">
    <ol class="ratingValues">
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </ol>
  </div>

可以不使用额外的DIV,但这会导致不支持多类CSS选择器的旧浏览器出现问题,所以我把它留在了。

CSS也很简单:

      .starRating {
        width:105px;
        height:20px;
        float:left;
        margin:20px 0;
      }

      .ratingValues {
        float:left;
        width:100%;
        list-style:none;
        background:url(starSprite.png) no-repeat 0 0;
      }

      .ratingValues li{
        display:block;
        float:left;
        width:21px;
        height:20px;
        text-indent:-999em;
        overflow:hidden;
        cursor:pointer;
      }

      .rating_1 .ratingValues {background-position:0 -20px}
      .rating_2 .ratingValues {background-position:0 -40px}
      .rating_3 .ratingValues {background-position:0 -60px}
      .rating_4 .ratingValues {background-position:0 -80px}
      .rating_5 .ratingValues {background-position:0 -100px}

在这里,我们将框设置为与精灵中的一行星相同的大小。列表项变为正确大小的正方形(图形中每个'星'一个正方形)。我使用了负文本缩进来隐藏每个<li>内的文本。

最有趣的是最后一个街区。在这里,我们根据包含元素的类来调整精灵的背景位置,因此,当.ratingValues位于具有“rating_3”类的内容时,背景将移动到位置:0 -60px。

我打赌你可以看到它的发展方向。这是javascript:

$(function(){
  starRatings = $('.starRating'); //Cache this to make future references faster

  starRatings.each(function(){ //Iterate through each rating, in case there's more than one per page
    var thisRating = $(this),
        triggers = $('.ratingValues > li', this); //More caching

    triggers 
      .hover(
        function(){ //The hover-over event
          var trigger = this;
          thisRating.addClass(function(){
            return 'rating_' + (triggers.index(trigger) + 1); //This sets the class to rating_ + the number of the element (1 - 5)
          })
        },
        function(){  //The hover-out event, just clears the classes
          thisRating.removeClass('rating_1 rating_2 rating_3 rating_4 rating_5');
        })
        .click(function(){ //The click event
          alert('Clicked ' + (triggers.index(this) + 1));
        });
  });

});

找到类.starRating的任何元素,并将事件处理程序分配给其中的<li>。将<li> s悬停在'starRating'div上,它基本上告诉我们选择了什么值(rating_1到rating_5)。 CSS此时启动,并将背景精灵移动到正确的位置。

对于额外的积分,您可以在每个<a href="{rateThis?rating=1}">1</a>中放置一个标准锚点,例如:LI,它会将请求发送到您的服务器并通过直接HTTP设置评级(无javascript) 。这样,如果Javascript关闭,一切仍然有效。

我希望这很清楚 - 如果你需要更多的帮助就大喊大叫!

答案 2 :(得分:1)

改进的解决方案

Example here

HTML:

<div>
    <div class="rating"><div class="value"></div></div>
</div>

CSS:

.rating {
    width:105px;
    height:20px; 
    background: url(http://i.stack.imgur.com/oZ9Id.png) no-repeat;
    cursor:pointer;
}
.rating .value {
    width:0;
    height:20px;   
    background: url(http://i.stack.imgur.com/oZ9Id.png) no-repeat 0px -100px;  
}

的Javascript

$(document).ready(function() {
    var starWidth = $(".rating").width() / 5;
    $(".rating").click(function(e) {
        $(this).find(".value").css({width:(Math.ceil(e.offsetX / starWidth) * starWidth)+"px"});
    });
});

原始解决方案:here


此解决方案优于其他人:

  1. 最少量的代码,标记和CSS。非常容易阅读和 支持。
  2. 解决OP中的一般设计问题而不是尝试 用jQuery糖修补它。
  3. 支持浮点分数(只需将宽度设置为值/ maxWidth)
  4. 支持简单地在可点击和只读视图之间切换 禁用点击事件(无需修改HTML)。
  5. 在3和4之后 - 它是一个显示两者的单一控件 个人用户得分和综合得分。
  6. 小于Beejamin答案所需的图像尺寸(仅使用第一行和最后一行)。
  7. 没有复杂的DOM操作或CSS查找
  8. 缺点:我无法看到。

    自上次迭代以来已修复:

    1. 删除了js对图像宽度的依赖性。现在它是动态计算的,尽管我仍然认为这是不必要的。
    2. 完整且功能齐全的版本here。点击动画here

      的精美版本