2

I'm looking to build a simple ranking system, where divs are generated dynamically, so there could be a couple or a few hundred, and each div can be ranked up or down. I have it working for 1, but I'm not sure how I can do it on a larger scale where each div has a unique id.

HTML

<button class="up">Up</button> 
<button class="down">Dowm</button> 

<div id="rank">Rank = 0</div>

JavaScript

var rank = 0;
var rankPercent = 0;
var rankTotal = 0;

$('.up').click(function(){
     rank++;
     rankTotal++;
     rankPercent = rank/rankTotal;
    $('#rank').text("Rank = "+ rankPercent);
});

$('.down').click(function(){
     rankTotal++;
     rankPercent = rank/rankTotal; 
    $('#rank').text("Rank = "+ rankPercent);
});
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
MVC_Future_Guru
  • 239
  • 4
  • 15
  • What does rank total do? and rank Percent? Can you elaborate please? – Michal Apr 08 '14 at 22:41
  • rankTotal is the total number of votes, and rankPercent shows a percentage of the votes, so 1 up vote out of 2 total votes would equal 50% approve- or have chosen up. – MVC_Future_Guru Apr 08 '14 at 23:12

4 Answers4

0

The easiest way to do this within JQuery is to have class="rank" on that rank div also. Then since you get sender in click button handler (you just need to change signature to $('.up').click(function(eventObject){ ... })) you can search for next element that has .rank class.

That all being said, I STRONGLY recommend you abandon this approach (since it's really error prone) and instead of building components yourself, invest time in learning something like AngularJs.

Take a look at this question if you want to look into AngularJS - How to master AngularJS?

EDIT: Thanks for the downvote... I was busy with making example in JsFiddle:

http://jsfiddle.net/7zrej/

Community
  • 1
  • 1
nikib3ro
  • 20,366
  • 24
  • 120
  • 181
  • I've heard of angular but haven't done much with it. After reading a little it seems pretty helpful, but I think you may have broken my brain for the next few days. I found a tutorial on thinkster.io that seems very close to what I'm looking to accomplish, except I seem to be completely lost as to just getting my environment set up. It just dives into asking me to install via my terminal, so I downloaded node.js, ran what looks to be a command line, but it says to use my normal shell. Think I'm going to have to read more - but thank you for this suggestion – MVC_Future_Guru Apr 08 '14 at 22:41
  • I don't know why any of these are downvoted, I think they're all great. – MVC_Future_Guru Apr 08 '14 at 22:47
  • @MVC_Future_Guru I know it may seem hard to jump into AngularJS - but believe me you'll get that week back after you utilize power of databinding, rather than trying to do same stuff with jquery or plain javascript. Here is the tutorial that taught me AngularJS in like 3 days: http://www.thinkster.io/angularjs/GtaQ0oMGIl/a-better-way-to-learn-angularjs . If you also need to improve your Javascript knowledge, start with this and follow up watching other parts: http://yuiblog.com/blog/2007/01/24/video-crockford-tjpl/ – nikib3ro Apr 09 '14 at 01:09
  • Will check your links out. I spent about 4 hours yesterday trying to understand what node, yeomon, and several other Linux type set-ups. They sound awesome when working, but I'm somewhat lost. I think the first tutorial you sent seems more up my alley at this point. Thanks again. – MVC_Future_Guru Apr 09 '14 at 19:52
0

Think of it a little differently. Create an upshift() and downshift() function, where the node swaps rank with whatever's above or below it (or do nothing if there's nothing below it).

So,

function upshift (node) {
  var nodeAbove = getNodeAbove(node);
  if (nodeAbove) swapRanks(node, nodeAbove);
  return node;
}

function downshift (node) {
  var nodeBelow = getNodeBelow(node);
  if (nodeBelow) swapRanks(node, nodeBelow);
  return node;
}

As a side thing, perhaps consider doing this with a more Object Oriented approach:

var ranks = [];

function Node (node_id) {
  var node = this;
  ranks.push(node);
  node.rank = ranks.length-1;
}

