Larger nicklist items when on a touchscreen
[KiwiIRC.git] / client / src / views / application.js
CommitLineData
50ac472f
D
1_kiwi.view.Application = Backbone.View.extend({
2 initialize: function () {
3 var that = this;
4
00203b94
D
5 this.$el = $($('#tmpl_application').html().trim());
6 this.el = this.$el[0];
7
8 $(this.model.get('container') || 'body').append(this.$el);
9aa4b87d 9
783fcf1f
D
10 this.elements = {
11 panels: this.$el.find('.panels'),
9936359c 12 right_bar: this.$el.find('.right_bar'),
783fcf1f
D
13 toolbar: this.$el.find('.toolbar'),
14 controlbox: this.$el.find('.controlbox'),
15 resize_handle: this.$el.find('.memberlists_resize_handle')
16 };
17
50ac472f 18 $(window).resize(function() { that.doLayout.apply(that); });
783fcf1f
D
19 this.elements.toolbar.resize(function() { that.doLayout.apply(that); });
20 this.elements.controlbox.resize(function() { that.doLayout.apply(that); });
50ac472f
D
21
22 // Change the theme when the config is changed
23 _kiwi.global.settings.on('change:theme', this.updateTheme, this);
24 this.updateTheme(getQueryVariable('theme'));
25
26 _kiwi.global.settings.on('change:channel_list_style', this.setTabLayout, this);
27 this.setTabLayout(_kiwi.global.settings.get('channel_list_style'));
28
29 _kiwi.global.settings.on('change:show_timestamps', this.displayTimestamps, this);
30 this.displayTimestamps(_kiwi.global.settings.get('show_timestamps'));
31
9aa4b87d 32 this.$el.appendTo($('body'));
50ac472f
D
33 this.doLayout();
34
35 $(document).keydown(this.setKeyFocus);
36
37 // Confirmation require to leave the page
38 window.onbeforeunload = function () {
39 if (_kiwi.gateway.isConnected()) {
247dd7ac 40 return _kiwi.global.i18n.translate('client_views_application_close_notice').fetch();
50ac472f
D
41 }
42 };
43
ee2f0962
D
44 // Keep tabs on the browser having focus
45 this.has_focus = true;
46
c012a0e5 47 $(window).on('focus', function windowOnFocus() {
ee2f0962
D
48 that.has_focus = true;
49 });
c012a0e5 50 $(window).on('blur', function windowOnBlur() {
ee2f0962
D
51 that.has_focus = false;
52 });
53
c012a0e5
D
54 // If we get a touchstart event, make note of it so we know we're using a touchscreen
55 $(window).on('touchstart', function windowOnTouchstart() {
56 that.$el.addClass('touch');
57 $(window).off('touchstart', windowOnTouchstart);
58 });
59
ee2f0962 60
0b7949de 61 this.favicon = new _kiwi.view.Favicon();
50ac472f 62 this.initSound();
68c7f7c0
CC
63
64 this.monitorPanelFallback();
50ac472f
D
65 },
66
67
68
69 updateTheme: function (theme_name) {
70 // If called by the settings callback, get the correct new_value
71 if (theme_name === _kiwi.global.settings) {
72 theme_name = arguments[1];
73 }
74
75 // If we have no theme specified, get it from the settings
05934d33
JA
76 if (!theme_name) theme_name = _kiwi.global.settings.get('theme') || 'relaxed';
77
78 theme_name = theme_name.toLowerCase();
50ac472f
D
79
80 // Clear any current theme
f80d5a6b 81 $('[data-theme]:not([disabled])').each(function (idx, link) {
05934d33 82 var $link = $(link);
15dc5f90 83 $link.attr('rel', 'alternate ' + $link.attr('rel')).attr('disabled', true)[0].disabled = true;
50ac472f
D
84 });
85
86 // Apply the new theme
f80d5a6b 87 var link = $('[data-theme][title=' + theme_name + ']');
05934d33 88 if (link.length > 0) {
15dc5f90 89 link.attr('rel', 'stylesheet').attr('disabled', false)[0].disabled = false;
05934d33 90 }
f7c668a5
D
91
92 this.doLayout();
50ac472f
D
93 },
94
95
96 setTabLayout: function (layout_style) {
97 // If called by the settings callback, get the correct new_value
98 if (layout_style === _kiwi.global.settings) {
99 layout_style = arguments[1];
100 }
ee2f0962 101
50ac472f
D
102 if (layout_style == 'list') {
103 this.$el.addClass('chanlist_treeview');
104 } else {
105 this.$el.removeClass('chanlist_treeview');
106 }
ee2f0962 107
50ac472f
D
108 this.doLayout();
109 },
110
111
112 displayTimestamps: function (show_timestamps) {
113 // If called by the settings callback, get the correct new_value
114 if (show_timestamps === _kiwi.global.settings) {
115 show_timestamps = arguments[1];
116 }
117
118 if (show_timestamps) {
119 this.$el.addClass('timestamps');
120 } else {
121 this.$el.removeClass('timestamps');
122 }
123 },
124
125
126 // Globally shift focus to the command input box on a keypress
127 setKeyFocus: function (ev) {
128 // If we're copying text, don't shift focus
129 if (ev.ctrlKey || ev.altKey || ev.metaKey) {
130 return;
131 }
132
133 // If we're typing into an input box somewhere, ignore
134 if ((ev.target.tagName.toLowerCase() === 'input') || (ev.target.tagName.toLowerCase() === 'textarea') || $(ev.target).attr('contenteditable')) {
135 return;
136 }
137
138 $('#kiwi .controlbox .inp').focus();
139 },
140
141
142 doLayout: function () {
89aa6dc0
D
143 var $kiwi = this.$el;
144 var $panels = this.elements.panels;
145 var $right_bar = this.elements.right_bar;
146 var $toolbar = this.elements.toolbar;
147 var $controlbox = this.elements.controlbox;
148 var $resize_handle = this.elements.resize_handle;
149
150 if (!$kiwi.is(':visible')) {
9aa4b87d
D
151 return;
152 }
153
50ac472f 154 var css_heights = {
89aa6dc0
D
155 top: $toolbar.outerHeight(true),
156 bottom: $controlbox.outerHeight(true)
50ac472f
D
157 };
158
159
160 // If any elements are not visible, full size the panals instead
89aa6dc0 161 if (!$toolbar.is(':visible')) {
50ac472f
D
162 css_heights.top = 0;
163 }
164
89aa6dc0 165 if (!$controlbox.is(':visible')) {
50ac472f
D
166 css_heights.bottom = 0;
167 }
168
169 // Apply the CSS sizes
89aa6dc0
D
170 $panels.css(css_heights);
171 $right_bar.css(css_heights);
172 $resize_handle.css(css_heights);
50ac472f
D
173
174 // If we have channel tabs on the side, adjust the height
89aa6dc0
D
175 if ($kiwi.hasClass('chanlist_treeview')) {
176 this.$el.find('.tabs', $kiwi).css(css_heights);
50ac472f
D
177 }
178
179 // Determine if we have a narrow window (mobile/tablet/or even small desktop window)
89aa6dc0
D
180 if ($kiwi.outerWidth() < 420) {
181 $kiwi.addClass('narrow');
95d37c14
D
182 if (this.model.rightbar && this.model.rightbar.keep_hidden !== true)
183 this.model.rightbar.toggle(true);
50ac472f 184 } else {
89aa6dc0 185 $kiwi.removeClass('narrow');
95d37c14
D
186 if (this.model.rightbar && this.model.rightbar.keep_hidden !== false)
187 this.model.rightbar.toggle(false);
50ac472f
D
188 }
189
190 // Set the panels width depending on the memberlist visibility
89aa6dc0 191 if (!$right_bar.hasClass('disabled')) {
50ac472f 192 // Panels to the side of the memberlist
89aa6dc0 193 $panels.css('right', $right_bar.outerWidth(true));
50ac472f 194 // The resize handle sits overlapping the panels and memberlist
89aa6dc0 195 $resize_handle.css('left', $right_bar.position().left - ($resize_handle.outerWidth(true) / 2));
50ac472f
D
196 } else {
197 // Memberlist is hidden so panels to the right edge
89aa6dc0 198 $panels.css('right', 0);
50ac472f 199 // And move the handle just out of sight to the right
89aa6dc0 200 $resize_handle.css('left', $panels.outerWidth(true));
50ac472f
D
201 }
202
2fe671c0 203 var input_wrap_width = parseInt($controlbox.find('.input_tools').outerWidth(), 10);
89aa6dc0 204 $controlbox.find('.input_wrap').css('right', input_wrap_width + 7);
50ac472f
D
205 },
206
207
208 alertWindow: function (title) {
209 if (!this.alertWindowTimer) {
210 this.alertWindowTimer = new (function () {
211 var that = this;
212 var tmr;
213 var has_focus = true;
214 var state = 0;
73b7cc44 215 var default_title = _kiwi.app.server_settings.client.window_title || 'Kiwi IRC';
50ac472f
D
216 var title = 'Kiwi IRC';
217
218 this.setTitle = function (new_title) {
219 new_title = new_title || default_title;
220 window.document.title = new_title;
221 return new_title;
222 };
223
224 this.start = function (new_title) {
225 // Don't alert if we already have focus
226 if (has_focus) return;
227
228 title = new_title;
229 if (tmr) return;
230 tmr = setInterval(this.update, 1000);
231 };
232
233 this.stop = function () {
234 // Stop the timer and clear the title
235 if (tmr) clearInterval(tmr);
236 tmr = null;
237 this.setTitle();
238
239 // Some browsers don't always update the last title correctly
240 // Wait a few seconds and then reset
241 setTimeout(this.reset, 2000);
242 };
243
244 this.reset = function () {
245 if (tmr) return;
246 that.setTitle();
247 };
248
249
250 this.update = function () {
251 if (state === 0) {
252 that.setTitle(title);
253 state = 1;
254 } else {
255 that.setTitle();
256 state = 0;
257 }
258 };
259
260 $(window).focus(function (event) {
261 has_focus = true;
262 that.stop();
263
264 // Some browsers don't always update the last title correctly
265 // Wait a few seconds and then reset
266 setTimeout(that.reset, 2000);
267 });
268
269 $(window).blur(function (event) {
270 has_focus = false;
271 });
272 })();
273 }
274
275 this.alertWindowTimer.start(title);
276 },
277
278
279 barsHide: function (instant) {
280 var that = this;
281
282 if (!instant) {
283 this.$el.find('.toolbar').slideUp({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});
284 $('#kiwi .controlbox').slideUp({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});
285 } else {
286 this.$el.find('.toolbar').slideUp(0);
287 $('#kiwi .controlbox').slideUp(0);
288 this.doLayout();
289 }
290 },
291
292 barsShow: function (instant) {
293 var that = this;
294
295 if (!instant) {
296 this.$el.find('.toolbar').slideDown({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});
297 $('#kiwi .controlbox').slideDown({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});
298 } else {
299 this.$el.find('.toolbar').slideDown(0);
300 $('#kiwi .controlbox').slideDown(0);
301 this.doLayout();
302 }
303 },
304
305
306 initSound: function () {
307 var that = this,
308 base_path = this.model.get('base_path');
309
310 $script(base_path + '/assets/libs/soundmanager2/soundmanager2-nodebug-jsmin.js', function() {
311 if (typeof soundManager === 'undefined')
312 return;
313
314 soundManager.setup({
315 url: base_path + '/assets/libs/soundmanager2/',
316 flashVersion: 9, // optional: shiny features (default = 8)// optional: ignore Flash where possible, use 100% HTML5 mode
317 preferFlash: true,
318
319 onready: function() {
320 that.sound_object = soundManager.createSound({
321 id: 'highlight',
322 url: base_path + '/assets/sound/highlight.mp3'
323 });
324 }
325 });
326 });
327 },
328
329
330 playSound: function (sound_id) {
331 if (!this.sound_object) return;
332
333 if (_kiwi.global.settings.get('mute_sounds'))
334 return;
ee2f0962 335
50ac472f 336 soundManager.play(sound_id);
d70c63d4
K
337 },
338
ee2f0962
D
339
340 showNotification: function(title, message) {
98bc1a84
D
341 var icon = this.model.get('base_path') + '/assets/img/ico.png',
342 notification;
ee2f0962
D
343
344 if (this.has_focus)
345 return;
346
98bc1a84
D
347 // Different versions of Chrome/firefox have different implimentations
348 if ('Notification' in window && Notification.permission && Notification.permission === 'granted') {
349 notification = new Notification(title, {icon: icon, body: message});
350
351 } else if ('webkitNotifications' in window && webkitNotifications.checkPermission() === 0) {
352 notification = window.webkitNotifications.createNotification(icon, title, message);
353
354 } else if ('mozNotification' in navigator) {
355 notification = navigator.mozNotification.createNotification(title, message, icon);
ee2f0962 356 }
98bc1a84
D
357
358 if (!notification) {
359 // Couldn't find any notification support
360 return;
361 }
362
363 setTimeout(function() {
364 (notification.cancel || notification.close).call(notification);
365 }, 5000);
68c7f7c0
CC
366 },
367
368 monitorPanelFallback: function() {
369 var panel_access = [];
370
371 this.model.panels.on('active', function() {
372 var panel = _kiwi.app.panels().active,
373 panel_index;
374
375 // If the panel is already open, remove it so we can put it back in first place
376 panel_index = _.indexOf(panel_access, panel.cid);
377
378 if (panel_index > -1) {
379 panel_access.splice(panel_index, 1);
380 }
381
382 //Make this panel the most recently accessed
383 panel_access.unshift(panel.cid);
384 });
2fe671c0 385
d1925bdf
CC
386 this.model.panels.on('remove', function(panel) {
387 // If closing the active panel, switch to the last-accessed panel
388 if (panel_access[0] === panel.cid) {
389 panel_access.shift();
390
391 //Get the last-accessed panel model now that we removed the closed one
392 var model = _.find(_kiwi.app.panels('applets').concat(_kiwi.app.panels('connections')), {cid: panel_access[0]});
393
394 if (model) {
395 model.view.show();
396 }
397 }
398 });
50ac472f 399 }
d70c63d4 400});