1 _kiwi
.view
.ControlBox
= Backbone
.View
.extend({
3 'keydown .inp': 'process',
4 'click .nick': 'showNickChange'
7 initialize: function () {
10 this.buffer
= []; // Stores previously run commands
11 this.buffer_pos
= 0; // The current position in the buffer
13 this.preprocessor
= new InputPreProcessor();
14 this.preprocessor
.recursive_depth
= 5;
16 // Hold tab autocomplete data
17 this.tabcomplete
= {active
: false, data
: [], prefix
: ''};
19 // Keep the nick view updated with nick changes
20 _kiwi
.app
.connections
.on('change:nick', function(connection
) {
21 // Only update the nick view if it's the active connection
22 if (connection
!== _kiwi
.app
.connections
.active_connection
)
25 $('.nick', that
.$el
).text(connection
.get('nick'));
28 // Update our nick view as we flick between connections
29 _kiwi
.app
.connections
.on('active', function(panel
, connection
) {
30 $('.nick', that
.$el
).text(connection
.get('nick'));
34 showNickChange: function (ev
) {
35 (new _kiwi
.view
.NickChangeBox()).render();
38 process: function (ev
) {
40 inp
= $(ev
.currentTarget
),
44 if (navigator
.appVersion
.indexOf("Mac") !== -1) {
50 // If not a tab key, reset the tabcomplete data
51 if (this.tabcomplete
.active
&& ev
.keyCode
!== 9) {
52 this.tabcomplete
.active
= false;
53 this.tabcomplete
.data
= [];
54 this.tabcomplete
.prefix
= '';
58 case (ev
.keyCode
=== 13): // return
59 inp_val
= inp_val
.trim();
62 $.each(inp_val
.split('\n'), function (idx
, line
) {
63 that
.processInput(line
);
66 this.buffer
.push(inp_val
);
67 this.buffer_pos
= this.buffer
.length
;
75 case (ev
.keyCode
=== 38): // up
76 if (this.buffer_pos
> 0) {
78 inp
.val(this.buffer
[this.buffer_pos
]);
80 //suppress browsers default behavior as it would set the cursor at the beginning
83 case (ev
.keyCode
=== 40): // down
84 if (this.buffer_pos
< this.buffer
.length
) {
86 inp
.val(this.buffer
[this.buffer_pos
]);
90 case (ev
.keyCode
=== 219 && meta
): // [ + meta
91 // Find all the tab elements and get the index of the active tab
92 var $tabs
= $('#kiwi .tabs').find('li[class!=connection]');
93 var cur_tab_ind
= (function() {
94 for (var idx
=0; idx
<$tabs
.length
; idx
++){
95 if ($($tabs
[idx
]).hasClass('active'))
100 // Work out the previous tab along. Wrap around if needed
101 if (cur_tab_ind
=== 0) {
102 $prev_tab
= $($tabs
[$tabs
.length
- 1]);
104 $prev_tab
= $($tabs
[cur_tab_ind
- 1]);
110 case (ev
.keyCode
=== 221 && meta
): // ] + meta
111 // Find all the tab elements and get the index of the active tab
112 var $tabs
= $('#kiwi .tabs').find('li[class!=connection]');
113 var cur_tab_ind
= (function() {
114 for (var idx
=0; idx
<$tabs
.length
; idx
++){
115 if ($($tabs
[idx
]).hasClass('active'))
120 // Work out the next tab along. Wrap around if needed
121 if (cur_tab_ind
=== $tabs
.length
- 1) {
122 $next_tab
= $($tabs
[0]);
124 $next_tab
= $($tabs
[cur_tab_ind
+ 1]);
130 case (ev
.keyCode
=== 9): // tab
131 this.tabcomplete
.active
= true;
132 if (_
.isEqual(this.tabcomplete
.data
, [])) {
133 // Get possible autocompletions
135 members
= _kiwi
.app
.panels().active
.get('members');
137 // If we have a members list, get the models. Otherwise empty array
138 members
= members
? members
.models
: [];
140 $.each(members
, function (i
, member
) {
142 ac_data
.push(member
.get('nick'));
145 ac_data
.push(_kiwi
.app
.panels().active
.get('name'));
147 ac_data
= _
.sortBy(ac_data
, function (nick
) {
150 this.tabcomplete
.data
= ac_data
;
153 if (inp_val
[inp
[0].selectionStart
- 1] === ' ') {
158 var tokens
, // Words before the cursor position
159 val
, // New value being built up
160 p1
, // Position in the value just before the nick
161 newnick
, // New nick to be displayed (cycles through)
162 range
, // TextRange for setting new text cursor position
163 nick
, // Current nick in the value
164 trailing
= ': '; // Text to be inserted after a tabbed nick
166 tokens
= inp_val
.substring(0, inp
[0].selectionStart
).split(' ');
167 if (tokens
[tokens
.length
-1] == ':')
170 nick
= tokens
[tokens
.length
- 1];
172 if (this.tabcomplete
.prefix
=== '') {
173 this.tabcomplete
.prefix
= nick
;
176 this.tabcomplete
.data
= _
.select(this.tabcomplete
.data
, function (n
) {
177 return (n
.toLowerCase().indexOf(that
.tabcomplete
.prefix
.toLowerCase()) === 0);
180 if (this.tabcomplete
.data
.length
> 0) {
181 // Get the current value before cursor position
182 p1
= inp
[0].selectionStart
- (nick
.length
);
183 val
= inp_val
.substr(0, p1
);
185 // Include the current selected nick
186 newnick
= this.tabcomplete
.data
.shift();
187 this.tabcomplete
.data
.push(newnick
);
190 if (inp_val
.substr(inp
[0].selectionStart
, 2) !== trailing
)
193 // Now include the rest of the current value
194 val
+= inp_val
.substr(inp
[0].selectionStart
);
198 // Move the cursor position to the end of the nick
199 if (inp
[0].setSelectionRange
) {
200 inp
[0].setSelectionRange(p1
+ newnick
.length
+ trailing
.length
, p1
+ newnick
.length
+ trailing
.length
);
201 } else if (inp
[0].createTextRange
) { // not sure if this bit is actually needed....
202 range
= inp
[0].createTextRange();
203 range
.collapse(true);
204 range
.moveEnd('character', p1
+ newnick
.length
+ trailing
.length
);
205 range
.moveStart('character', p1
+ newnick
.length
+ trailing
.length
);
215 processInput: function (command_raw
) {
219 // The default command
220 if (command_raw
[0] !== '/' || command_raw
.substr(0, 2) === '//') {
221 // Remove any slash escaping at the start (ie. //)
222 command_raw
= command_raw
.replace(/^\/\//, '/');
224 // Prepend the default command
225 command_raw
= '/msg ' + _kiwi
.app
.panels().active
.get('name') + ' ' + command_raw
;
228 // Process the raw command for any aliases
229 this.preprocessor
.vars
.server
= _kiwi
.app
.connections
.active_connection
.get('name');
230 this.preprocessor
.vars
.channel
= _kiwi
.app
.panels().active
.get('name');
231 this.preprocessor
.vars
.destination
= this.preprocessor
.vars
.channel
;
232 command_raw
= this.preprocessor
.process(command_raw
);
234 // Extract the command and parameters
235 params
= command_raw
.split(' ');
236 if (params
[0][0] === '/') {
237 command
= params
[0].substr(1).toLowerCase();
238 params
= params
.splice(1, params
.length
- 1);
242 params
.unshift(_kiwi
.app
.panels().active
.get('name'));
245 // Trigger the command events
246 this.trigger('command', {command
: command
, params
: params
});
247 this.trigger('command:' + command
, {command
: command
, params
: params
});
249 // If we didn't have any listeners for this event, fire a special case
250 // TODO: This feels dirty. Should this really be done..?
251 if (!this._events
['command:' + command
]) {
252 this.trigger('unknown_command', {command
: command
, params
: params
});
257 addPluginIcon: function ($icon
) {
258 var $tool
= $('<div class="tool"></div>').append($icon
);
259 this.$el
.find('.input_tools').append($tool
);
260 _kiwi
.app
.view
.doLayout();