Hiding new connection/startup app button if in a restricted server mode
[KiwiIRC.git] / client / src / views / controlbox.js
CommitLineData
50ac472f
D
1_kiwi.view.ControlBox = Backbone.View.extend({
2 events: {
3 'keydown .inp': 'process',
4 'click .nick': 'showNickChange'
5 },
6
7 initialize: function () {
8 var that = this;
9
10 this.buffer = []; // Stores previously run commands
11 this.buffer_pos = 0; // The current position in the buffer
12
13 this.preprocessor = new InputPreProcessor();
14 this.preprocessor.recursive_depth = 5;
15
16 // Hold tab autocomplete data
17 this.tabcomplete = {active: false, data: [], prefix: ''};
18
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)
23 return;
24
25 $('.nick', that.$el).text(connection.get('nick'));
26 });
27
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'));
31 });
32 },
33
34 showNickChange: function (ev) {
4caae868
D
35 // Nick box already open? Don't do it again
36 if (this.nick_change)
37 return;
38
39 this.nick_change = new _kiwi.view.NickChangeBox();
40 this.nick_change.render();
41
42 this.listenTo(this.nick_change, 'close', function() {
43 delete this.nick_change;
44 });
50ac472f
D
45 },
46
47 process: function (ev) {
48 var that = this,
49 inp = $(ev.currentTarget),
50 inp_val = inp.val(),
51 meta;
52
53 if (navigator.appVersion.indexOf("Mac") !== -1) {
54 meta = ev.metaKey;
55 } else {
56 meta = ev.altKey;
57 }
58
59 // If not a tab key, reset the tabcomplete data
60 if (this.tabcomplete.active && ev.keyCode !== 9) {
61 this.tabcomplete.active = false;
62 this.tabcomplete.data = [];
63 this.tabcomplete.prefix = '';
64 }
4caae868 65
50ac472f
D
66 switch (true) {
67 case (ev.keyCode === 13): // return
68 inp_val = inp_val.trim();
69
70 if (inp_val) {
71 $.each(inp_val.split('\n'), function (idx, line) {
72 that.processInput(line);
73 });
74
75 this.buffer.push(inp_val);
76 this.buffer_pos = this.buffer.length;
77 }
78
79 inp.val('');
80 return false;
81
82 break;
83
84 case (ev.keyCode === 38): // up
85 if (this.buffer_pos > 0) {
86 this.buffer_pos--;
87 inp.val(this.buffer[this.buffer_pos]);
88 }
89 //suppress browsers default behavior as it would set the cursor at the beginning
90 return false;
91
92 case (ev.keyCode === 40): // down
93 if (this.buffer_pos < this.buffer.length) {
94 this.buffer_pos++;
95 inp.val(this.buffer[this.buffer_pos]);
96 }
97 break;
98
99 case (ev.keyCode === 219 && meta): // [ + meta
100 // Find all the tab elements and get the index of the active tab
101 var $tabs = $('#kiwi .tabs').find('li[class!=connection]');
102 var cur_tab_ind = (function() {
103 for (var idx=0; idx<$tabs.length; idx++){
104 if ($($tabs[idx]).hasClass('active'))
105 return idx;
106 }
107 })();
108
109 // Work out the previous tab along. Wrap around if needed
110 if (cur_tab_ind === 0) {
111 $prev_tab = $($tabs[$tabs.length - 1]);
112 } else {
113 $prev_tab = $($tabs[cur_tab_ind - 1]);
114 }
115
116 $prev_tab.click();
117 return false;
118
119 case (ev.keyCode === 221 && meta): // ] + meta
120 // Find all the tab elements and get the index of the active tab
121 var $tabs = $('#kiwi .tabs').find('li[class!=connection]');
122 var cur_tab_ind = (function() {
123 for (var idx=0; idx<$tabs.length; idx++){
124 if ($($tabs[idx]).hasClass('active'))
125 return idx;
126 }
127 })();
128
129 // Work out the next tab along. Wrap around if needed
130 if (cur_tab_ind === $tabs.length - 1) {
131 $next_tab = $($tabs[0]);
132 } else {
133 $next_tab = $($tabs[cur_tab_ind + 1]);
134 }
135
136 $next_tab.click();
137 return false;
138
c71ae076 139 case (ev.keyCode === 9 //Check if ONLY tab is pressed
4caae868 140 && !ev.shiftKey //(user could be using some browser
c71ae076 141 && !ev.altKey //keyboard shortcut)
4caae868
D
142 && !ev.metaKey
143 && !ev.ctrlKey):
50ac472f
D
144 this.tabcomplete.active = true;
145 if (_.isEqual(this.tabcomplete.data, [])) {
146 // Get possible autocompletions
147 var ac_data = [],
148 members = _kiwi.app.panels().active.get('members');
149
150 // If we have a members list, get the models. Otherwise empty array
151 members = members ? members.models : [];
152
153 $.each(members, function (i, member) {
154 if (!member) return;
155 ac_data.push(member.get('nick'));
156 });
157
158 ac_data.push(_kiwi.app.panels().active.get('name'));
159
160 ac_data = _.sortBy(ac_data, function (nick) {
161 return nick;
162 });
163 this.tabcomplete.data = ac_data;
164 }
165
166 if (inp_val[inp[0].selectionStart - 1] === ' ') {
167 return false;
168 }
4caae868 169
50ac472f
D
170 (function () {
171 var tokens, // Words before the cursor position
172 val, // New value being built up
4caae868 173 p1, // Position in the value just before the nick
50ac472f
D
174 newnick, // New nick to be displayed (cycles through)
175 range, // TextRange for setting new text cursor position
176 nick, // Current nick in the value
177 trailing = ': '; // Text to be inserted after a tabbed nick
178
179 tokens = inp_val.substring(0, inp[0].selectionStart).split(' ');
180 if (tokens[tokens.length-1] == ':')
181 tokens.pop();
182
9a0720d3
D
183 // Only add the trailing text if not at the beginning of the line
184 if (tokens.length > 1)
185 trailing = '';
186
50ac472f
D
187 nick = tokens[tokens.length - 1];
188
189 if (this.tabcomplete.prefix === '') {
190 this.tabcomplete.prefix = nick;
191 }
192
193 this.tabcomplete.data = _.select(this.tabcomplete.data, function (n) {
194 return (n.toLowerCase().indexOf(that.tabcomplete.prefix.toLowerCase()) === 0);
195 });
196
197 if (this.tabcomplete.data.length > 0) {
198 // Get the current value before cursor position
199 p1 = inp[0].selectionStart - (nick.length);
200 val = inp_val.substr(0, p1);
201
202 // Include the current selected nick
203 newnick = this.tabcomplete.data.shift();
204 this.tabcomplete.data.push(newnick);
205 val += newnick;
206
207 if (inp_val.substr(inp[0].selectionStart, 2) !== trailing)
208 val += trailing;
209
210 // Now include the rest of the current value
211 val += inp_val.substr(inp[0].selectionStart);
212
213 inp.val(val);
214
215 // Move the cursor position to the end of the nick
216 if (inp[0].setSelectionRange) {
217 inp[0].setSelectionRange(p1 + newnick.length + trailing.length, p1 + newnick.length + trailing.length);
218 } else if (inp[0].createTextRange) { // not sure if this bit is actually needed....
219 range = inp[0].createTextRange();
220 range.collapse(true);
221 range.moveEnd('character', p1 + newnick.length + trailing.length);
222 range.moveStart('character', p1 + newnick.length + trailing.length);
223 range.select();
224 }
225 }
226 }).apply(this);
227 return false;
228 }
229 },
230
231
232 processInput: function (command_raw) {
233 var command, params,
234 pre_processed;
4caae868 235
50ac472f
D
236 // The default command
237 if (command_raw[0] !== '/' || command_raw.substr(0, 2) === '//') {
19318643
VC
238 // Remove any slash escaping at the start (ie. //)
239 command_raw = command_raw.replace(/^\/\//, '/');
50ac472f
D
240
241 // Prepend the default command
242 command_raw = '/msg ' + _kiwi.app.panels().active.get('name') + ' ' + command_raw;
243 }
244
245 // Process the raw command for any aliases
246 this.preprocessor.vars.server = _kiwi.app.connections.active_connection.get('name');
247 this.preprocessor.vars.channel = _kiwi.app.panels().active.get('name');
248 this.preprocessor.vars.destination = this.preprocessor.vars.channel;
249 command_raw = this.preprocessor.process(command_raw);
250
251 // Extract the command and parameters
19318643 252 params = command_raw.split(/\s/);
50ac472f
D
253 if (params[0][0] === '/') {
254 command = params[0].substr(1).toLowerCase();
255 params = params.splice(1, params.length - 1);
256 } else {
257 // Default command
258 command = 'msg';
259 params.unshift(_kiwi.app.panels().active.get('name'));
260 }
261
262 // Trigger the command events
263 this.trigger('command', {command: command, params: params});
264 this.trigger('command:' + command, {command: command, params: params});
265
266 // If we didn't have any listeners for this event, fire a special case
267 // TODO: This feels dirty. Should this really be done..?
268 if (!this._events['command:' + command]) {
269 this.trigger('unknown_command', {command: command, params: params});
270 }
271 },
272
273
274 addPluginIcon: function ($icon) {
275 var $tool = $('<div class="tool"></div>').append($icon);
276 this.$el.find('.input_tools').append($tool);
277 _kiwi.app.view.doLayout();
278 }
c71ae076 279});