Node.prototype.upshift = function upshift () {};
Node.prototype.downshift = function upshift () {};

var n1 = new Node(),
    n2 = new Node(),
    n3 = new Node();
ChaseMoskal
  • 7,151
  • 5
  • 37
  • 50
  • You may have lost me slightly, I first started with an object style approach, but then switched over. Thank you for the idea, everyone here has been very helpful, I feel like I just gained a week of work on just understanding this question. – MVC_Future_Guru Apr 08 '14 at 22:46
  • @MVC_Future_Guru: "I feel like I just gained a week of work on just understanding this question." -- Oh, much more than that my friend: These are concepts you'll be expanding on for years! ;) No worries though, continue your project the way you have been, with well-organized procedural code (nothin' too wrong with that), consider my upshift/downshift way of looking at the problem, and save the suggestions in your back pocket for your next project (or experiment, preferably ;) – ChaseMoskal Apr 09 '14 at 06:32
  • Will do, thanks again. I'm of the impression that I'll never fully understand, just hope to improve and keep up. Good times – MVC_Future_Guru Apr 09 '14 at 19:53
0

One of many ways would be to leverage data attributes to keep your rank data on your elements themselves. You can generate unique IDs for each div when you generate them, and put those in data attributes for your buttons too.

Your HTML with initial data attributes might look like this:

<button class="up" data-id="0">Up</button>
<button class="down" data-id="0">Down</button>
<div id="rank-0" data-rank="0">0</div>

<button class="up" data-id="1">Up</button>
<button class="down" data-id="1">Down</button>
<div id="rank-1" data-rank="0">0</div>

<button class="up" data-id="2">Up</button>
<button class="down" data-id="2">Down</button>
<div id="rank-2" data-rank="0">0</div>

And your JavaScript like this:

$(".up").click(function() {
    var id = $(this).data("id");
    var rank = $("#rank-" + id).data("rank");
    rank++;
    $("#rank-" + id).data("rank", rank).text(rank);
});

$(".down").click(function() {
    var id = $(this).data("id");
    var rank = $("#rank-" + id).data("rank");
    rank--;
    $("#rank-" + id).data("rank", rank).text(rank);
});

Live example

Alex Turpin
  • 46,743
  • 23
  • 113
  • 145
  • Thank you for this approach, I think it fills in a few holes I've been having. I'm still new to javascript in general, and there seems to be quite a few ways ways or thousands to accomplish. Thanks again. – MVC_Future_Guru Apr 08 '14 at 22:43
0

I'm writing up a longer answer but it would be helpful if you could describe in more detail exactly what sort of behavior you're trying to create.

Are you expecting that the div's reorder themselves when ranks change so that they are always in order of highest ranked to lowest ranked?

Question lacks detail.

EDIT: http://codepen.io/shawkdsn/pen/lojwb/

This example shows a dynamic list of elements with adjustable ranks that maintains the order from highest approval rating to lowest.

EDIT2: I should add that this codepen example is purely front-end code (incomplete solution) and any real ranking system would require integration with a back-end layer. Angular is a good option to explore and is relatively easy to pick up.

user1967
  • 91
  • 4
  • Yes, I'm hoping to have them ordered based on the rankPercent. – MVC_Future_Guru Apr 08 '14 at 22:38
  • Here you go: http://codepen.io/shawkdsn/pen/lojwb/ This is a complex example and probably won't provide exactly what you need but there's a lot to be learned just from dissecting this example. Let me know if you have questions. – user1967 Apr 08 '14 at 23:40
  • I didn't quite "get" what you were trying to do until just now. I'm going to update my codepen example with some more relevant code. +1 for recommending angular.js – user1967 Apr 09 '14 at 03:04
  • Awesome, this is great stuff. Thank you for the help. Have a lot of work to do. – MVC_Future_Guru Apr 09 '14 at 19:55
  • No problem. :) If the question is answered, don't forget to choose a response. – user1967 Apr 09 '14 at 21:37