You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

629 lines
15 KiB
JavaScript

11 years ago
"use strict";
/*global io, templates, ajaxify, utils, bootbox, RELATIVE_PATH, config, Visibility*/
11 years ago
var socket,
10 years ago
app = app || {};
app.isFocused = true;
app.isConnected = false;
app.currentRoom = null;
app.widgets = {};
app.cacheBuster = null;
(function () {
var showWelcomeMessage = false;
var reconnecting = false;
function socketIOConnect() {
var ioParams = {
reconnectionAttempts: config.maxReconnectionAttempts,
reconnectionDelay: config.reconnectionDelay,
transports: config.socketioTransports,
path: config.relative_path + '/socket.io'
};
socket = io(config.websocketAddress, ioParams);
reconnecting = false;
10 years ago
socket.on('event:connect', function () {
app.showLoginMessage();
app.replaceSelfLinks();
$(window).trigger('action:connected');
app.isConnected = true;
});
socket.on('connect', onSocketConnect);
socket.on('event:disconnect', function() {
$(window).trigger('action:disconnected');
app.isConnected = false;
socket.connect();
});
socket.on('reconnecting', function (attempt) {
reconnecting = true;
var reconnectEl = $('#reconnect');
if (!reconnectEl.hasClass('active')) {
reconnectEl.html('<i class="fa fa-spinner fa-spin"></i>');
}
reconnectEl.addClass('active').removeClass("hide").tooltip({
placement: 'bottom'
});
});
socket.on('event:banned', function() {
app.alert({
title: '[[global:alert.banned]]',
message: '[[global:alert.banned.message]]',
type: 'danger',
timeout: 1000
});
setTimeout(function() {
window.location.href = config.relative_path + '/';
}, 1000);
});
10 years ago
socket.on('event:logout', app.logout);
socket.on('event:alert', function(data) {
app.alert(data);
});
socket.on('reconnect_failed', function() {
// Wait ten times the reconnection delay and then start over
setTimeout(socket.connect.bind(socket), parseInt(config.reconnectionDelay, 10) * 10);
});
}
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
11 years ago
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;
case 'categories':
room = 'categories';
break;
}
app.currentRoom = '';
app.enterRoom(room);
11 years ago
11 years ago
socket.emit('meta.reconnected');
app.isConnected = true;
$(window).trigger('action:reconnected');
11 years ago
setTimeout(function() {
reconnectEl.removeClass('active').addClass('hide');
}, 3000);
}
}
11 years ago
app.logout = function() {
10 years ago
require(['csrf'], function(csrf) {
$.ajax(RELATIVE_PATH + '/logout', {
type: 'POST',
headers: {
'x-csrf-token': csrf.get()
},
success: function() {
window.location.href = RELATIVE_PATH + '/';
}
});
11 years ago
});
};
11 years ago
app.alert = function (params) {
require(['alerts'], function(alerts) {
alerts.alert(params);
});
};
app.removeAlert = function(id) {
require(['alerts'], function(alerts) {
alerts.remove(id);
});
11 years ago
};
app.alertSuccess = function (message, timeout) {
app.alert({
title: '[[global:alert.success]]',
message: message,
type: 'success',
timeout: timeout ? timeout : 2000
});
};
app.alertError = function (message, timeout) {
app.alert({
title: '[[global:alert.error]]',
message: message,
type: 'danger',
10 years ago
timeout: timeout ? timeout : 5000
});
};
12 years ago
app.enterRoom = function (room, callback) {
callback = callback || function() {};
12 years ago
if (socket) {
if (app.currentRoom === room) {
return;
}
socket.emit('meta.rooms.enter', {
enter: room,
10 years ago
username: app.user.username,
userslug: app.user.userslug,
picture: app.user.picture
}, function(err) {
if (err) {
app.alertError(err.message);
10 years ago
return;
}
app.currentRoom = room;
});
}
};
function highlightNavigationLink() {
var path = window.location.pathname;
$('#main-nav li').removeClass('active');
if (path) {
$('#main-nav li a').each(function () {
var href = $(this).attr('href');
11 years ago
if (href && path.startsWith(href)) {
$(this.parentNode).addClass('active');
return false;
12 years ago
}
});
}
}
app.createUserTooltips = function() {
$('img[title].teaser-pic,img[title].user-img').each(function() {
$(this).tooltip({
placement: 'top',
title: $(this).attr('title')
});
});
};
11 years ago
app.createStatusTooltips = function() {
$('body').tooltip({
selector:'.fa-circle.status',
placement: 'top'
});
};
11 years ago
app.replaceSelfLinks = function(selector) {
selector = selector || $('a');
selector.each(function() {
var href = $(this).attr('href');
10 years ago
if (href && app.user.userslug && href.indexOf('user/_self_') !== -1) {
$(this).attr('href', href.replace(/user\/_self_/g, 'user/' + app.user.userslug));
}
});
};
app.processPage = function () {
highlightNavigationLink();
12 years ago
$('.timeago').timeago();
11 years ago
utils.makeNumbersHumanReadable($('.human-readable-number'));
12 years ago
utils.addCommasToNumbers($('.formatted-number'));
app.createUserTooltips();
11 years ago
app.createStatusTooltips();
app.replaceSelfLinks();
10 years ago
// Scroll back to top of page
window.scrollTo(0, 0);
};
app.showLoginMessage = function () {
function showAlert() {
12 years ago
app.alert({
type: 'success',
10 years ago
title: '[[global:welcome_back]] ' + app.user.username + '!',
11 years ago
message: '[[global:you_have_successfully_logged_in]]',
12 years ago
timeout: 5000
});
}
12 years ago
if (showWelcomeMessage) {
showWelcomeMessage = false;
12 years ago
if (document.readyState !== 'complete') {
$(document).ready(showAlert);
} else {
showAlert();
}
}
};
12 years ago
app.openChat = function (username, touid) {
10 years ago
if (username === app.user.username) {
return app.alertError('[[error:cant-chat-with-yourself]]');
}
10 years ago
if (!app.user.uid) {
return app.alertError('[[error:not-logged-in]]');
}
require(['chat'], function (chat) {
function loadAndCenter(chatModal) {
chat.load(chatModal.attr('UUID'));
chat.center(chatModal);
10 years ago
chat.focusInput(chatModal);
}
10 years ago
if (!chat.modalExists(touid)) {
chat.createModal(username, touid, loadAndCenter);
} else {
loadAndCenter(chat.getModal(touid));
}
12 years ago
});
};
var titleObj = {
active: false,
interval: undefined,
titles: []
};
11 years ago
app.alternatingTitle = function (title) {
if (typeof title !== 'string') {
return;
}
if (title.length > 0 && !app.isFocused) {
11 years ago
if (!titleObj.titles[0]) {
titleObj.titles[0] = window.document.title;
}
11 years ago
require(['translator'], function(translator) {
translator.translate(title, function(translated) {
titleObj.titles[1] = translated;
if (titleObj.interval) {
clearInterval(titleObj.interval);
11 years ago
}
titleObj.interval = setInterval(function() {
var title = titleObj.titles[titleObj.titles.indexOf(window.document.title) ^ 1];
if (title) {
window.document.title = $('<div/>').html(title).text();
}
}, 2000);
});
11 years ago
});
} else {
if (titleObj.interval) {
clearInterval(titleObj.interval);
}
if (titleObj.titles[0]) {
window.document.title = $('<div/>').html(titleObj.titles[0]).text();
}
}
};
app.refreshTitle = function(url) {
if (!url) {
var a = document.createElement('a');
a.href = document.location;
url = a.pathname.slice(1);
}
11 years ago
socket.emit('meta.buildTitle', url, function(err, title, numNotifications) {
if (err) {
return;
}
titleObj.titles[0] = (numNotifications > 0 ? '(' + numNotifications + ') ' : '') + title;
app.alternatingTitle('');
});
};
app.toggleNavbar = function(state) {
var navbarEl = $('.navbar');
if (navbarEl) {
navbarEl.toggleClass('hidden', !!!state);
}
};
10 years ago
app.exposeConfigToTemplates = function() {
$(document).ready(function() {
templates.setGlobal('loggedIn', config.loggedIn);
templates.setGlobal('relative_path', RELATIVE_PATH);
for(var key in config) {
if (config.hasOwnProperty(key)) {
templates.setGlobal('config.' + key, config[key]);
}
}
});
};
function createHeaderTooltips() {
if (utils.findBootstrapEnvironment() === 'xs') {
return;
}
$('#header-menu li a[title]').each(function() {
11 years ago
$(this).tooltip({
placement: 'bottom',
title: $(this).attr('title')
});
});
$('#search-form').parent().tooltip({
placement: 'bottom',
title: $('#search-button i').attr('title')
});
$('#user_dropdown').tooltip({
placement: 'bottom',
title: $('#user_dropdown').attr('title')
});
}
app.handleSearch = function () {
var searchButton = $("#search-button"),
searchFields = $("#search-fields"),
searchInput = $('#search-fields input');
$('#search-form').on('submit', dismissSearch);
searchInput.on('blur', dismissSearch);
function dismissSearch(){
searchFields.hide();
searchButton.show();
}
function prepareSearch() {
searchFields.removeClass('hide').show();
searchButton.hide();
searchInput.focus();
}
searchButton.on('click', function(e) {
11 years ago
if (!config.loggedIn && !config.allowGuestSearching) {
11 years ago
app.alert({
message:'[[error:search-requires-login]]',
timeout: 3000
});
ajaxify.go('login');
return false;
}
e.stopPropagation();
prepareSearch();
return false;
});
require(['search', 'mousetrap'], function(search, Mousetrap) {
$('#search-form').on('submit', function (e) {
e.preventDefault();
10 years ago
var input = $(this).find('input');
search.query({term: input.val()}, function() {
input.val('');
});
});
$('.topic-search')
.on('click', '.prev', function() {
search.topicDOM.prev();
})
.on('click', '.next', function() {
search.topicDOM.next();
});
Mousetrap.bind('ctrl+f', function(e) {
10 years ago
if (config.topicSearchEnabled) {
// If in topic, open search window and populate, otherwise regular behaviour
var match = ajaxify.currentPage.match(/^topic\/([\d]+)/),
tid;
if (match) {
e.preventDefault();
tid = match[1];
searchInput.val('in:topic-' + tid + ' ');
prepareSearch();
}
}
});
});
}
function handleStatusChange() {
$('#user-control-list .user-status').off('click').on('click', function(e) {
var status = $(this).attr('data-status');
socket.emit('user.setStatus', status, function(err, data) {
if(err) {
return app.alertError(err.message);
}
$('#logged-in-menu #user_label #user-profile-link>i').attr('class', 'fa fa-circle status ' + status);
});
e.preventDefault();
});
}
app.updateUserStatus = function(el, status) {
if (!el.length) {
return;
}
translator.translate('[[global:' + status + ']]', function(translated) {
el.removeClass('online offline dnd away')
.addClass(status)
.attr('title', translated)
.attr('data-original-title', translated);
});
};
10 years ago
function handleNewTopic() {
$('#content').on('click', '#new_topic', function() {
require(['composer'], function(composer) {
var cid = ajaxify.variables.get('category_id');
if (cid) {
composer.newTopic(cid);
} else {
socket.emit('categories.getCategoriesByPrivilege', 'topics:create', function(err, categories) {
if (err) {
return app.alertError(err.message);
}
if (categories.length) {
composer.newTopic(categories[0].cid);
}
});
}
});
});
}
11 years ago
app.load = function() {
$('document').ready(function () {
var url = ajaxify.start(window.location.pathname.slice(1), true, window.location.search);
10 years ago
ajaxify.end(url, app.template);
handleStatusChange();
if (config.searchEnabled) {
app.handleSearch();
}
10 years ago
handleNewTopic();
$('#logout-link').on('click', app.logout);
Visibility.change(function(e, state){
if (state === 'visible') {
app.isFocused = true;
app.alternatingTitle('');
} else if (state === 'hidden') {
app.isFocused = false;
}
11 years ago
});
11 years ago
createHeaderTooltips();
app.showEmailConfirmWarning();
10 years ago
socket.removeAllListeners('event:nodebb.ready');
socket.on('event:nodebb.ready', function(cacheBusters) {
if (
!app.cacheBusters ||
app.cacheBusters.general !== cacheBusters.general ||
app.cacheBusters.css !== cacheBusters.css ||
app.cacheBusters.js !== cacheBusters.js
) {
app.cacheBusters = cacheBusters;
app.alert({
alert_id: 'forum_updated',
title: '[[global:updated.title]]',
message: '[[global:updated.message]]',
clickfn: function() {
window.location.reload();
},
type: 'warning'
});
}
});
10 years ago
require(['taskbar', 'helpers'], function(taskbar, helpers) {
taskbar.init();
10 years ago
// templates.js helpers
helpers.register();
});
});
11 years ago
};
10 years ago
app.loadJQueryUI = function(callback) {
if (typeof $().autocomplete === 'function') {
return callback();
}
$.getScript(RELATIVE_PATH + '/vendor/jquery/js/jquery-ui-1.10.4.custom.js', callback);
};
app.showEmailConfirmWarning = function(err) {
10 years ago
if (!config.requireEmailConfirmation || !app.user.uid) {
return;
}
if (!app.user.email) {
app.alert({
alert_id: 'email_confirm',
message: '[[error:no-email-to-confirm]]',
type: 'warning',
timeout: 0,
clickfn: function() {
app.removeAlert('email_confirm');
ajaxify.go('user/' + app.user.userslug + '/edit');
}
});
} else if (!app.user['email:confirmed']) {
10 years ago
app.alert({
alert_id: 'email_confirm',
message: err ? err.message : '[[error:email-not-confirmed]]',
10 years ago
type: 'warning',
timeout: 0,
clickfn: function() {
app.removeAlert('email_confirm');
socket.emit('user.emailConfirm', {}, function(err) {
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('[[notifications:email-confirm-sent]]');
});
}
});
}
};
10 years ago
11 years ago
showWelcomeMessage = window.location.href.indexOf('loggedin') !== -1;
10 years ago
app.exposeConfigToTemplates();
socketIOConnect();
app.cacheBuster = config['cache-buster'];
require(['csrf'], function(csrf) {
csrf.set(config.csrf_token);
});
bootbox.setDefaults({
locale: config.userLang
});
app.alternatingTitle('');
11 years ago
}());