Efficient algorithm to sort html list of players

We have list of players, which is represented in form like this:

<div class="players_list">
   <div class="player" data-points="500">
        <div class="name">Player1</div>
        <div class="position">1</div>
   </div>     
   <div class="player" data-points="400">
        <div class="name">Player2</div>
        <div class="position">2</div>
   </div>
   <div class="player" data-points="300">
        <div class="name">Player3</div>
        <div class="position">3</div>
   </div>
   <div class="player" data-points="200">
        <div class="name">Player4</div>
        <div class="position">4</div>
   </div>  
</div> 

Something happens, and Player 4 recieves 600 points. So it goes on 1st place.
With him – player3 recieves 300 points and goes on 2nd place.

It happens after same event – let’s assume, that they get these points from server, but that’s all load that is allowed on server and server does not calculate positions.

What is most efficent way to get view like this:

<div class="players_list">
   <div class="player" data-points="800">
        <div class="name">Player4</div>
        <div class="position">1</div>
   </div>
   <div class="player" data-points="700">
        <div class="name">Player3</div>
        <div class="position">2</div>
   </div>

   <div class="player" data-points="500">
        <div class="name">Player1</div>
        <div class="position">3</div>
   </div>     
   <div class="player" data-points="400">
        <div class="name">Player2</div>
        <div class="position">4</div>
   </div>
</div> 

It’s not question about code, it’s question about:

  • What kind of task it is? Just sort?
  • Is it ok to use JavaScript to solve this task if lists are less than 500 rows?
  • Is it ok to re-render whole players list, or there are some ways to just change div element position(index in DOM or something like this)?
  • Are there any tools and libraries around, that can help solve this task efficiently?

P.S.: If we want to animate all this story – we should create a queue of animation tasks each time scores for all players recalculates?

Update:

I have followed @Jalayn’s answer, and stuck on following problem:

Let’s assume that list [1,2,3,4] transforms to [2,3,4,1]. If we map it, we will get following position diffs [+1, +1, +1, -3].. Now, if we move one by one elements to it’s position change, all will be ok, till we get to negotiate position diff – 1st position diff can’t move down any more..

So, my update to question – how we can animate rows more than twice?

And final problem, on which I am stucked:

Not sure, if it most be solved in this question. BTW, if 2 players have same points – animation plan brakes and element_ids duplicates.

