简体   繁体   中英

Creating a leaderboard with Firebase

I'm trying to build a top 10 leaderboard using the Firebase Realtime DB - I am able to pull the top 10 ordered by score (last 10 due to the way firebase stores in ascending order) however when I attempt to place them in the page they all appear in key order.

If I was a betting man I'd guess it's to do with the for loop I have to create the elements - but I'm not good enough at Javascript to work out where the issue is I've spent the last 3 hours on MDN and W3Schools and I can't for the life of me work it out.

Either that or I need to run a For Each loop on the actual data query? but I feel like I could avoid that as I'm already collecting the score data so I could just arrange that somehow?

I was sort of expecting everything to appear in ascending order - meaning I would have to go back and prepend my JQuery but instead I've managed to accidentally create a new problem for myself.

Any suggestions will be GREATLY appreciated

Here is my current code:

var db = firebase.database()
    var ref = db.ref('images')
    ref.orderByChild('score').limitToLast(10).on('value', gotData, errData);

    function gotData(data) {
        var scores = data.val();
        var keys = Object.keys(scores);
        var currentRow;
        for (var i = 0; i < keys.length; i++){
            var currentObject = scores[keys[i]];
            if(i % 1 == 0 ){
                currentRow = document.createElement("div");
                $(currentRow).addClass("pure-u-1-5")
                $("#content").append(currentRow);
            }
            var col = document.createElement("div")
            $(col).addClass("col-lg-5");
            var image = document.createElement("img")
            image.src=currentObject.url;
            $(image).addClass("contentImage")
            var p = document.createElement("P")
            $(p).html(currentObject.score)
            $(p).addClass("contentScore");
            $(col).append(image);
            $(col).append(p);
            $(currentRow).append(col);
        }
    }

Use .sort() beforehand, then iterate over each score object to add it to the page:

function gotData(data) {
  const scores = data.val();
  const keys = Object.keys(scores);
  const sortedKeys = keys.sort((keyA, keyB) => scores[keyB].score - scores[keyA].score);
  const content = document.querySelector('#content');
  sortedKeys.map(sortedKey => scores[sortedKey])
  .forEach(scoreObj => {
    const row = content.appendChild(document.createElement('div'));
    row.classList.add('pure-u-1-5'); // better done in the CSS if possible
    const col = row.appendChild(document.createElement('div'));
    col.classList.add('col-lg-5');
    const img = col.appendChild(document.createElement('img'));
    img.src = scoreObj.url;
    img.classList.add('contentScore');
    col.appendChild(document.createElement('p')).textContent = scoreObj.score;
  });
}

For loops have worse abstraction, require manual iteration, and have hoisting problems when you use var - use the array methods instead when you can.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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