Place to store the code and config used for the next-Iterations live event.
https://iterations.space/live/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.9 KiB
114 lines
3.9 KiB
_kiwi.model.MemberList = Backbone.Collection.extend({
|
|
model: _kiwi.model.Member,
|
|
comparator: function (a, b) {
|
|
var i, a_modes, b_modes, a_idx, b_idx, a_nick, b_nick;
|
|
var user_prefixes = this.channel.get('network').get('user_prefixes');
|
|
|
|
a_modes = a.get("modes");
|
|
b_modes = b.get("modes");
|
|
|
|
// Try to sort by modes first
|
|
if (a_modes.length > 0) {
|
|
// a has modes, but b doesn't so a should appear first
|
|
if (b_modes.length === 0) {
|
|
return -1;
|
|
}
|
|
a_idx = b_idx = -1;
|
|
// Compare the first (highest) mode
|
|
for (i = 0; i < user_prefixes.length; i++) {
|
|
if (user_prefixes[i].mode === a_modes[0]) {
|
|
a_idx = i;
|
|
}
|
|
}
|
|
for (i = 0; i < user_prefixes.length; i++) {
|
|
if (user_prefixes[i].mode === b_modes[0]) {
|
|
b_idx = i;
|
|
}
|
|
}
|
|
if (a_idx < b_idx) {
|
|
return -1;
|
|
} else if (a_idx > b_idx) {
|
|
return 1;
|
|
}
|
|
// If we get to here both a and b have the same highest mode so have to resort to lexicographical sorting
|
|
|
|
} else if (b_modes.length > 0) {
|
|
// b has modes but a doesn't so b should appear first
|
|
return 1;
|
|
}
|
|
a_nick = a.get("nick").toLocaleLowerCase();
|
|
b_nick = b.get("nick").toLocaleLowerCase();
|
|
// Lexicographical sorting
|
|
if (a_nick < b_nick) {
|
|
return -1;
|
|
} else if (a_nick > b_nick) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
},
|
|
|
|
|
|
initialize: function (options) {
|
|
this.view = new _kiwi.view.MemberList({"model": this});
|
|
this.initNickCache();
|
|
},
|
|
|
|
|
|
/*
|
|
* Keep a reference to each member by the nick. Speeds up .getByNick()
|
|
* so it doesn't need to loop over every model for each nick lookup
|
|
*/
|
|
initNickCache: function() {
|
|
var updateRegex = _.bind(function () {
|
|
// Allows checking for a nick that contains 'the_nick' or '<punctuation>the_nick<punctuation>'
|
|
// .. where <punctuation> is any character not allowed in an IRC nick
|
|
var regex_valid_nick_chars = 'a-z0-9_\\-{}[\\]^`|\\\\';
|
|
var regex_nicks = Object.keys(this.nick_cache)
|
|
.map(_.escapeRegExp)
|
|
.join('|');
|
|
|
|
this.nick_regex = new RegExp(
|
|
'^[^'+regex_valid_nick_chars+']?(' + regex_nicks + ')[^'+regex_valid_nick_chars+']?$', 'i'
|
|
);
|
|
}, this);
|
|
|
|
function getNick (member) {
|
|
return member.get('nick').toLowerCase();
|
|
};
|
|
|
|
this.nick_cache = Object.create(null);
|
|
this.nick_regex = null;
|
|
|
|
this.on('reset', function() {
|
|
this.nick_cache = _.reduce(this.models, function(memo, member) {
|
|
memo[getNick(member)] = member;
|
|
return memo;
|
|
}, Object.create(null));
|
|
updateRegex();
|
|
});
|
|
|
|
this.on('add', function(member) {
|
|
this.nick_cache[getNick(member)] = member;
|
|
updateRegex();
|
|
});
|
|
|
|
this.on('remove', function(member) {
|
|
delete this.nick_cache[getNick(member)];
|
|
updateRegex();
|
|
});
|
|
|
|
this.on('change:nick', function(member) {
|
|
this.nick_cache[getNick(member)] = member;
|
|
delete this.nick_cache[member.previous('nick').toLowerCase()];
|
|
updateRegex();
|
|
});
|
|
},
|
|
|
|
getByNick: function (nick) {
|
|
var matches;
|
|
if (this.nick_regex && (matches = this.nick_regex.exec(nick))) {
|
|
return this.nick_cache[matches[1].toLowerCase()];
|
|
}
|
|
}
|
|
});
|
|
|