My question now is how to make following transformation of structures list:
[(#id1, 1, 100),(#id2, 2, 50), (#id3, 2, 50), (#id4, 4, 25)] => [(#id3, 1, 150), (#id1, 2, 100), (#id4, 3, 75), (#id2, 4, 50)]

For now my solution is to refresh whole list, but not completly regenerate it – just move all elements to the first position in order they sorted in backed JSON. Animation is too complex to be done cause of final problem.

7

Well I hope, I’ll answer all your questions and be precise enough.

The answer to all your questions is yes, it is possible to do all of that in Javascript:

What kind of task it is? Just sort?

You have to sort data, but you also have to update some data (points, name?, position) and display it to the user.

Is it ok to use JavaScript to solve this task if lists are less than
500 rows?

You can rearrange tables composed of 500 rows with JavaScript, no problem (using a bit of JQuery), and I don’t think you would have any performance trouble with that. The only problem you could have is if you attempt to animate 500 moving rows (more on that later)

Is it ok to re-render whole players list, or there are some ways to
just change div element position(index in DOM or something like this)?

Well, I think it is ok to re-render the whole players list, but if you do that, how will perform position-change animations ?

Are there any tools and libraries around, that can help solve this
task efficiently?

Obvious answer: JQuery and JQuery UI (or your favorite JavaScript framework for performing animations)

If we want to animate all this story – we should create a queue of
animation tasks each time scores for all players recalculates?

I think you should perform the animations one by one after you know the final position of each player. Otherwise, you could perform animations when nothing has changed (player3 may move from 3 to 1, then player2 moves from 2 to 1, then player1 moves from 1 to … 1, nothing has changed!)

DOM only vs DOM backed by a JSON Data Model

Now, regardless of the tools, or algorithm you are going to use, if you work only with DOM elements, without having a “backend” JSON data model (please someone complete here if you see more problems):

  • Finding the new position of a given player will be a pain
  • Updating the positions of every player will be a pain

If you work with DOM elements for rendering, backed by a JSON data model, and provided you make the following changes to your individual player display, you will have a much easier time:

   <div class="player" id="player2">
        <div class="name">Player2</div>
        <div class="points" id="playerPoints2">400</div>
        <div class="position" id="playerPosition2">2</div>
   </div>
  • Notice that I’ve added an id attribute to the player <div> and to the elements displaying the points (“playerPoints2”) and the position (“playerPosition2”). Doing that will allow you to quickly find the position of a player or its points, given its unique id. You could do without, but that would affect performance and you would have to use more complex queries (see JQuery’s .find())

My attempt:

In short, what I try to do is moving as few DOM elements as possible, and decorrelating the data from the display.

Imagine having the following JSON data model in addition to your DOM model for displaying the players:

  • player (array of players)
    • id
    • position (you can write a custom function for sorting the array given the “position” attribute if each item of the array)
    • points
    • name

and the following JSON data model for performing animations later:

  • playerChanges (array of player changes)
    • id
    • deltaPosition (example: +3 = 3 ranks higher than before)
      . * isComputed (boolean)

After receiving data from the server, here’s what I would do:

  • sort the list of backend players, given their respective position. The first element of the array should be the top ranked player.
  • loop over the data received from the server
  • if the points of a player change, then:
    • look up the player in the array
    • update its points
    • move the player to the position in the array where it should fit, but don’t change the “position” attribute
    • create a new entry in the “playerChanges” array, storing only the id of the player (we will compute the delta only at the end)
  • loop on the array of backend players, and for each player in “playerChanges” (this is important) that is nit yet conputed, compute the position attribute regarding to the position of the player in the array. Since you have his “old” position, and the position in the array, you can compute the “deltaPosition”. Edit: after you compute the delta, mark the “playerChange” as computed and restart looping on the array of backend players. Do that as long as there is an uncomputed “”playerChange”” in the array.

In the end you should have an array of “playerChanges”. This is the list of rows that you should move, given the “deltaPosition” of each player. Notice that it could be 0, which means that the player received new points, but his position did not change. To perform the animation, I would suggest looking at this brilliant answer.

After you have done these animations, you can loop again on the list of backend players in order to update the displayed position (“playerPositionXXX” where XXX is the id of the player) of each player.

What I’ve attempted to do here is to decorrelate the “update and sort” from what happens on the screen, the animation that the user sees.

Edit: here is a working code sample (on Chrome at least) of an animation with JQuery and JQueryUI.

<html>
    <head>
        <title>Temp test</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
        <style type="text/css">
            * { font-family: Calibri;}
            .player { border: 1px solid grey; background: #f0f0f0; width: 300px; 
                        padding: 10px; margin-bottom: 5px; margin-top: 5px; }
                .name { margin-left: 30px; font-size: 20px; font-weight: bold; }
                .points { float: right; color: whitesmoke; font-size: 24px; font-weight: bold; margin-top: -30px; 
                            background-color: #999; padding: 3px;}
                .position { clear: both; display: block; float: left; 
                            font-size: 20px; font-weight: bold; margin-top: -29px; padding-right: 10px; 
                            border-right: 1px solid black;}
        </style>
        <script type="text/javascript">

            function movePlayer(playerToMoveId, delta) {
                var $old = $(playerToMoveId);
                var $new = $old.clone();

                // TODO: here I don't take into account the delta
                // 
                // you need to write a simple method for determining the player
                // that will be replaced (here I hardcoded "p4"). 
                $("#p4").before($new);

                var newOffset = $new.offset();
                //Get the old position relative to document
                var oldOffset = $old.offset();
                //we also clone old to the document for the animation
                var $temp = $old.clone().appendTo('body');
                //hide new and old and move $temp to position
                //also big z-index, make sure to edit this to something that works with the page
                $temp
                  .css('position', 'absolute')
                  .css('left', oldOffset.left)
                  .css('top', oldOffset.top)
                  .css('zIndex', 1000);
                $new.hide();
                $old.hide();
                //animate the $temp to the position of the new img
                $temp.animate( {'top': newOffset.top, 'left':newOffset.left}, 'slow', function(){
                   //callback function, we remove $old and $temp and show $new
                   $new.show();
                   $old.remove();
                   $temp.remove();
                });
            }
        </script>
    </head>
    <body>
        <div class="players_list" id="plist">
           <div class="player" id ="p4">
                <div class="name" id="pName4">Player4</div>
                <div class="points" id="pPts4">800</div>
                <div class="position" id="pPos4">1</div>
           </div>
           <div class="player" id="p3">
                <div class="name" id="pName3">Player3</div>
                <div class="points" id="pPts3">500</div>
                <div class="position" id="pPos3">2</div>
           </div>

           <div class="player" id="p1">
                <div class="name" id="pName1">Player1</div>
                <div class="points" id="pPts1">300</div>
                <div class="position" id="pPos1">3</div>
           </div>     
           <div class="player" id="p2">
                <div class="name" id="pName2">Player2</div>
                <div class="points" id="pPts2">250</div>
                <div class="position" id="pPos2">4</div>
           </div>
        </div> 

        <input type="button" onclick="movePlayer($('#p2'), 3)" value="Animate"/>
    </body>
</html>

4

Assuming you have multiplayers on different systems and some type of hosts (could be node.js).

I would say, that this is a typical update-score event. Something that gets triggered on the server. Since when the scores are changing, the server should send to each player the new (ranked) scores.

I would use javascript (jquery) on the client side for rendering the score-list. With HTML5 you could use web sockets, and stream the new scores the moment the server (done calculating) sends out the event (or just notify the client that new score list is available).

I would keep as much as logic (as reasonable possible) on the server (MVC).

3

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật