Files
NodeBB/public/src/app.js

554 lines
13 KiB
JavaScript
Raw Normal View History

2014-03-12 18:30:13 -04:00
"use strict";
/*global io, templates, translator, ajaxify, utils, RELATIVE_PATH*/
2013-04-22 19:13:39 +00:00
var socket,
config,
2013-10-07 12:57:40 -04:00
app = {
'username': null,
'uid': null,
'isFocused': true,
2014-03-11 18:46:16 -04:00
'currentRoom': null,
2014-06-02 17:42:29 -04:00
'widgets': {},
'cacheBuster': null
2014-04-03 17:36:27 -04:00
};
2013-04-22 19:13:39 +00:00
(function () {
var showWelcomeMessage = false;
var reconnecting = false;
function onSocketConnect(data) {
if (reconnecting) {
var reconnectEl = $('#reconnect');
reconnectEl.tooltip('destroy');
reconnectEl.html('<i class="fa fa-check"></i>');
reconnecting = false;
// Rejoin room that was left when we disconnected
2014-05-16 09:39:46 -04:00
var url_parts = window.location.pathname.slice(RELATIVE_PATH.length).split('/').slice(1);
var room;
switch(url_parts[0]) {
case 'user':
room = 'user/' + ajaxify.variables.get('theirid');
break;
case 'topic':
room = 'topic_' + url_parts[1];
break;
case 'category':
room = 'category_' + url_parts[1];
break;
case 'recent': // intentional fall-through
case 'unread':
room = 'recent_posts';
break;
case 'admin':
room = 'admin';
break;
default:
room = 'global';
break;
}
app.enterRoom(room, true);
2014-02-20 13:23:29 -05:00
2014-06-02 17:42:29 -04:00
socket.emit('meta.reconnected', {}, function(err, cacheBuster) {
if (app.cacheBuster !== cacheBuster) {
app.cacheBuster = cacheBuster;
app.alert({
2014-06-25 12:57:04 -04:00
alert_id: 'forum_updated',
2014-06-03 14:38:33 -04:00
title: '[[global:updated.title]]',
message: '[[global:updated.message]]',
2014-06-02 17:42:29 -04:00
clickfn: function() {
window.location.reload();
},
type: 'warning'
});
}
});
2014-06-09 01:28:58 -04:00
$(window).trigger('action:reconnected');
2014-02-20 13:23:29 -05:00
setTimeout(function() {
reconnectEl.removeClass('active').addClass("hide");
}, 3000);
}
}
2014-04-08 17:35:23 -04:00
function onConfigLoad(data) {
config = data;
2013-09-24 14:56:51 -04:00
exposeConfigToTemplates();
2013-09-24 14:56:51 -04:00
if(socket) {
socket.disconnect();
setTimeout(function() {
socket.socket.connect();
}, 200);
} else {
var ioParams = {
'max reconnection attempts': config.maxReconnectionAttempts,
'reconnection delay': config.reconnectionDelay,
resource: RELATIVE_PATH.length ? RELATIVE_PATH.slice(1) + '/socket.io' : 'socket.io'
};
if (utils.isAndroidBrowser()) {
ioParams.transports = ['xhr-polling'];
}
2013-10-07 13:00:57 -04:00
socket = io.connect('', ioParams);
reconnecting = false;
2014-02-17 12:57:37 -05:00
socket.on('event:connect', function (data) {
app.username = data.username;
2014-04-30 17:42:50 -04:00
app.userslug = data.userslug;
app.uid = data.uid;
app.isAdmin = data.isAdmin;
2014-02-17 12:57:37 -05:00
templates.setGlobal('loggedIn', parseInt(data.uid, 10) !== 0);
app.showLoginMessage();
app.replaceSelfLinks();
$(window).trigger('action:connected');
});
socket.on('event:alert', function (data) {
app.alert(data);
});
socket.on('connect', onSocketConnect);
socket.on('event:disconnect', function() {
$(window).trigger('action:disconnected');
socket.socket.connect();
});
socket.on('reconnecting', function (data, attempt) {
2014-05-01 19:01:19 -04:00
if(attempt === parseInt(config.maxReconnectionAttempts, 10)) {
socket.socket.reconnectionAttempts = 0;
socket.socket.reconnectionDelay = config.reconnectionDelay;
return;
}
reconnecting = true;
var reconnectEl = $('#reconnect');
if (!reconnectEl.hasClass('active')) {
reconnectEl.html('<i class="fa fa-spinner fa-spin"></i>');
}
2013-10-28 14:36:31 -04:00
reconnectEl.addClass('active').removeClass("hide").tooltip({
placement: 'bottom'
});
});
2013-10-28 14:36:31 -04:00
socket.on('event:banned', function() {
app.alert({
title: '[[global:alert.banned]]',
message: '[[global:alert.banned.message]]',
type: 'warning',
timeout: 1000
});
setTimeout(app.logout, 1000);
});
2014-01-16 15:25:04 -05:00
app.enterRoom('global');
// if (config.environment === 'development' && console && console.log) {
// var log = console.log;
// console.log = function() {
// log.apply(this, arguments);
// socket.emit('tools.log', arguments);
// };
// }
2014-06-09 01:28:58 -04:00
2014-06-02 17:42:29 -04:00
app.cacheBuster = config['cache-buster'];
2014-06-23 19:45:45 -04:00
bootbox.setDefaults({
locale: config.defaultLang
});
}
}
app.loadConfig = function() {
$.ajax({
url: RELATIVE_PATH + '/api/config',
success: onConfigLoad,
2013-07-11 15:50:19 -04:00
async: false
});
2013-12-08 10:38:09 -05:00
};
2013-10-28 14:36:31 -04:00
app.logout = function() {
$.post(RELATIVE_PATH + '/logout', {
_csrf: $('#csrf_token').val()
}, function() {
2013-11-26 15:28:45 -05:00
window.location.href = RELATIVE_PATH + '/';
2013-10-28 14:36:31 -04:00
});
2013-12-08 10:38:09 -05:00
};
2013-10-28 14:36:31 -04:00
app.alert = function (params) {
require(['alerts'], function(alerts) {
alerts.alert(params);
});
2013-12-08 10:38:09 -05:00
};
2014-02-26 21:58:04 -05:00
app.removeAlert = function(id) {
require(['alerts'], function(alerts) {
alerts.remove(id);
});
2014-03-12 18:30:13 -04:00
};
2014-02-26 21:58:04 -05:00
app.alertSuccess = function (message, timeout) {
app.alert({
title: '[[global:alert.success]]',
message: message,
type: 'success',
timeout: timeout ? timeout : 2000
});
2013-12-08 10:38:09 -05:00
};
app.alertError = function (message, timeout) {
app.alert({
title: '[[global:alert.error]]',
message: message,
type: 'danger',
timeout: timeout ? timeout : 2000
});
2013-12-08 10:38:09 -05:00
};
2013-06-21 17:48:12 -04:00
app.enterRoom = function (room, force) {
2013-09-17 13:03:53 -04:00
if (socket) {
if (app.currentRoom === room && !force) {
2013-07-14 21:58:11 -04:00
return;
}
socket.emit('meta.rooms.enter', {
2013-07-14 21:58:11 -04:00
'enter': room,
'leave': app.currentRoom
2013-07-14 21:58:11 -04:00
});
app.currentRoom = room;
2013-07-14 21:58:11 -04:00
}
};
function highlightNavigationLink() {
var path = window.location.pathname,
parts = path.split('/'),
2013-09-17 13:03:53 -04:00
active = parts[parts.length - 1];
$('#main-nav li').removeClass('active');
2013-09-17 13:03:53 -04:00
if (active) {
$('#main-nav li a').each(function () {
var href = $(this).attr('href');
2014-03-12 18:30:13 -04:00
if (active === "sort-posts" || active === "sort-reputation" || active === "search" || active === "latest" || active === "online") {
2013-07-22 18:29:09 -04:00
active = 'users';
2014-03-12 18:30:13 -04:00
}
2013-07-24 12:33:37 -04:00
if (href && href.match(active)) {
$(this.parentNode).addClass('active');
2013-07-22 18:29:09 -04:00
return false;
}
});
}
}
2013-11-24 22:48:58 -05:00
app.createUserTooltips = function() {
$('img[title].teaser-pic,img[title].user-img').each(function() {
$(this).tooltip({
placement: 'top',
title: $(this).attr('title')
});
});
2013-12-08 10:38:09 -05:00
};
2013-11-24 22:48:58 -05:00
2014-02-23 21:50:02 -05:00
app.createStatusTooltips = function() {
$('body').tooltip({
selector:'.fa-circle.status',
placement: 'top'
});
};
2014-02-23 21:50:02 -05:00
2014-04-30 17:42:50 -04:00
app.replaceSelfLinks = function(selector) {
selector = selector || $('a');
selector.each(function() {
var href = $(this).attr('href');
2014-04-30 17:42:50 -04:00
if (href && app.userslug) {
$(this).attr('href', href.replace(/\[self\]/g, app.userslug));
}
});
};
app.processPage = function () {
highlightNavigationLink();
2013-07-22 18:29:09 -04:00
2013-09-19 15:02:35 -04:00
$('span.timeago').timeago();
2013-11-28 11:16:52 -05:00
2014-03-31 14:43:44 -04:00
utils.makeNumbersHumanReadable($('.human-readable-number'));
2013-09-23 14:40:31 -04:00
2014-05-08 19:17:31 -04:00
utils.addCommasToNumbers($('.formatted-number'));
2013-11-24 22:48:58 -05:00
app.createUserTooltips();
2014-02-23 21:50:02 -05:00
app.createStatusTooltips();
2014-04-30 17:42:50 -04:00
app.replaceSelfLinks();
setTimeout(function () {
window.scrollTo(0, 1); // rehide address bar on mobile after page load completes.
}, 100);
2013-12-08 10:38:09 -05:00
};
app.showLoginMessage = function () {
function showAlert() {
2013-07-25 16:20:18 -04:00
app.alert({
type: 'success',
2014-02-16 11:36:11 -05:00
title: '[[global:welcome_back]] ' + app.username + '!',
message: '[[global:you_have_successfully_logged_in]]',
2013-07-25 16:20:18 -04:00
timeout: 5000
});
}
2013-09-17 13:03:53 -04:00
if (showWelcomeMessage) {
showWelcomeMessage = false;
2013-09-17 13:03:53 -04:00
if (document.readyState !== 'complete') {
$(document).ready(showAlert);
} else {
showAlert();
}
}
2013-12-08 10:38:09 -05:00
};
2013-07-25 16:20:18 -04:00
app.openChat = function (username, touid) {
if (username === app.username) {
2014-04-10 12:47:48 -04:00
return app.alertError('[[error:cant-chat-with-yourself]]');
}
2013-11-21 20:11:06 -05:00
2014-02-28 15:36:57 -05:00
if (!app.uid) {
2014-04-10 12:47:48 -04:00
return app.alertError('[[error:not-logged-in]]');
}
require(['chat'], function (chat) {
2013-09-17 13:03:53 -04:00
if (!chat.modalExists(touid)) {
chat.createModal(username, touid, loadAndCenter);
2013-08-30 14:25:59 -04:00
} else {
loadAndCenter(chat.getModal(touid));
}
function loadAndCenter(chatModal) {
chat.load(chatModal.attr('UUID'));
chat.center(chatModal);
2013-08-30 14:25:59 -04:00
}
});
2013-12-08 10:38:09 -05:00
};
2013-11-26 14:25:46 -05:00
var titleObj = {
active: false,
interval: undefined,
titles: []
};
2014-01-16 17:11:27 -05:00
app.alternatingTitle = function (title) {
if (typeof title !== 'string') {
return;
}
2014-01-19 22:38:44 +01:00
if (title.length > 0 && !app.isFocused) {
2014-05-09 17:46:10 -04:00
if (!titleObj.titles[0]) {
titleObj.titles[0] = window.document.title;
}
2014-05-09 17:57:39 -04:00
translator.translate(title, function(translated) {
titleObj.titles[1] = translated;
if (titleObj.interval) {
clearInterval(titleObj.interval);
2014-02-10 14:05:09 -05:00
}
2014-05-09 17:57:39 -04:00
titleObj.interval = setInterval(function() {
var title = titleObj.titles[titleObj.titles.indexOf(window.document.title) ^ 1];
if (title) {
window.document.title = title;
}
}, 2000);
});
} else {
if (titleObj.interval) {
clearInterval(titleObj.interval);
}
if (titleObj.titles[0]) {
window.document.title = titleObj.titles[0];
}
}
};
app.refreshTitle = function(url) {
if (!url) {
var a = document.createElement('a');
a.href = document.location;
url = a.pathname.slice(1);
}
2014-01-16 17:11:27 -05:00
socket.emit('meta.buildTitle', url, function(err, title, numNotifications) {
titleObj.titles[0] = (numNotifications > 0 ? '(' + numNotifications + ') ' : '') + title;
app.alternatingTitle('');
});
};
2014-01-31 16:21:41 -05:00
function updateOnlineStatus(uid) {
socket.emit('user.isOnline', uid, function(err, data) {
2014-01-31 22:52:11 -05:00
$('#logged-in-menu #user_label #user-profile-link>i').attr('class', 'fa fa-circle status ' + data.status);
2014-01-31 16:21:41 -05:00
});
}
function exposeConfigToTemplates() {
$(document).ready(function() {
templates.setGlobal('relative_path', RELATIVE_PATH);
for(var key in config) {
if (config.hasOwnProperty(key)) {
templates.setGlobal('config.' + key, config[key]);
}
}
});
}
function createHeaderTooltips() {
$('#header-menu li i[title]').each(function() {
$(this).parents('a').tooltip({
placement: 'bottom',
title: $(this).attr('title')
});
});
$('#search-form').parent().tooltip({
placement: 'bottom',
title: $('#search-button i').attr('title')
});
2014-01-31 16:21:41 -05:00
$('#user_dropdown').tooltip({
placement: 'bottom',
title: $('#user_dropdown').attr('title')
});
}
function handleSearch() {
2014-04-09 13:25:02 +01:00
var searchButton = $("#search-button"),
searchFields = $("#search-fields"),
searchInput = $('#search-fields input');
function dismissSearch(){
searchFields.hide();
searchButton.show();
}
searchButton.off().on('click', function(e) {
2014-06-19 18:46:01 -04:00
if (!config.isLoggedIn && !config.allowGuestSearching) {
app.alert({
message:'[[error:search-requires-login]]',
timeout: 3000
});
ajaxify.go('login');
return false;
}
e.stopPropagation();
2014-04-09 13:25:02 +01:00
searchFields.removeClass('hide').show();
$(this).hide();
2014-04-09 13:25:02 +01:00
searchInput.focus();
2014-04-09 13:25:02 +01:00
$('#search-form').on('submit', dismissSearch);
searchInput.on('blur', dismissSearch);
2014-01-20 21:41:04 -05:00
return false;
});
$('#search-form').on('submit', function () {
var input = $(this).find('input');
ajaxify.go('search/' + input.val().replace(/^[ ?#]*/, ''));
input.val('');
return false;
});
}
function collapseNavigationOnClick() {
2014-04-09 13:26:40 +01:00
$('#main-nav a, #user-control-list a, #logged-out-menu li a, #logged-in-menu .visible-xs').off('click').on('click', function() {
if($('.navbar .navbar-collapse').hasClass('in')) {
$('.navbar-header button').click();
}
});
}
2014-01-31 15:13:52 -05:00
function handleStatusChange() {
2014-01-31 16:21:41 -05:00
$('#user-control-list .user-status').off('click').on('click', function(e) {
socket.emit('user.setStatus', $(this).attr('data-status'), function(err, data) {
2014-01-31 15:13:52 -05:00
if(err) {
return app.alertError(err.message);
}
2014-01-31 16:21:41 -05:00
updateOnlineStatus(data.uid);
2014-01-31 15:13:52 -05:00
});
2014-01-31 16:21:41 -05:00
e.preventDefault();
2014-01-31 15:13:52 -05:00
});
2014-01-27 01:48:43 -05:00
}
2014-03-11 14:41:32 -04:00
app.load = function() {
$('document').ready(function () {
2014-06-16 10:28:57 +07:00
var url = ajaxify.removeRelativePath(window.location.pathname.slice(1).replace(/\/$/, "")),
2014-06-15 23:30:40 -04:00
tpl_url = ajaxify.getTemplateMapping(url),
2014-05-16 01:38:20 -04:00
search = window.location.search,
2014-05-16 09:39:46 -04:00
hash = window.location.hash,
$window = $(window);
2014-05-30 15:29:17 -04:00
2014-05-16 09:39:46 -04:00
$window.trigger('action:ajaxify.start', {
2014-03-11 14:41:32 -04:00
url: url
});
collapseNavigationOnClick();
handleStatusChange();
handleSearch();
$('#logout-link').on('click', app.logout);
2014-05-16 09:39:46 -04:00
$window.blur(function(){
2014-03-11 14:41:32 -04:00
app.isFocused = false;
});
2014-05-16 09:39:46 -04:00
$window.focus(function(){
2014-03-11 14:41:32 -04:00
app.isFocused = true;
app.alternatingTitle('');
});
2014-03-11 14:41:32 -04:00
createHeaderTooltips();
ajaxify.variables.parse();
2014-04-18 13:20:50 -04:00
ajaxify.currentPage = url;
$window.trigger('action:ajaxify.contentLoaded', {
url: url
});
if (window.history && window.history.replaceState) {
window.history.replaceState({
2014-05-16 01:38:20 -04:00
url: url + search + hash
2014-05-16 01:55:13 -04:00
}, url, RELATIVE_PATH + '/' + url + search + hash);
}
2014-03-11 14:41:32 -04:00
ajaxify.loadScript(tpl_url, function() {
ajaxify.widgets.render(tpl_url, url, function() {
app.processPage();
$window.trigger('action:ajaxify.end', {
url: url
});
2014-03-11 18:46:16 -04:00
});
2014-03-11 14:41:32 -04:00
});
});
2014-03-11 14:41:32 -04:00
};
2014-05-16 09:39:46 -04:00
showWelcomeMessage = window.location.href.indexOf('loggedin') !== -1;
2013-09-24 14:56:51 -04:00
app.loadConfig();
app.alternatingTitle('');
2014-06-23 19:45:45 -04:00
}());