Created
January 22, 2013 08:52
-
-
Save victorstanciu/4593140 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define(function () { | |
var Bracket = function (element, manager) { | |
this.element = element; | |
this.manager = manager; | |
this.id = parseInt(element.getAttribute('data-id')); // don't rely on this to be unique until a sync() is made | |
this.round = parseInt(element.getAttribute('data-round')); | |
this.rounds = parseInt(element.getAttribute('data-rounds')); | |
this.order = parseInt(element.getAttribute('data-order')); | |
this.dom = { | |
archers: this.element.select('select'), | |
scores: this.element.select('[data-role="score"]'), | |
winner: this.element.down('[data-role="winner"]') | |
}; | |
/** | |
* This object will eventually hold references to the previous and next brackets in the tree | |
* The values are set automatically on first use via the next() and previous() methods | |
*/ | |
this.relatives = {}; | |
this.listeners = {}; | |
}; | |
Bracket.prototype.addListeners = function() { | |
var self = this; | |
var next = this.next(); | |
if (next) { | |
// if one of the archers that takes part in this bracket also takes part in the next bracket, it means that he actually won this one | |
next.on('archer.select', function (id) { | |
if (self.has(id)) { | |
self.setWinner(id); | |
} | |
}); | |
next.on('archer.deselect', function (id) { | |
if (self.has(id)) { | |
self.check(); | |
} | |
}); | |
} | |
this.element.select('select').invoke('observe', 'change', function (event) { | |
var previous = parseInt(this.getAttribute('data-previous-value')); | |
var id = parseInt(this[this.selectedIndex].value); | |
if (!isNaN(previous)) { | |
self.emit('archer.deselect', previous); | |
} | |
self.check(); | |
if (!isNaN(id)) { | |
this.setAttribute('data-previous-value', id); | |
self.emit('archer.select', id); | |
} | |
}); | |
this.dom.scores.invoke('observe', 'blur', this.check.bind(this)); | |
}; | |
/** | |
* Tries to figure out this bracket's winner via the score fields | |
*/ | |
Bracket.prototype.check = function () { | |
this.clearWinner(); | |
var archers = this.getArchers(); | |
var scores = this.dom.scores.pluck('value').map(Number).reject(isNaN).uniq(); | |
if (archers.length == 2 && scores.length == 2) { | |
var max = scores.max(); | |
var winner = parseInt(this.dom.archers[scores.indexOf(max)].value); | |
} | |
if (this.bye()) { | |
var winner = parseInt(this.dom.archers[0].value); | |
} | |
if (typeof winner == 'undefined' || isNaN(winner)) { | |
return; | |
} | |
this.setWinner(winner); | |
}; | |
Bracket.prototype.setWinner = function (id) { | |
this.dom.winner.value = id; | |
this.dom.scores.invoke('removeClassName', 'bracket-winner'); | |
var archer_event = this.dom.archers.invoke('removeClassName', 'bracket-winner').find(function (select) { | |
return select.value == id; | |
}).addClassName('bracket-winner'); | |
this.dom.scores[this.dom.archers.indexOf(archer_event)].addClassName('bracket-winner'); | |
this.emit('winner', id); | |
var loser = this.getLoser(); | |
if (loser) { | |
this.emit('loser', loser); | |
} | |
}; | |
Bracket.prototype.clearWinner = function() { | |
this.dom.winner.value = ''; | |
this.dom.archers.invoke('removeClassName', 'bracket-winner') | |
this.dom.scores.invoke('removeClassName', 'bracket-winner'); | |
}; | |
Bracket.prototype.getWinner = function() { | |
var winner = parseInt(this.dom.winner.value); | |
if (!isNaN(winner) && winner > 0) { | |
return winner; | |
} | |
return false; | |
}; | |
Bracket.prototype.getLoser = function () { | |
var winner = this.getWinner(); | |
if (!winner) { | |
return false; | |
} | |
var archers = this.getArchers(); | |
if (archers.length == 1) { | |
return false; | |
} | |
return archers[Math.abs(1 - archers.indexOf(winner))]; | |
}; | |
Bracket.prototype.winner = function(id) { | |
id = parseInt(id); | |
if (isNaN(id) || id == 0) { | |
return false; | |
} | |
return this.dom.winner.value == id; | |
}; | |
Bracket.prototype.getArchers = function() { | |
return this.dom.archers.pluck('value').map(Number).reject(isNaN).reject(function (id) { | |
return id == 0 | |
}); | |
}; | |
Bracket.prototype.bye = function() { | |
return isNaN(Number(this.dom.archers[1].value)); | |
}; | |
/** | |
* Checks if the specified archer event is one of the two participants of this bracket | |
*/ | |
Bracket.prototype.has = function(id) { | |
if (this.dom.archers.find(function (select) { | |
return select[select.selectedIndex].value == id; | |
})) { | |
return true; | |
} | |
return false; | |
}; | |
Bracket.prototype.enable = function (ids) { | |
if (typeof ids == 'string' && ids == 'all') { | |
this.element.select('option').each(function (option) { | |
// option.disabled = false; | |
option.removeClassName('disabled'); | |
}) | |
return; | |
} | |
if (!(ids instanceof Array)) { | |
ids = [ids]; | |
} | |
this.element.select('option').each(function (option) { | |
if (ids.indexOf(parseInt(option.value)) != -1) { | |
option.removeClassName('disabled'); | |
} | |
}); | |
return this; | |
}; | |
Bracket.prototype.disable = function (ids) { | |
if (typeof ids == 'string' && ids == 'all') { | |
this.element.select('option[value][value!="-1"]').each(function (option) { | |
option.addClassName('disabled'); | |
}); | |
return; | |
} | |
if (!(ids instanceof Array)) { | |
ids = [ids]; | |
} | |
this.dom.archers.each(function (elm) { | |
elm.select('option[value][value!="-1"]').each(function (option, index) { | |
if (ids.indexOf(parseInt(option.value)) == -1) { | |
return; | |
} | |
option.addClassName('disabled'); | |
}) | |
}); | |
}; | |
Bracket.prototype.valid = function() { | |
var unset = this.element.select('selected').find(function (elm) { | |
return elm.selectedIndex == 0; | |
}); | |
if (unset) { | |
return false; | |
} | |
return true; | |
}; | |
Bracket.prototype.next = function () { | |
if (!this.relatives.hasOwnProperty('next')) { | |
var next_round = this.round - 1; | |
if (next_round >= 1) { | |
var next_order = Math.ceil(this.order / 2); | |
this.relatives.next = this.manager.getBracket(next_round, next_order); | |
} else { | |
this.relatives.next = false; | |
} | |
} | |
return this.relatives.next; | |
}; | |
/** | |
* Unlike next(), this method returns the previous TWO brackets, | |
* as the winners of those brackets participate in this one | |
*/ | |
Bracket.prototype.previous = function () { | |
if (!this.relatives.hasOwnProperty('previous')) { | |
var prev_round = this.round + 1; | |
if (this.round <= this.rounds) { | |
var prev_orders = [this.order * 2 - 1, this.order * 2]; | |
this.relatives.previous = this.manager.getBrackets(prev_round, prev_orders); | |
} else { | |
this.relatives.previous = false; | |
} | |
} | |
return this.relatives.previous; | |
}; | |
Bracket.prototype.emit = function(event) { | |
if (!this.listeners.hasOwnProperty(event)) { | |
return; | |
} | |
var listeners = this.listeners[event]; | |
var args = Array.prototype.slice.call(arguments); | |
args.splice(0, 1); | |
for (var i = 0; i < listeners.length; i++) { | |
listeners[i].apply(this, args); | |
} | |
return this; | |
}; | |
Bracket.prototype.on = function(events, handler) { | |
if (!(events instanceof Array)) { | |
events = [events]; | |
} | |
for (var i = 0; i < events.length; i++) { | |
var event = events[i]; | |
if (!this.listeners.hasOwnProperty(event)) { | |
this.listeners[event] = []; | |
} | |
this.listeners[event].push(handler); | |
} | |
return this; | |
}; | |
/** | |
* Called when data is fetched from the database (on bracket.save(), for example) | |
*/ | |
Bracket.prototype.sync = function(data) { | |
this.id = data.id; | |
this.element.setAttribute('data-id', this.id); | |
this.element.down('input[name="id[]"]').value = this.id; | |
}; | |
/** | |
* Called when a bracket round is removed | |
*/ | |
Bracket.prototype.remove = function() { | |
}; | |
return Bracket; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define(['events/bracket'], function (Bracket) { | |
var Brackets = function (element, archer_events, options) { | |
var self = this; | |
self.brackets = []; | |
self.element = element; | |
self.archer_events = archer_events; | |
self.division = self.element.getAttribute('data-division'); | |
self.options = Object.extend({}, options || {}); | |
self.element.select('.bracket').each(function (elm) { | |
var bracket = self.create(elm); | |
}); | |
self.dom = { | |
indicator: self.element.down('[data-role="indicator"]') | |
}; | |
self.addListeners(); | |
self.update(); | |
}; | |
Brackets.prototype.enable = function(ids, round) { | |
this.getBrackets(round).each(function (bracket) { | |
bracket.enable(ids); | |
}); | |
}; | |
Brackets.prototype.disable = function(ids, round) { | |
this.getBrackets(round).each(function (bracket) { | |
bracket.disable(ids); | |
}); | |
}; | |
Brackets.prototype.update = function() { | |
var self = this; | |
for (var round = self.options.start; round >= 1; round--) { | |
var brackets = self.getBrackets(round); | |
var participants = []; | |
var winners = []; | |
var losers = []; | |
brackets.each(function (bracket) { | |
var p = bracket.getArchers(); | |
if (p.length) { | |
participants = participants.concat(p); | |
} | |
var winner = bracket.getWinner(); | |
if (winner) { | |
winners.push(winner); | |
var loser = bracket.getLoser(); | |
if (loser) { | |
losers.push(loser); | |
} | |
} | |
}); | |
if (round == this.options.start) { | |
this.enable('all', round); | |
} | |
this.disable(participants, round); | |
// go through all the rounds that follow after the current one and disable the archers that have been eliminated | |
for (var next_round = round - 1; next_round >= 1; next_round--) { | |
this.disable('all', next_round); | |
this.enable(participants, next_round); | |
if (next_round > 1) { | |
// losers play in the second round of finals, don't disable them | |
this.disable(losers, next_round); | |
} | |
} | |
} | |
}; | |
Brackets.prototype.addListeners = function() { | |
var self = this; | |
self.element.on('submit', function (event) { | |
event.stop(); | |
self.save(); | |
}); | |
if (self.options.start > 2) { // semi-finals and finals cannot be removed | |
self.element.down('[data-role="remove-round"]').on('click', self.removeRound.bind(self)); | |
} | |
for (var i = 0; i < self.brackets.length; i++) { | |
var bracket = self.brackets[i]; | |
bracket.addListeners(); | |
bracket.on(['archer.select', 'archer.deselect', 'winner', 'loser'], self.update.bind(self)); | |
} | |
}; | |
Brackets.prototype.save = function() { | |
var self = this; | |
var data = self.element.serialize(true); | |
self.element.disable(); | |
self.dom.indicator.show(); | |
new Ajax.Request(APP.url('admin/brackets/save'), { | |
parameters: data, | |
onSuccess: function (transport) { | |
self.element.enable(); | |
self.dom.indicator.hide(); | |
var response = transport.responseText.evalJSON(); | |
for (var round in response) { | |
for (var order in response[round]) { | |
var bracket = self.getBracket(round, order); | |
bracket.sync(response[round][order]); | |
} | |
} | |
} | |
}); | |
}; | |
Brackets.prototype.create = function (element) { | |
var bracket = new Bracket(element, this); | |
this.brackets.push(bracket); | |
return bracket; | |
}; | |
Brackets.prototype.getBrackets = function(round, orders) { | |
var brackets = []; | |
for (var i = 0; i < this.brackets.length; i++) { | |
if (this.brackets[i].round == round) { | |
brackets.push(this.brackets[i]); | |
} | |
} | |
if (typeof orders != 'undefined' && orders.length > 1) { | |
var ret = []; | |
for (var i = 0; i < orders.length; i++) { | |
if (typeof brackets[orders[i] - 1] == 'undefined') { | |
continue; | |
} | |
ret.push(brackets[orders[i] - 1]); | |
} | |
return ret; | |
} | |
return brackets; | |
}; | |
Brackets.prototype.getBracket = function(round, order) { | |
var brackets = this.getBrackets(round); | |
if (!brackets.length) { | |
return false; | |
} | |
return brackets[order - 1]; | |
}; | |
Brackets.prototype.removeRound = function(event) { | |
var self = this; | |
if (!confirm('Ești sigur(ă)?')) { | |
return; | |
} | |
var round = event.element().getAttribute('data-round'); | |
new Ajax.Request(APP.url('admin/event_divisions/remove_round'), { | |
parameters: { | |
id: self.division, | |
round: round | |
}, | |
onSuccess: function (transport) { | |
var response = transport.responseText.evalJSON(); | |
if (response.error) { | |
require(['growler'], function (growler) { | |
growler.error('Eroare', response.error); | |
}) | |
return false; | |
} | |
for (var i = 0; i < self.brackets.length; i++) { | |
brackets[i].remove(); | |
} | |
console.log(brackets);; | |
// self.element.select('th[data-round="'+round+'"]', 'td[data-round="'+round+'"]').invoke(''); | |
console.log(response); | |
} | |
}); | |
}; | |
return Brackets; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment