.data('member', member);\r
});\r
},\r
- nickClick: function (x) {\r
- var $target = $(x.currentTarget).parent('li'),\r
+ nickClick: function (event) {\r
+ var $target = $(event.currentTarget).parent('li'),\r
member = $target.data('member'),\r
userbox;\r
\r
+ event.stopPropagation();\r
+\r
// If the userbox already exists here, hide it\r
if ($target.find('.userbox').length > 0) {\r
$('.userbox', this.$el).remove();\r
\r
userbox = new _kiwi.view.UserBox();\r
userbox.member = member;\r
+ userbox.channel = this.model.channel;\r
+\r
+ if (!this.model.getByNick(_kiwi.app.connections.active_connection.get('nick')).get('is_op')) {\r
+ userbox.$el.children('.if_op').remove();\r
+ }\r
\r
- // Remove any existing userboxes\r
- $('.userbox', this.$el).remove();\r
+ var menu = new _kiwi.view.MenuBox(member.get('nick') || 'User');\r
+ menu.addItem('userbox', userbox.$el);\r
+ menu.show();\r
+\r
+ // Position the userbox + menubox\r
+ (function() {\r
+ var t = event.pageY,\r
+ m_bottom = t + menu.$el.outerHeight(), // Where the bottom of menu will be\r
+ memberlist_bottom = this.$el.parent().offset().top + this.$el.parent().outerHeight();\r
+\r
+ // If the bottom of the userbox is going to be too low.. raise it\r
+ if (m_bottom > memberlist_bottom){\r
+ t = memberlist_bottom - menu.$el.outerHeight();\r
+ }\r
\r
- $target.append(userbox.$el);\r
+ // Set the new positon\r
+ menu.$el.offset({\r
+ left: _kiwi.app.view.$el.width() - menu.$el.outerWidth() - 20,\r
+ top: t\r
+ });\r
+ }).call(this);\r
},\r
show: function () {\r
$('#memberlists').children().removeClass('active');\r
events: {\r
'click .query': 'queryClick',\r
'click .info': 'infoClick',\r
- 'click .slap': 'slapClick'\r
+ 'click .slap': 'slapClick',\r
+ 'click .op': 'opClick',\r
+ 'click .deop': 'deopClick',\r
+ 'click .voice': 'voiceClick',\r
+ 'click .devoice': 'devoiceClick',\r
+ 'click .kick': 'kickClick',\r
+ 'click .ban': 'banClick'\r
},\r
\r
initialize: function () {\r
\r
queryClick: function (event) {\r
var panel = new _kiwi.model.Query({name: this.member.get('nick')});\r
- _kiwi.app.panels.add(panel);\r
+ _kiwi.app.connections.active_connection.panels.add(panel);\r
panel.view.show();\r
},\r
\r
\r
slapClick: function (event) {\r
_kiwi.app.controlbox.processInput('/slap ' + this.member.get('nick'));\r
+ },\r
+\r
+ opClick: function (event) {\r
+ _kiwi.app.controlbox.processInput('/mode ' + this.channel.get('name') + ' +o ' + this.member.get('nick'));\r
+ },\r
+\r
+ deopClick: function (event) {\r
+ _kiwi.app.controlbox.processInput('/mode ' + this.channel.get('name') + ' -o ' + this.member.get('nick'));\r
+ },\r
+\r
+ voiceClick: function (event) {\r
+ _kiwi.app.controlbox.processInput('/mode ' + this.channel.get('name') + ' +v ' + this.member.get('nick'));\r
+ },\r
+\r
+ devoiceClick: function (event) {\r
+ _kiwi.app.controlbox.processInput('/mode ' + this.channel.get('name') + ' -v ' + this.member.get('nick'));\r
+ },\r
+\r
+ kickClick: function (event) {\r
+ // TODO: Enable the use of a custom kick message\r
+ _kiwi.app.controlbox.processInput('/kick ' + this.member.get('nick') + ' Bye!');\r
+ },\r
+\r
+ banClick: function (event) {\r
+ // TODO: Set ban on host, not just on nick\r
+ _kiwi.app.controlbox.processInput('/mode ' + this.channel.get('name') + ' +b ' + this.member.get('nick') + '!*');\r
}\r
});\r
\r
\r
changeNick: function (event) {\r
var that = this;\r
- _kiwi.gateway.changeNick(this.$el.find('input').val(), function (err, val) {\r
+\r
+ event.preventDefault();\r
+\r
+ _kiwi.app.connections.active_connection.gateway.changeNick(this.$el.find('input').val(), function (err, val) {\r
that.close();\r
});\r
return false;\r
}\r
}\r
\r
-\r
_kiwi.gateway.bind('onconnect', this.networkConnected, this);\r
_kiwi.gateway.bind('connecting', this.networkConnecting, this);\r
+ _kiwi.gateway.bind('onirc_error', this.onIrcError, this);\r
+ },\r
\r
- _kiwi.gateway.bind('onirc_error', function (data) {\r
- $('button', this.$el).attr('disabled', null);\r
-\r
- if (data.error == 'nickname_in_use') {\r
- this.setStatus('Nickname already taken');\r
- this.show('nick_change');\r
- }\r
+ dispose: function() {\r
+ _kiwi.gateway.off('onconnect', this.networkConnected, this);\r
+ _kiwi.gateway.off('connecting', this.networkConnecting, this);\r
+ _kiwi.gateway.off('onirc_error', this.onIrcError, this);\r
\r
- if (data.error == 'password_mismatch') {\r
- this.setStatus('Incorrect Password');\r
- this.show('nick_change');\r
- that.$el.find('.password').select();\r
- }\r
- }, this);\r
+ this.$el.remove();\r
},\r
\r
submitForm: function (event) {\r
+ event.preventDefault();\r
+\r
+ // Make sure a nick is chosen\r
+ if (!$('input.nick', this.$el).val().trim()) {\r
+ this.setStatus('Select a nickname first!');\r
+ $('input.nick', this.$el).select();\r
+ return;\r
+ }\r
+\r
if (state === 'nick_change') {\r
this.submitNickChange(event);\r
} else {\r
}\r
\r
$('button', this.$el).attr('disabled', 1);\r
- return false;\r
+ return;\r
},\r
\r
submitLogin: function (event) {\r
// If submitting is disabled, don't do anything\r
if ($('button', this.$el).attr('disabled')) return;\r
- \r
+\r
var values = {\r
nick: $('input.nick', this.$el).val(),\r
server: $('input.server', this.$el).val(),\r
$('.status', this.$el)\r
.text(text)\r
.attr('class', 'status')\r
- .addClass(class_name)\r
+ .addClass(class_name||'')\r
.show();\r
},\r
clearStatus: function () {\r
this.setStatus('Connecting..', 'ok');\r
},\r
\r
+ onIrcError: function (data) {\r
+ $('button', this.$el).attr('disabled', null);\r
+\r
+ if (data.error == 'nickname_in_use') {\r
+ this.setStatus('Nickname already taken');\r
+ this.show('nick_change');\r
+ }\r
+\r
+ if (data.error == 'password_mismatch') {\r
+ this.setStatus('Incorrect Password');\r
+ this.show('nick_change');\r
+ that.$el.find('.password').select();\r
+ }\r
+ },\r
+\r
showError: function (event) {\r
this.setStatus('Error connecting', 'error');\r
$('button', this.$el).attr('disabled', null);\r
\r
_kiwi.view.Panel = Backbone.View.extend({\r
tagName: "div",\r
- className: "messages",\r
+ className: "panel messages",\r
+\r
events: {\r
"click .chan": "chanClick",\r
'click .media .open': 'mediaClick',\r
nick_colour_hex, nick_hex, is_highlight, msg_css_classes = '';\r
\r
// Nick highlight detecting\r
- if ((new RegExp('\\b' + _kiwi.gateway.get('nick') + '\\b', 'i')).test(msg.msg)) {\r
+ if ((new RegExp('\\b' + _kiwi.app.connections.active_connection.get('nick') + '\\b', 'i')).test(msg.msg)) {\r
is_highlight = true;\r
msg_css_classes += ' highlight';\r
}\r
\r
} else if (is_highlight) {\r
_kiwi.app.view.alertWindow('* People are talking!');\r
+ _kiwi.app.view.playSound('highlight');\r
this.alert('highlight');\r
\r
} else {\r
this.alert('activity');\r
}\r
\r
+ if (this.model.isQuery() && !this.model.isActive()) {\r
+ _kiwi.app.view.alertWindow('* People are talking!');\r
+ _kiwi.app.view.playSound('highlight');\r
+ }\r
+\r
// Update the activity counters\r
(function () {\r
// Only inrement the counters if we're not the active panel\r
var $this = this.$el;\r
\r
// Hide all other panels and show this one\r
- this.$container.children().css('display', 'none');\r
+ this.$container.children('.panel').css('display', 'none');\r
$this.css('display', 'block');\r
\r
// Show this panels memberlist\r
$('#memberlists').addClass('disabled').children().removeClass('active');\r
}\r
\r
- _kiwi.app.view.doLayout();\r
-\r
// Remove any alerts and activity counters for this panel\r
this.alert('none');\r
this.model.tab.find('.activity').text('0').addClass('zero');\r
\r
- this.trigger('active', this.model);\r
- _kiwi.app.panels.trigger('active', this.model, _kiwi.app.panels.active);\r
+ _kiwi.app.panels.trigger('active', this.model, _kiwi.app.panels().active);\r
+ this.model.trigger('active', this.model);\r
+\r
+ _kiwi.app.view.doLayout();\r
\r
this.scrollToBottom(true);\r
},\r
\r
alert: function (level) {\r
// No need to highlight if this si the active panel\r
- if (this.model == _kiwi.app.panels.active) return;\r
+ if (this.model == _kiwi.app.panels().active) return;\r
\r
var types, type_idx;\r
types = ['none', 'action', 'activity', 'highlight'];\r
// Scroll to the bottom of the panel\r
scrollToBottom: function (force_down) {\r
// If this isn't the active panel, don't scroll\r
- if (this.model !== _kiwi.app.panels.active) return;\r
+ if (this.model !== _kiwi.app.panels().active) return;\r
\r
// Don't scroll down if we're scrolled up the panel a little\r
if (force_down || this.$container.scrollTop() + this.$container.height() > this.$el.outerHeight() - 150) {\r
this.initializePanel(options);\r
this.model.bind('change:topic', this.topic, this);\r
\r
- this.$el.append('<div class="initial_loader" style="margin:1em;">Joining channel.. <span class="loader"></span></div>');\r
+ // Only show the loader if this is a channel (ie. not a query)\r
+ if (this.model.isChannel()) {\r
+ this.$el.append('<div class="initial_loader" style="margin:1em;text-align:center;">Joining channel.. <span class="loader"></span></div>');\r
+ }\r
},\r
\r
// Override the existing newMsg() method to remove the joining channel loader\r
this.$el.find('.initial_loader').slideUp(function () {\r
$(this).remove();\r
});\r
+\r
return this.constructor.__super__.newMsg.apply(this, arguments);\r
},\r
\r
if (typeof topic !== 'string' || !topic) {\r
topic = this.model.get("topic");\r
}\r
- \r
+\r
this.model.addMsg('', '== Topic for ' + this.model.get('name') + ' is: ' + topic, 'topic');\r
\r
// If this is the active channel then update the topic bar\r
- if (_kiwi.app.panels.active === this) {\r
+ if (_kiwi.app.panels().active === this) {\r
_kiwi.app.topicbar.setCurrentTopic(this.model.get("topic"));\r
}\r
}\r
});\r
\r
+\r
+\r
+// Model for this = _kiwi.model.NetworkPanelList\r
+_kiwi.view.NetworkTabs = Backbone.View.extend({\r
+ tagName: 'ul',\r
+ className: 'connections',\r
+\r
+ initialize: function() {\r
+ this.model.on('add', this.networkAdded, this);\r
+ this.model.on('remove', this.networkRemoved, this);\r
+\r
+ this.$el.appendTo($('#kiwi #tabs'));\r
+ },\r
+\r
+ networkAdded: function(network) {\r
+ $('<li class="connection"></li>')\r
+ .append(network.panels.view.$el)\r
+ .appendTo(this.$el);\r
+ },\r
+\r
+ networkRemoved: function(network) {\r
+ network.panels.view.remove();\r
+\r
+ _kiwi.app.view.doLayout();\r
+ }\r
+});\r
+\r
+\r
+\r
// Model for this = _kiwi.model.PanelList\r
_kiwi.view.Tabs = Backbone.View.extend({\r
+ tagName: 'ul',\r
+ className: 'panellist',\r
+\r
events: {\r
'click li': 'tabClick',\r
'click li .part': 'partClick'\r
\r
this.model.on('active', this.panelActive, this);\r
\r
- this.tabs_applets = $('ul.applets', this.$el);\r
- this.tabs_msg = $('ul.channels', this.$el);\r
+ // Network tabs start with a server, so determine what we are now\r
+ this.is_network = false;\r
\r
- _kiwi.gateway.on('change:name', function (gateway, new_val) {\r
- $('span', this.model.server.tab).text(new_val);\r
- }, this);\r
+ if (this.model.network) {\r
+ this.is_network = true;\r
+\r
+ this.model.network.on('change:name', function (network, new_val) {\r
+ $('span', this.model.server.tab).text(new_val);\r
+ }, this);\r
+ }\r
},\r
+\r
render: function () {\r
var that = this;\r
\r
- this.tabs_msg.empty();\r
+ this.$el.empty();\r
\r
- // Add the server tab first\r
- this.model.server.tab\r
- .data('panel_id', this.model.server.cid)\r
- .appendTo(this.tabs_msg);\r
+ if (this.is_network) {\r
+ // Add the server tab first\r
+ this.model.server.tab\r
+ .data('panel', this.model.server)\r
+ .data('connection_id', this.model.network.get('connection_id'))\r
+ .appendTo(this.$el);\r
+ }\r
\r
// Go through each panel adding its tab\r
this.model.forEach(function (panel) {\r
// If this is the server panel, ignore as it's already added\r
- if (panel == that.model.server) return;\r
+ if (this.is_network && panel == that.model.server)\r
+ return;\r
+\r
+ panel.tab.data('panel', panel);\r
+\r
+ if (this.is_network)\r
+ panel.tab.data('connection_id', this.model.network.get('connection_id'));\r
\r
- panel.tab\r
- .data('panel_id', panel.cid)\r
- .appendTo(panel.isApplet() ? this.tabs_applets : this.tabs_msg);\r
+ panel.tab.appendTo(that.$el);\r
});\r
\r
_kiwi.app.view.doLayout();\r
\r
if (panel.isServer()) {\r
panel.tab.addClass('server');\r
+ panel.tab.addClass('icon-nonexistant');\r
}\r
\r
- panel.tab.data('panel_id', panel.cid)\r
- .appendTo(panel.isApplet() ? this.tabs_applets : this.tabs_msg);\r
+ panel.tab.data('panel', panel);\r
+\r
+ if (this.is_network)\r
+ panel.tab.data('connection_id', this.model.network.get('connection_id'));\r
+\r
+ panel.tab.appendTo(this.$el);\r
\r
panel.bind('change:title', this.updateTabTitle);\r
_kiwi.app.view.doLayout();\r
\r
panelActive: function (panel, previously_active_panel) {\r
// Remove any existing tabs or part images\r
- $('.part', this.$el).remove();\r
- this.tabs_applets.children().removeClass('active');\r
- this.tabs_msg.children().removeClass('active');\r
+ _kiwi.app.view.$el.find('.panellist .part').remove();\r
+ _kiwi.app.view.$el.find('.panellist .active').removeClass('active');\r
\r
panel.tab.addClass('active');\r
\r
// Only show the part image on non-server tabs\r
if (!panel.isServer()) {\r
- panel.tab.append('<span class="part"></span>');\r
+ panel.tab.append('<span class="part icon-nonexistant"></span>');\r
}\r
},\r
\r
tabClick: function (e) {\r
var tab = $(e.currentTarget);\r
\r
- var panel = this.model.getByCid(tab.data('panel_id'));\r
+ var panel = tab.data('panel');\r
if (!panel) {\r
// A panel wasn't found for this tab... wadda fuck\r
return;\r
\r
partClick: function (e) {\r
var tab = $(e.currentTarget).parent();\r
- var panel = this.model.getByCid(tab.data('panel_id'));\r
+ var panel = this.model.getByCid(tab.data('panel'));\r
\r
// Only need to part if it's a channel\r
// If the nicklist is empty, we haven't joined the channel as yet\r
if (panel.isChannel() && panel.get('members').models.length > 0) {\r
- _kiwi.gateway.part(panel.get('name'));\r
+ this.model.network.gateway.part(panel.get('name'));\r
} else {\r
panel.close();\r
}\r
},\r
\r
next: function () {\r
- var next = _kiwi.app.panels.active.tab.next();\r
- if (!next.length) next = $('li:first', this.tabs_msgs);\r
+ var next = this.$tab_container.find('.active').next();\r
+ if (!next.length) next = $('li:first', this.$tab_container);\r
\r
next.click();\r
},\r
prev: function () {\r
- var prev = _kiwi.app.panels.active.tab.prev();\r
- if (!prev.length) prev = $('li:last', this.tabs_msgs);\r
+ var prev = this.$tab_container.find('.active').prev();\r
+ if (!prev.length) prev = $('li:last', this.$tab_container);\r
\r
prev.click();\r
}\r
inp_val = inp.text();\r
\r
// Only allow topic editing if this is a channel panel\r
- if (!_kiwi.app.panels.active.isChannel()) {\r
+ if (!_kiwi.app.panels().active.isChannel()) {\r
return false;\r
}\r
\r
// If hit return key, update the current topic\r
if (ev.keyCode === 13) {\r
- _kiwi.gateway.topic(_kiwi.app.panels.active.get('name'), inp_val);\r
+ _kiwi.gateway.topic(_kiwi.app.panels().active.get('name'), inp_val);\r
return false;\r
}\r
},\r
// Hold tab autocomplete data\r
this.tabcomplete = {active: false, data: [], prefix: ''};\r
\r
- _kiwi.gateway.bind('change:nick', function () {\r
- $('.nick', that.$el).text(this.get('nick'));\r
+ // Keep the nick view updated with nick changes\r
+ _kiwi.app.connections.on('change:nick', function(connection) {\r
+ // Only update the nick view if it's the active connection\r
+ if (connection !== _kiwi.app.connections.active_connection)\r
+ return;\r
+\r
+ $('.nick', that.$el).text(connection.get('nick'));\r
+ });\r
+\r
+ // Update our nick view as we flick between connections\r
+ _kiwi.app.connections.on('active', function(panel, connection) {\r
+ $('.nick', that.$el).text(connection.get('nick'));\r
});\r
},\r
\r
this.tabcomplete.active = true;\r
if (_.isEqual(this.tabcomplete.data, [])) {\r
// Get possible autocompletions\r
- var ac_data = [];\r
- $.each(_kiwi.app.panels.active.get('members').models, function (i, member) {\r
+ var ac_data = [],\r
+ members = _kiwi.app.panels().active.get('members');\r
+\r
+ // If we have a members list, get the models. Otherwise empty array\r
+ members = members ? members.models : [];\r
+\r
+ $.each(members, function (i, member) {\r
if (!member) return;\r
ac_data.push(member.get('nick'));\r
});\r
+\r
+ ac_data.push(_kiwi.app.panels().active.get('name'));\r
+\r
ac_data = _.sortBy(ac_data, function (nick) {\r
return nick;\r
});\r
}\r
\r
(function () {\r
- var tokens = inp_val.substring(0, inp[0].selectionStart).split(' '),\r
- val,\r
- p1,\r
- newnick,\r
- range,\r
- nick = tokens[tokens.length - 1];\r
+ var tokens, // Words before the cursor position\r
+ val, // New value being built up\r
+ p1, // Position in the value just before the nick \r
+ newnick, // New nick to be displayed (cycles through)\r
+ range, // TextRange for setting new text cursor position\r
+ nick, // Current nick in the value\r
+ trailing = ': '; // Text to be inserted after a tabbed nick\r
+\r
+ tokens = inp_val.substring(0, inp[0].selectionStart).split(' ');\r
+ if (tokens[tokens.length-1] == ':')\r
+ tokens.pop();\r
+\r
+ nick = tokens[tokens.length - 1];\r
+\r
if (this.tabcomplete.prefix === '') {\r
this.tabcomplete.prefix = nick;\r
}\r
});\r
\r
if (this.tabcomplete.data.length > 0) {\r
+ // Get the current value before cursor position\r
p1 = inp[0].selectionStart - (nick.length);\r
val = inp_val.substr(0, p1);\r
+\r
+ // Include the current selected nick\r
newnick = this.tabcomplete.data.shift();\r
this.tabcomplete.data.push(newnick);\r
val += newnick;\r
+\r
+ if (inp_val.substr(inp[0].selectionStart, 2) !== trailing)\r
+ val += trailing;\r
+\r
+ // Now include the rest of the current value\r
val += inp_val.substr(inp[0].selectionStart);\r
+\r
inp.val(val);\r
\r
+ // Move the cursor position to the end of the nick\r
if (inp[0].setSelectionRange) {\r
- inp[0].setSelectionRange(p1 + newnick.length, p1 + newnick.length);\r
+ inp[0].setSelectionRange(p1 + newnick.length + trailing.length, p1 + newnick.length + trailing.length);\r
} else if (inp[0].createTextRange) { // not sure if this bit is actually needed....\r
range = inp[0].createTextRange();\r
range.collapse(true);\r
- range.moveEnd('character', p1 + newnick.length);\r
- range.moveStart('character', p1 + newnick.length);\r
+ range.moveEnd('character', p1 + newnick.length + trailing.length);\r
+ range.moveStart('character', p1 + newnick.length + trailing.length);\r
range.select();\r
}\r
}\r
command_raw = command_raw.replace(/^\/\//, '/');\r
\r
// Prepend the default command\r
- command_raw = '/msg ' + _kiwi.app.panels.active.get('name') + ' ' + command_raw;\r
+ command_raw = '/msg ' + _kiwi.app.panels().active.get('name') + ' ' + command_raw;\r
}\r
\r
// Process the raw command for any aliases\r
- this.preprocessor.vars.server = _kiwi.gateway.get('name');\r
- this.preprocessor.vars.channel = _kiwi.app.panels.active.get('name');\r
+ this.preprocessor.vars.server = _kiwi.app.connections.active_connection.get('name');\r
+ this.preprocessor.vars.channel = _kiwi.app.panels().active.get('name');\r
this.preprocessor.vars.destination = this.preprocessor.vars.channel;\r
command_raw = this.preprocessor.process(command_raw);\r
\r
} else {\r
// Default command\r
command = 'msg';\r
- params.unshift(_kiwi.app.panels.active.get('name'));\r
+ params.unshift(_kiwi.app.panels().active.get('name'));\r
}\r
\r
// Trigger the command events\r
this.trigger('command', {command: command, params: params});\r
- this.trigger('command_' + command, {command: command, params: params});\r
+ this.trigger('command:' + command, {command: command, params: params});\r
\r
// If we didn't have any listeners for this event, fire a special case\r
// TODO: This feels dirty. Should this really be done..?\r
- if (!this._callbacks['command_' + command]) {\r
+ if (!this._callbacks['command:' + command]) {\r
this.trigger('unknown_command', {command: command, params: params});\r
}\r
+ },\r
+\r
+\r
+ addPluginIcon: function ($icon) {\r
+ var $tool = $('<div class="tool"></div>').append($icon);\r
+ this.$el.find('.input_tools').append($tool);\r
+ _kiwi.app.view.doLayout();\r
}\r
});\r
\r
opt.timeout = opt.timeout || 5000;\r
\r
this.$el.text(text).attr('class', opt.type);\r
- this.$el.slideDown(_kiwi.app.view.doLayout);\r
+ this.$el.slideDown($.proxy(_kiwi.app.view.doLayout, this));\r
\r
if (opt.timeout) this.doTimeout(opt.timeout);\r
},\r
},\r
\r
hide: function () {\r
- this.$el.slideUp(_kiwi.app.view.doLayout);\r
+ this.$el.slideUp($.proxy(_kiwi.app.view.doLayout, this));\r
},\r
\r
doTimeout: function (length) {\r
\r
_kiwi.view.Application = Backbone.View.extend({\r
initialize: function () {\r
- $(window).resize(this.doLayout);\r
- $('#toolbar').resize(this.doLayout);\r
- $('#controlbox').resize(this.doLayout);\r
+ var that = this;\r
+\r
+ $(window).resize(function() { that.doLayout.apply(that); });\r
+ $('#toolbar').resize(function() { that.doLayout.apply(that); });\r
+ $('#controlbox').resize(function() { that.doLayout.apply(that); });\r
\r
// Change the theme when the config is changed\r
_kiwi.global.settings.on('change:theme', this.updateTheme, this);\r
_kiwi.global.settings.on('change:channel_list_style', this.setTabLayout, this);\r
this.setTabLayout(_kiwi.global.settings.get('channel_list_style'));\r
\r
+ _kiwi.global.settings.on('change:show_timestamps', this.displayTimestamps, this);\r
+ this.displayTimestamps(_kiwi.global.settings.get('show_timestamps'));\r
+\r
this.doLayout();\r
\r
$(document).keydown(this.setKeyFocus);\r
return 'This will close all KiwiIRC conversations. Are you sure you want to close this window?';\r
}\r
};\r
+\r
+ this.initSound();\r
},\r
\r
\r
},\r
\r
\r
+ displayTimestamps: function (show_timestamps) {\r
+ // If called by the settings callback, get the correct new_value\r
+ if (show_timestamps === _kiwi.global.settings) {\r
+ show_timestamps = arguments[1];\r
+ }\r
+\r
+ if (show_timestamps) {\r
+ this.$el.addClass('timestamps');\r
+ } else {\r
+ this.$el.removeClass('timestamps');\r
+ }\r
+ },\r
+\r
+\r
// Globally shift focus to the command input box on a keypress\r
setKeyFocus: function (ev) {\r
// If we're copying text, don't shift focus\r
}\r
\r
// If we're typing into an input box somewhere, ignore\r
- if ((ev.target.tagName.toLowerCase() === 'input') || $(ev.target).attr('contenteditable')) {\r
+ if ((ev.target.tagName.toLowerCase() === 'input') || (ev.target.tagName.toLowerCase() === 'textarea') || $(ev.target).attr('contenteditable')) {\r
return;\r
}\r
\r
\r
\r
doLayout: function () {\r
- var el_kiwi = $('#kiwi');\r
- var el_panels = $('#panels');\r
- var el_memberlists = $('#memberlists');\r
- var el_toolbar = $('#toolbar');\r
- var el_controlbox = $('#controlbox');\r
- var el_resize_handle = $('#memberlists_resize_handle');\r
+ var el_kiwi = this.$el;\r
+ var el_panels = $('#kiwi #panels');\r
+ var el_memberlists = $('#kiwi #memberlists');\r
+ var el_toolbar = $('#kiwi #toolbar');\r
+ var el_controlbox = $('#kiwi #controlbox');\r
+ var el_resize_handle = $('#kiwi #memberlists_resize_handle');\r
\r
var css_heights = {\r
top: el_toolbar.outerHeight(true),\r
\r
// If we have channel tabs on the side, adjust the height\r
if (el_kiwi.hasClass('chanlist_treeview')) {\r
- $('#kiwi #tabs').css(css_heights);\r
+ $('#tabs', el_kiwi).css(css_heights);\r
}\r
\r
// Determine if we have a narrow window (mobile/tablet/or even small desktop window)\r
// And move the handle just out of sight to the right\r
el_resize_handle.css('left', el_panels.outerWidth(true));\r
}\r
+\r
+ var input_wrap_width = parseInt($('#kiwi #controlbox .input_tools').outerWidth());\r
+ el_controlbox.find('.input_wrap').css('right', input_wrap_width + 7);\r
},\r
\r
\r
var that = this;\r
\r
if (!instant) {\r
- $('#toolbar').slideUp({queue: false, duration: 400, step: this.doLayout});\r
- $('#controlbox').slideUp({queue: false, duration: 400, step: this.doLayout});\r
+ $('#toolbar').slideUp({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});\r
+ $('#controlbox').slideUp({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});\r
} else {\r
$('#toolbar').slideUp(0);\r
$('#controlbox').slideUp(0);\r
var that = this;\r
\r
if (!instant) {\r
- $('#toolbar').slideDown({queue: false, duration: 400, step: this.doLayout});\r
- $('#controlbox').slideDown({queue: false, duration: 400, step: this.doLayout});\r
+ $('#toolbar').slideDown({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});\r
+ $('#controlbox').slideDown({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});\r
} else {\r
$('#toolbar').slideDown(0);\r
$('#controlbox').slideDown(0);\r
this.doLayout();\r
}\r
+ },\r
+\r
+\r
+ initSound: function () {\r
+ var that = this,\r
+ base_path = this.model.get('base_path');\r
+\r
+ $script(base_path + '/assets/libs/soundmanager2/soundmanager2-nodebug-jsmin.js', function() {\r
+ if (typeof soundManager === 'undefined')\r
+ return;\r
+\r
+ soundManager.setup({\r
+ url: base_path + '/assets/libs/soundmanager2/',\r
+ flashVersion: 9, // optional: shiny features (default = 8)// optional: ignore Flash where possible, use 100% HTML5 mode\r
+ preferFlash: true,\r
+\r
+ onready: function() {\r
+ that.sound_object = soundManager.createSound({\r
+ id: 'highlight',\r
+ url: base_path + '/assets/sound/highlight.mp3'\r
+ });\r
+ }\r
+ });\r
+ });\r
+ },\r
+\r
+\r
+ playSound: function (sound_id) {\r
+ if (!this.sound_object) return;\r
+\r
+ if (_kiwi.global.settings.get('mute_sounds'))\r
+ return;\r
+ \r
+ soundManager.play(sound_id);\r
}\r
});\r
\r
\r
return html;\r
}\r
-});
\ No newline at end of file
+});\r
+\r
+\r
+\r
+_kiwi.view.MenuBox = Backbone.View.extend({\r
+ events: {\r
+ 'click .ui_menu_foot .close': 'dispose'\r
+ },\r
+\r
+ initialize: function(title) {\r
+ var that = this;\r
+\r
+ this.$el = $('<div class="ui_menu"></div>');\r
+\r
+ this._title = title || '';\r
+ this._items = {};\r
+ this._display_footer = true;\r
+ this._close_on_blur = true;\r
+\r
+ this._close_proxy = function(event) {\r
+ that.onDocumentClick(event);\r
+ };\r
+ $(document).on('click', this._close_proxy);\r
+ },\r
+\r
+\r
+ render: function() {\r
+ var that = this;\r
+\r
+ this.$el.find('*').remove();\r
+\r
+ if (this._title) {\r
+ $('<div class="ui_menu_title"></div>')\r
+ .text(this._title)\r
+ .appendTo(this.$el);\r
+ }\r
+\r
+\r
+ _.each(this._items, function(item) {\r
+ var $item = $('<div class="ui_menu_content hover"></div>')\r
+ .append(item);\r
+\r
+ that.$el.append($item);\r
+ });\r
+\r
+ if (this._display_footer)\r
+ this.$el.append('<div class="ui_menu_foot"><a class="close" onclick="">Close <i class="icon-remove"></i></a></div>');\r
+ },\r
+\r
+\r
+ onDocumentClick: function(event) {\r
+ var $target = $(event.target);\r
+\r
+ if (!this._close_on_blur)\r
+ return;\r
+\r
+ // If this is not itself AND we don't contain this element, dispose $el\r
+ if ($target[0] != this.$el[0] && this.$el.has($target).length === 0)\r
+ this.dispose();\r
+ },\r
+\r
+\r
+ dispose: function() {\r
+ _.each(this._items, function(item) {\r
+ item.dispose && item.dispose();\r
+ item.remove && item.remove();\r
+ });\r
+\r
+ this._items = null;\r
+ this.remove();\r
+\r
+ $(document).off('click', this._close_proxy);\r
+ },\r
+\r
+\r
+ addItem: function(item_name, $item) {\r
+ $item = $($item);\r
+ if ($item.is('a')) $item.addClass('icon-chevron-right');\r
+ this._items[item_name] = $item;\r
+ },\r
+\r
+\r
+ removeItem: function(item_name) {\r
+ delete this._items[item_name];\r
+ },\r
+\r
+\r
+ showFooter: function(show) {\r
+ this._display_footer = show;\r
+ },\r
+\r
+\r
+ closeOnBlur: function(close_it) {\r
+ this._close_on_blur = close_it;\r
+ },\r
+\r
+\r
+ show: function() {\r
+ this.render();\r
+ this.$el.appendTo(_kiwi.app.view.$el);\r
+ }\r
+});\r