f68e52b8d3cb8f25edc29d8ddfc77b6b6ccb27d4
[KiwiIRC.git] / client / src / views / application.js
1 _kiwi.view.Application = Backbone.View.extend({
2 initialize: function () {
3 var that = this;
4
5 this.$el.append($('#tmpl_application').html().trim());
6
7 this.elements = {
8 panels: this.$el.find('.panels'),
9 memberlists: this.$el.find('.memberlists'),
10 toolbar: this.$el.find('.toolbar'),
11 controlbox: this.$el.find('.controlbox'),
12 resize_handle: this.$el.find('.memberlists_resize_handle')
13 };
14
15 $(window).resize(function() { that.doLayout.apply(that); });
16 this.elements.toolbar.resize(function() { that.doLayout.apply(that); });
17 this.elements.controlbox.resize(function() { that.doLayout.apply(that); });
18
19 // Change the theme when the config is changed
20 _kiwi.global.settings.on('change:theme', this.updateTheme, this);
21 this.updateTheme(getQueryVariable('theme'));
22
23 _kiwi.global.settings.on('change:channel_list_style', this.setTabLayout, this);
24 this.setTabLayout(_kiwi.global.settings.get('channel_list_style'));
25
26 _kiwi.global.settings.on('change:show_timestamps', this.displayTimestamps, this);
27 this.displayTimestamps(_kiwi.global.settings.get('show_timestamps'));
28
29 this.$el.appendTo($('body'));
30 this.doLayout();
31
32 $(document).keydown(this.setKeyFocus);
33
34 // Confirmation require to leave the page
35 window.onbeforeunload = function () {
36 if (_kiwi.gateway.isConnected()) {
37 return _kiwi.global.i18n.translate('client_views_application_close_notice').fetch();
38 }
39 };
40
41 // Keep tabs on the browser having focus
42 this.has_focus = true;
43
44 $(window).on('focus', function () {
45 that.has_focus = true;
46 });
47 $(window).on('blur', function () {
48 that.has_focus = false;
49 });
50
51
52 this.favicon = new _kiwi.view.Favicon();
53 this.initSound();
54 },
55
56
57
58 updateTheme: function (theme_name) {
59 // If called by the settings callback, get the correct new_value
60 if (theme_name === _kiwi.global.settings) {
61 theme_name = arguments[1];
62 }
63
64 // If we have no theme specified, get it from the settings
65 if (!theme_name) theme_name = _kiwi.global.settings.get('theme');
66
67 // Clear any current theme
68 this.$el.removeClass(function (i, css) {
69 return (css.match(/\btheme_\S+/g) || []).join(' ');
70 });
71
72 // Apply the new theme
73 this.$el.addClass('theme_' + (theme_name || 'relaxed'));
74 },
75
76
77 setTabLayout: function (layout_style) {
78 // If called by the settings callback, get the correct new_value
79 if (layout_style === _kiwi.global.settings) {
80 layout_style = arguments[1];
81 }
82
83 if (layout_style == 'list') {
84 this.$el.addClass('chanlist_treeview');
85 } else {
86 this.$el.removeClass('chanlist_treeview');
87 }
88
89 this.doLayout();
90 },
91
92
93 displayTimestamps: function (show_timestamps) {
94 // If called by the settings callback, get the correct new_value
95 if (show_timestamps === _kiwi.global.settings) {
96 show_timestamps = arguments[1];
97 }
98
99 if (show_timestamps) {
100 this.$el.addClass('timestamps');
101 } else {
102 this.$el.removeClass('timestamps');
103 }
104 },
105
106
107 // Globally shift focus to the command input box on a keypress
108 setKeyFocus: function (ev) {
109 // If we're copying text, don't shift focus
110 if (ev.ctrlKey || ev.altKey || ev.metaKey) {
111 return;
112 }
113
114 // If we're typing into an input box somewhere, ignore
115 if ((ev.target.tagName.toLowerCase() === 'input') || (ev.target.tagName.toLowerCase() === 'textarea') || $(ev.target).attr('contenteditable')) {
116 return;
117 }
118
119 $('#kiwi .controlbox .inp').focus();
120 },
121
122
123 doLayout: function () {
124 var el_kiwi = this.$el;
125 var el_panels = this.elements.panels;
126 var el_memberlists = this.elements.memberlists;
127 var el_toolbar = this.elements.toolbar;
128 var el_controlbox = this.elements.controlbox;
129 var el_resize_handle = this.elements.resize_handle;
130
131 if (!el_kiwi.is(':visible')) {
132 return;
133 }
134
135 var css_heights = {
136 top: el_toolbar.outerHeight(true),
137 bottom: el_controlbox.outerHeight(true)
138 };
139
140
141 // If any elements are not visible, full size the panals instead
142 if (!el_toolbar.is(':visible')) {
143 css_heights.top = 0;
144 }
145
146 if (!el_controlbox.is(':visible')) {
147 css_heights.bottom = 0;
148 }
149
150 // Apply the CSS sizes
151 el_panels.css(css_heights);
152 el_memberlists.css(css_heights);
153 el_resize_handle.css(css_heights);
154
155 // If we have channel tabs on the side, adjust the height
156 if (el_kiwi.hasClass('chanlist_treeview')) {
157 this.$el.find('.tabs', el_kiwi).css(css_heights);
158 }
159
160 // Determine if we have a narrow window (mobile/tablet/or even small desktop window)
161 if (el_kiwi.outerWidth() < 400) {
162 el_kiwi.addClass('narrow');
163 } else {
164 el_kiwi.removeClass('narrow');
165 }
166
167 // Set the panels width depending on the memberlist visibility
168 if (el_memberlists.css('display') != 'none') {
169 // Panels to the side of the memberlist
170 el_panels.css('right', el_memberlists.outerWidth(true));
171 // The resize handle sits overlapping the panels and memberlist
172 el_resize_handle.css('left', el_memberlists.position().left - (el_resize_handle.outerWidth(true) / 2));
173 } else {
174 // Memberlist is hidden so panels to the right edge
175 el_panels.css('right', 0);
176 // And move the handle just out of sight to the right
177 el_resize_handle.css('left', el_panels.outerWidth(true));
178 }
179
180 var input_wrap_width = parseInt($('#kiwi .controlbox .input_tools').outerWidth());
181 el_controlbox.find('.input_wrap').css('right', input_wrap_width + 7);
182 },
183
184
185 alertWindow: function (title) {
186 if (!this.alertWindowTimer) {
187 this.alertWindowTimer = new (function () {
188 var that = this;
189 var tmr;
190 var has_focus = true;
191 var state = 0;
192 var default_title = 'Kiwi IRC';
193 var title = 'Kiwi IRC';
194
195 this.setTitle = function (new_title) {
196 new_title = new_title || default_title;
197 window.document.title = new_title;
198 return new_title;
199 };
200
201 this.start = function (new_title) {
202 // Don't alert if we already have focus
203 if (has_focus) return;
204
205 title = new_title;
206 if (tmr) return;
207 tmr = setInterval(this.update, 1000);
208 };
209
210 this.stop = function () {
211 // Stop the timer and clear the title
212 if (tmr) clearInterval(tmr);
213 tmr = null;
214 this.setTitle();
215
216 // Some browsers don't always update the last title correctly
217 // Wait a few seconds and then reset
218 setTimeout(this.reset, 2000);
219 };
220
221 this.reset = function () {
222 if (tmr) return;
223 that.setTitle();
224 };
225
226
227 this.update = function () {
228 if (state === 0) {
229 that.setTitle(title);
230 state = 1;
231 } else {
232 that.setTitle();
233 state = 0;
234 }
235 };
236
237 $(window).focus(function (event) {
238 has_focus = true;
239 that.stop();
240
241 // Some browsers don't always update the last title correctly
242 // Wait a few seconds and then reset
243 setTimeout(that.reset, 2000);
244 });
245
246 $(window).blur(function (event) {
247 has_focus = false;
248 });
249 })();
250 }
251
252 this.alertWindowTimer.start(title);
253 },
254
255
256 barsHide: function (instant) {
257 var that = this;
258
259 if (!instant) {
260 this.$el.find('.toolbar').slideUp({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});
261 $('#kiwi .controlbox').slideUp({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});
262 } else {
263 this.$el.find('.toolbar').slideUp(0);
264 $('#kiwi .controlbox').slideUp(0);
265 this.doLayout();
266 }
267 },
268
269 barsShow: function (instant) {
270 var that = this;
271
272 if (!instant) {
273 this.$el.find('.toolbar').slideDown({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});
274 $('#kiwi .controlbox').slideDown({queue: false, duration: 400, step: $.proxy(this.doLayout, this)});
275 } else {
276 this.$el.find('.toolbar').slideDown(0);
277 $('#kiwi .controlbox').slideDown(0);
278 this.doLayout();
279 }
280 },
281
282
283 initSound: function () {
284 var that = this,
285 base_path = this.model.get('base_path');
286
287 $script(base_path + '/assets/libs/soundmanager2/soundmanager2-nodebug-jsmin.js', function() {
288 if (typeof soundManager === 'undefined')
289 return;
290
291 soundManager.setup({
292 url: base_path + '/assets/libs/soundmanager2/',
293 flashVersion: 9, // optional: shiny features (default = 8)// optional: ignore Flash where possible, use 100% HTML5 mode
294 preferFlash: true,
295
296 onready: function() {
297 that.sound_object = soundManager.createSound({
298 id: 'highlight',
299 url: base_path + '/assets/sound/highlight.mp3'
300 });
301 }
302 });
303 });
304 },
305
306
307 playSound: function (sound_id) {
308 if (!this.sound_object) return;
309
310 if (_kiwi.global.settings.get('mute_sounds'))
311 return;
312
313 soundManager.play(sound_id);
314 },
315
316
317 showNotification: function(title, message) {
318 var icon = this.model.get('base_path') + '/assets/img/ico.png';
319
320 // Check if we have notification support
321 if (!window.webkitNotifications)
322 return;
323
324 if (this.has_focus)
325 return;
326
327 if (webkitNotifications.checkPermission() === 0){
328 window.webkitNotifications.createNotification(icon, title, message).show();
329 }
330 }
331 });