... not sure why that didn't all go through in one commit

v1.18.x
psychobunny 11 years ago
parent b51c90dcb3
commit 0f759f9df4

@ -1,336 +0,0 @@
'use strict';
/* globals define, ajaxify, socket, app, config, utils, translator, bootbox */
define('forum/account/edit', ['forum/account/header', 'uploader'], function(header, uploader) {
var AccountEdit = {},
gravatarPicture = '',
uploadedPicture = '',
selectedImageType = '',
currentEmail;
AccountEdit.init = function() {
gravatarPicture = ajaxify.variables.get('gravatarpicture');
uploadedPicture = ajaxify.variables.get('uploadedpicture');
header.init();
$('#submitBtn').on('click', updateProfile);
$('#inputBirthday').datepicker({
changeMonth: true,
changeYear: true,
yearRange: '1900:+0'
});
currentEmail = $('#inputEmail').val();
handleImageChange();
handleAccountDelete();
handleImageUpload();
handleEmailConfirm();
handlePasswordChange();
updateSignature();
updateImages();
};
function updateProfile() {
var userData = {
uid: $('#inputUID').val(),
username: $('#inputUsername').val(),
email: $('#inputEmail').val(),
fullname: $('#inputFullname').val(),
website: $('#inputWebsite').val(),
birthday: $('#inputBirthday').val(),
location: $('#inputLocation').val(),
signature: $('#inputSignature').val()
};
socket.emit('user.updateProfile', userData, function(err, data) {
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('[[user:profile_update_success]]');
if (data.picture) {
$('#user-current-picture').attr('src', data.picture);
$('#user_label img').attr('src', data.picture);
}
if (data.gravatarpicture) {
$('#user-gravatar-picture').attr('src', data.gravatarpicture);
gravatarPicture = data.gravatarpicture;
}
if (data.userslug) {
var oldslug = $('.account-username-box').attr('data-userslug');
$('.account-username-box a').each(function(index) {
$(this).attr('href', $(this).attr('href').replace(oldslug, data.userslug));
});
$('.account-username-box').attr('data-userslug', data.userslug);
$('#user-profile-link').attr('href', config.relative_path + '/user/' + data.userslug);
$('#user-header-name').text(userData.username);
}
if (currentEmail !== data.email) {
currentEmail = data.email;
$('#confirm-email').removeClass('hide');
}
});
return false;
}
function handleImageChange() {
function selectImageType(type) {
$('#gravatar-box .fa-check').toggle(type === 'gravatar');
$('#uploaded-box .fa-check').toggle(type === 'uploaded');
selectedImageType = type;
}
$('#changePictureBtn').on('click', function() {
selectedImageType = '';
updateImages();
$('#change-picture-modal').modal('show');
$('#change-picture-modal').removeClass('hide');
return false;
});
$('#gravatar-box').on('click', function() {
selectImageType('gravatar');
});
$('#uploaded-box').on('click', function() {
selectImageType('uploaded');
});
$('#savePictureChangesBtn').on('click', function() {
$('#change-picture-modal').modal('hide');
if (selectedImageType) {
changeUserPicture(selectedImageType);
if (selectedImageType === 'gravatar') {
$('#user-current-picture').attr('src', gravatarPicture);
$('#user-header-picture').attr('src', gravatarPicture);
} else if (selectedImageType === 'uploaded') {
$('#user-current-picture').attr('src', uploadedPicture);
$('#user-header-picture').attr('src', uploadedPicture);
}
}
});
}
function handleAccountDelete() {
$('#deleteAccountBtn').on('click', function() {
translator.translate('[[user:delete_account_confirm]]', function(translated) {
bootbox.confirm(translated + '<p><input type="text" class="form-control" id="confirm-username" /></p>', function(confirm) {
if (!confirm) {
return;
}
if ($('#confirm-username').val() !== app.username) {
app.alertError('[[error:invalid-username]]');
return false;
} else {
socket.emit('user.deleteAccount', {}, function(err) {
if (!err) {
app.logout();
}
});
}
});
});
return false;
});
}
function handleImageUpload() {
function onUploadComplete(urlOnServer) {
urlOnServer = urlOnServer + '?' + new Date().getTime();
$('#user-current-picture').attr('src', urlOnServer);
$('#user-uploaded-picture').attr('src', urlOnServer);
$('#user-header-picture').attr('src', urlOnServer);
uploadedPicture = urlOnServer;
}
$('#upload-picture-modal').on('hide', function() {
$('#userPhotoInput').val('');
});
$('#uploadPictureBtn').on('click', function() {
$('#change-picture-modal').modal('hide');
uploader.open(config.relative_path + '/api/user/' + ajaxify.variables.get('userslug') + '/uploadpicture', {}, config.maximumProfileImageSize, function(imageUrlOnServer) {
onUploadComplete(imageUrlOnServer);
});
return false;
});
$('#uploadFromUrlBtn').on('click', function() {
$('#change-picture-modal').modal('hide');
var uploadModal = $('#upload-picture-from-url-modal');
uploadModal.modal('show').removeClass('hide');
uploadModal.find('.upload-btn').on('click', function() {
var url = uploadModal.find('#uploadFromUrl').val();
if (!url) {
return;
}
socket.emit('user.uploadProfileImageFromUrl', url, function(err, imageUrlOnServer) {
if (err) {
return app.alertError(err.message);
}
onUploadComplete(imageUrlOnServer);
uploadModal.modal('hide');
});
return false;
});
return false;
});
}
function handleEmailConfirm() {
$('#confirm-email').on('click', function() {
socket.emit('user.emailConfirm', {}, function(err) {
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('[[notifications:email-confirm-sent]]');
});
});
}
function handlePasswordChange() {
var currentPassword = $('#inputCurrentPassword');
var password_notify = $('#password-notify');
var password_confirm_notify = $('#password-confirm-notify');
var password = $('#inputNewPassword');
var password_confirm = $('#inputNewPasswordAgain');
var passwordvalid = false;
var passwordsmatch = false;
var successIcon = '<i class="fa fa-check"></i>';
function onPasswordChanged() {
passwordvalid = utils.isPasswordValid(password.val());
if (password.val().length < config.minimumPasswordLength) {
showError(password_notify, '[[user:change_password_error_length]]');
} else if (!passwordvalid) {
showError(password_notify, '[[user:change_password_error]]');
} else {
showSuccess(password_notify, successIcon);
}
}
function onPasswordConfirmChanged() {
if(password.val()) {
if (password.val() !== password_confirm.val()) {
showError(password_confirm_notify, '[[user:change_password_error_match]]');
passwordsmatch = false;
} else {
showSuccess(password_confirm_notify, successIcon);
passwordsmatch = true;
}
}
}
password.on('blur', onPasswordChanged);
password_confirm.on('blur', onPasswordConfirmChanged);
$('#changePasswordBtn').on('click', function() {
if ((passwordvalid && passwordsmatch) || app.isAdmin) {
socket.emit('user.changePassword', {
'currentPassword': currentPassword.val(),
'newPassword': password.val(),
'uid': ajaxify.variables.get('theirid')
}, function(err) {
currentPassword.val('');
password.val('');
password_confirm.val('');
passwordsmatch = false;
passwordvalid = false;
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('[[user:change_password_success]]');
});
}
return false;
});
}
function changeUserPicture(type) {
socket.emit('user.changePicture', {
type: type,
uid: ajaxify.variables.get('theirid')
}, function(err) {
if(err) {
app.alertError(err.message);
}
});
}
function updateImages() {
var currentPicture = $('#user-current-picture').attr('src');
if (gravatarPicture) {
$('#user-gravatar-picture').attr('src', gravatarPicture);
}
if (uploadedPicture) {
$('#user-uploaded-picture').attr('src', uploadedPicture);
}
$('#gravatar-box').toggle(!!gravatarPicture);
$('#uploaded-box').toggle(!!uploadedPicture);
$('#gravatar-box .fa-check').toggle(currentPicture !== uploadedPicture);
$('#uploaded-box .fa-check').toggle(currentPicture === uploadedPicture);
}
function updateSignature() {
function getSignatureCharsLeft() {
return $('#inputSignature').length ? '(' + $('#inputSignature').val().length + '/' + config.maximumSignatureLength + ')' : '';
}
$('#signatureCharCountLeft').html(getSignatureCharsLeft());
$('#inputSignature').on('keyup change', function(ev) {
$('#signatureCharCountLeft').html(getSignatureCharsLeft());
});
}
function showError(element, msg) {
translator.translate(msg, function(msg) {
element.html(msg);
element.parent()
.removeClass('alert-success')
.addClass('alert-danger');
element.show();
});
}
function showSuccess(element, msg) {
translator.translate(msg, function(msg) {
element.html(msg);
element.parent()
.removeClass('alert-danger')
.addClass('alert-success');
element.show();
});
}
return AccountEdit;
});

@ -1,45 +0,0 @@
'use strict';
/* globals define, app, utils */
define('forum/account/favourites', ['forum/account/header', 'forum/infinitescroll'], function(header, infinitescroll) {
var Favourites = {};
Favourites.init = function() {
header.init();
$('.user-favourite-posts img').addClass('img-responsive');
infinitescroll.init(loadMore);
};
function loadMore(direction) {
if (direction < 0) {
return;
}
infinitescroll.loadMore('posts.loadMoreFavourites', {
after: $('.user-favourite-posts').attr('data-nextstart')
}, function(data, done) {
if (data.posts && data.posts.length) {
onPostsLoaded(data.posts, done);
$('.user-favourite-posts').attr('data-nextstart', data.nextStart);
} else {
done();
}
});
}
function onPostsLoaded(posts, callback) {
infinitescroll.parseAndTranslate('account/favourites', 'posts', {posts: posts}, function(html) {
$('.user-favourite-posts').append(html);
html.find('img').addClass('img-responsive');
html.find('span.timeago').timeago();
app.createUserTooltips();
utils.makeNumbersHumanReadable(html.find('.human-readable-number'));
callback();
});
}
return Favourites;
});

@ -1,19 +0,0 @@
define('forum/account/followers', ['forum/account/header'], function(header) {
var Followers = {};
Followers.init = function() {
header.init();
var yourid = ajaxify.variables.get('yourid'),
theirid = ajaxify.variables.get('theirid'),
followersCount = ajaxify.variables.get('followersCount');
if (parseInt(followersCount, 10) === 0) {
$('#no-followers-notice').removeClass('hide');
}
};
return Followers;
});

@ -1,15 +0,0 @@
define('forum/account/following', ['forum/account/header'], function(header) {
var Following = {};
Following.init = function() {
header.init();
var followingCount = ajaxify.variables.get('followingCount');
if (parseInt(followingCount, 10) === 0) {
$('#no-following-notice').removeClass('hide');
}
};
return Following;
});

@ -1,34 +0,0 @@
define('forum/account/header', function() {
var AccountHeader = {};
AccountHeader.init = function() {
displayAccountMenus();
selectActivePill();
};
function displayAccountMenus() {
var yourid = ajaxify.variables.get('yourid'),
theirid = ajaxify.variables.get('theirid');
if (parseInt(yourid, 10) !== 0 && parseInt(yourid, 10) === parseInt(theirid, 10)) {
$('#editLink, #settingsLink, #favouritesLink').removeClass('hide');
} else {
$('.account-sub-links .plugin-link').each(function() {
var $this = $(this);
$this.toggleClass('hide', $this.hasClass('private'));
});
}
}
function selectActivePill() {
$('.account-sub-links li').removeClass('active').each(function() {
var href = $(this).find('a').attr('href');
if (window.location.href.indexOf(href) !== -1) {
$(this).addClass('active');
return false;
}
});
}
return AccountHeader;
});

@ -1,46 +0,0 @@
'use strict';
/* globals define, app, socket, utils */
define('forum/account/posts', ['forum/account/header', 'forum/infinitescroll'], function(header, infinitescroll) {
var AccountPosts = {};
AccountPosts.init = function() {
header.init();
$('.user-favourite-posts img').addClass('img-responsive');
infinitescroll.init(loadMore);
};
function loadMore(direction) {
if (direction < 0) {
return;
}
infinitescroll.loadMore('posts.loadMoreUserPosts', {
uid: $('.account-username-box').attr('data-uid'),
after: $('.user-favourite-posts').attr('data-nextstart')
}, function(data, done) {
if (data.posts && data.posts.length) {
onPostsLoaded(data.posts, done);
$('.user-favourite-posts').attr('data-nextstart', data.nextStart);
} else {
done();
}
});
}
function onPostsLoaded(posts, callback) {
infinitescroll.parseAndTranslate('account/posts', 'posts', {posts: posts}, function(html) {
$('.user-favourite-posts').append(html);
html.find('img').addClass('img-responsive');
html.find('span.timeago').timeago();
app.createUserTooltips();
utils.makeNumbersHumanReadable(html.find('.human-readable-number'));
callback();
});
}
return AccountPosts;
});

@ -1,127 +0,0 @@
'use strict';
/* globals define, ajaxify, app, utils, socket, translator*/
define('forum/account/profile', ['forum/account/header', 'forum/infinitescroll'], function(header, infinitescroll) {
var Account = {},
yourid,
theirid,
isFollowing;
Account.init = function() {
header.init();
yourid = ajaxify.variables.get('yourid');
theirid = ajaxify.variables.get('theirid');
isFollowing = ajaxify.variables.get('isFollowing');
app.enterRoom('user/' + theirid);
processPage();
updateButtons();
$('#follow-btn').on('click', function() {
return toggleFollow('follow');
});
$('#unfollow-btn').on('click', function() {
return toggleFollow('unfollow');
});
$('#chat-btn').on('click', function() {
app.openChat($('.account-username').html(), theirid);
});
socket.removeListener('event:user_status_change', onUserStatusChange);
socket.on('event:user_status_change', onUserStatusChange);
if (yourid !== theirid) {
socket.emit('user.increaseViewCount', theirid);
}
infinitescroll.init(loadMoreTopics);
};
function processPage() {
$('.user-recent-posts img, .post-signature img').addClass('img-responsive');
}
function updateButtons() {
var isSelfOrNotLoggedIn = yourid === theirid || parseInt(yourid, 10) === 0;
$('#follow-btn').toggleClass('hide', isFollowing || isSelfOrNotLoggedIn);
$('#unfollow-btn').toggleClass('hide', !isFollowing || isSelfOrNotLoggedIn);
$('#chat-btn').toggleClass('hide', isSelfOrNotLoggedIn);
}
function toggleFollow(type) {
socket.emit('user.' + type, {
uid: theirid
}, function(err) {
if(err) {
return app.alertError(err.message);
}
$('#follow-btn').toggleClass('hide', type === 'follow');
$('#unfollow-btn').toggleClass('hide', type === 'unfollow');
app.alertSuccess('[[global:alert.' + type + ', ' + $('.account-username').html() + ']]');
});
return false;
}
function onUserStatusChange(data) {
var onlineStatus = $('.account-online-status');
if(parseInt(ajaxify.variables.get('theirid'), 10) !== parseInt(data.uid, 10)) {
return;
}
translator.translate('[[global:' + data.status + ']]', function(translated) {
onlineStatus.attr('class', 'account-online-status fa fa-circle status ' + data.status)
.attr('title', translated)
.attr('data-original-title', translated);
});
}
function loadMoreTopics(direction) {
if(direction < 0 || !$('.user-recent-posts').length) {
return;
}
$('.loading-indicator').removeClass('hidden');
infinitescroll.loadMore('user.loadMoreRecentPosts', {
after: $('.user-recent-posts').attr('data-nextstart'),
uid: theirid
}, function(data, done) {
if (data.posts && data.posts.length) {
onPostsLoaded(data.posts, done);
$('.user-recent-posts').attr('data-nextstart', data.nextStart);
} else {
done();
}
$('.loading-indicator').addClass('hidden');
});
}
function onPostsLoaded(posts, callback) {
posts = posts.filter(function(post) {
return !$('.user-recent-posts div[data-pid=' + post.pid + ']').length;
});
if (!posts.length) {
return callback();
}
infinitescroll.parseAndTranslate('account/profile', 'posts', {posts: posts}, function(html) {
$('.user-recent-posts .loading-indicator').before(html);
html.find('span.timeago').timeago();
callback();
});
}
return Account;
});

@ -1,71 +0,0 @@
define('forum/account/settings', ['forum/account/header'], function(header) {
var AccountSettings = {};
AccountSettings.init = function() {
header.init();
$('#submitBtn').on('click', function() {
var settings = {};
$('.account').find('input, textarea, select').each(function(id, input) {
input = $(input);
var setting = input.attr('data-property');
if (input.is('select')) {
settings[setting] = input.val();
return;
}
switch (input.attr('type')) {
case 'text':
case 'textarea':
settings[setting] = input.val();
break;
case 'checkbox':
settings[setting] = input.is(':checked') ? 1 : 0;
break;
}
});
socket.emit('user.saveSettings', {uid: ajaxify.variables.get('theirid'), settings: settings}, function(err) {
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('[[success:settings-saved]]');
app.loadConfig();
if (parseInt(app.uid, 10) === parseInt(ajaxify.variables.get('theirid'), 10)) {
ajaxify.refresh();
}
});
return false;
});
socket.emit('user.getSettings', {uid: ajaxify.variables.get('theirid')}, function(err, settings) {
var inputs = $('.account').find('input, textarea, select');
inputs.each(function(index, input) {
input = $(input);
var setting = input.attr('data-property');
if (setting) {
if (input.is('select')) {
input.val(settings[setting]);
return;
}
switch (input.attr('type')) {
case 'text' :
case 'textarea' :
input.val(settings[setting]);
break;
case 'checkbox' :
input.prop('checked', !!settings[setting]);
break;
}
}
});
});
};
return AccountSettings;
});

@ -1,44 +0,0 @@
'use strict';
/* globals define, app, socket, utils */
define('forum/account/topics', ['forum/account/header', 'forum/infinitescroll'], function(header, infinitescroll) {
var AccountTopics = {};
AccountTopics.init = function() {
header.init();
infinitescroll.init(loadMore);
};
function loadMore(direction) {
if (direction < 0) {
return;
}
infinitescroll.loadMore('topics.loadMoreFromSet', {
set: 'uid:' + $('.account-username-box').attr('data-uid') + ':topics',
after: $('.user-topics').attr('data-nextstart')
}, function(data, done) {
if (data.topics && data.topics.length) {
onTopicsLoaded(data.topics, done);
$('.user-topics').attr('data-nextstart', data.nextStart);
} else {
done();
}
});
}
function onTopicsLoaded(topics, callback) {
infinitescroll.parseAndTranslate('account/topics', 'topics', {topics: topics}, function(html) {
$('#topics-container').append(html);
html.find('span.timeago').timeago();
app.createUserTooltips();
utils.makeNumbersHumanReadable(html.find('.human-readable-number'));
callback();
});
}
return AccountTopics;
});

@ -1,33 +0,0 @@
"use strict";
/* global define, app, socket */
define('forum/admin/appearance/customise', ['forum/admin/settings'], function(Settings) {
var Customise = {};
Customise.init = function() {
Settings.prepare(function() {
$('#customCSS').text($('#customCSS-holder').val());
$('#customHTML').text($('#customHTML-holder').val());
var customCSS = ace.edit("customCSS"),
customHTML = ace.edit("customHTML");
customCSS.setTheme("ace/theme/twilight");
customCSS.getSession().setMode("ace/mode/css");
customCSS.on('change', function(e) {
$('#customCSS-holder').val(customCSS.getValue());
});
customHTML.setTheme("ace/theme/twilight");
customHTML.getSession().setMode("ace/mode/html");
customHTML.on('change', function(e) {
$('#customHTML-holder').val(customHTML.getValue());
});
});
};
return Customise;
});

@ -1,73 +0,0 @@
"use strict";
/* global define, app, socket */
define('forum/admin/appearance/skins', function() {
var Skins = {};
Skins.init = function() {
var scriptEl = $('<script />');
scriptEl.attr('src', '//bootswatch.aws.af.cm/3/?callback=bootswatchListener');
$('body').append(scriptEl);
$('#bootstrap_themes').on('click', function(e){
var target = $(e.target),
action = target.attr('data-action');
if (action && action === 'use') {
var parentEl = target.parents('li'),
themeType = parentEl.attr('data-type'),
cssSrc = parentEl.attr('data-css'),
themeId = parentEl.attr('data-theme');
socket.emit('admin.themes.set', {
type: themeType,
id: themeId,
src: cssSrc
}, function(err) {
if (err) {
return app.alertError(err.message);
}
highlightSelectedTheme(themeId);
app.alert({
alert_id: 'admin:theme',
type: 'info',
title: 'Theme Changed',
message: 'Please restart your NodeBB to fully activate this theme',
timeout: 5000,
clickfn: function() {
socket.emit('admin.restart');
}
});
});
}
});
};
Skins.render = function(bootswatch) {
var themeContainer = $('#bootstrap_themes');
templates.parse('admin/partials/theme_list', {
themes: bootswatch.themes.map(function(theme) {
return {
type: 'bootswatch',
id: theme.name,
name: theme.name,
description: theme.description,
screenshot_url: theme.thumbnail,
url: theme.preview,
css: theme.cssCdn
};
})
}, function(html) {
themeContainer.html(html);
});
};
function highlightSelectedTheme(themeId) {
$('.themes li[data-theme]').removeClass('btn-warning');
$('.themes li[data-theme="' + themeId + '"]').addClass('btn-warning');
}
return Skins;
});

@ -1,93 +0,0 @@
"use strict";
/* global define, app, socket */
define('forum/admin/appearance/themes', function() {
var Themes = {};
Themes.init = function() {
$('#installed_themes').on('click', function(e){
var target = $(e.target),
action = target.attr('data-action');
if (action && action === 'use') {
var parentEl = target.parents('li'),
themeType = parentEl.attr('data-type'),
cssSrc = parentEl.attr('data-css'),
themeId = parentEl.attr('data-theme');
socket.emit('admin.themes.set', {
type: themeType,
id: themeId,
src: cssSrc
}, function(err) {
if (err) {
return app.alertError(err.message);
}
highlightSelectedTheme(themeId);
app.alert({
alert_id: 'admin:theme',
type: 'info',
title: 'Theme Changed',
message: 'Please restart your NodeBB to fully activate this theme',
timeout: 5000,
clickfn: function() {
socket.emit('admin.restart');
}
});
});
}
});
$('#revert_theme').on('click', function() {
bootbox.confirm('Are you sure you wish to remove the custom theme and restore the NodeBB default theme?', function(confirm) {
if (confirm) {
socket.emit('admin.themes.set', {
type: 'local',
id: 'nodebb-theme-vanilla'
}, function(err) {
if (err) {
return app.alertError(err.message);
}
highlightSelectedTheme('nodebb-theme-vanilla');
app.alert({
alert_id: 'admin:theme',
type: 'success',
title: 'Theme Changed',
message: 'You have successfully reverted your NodeBB back to it\'s default theme.',
timeout: 3500
});
});
}
});
});
// Installed Themes
socket.emit('admin.themes.getInstalled', function(err, themes) {
if(err) {
return app.alertError(err.message);
}
var instListEl = $('#installed_themes');
if (!themes.length) {
instListEl.append($('<li/ >').addClass('no-themes').html('No installed themes found'));
return;
} else {
templates.parse('admin/partials/theme_list', {
themes: themes
}, function(html) {
instListEl.html(html);
highlightSelectedTheme(config['theme:id']);
});
}
});
};
function highlightSelectedTheme(themeId) {
$('.themes li[data-theme]').removeClass('btn-warning');
$('.themes li[data-theme="' + themeId + '"]').addClass('btn-warning');
}
return Themes;
});

@ -1,83 +0,0 @@
"use strict";
/* global define, app, socket */
define('forum/admin/extend/plugins', function() {
var Plugins = {
init: function() {
var pluginsList = $('.plugins'),
numPlugins = pluginsList[0].querySelectorAll('li').length,
pluginID;
if (numPlugins > 0) {
pluginsList.on('click', 'button[data-action="toggleActive"]', function() {
pluginID = $(this).parents('li').attr('data-plugin-id');
var btn = $(this);
socket.emit('admin.plugins.toggleActive', pluginID, function(err, status) {
btn.html('<i class="fa fa-power-off"></i> ' + (status.active ? 'Deactivate' : 'Activate'));
btn.toggleClass('btn-warning', status.active).toggleClass('btn-success', !status.active);
app.alert({
alert_id: 'plugin_toggled',
title: 'Plugin ' + (status.active ? 'Enabled' : 'Disabled'),
message: status.active ? 'Please restart your NodeBB to fully activate this plugin' : 'Plugin successfully deactivated',
type: status.active ? 'warning' : 'success',
timeout: 5000,
clickfn: function() {
socket.emit('admin.restart');
}
});
});
});
pluginsList.on('click', 'button[data-action="toggleInstall"]', function() {
pluginID = $(this).parents('li').attr('data-plugin-id');
var btn = $(this);
var activateBtn = btn.siblings('[data-action="toggleActive"]');
btn.html(btn.html() + 'ing')
.attr('disabled', true)
.find('i').attr('class', 'fa fa-refresh fa-spin');
socket.emit('admin.plugins.toggleInstall', pluginID, function(err, status) {
if (err) {
return app.alertError(err.message);
}
if (status.installed) {
btn.html('<i class="fa fa-trash-o"></i> Uninstall');
} else {
btn.html('<i class="fa fa-download"></i> Install');
}
activateBtn.toggleClass('hidden', !status.installed);
btn.toggleClass('btn-danger', status.installed).toggleClass('btn-success', !status.installed)
.attr('disabled', false);
app.alert({
alert_id: 'plugin_toggled',
title: 'Plugin ' + (status.installed ? 'Installed' : 'Uninstalled'),
message: status.installed ? 'Plugin successfully installed, please activate the plugin.' : 'The plugin has been successfully deactivated and uninstalled.',
type: 'info',
timeout: 5000
});
});
});
$('#plugin-search').on('input propertychange', function() {
var term = $(this).val();
$('.plugins li').each(function() {
var pluginId = $(this).attr('data-plugin-id');
$(this).toggleClass('hide', pluginId && pluginId.indexOf(term) === -1);
});
});
} else {
pluginsList.append('<li><p><i>No plugins found.</i></p></li>');
}
}
};
return Plugins;
});

@ -1,198 +0,0 @@
"use strict";
/* global define, app, socket */
define('forum/admin/extend/widgets', function() {
var Widgets = {};
Widgets.init = function() {
prepareWidgets();
$('#widgets .nav-pills a').on('click', function(ev) {
var $this = $(this);
$('#widgets .nav-pills li').removeClass('active');
$this.parent().addClass('active');
$('#widgets .tab-pane').removeClass('active');
$('#widgets .tab-pane[data-template="' + $this.attr('data-template') + '"]').addClass('active');
ev.preventDefault();
return false;
});
};
function prepareWidgets() {
$('[data-location="drafts"]').insertAfter($('[data-location="drafts"]').closest('.tab-content'));
$('#widgets .available-widgets .widget-panel').draggable({
helper: function(e) {
return $(e.target).parents('.widget-panel').clone().addClass('block').width($(e.target.parentNode).width());
},
distance: 10,
connectToSortable: ".widget-area"
});
$('#widgets .available-containers .containers > [data-container-html]').draggable({
helper: function(e) {
var target = $(e.target);
target = target.attr('data-container-html') ? target : target.parents('[data-container-html]');
return target.clone().addClass('block').width(target.width()).css('opacity', '0.5');
},
distance: 10
});
function appendToggle(el) {
if (!el.hasClass('block')) {
el.addClass('block')
.droppable({
accept: '[data-container-html]',
drop: function(event, ui) {
var el = $(this);
el.find('.panel-body .container-html').val(ui.draggable.attr('data-container-html'));
el.find('.panel-body').removeClass('hidden');
},
hoverClass: "panel-info"
})
.children('.panel-heading')
.append('<div class="pull-right pointer"><span class="delete-widget"><i class="fa fa-times-circle"></i></span></div><div class="pull-left pointer"><span class="toggle-widget"><i class="fa fa-chevron-circle-down"></i></span>&nbsp;</div>')
.children('small').html('');
}
}
$('#widgets .widget-area').sortable({
update: function (event, ui) {
appendToggle(ui.item);
},
connectWith: "div"
}).on('click', '.toggle-widget', function() {
$(this).parents('.widget-panel').children('.panel-body').toggleClass('hidden');
}).on('click', '.delete-widget', function() {
var panel = $(this).parents('.widget-panel');
bootbox.confirm('Are you sure you wish to delete this widget?', function(confirm) {
if (confirm) {
panel.remove();
}
});
}).on('dblclick', '.panel-heading', function() {
$(this).parents('.widget-panel').children('.panel-body').toggleClass('hidden');
});
$('#widgets .save').on('click', saveWidgets);
function saveWidgets() {
var total = $('#widgets [data-template][data-location]').length;
$('#widgets [data-template][data-location]').each(function(i, el) {
el = $(el);
var template = el.attr('data-template'),
location = el.attr('data-location'),
area = el.children('.widget-area'),
widgets = [];
area.find('.widget-panel[data-widget]').each(function() {
var widgetData = {},
data = $(this).find('form').serializeArray();
for (var d in data) {
if (data.hasOwnProperty(d)) {
if (data[d].name) {
widgetData[data[d].name] = data[d].value;
}
}
}
widgets.push({
widget: $(this).attr('data-widget'),
data: widgetData
});
});
socket.emit('admin.widgets.set', {
template: template,
location: location,
widgets: widgets
}, function(err) {
total--;
if (err) {
app.alertError(err.message);
}
if (total === 0) {
app.alert({
alert_id: 'admin:widgets',
type: 'success',
title: 'Widgets Updated',
message: 'Successfully updated widgets',
timeout: 2500
});
}
});
});
}
function populateWidget(widget, data) {
if (data.title) {
var title = widget.find('.panel-heading strong');
title.text(title.text() + ' - ' + data.title);
}
widget.find('input, textarea').each(function() {
var input = $(this),
value = data[input.attr('name')];
if (this.type === 'checkbox') {
input.attr('checked', !!value);
} else {
input.val(value);
}
});
return widget;
}
$.get(RELATIVE_PATH + '/api/admin/extend/widgets', function(data) {
var areas = data.areas;
for(var i=0; i<areas.length; ++i) {
var area = areas[i],
widgetArea = $('#widgets .area[data-template="' + area.template + '"][data-location="' + area.location + '"]').find('.widget-area');
widgetArea.html('');
for (var k=0; k<area.data.length; ++k) {
var widgetData = area.data[k],
widgetEl = $('.available-widgets [data-widget="' + widgetData.widget + '"]').clone(true);
widgetArea.append(populateWidget(widgetEl, widgetData.data));
appendToggle(widgetEl);
}
}
});
$('.color-selector').on('click', '.btn', function() {
var btn = $(this),
selector = btn.parents('.color-selector'),
container = selector.parents('[data-container-html]'),
classList = [];
selector.children().each(function() {
classList.push($(this).attr('data-class'));
});
container
.removeClass(classList.join(' '))
.addClass(btn.attr('data-class'));
container.attr('data-container-html', container.attr('data-container-html')
.replace(/class="[a-zA-Z0-9-\s]+"/, 'class="' + container[0].className.replace(' pointer ui-draggable', '') + '"')
);
});
}
return Widgets;
});

@ -1,190 +0,0 @@
"use strict";
/*global define, app, socket, Hammer, RELATIVE_PATH */
define('forum/admin/footer', ['forum/admin/settings'], function(Settings) {
var acpIndex;
$(document).ready(function() {
if(!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
getSearchIndex();
} else {
activateMobile();
}
$(window).on('action:ajaxify.end', function(ev, data) {
var url = data.url;
selectMenuItem(data.url);
});
setupMainMenu();
});
function activateMobile() {
$('.admin').addClass('mobile');
$('#main-menu').addClass('transitioning');
Hammer(document.body).on('swiperight', function(e) {
$('#main-menu').addClass('open');
});
Hammer(document.body).on('swipeleft', function(e) {
$('#main-menu').removeClass('open');
});
Hammer($('#main-menu')[0]).on('swiperight', function(e) {
$('#main-menu').addClass('open');
});
Hammer($('#main-menu')[0]).on('swipeleft', function(e) {
$('#main-menu').removeClass('open');
});
$(window).on('scroll', function() {
$('#main-menu').height($(window).height() + 20);
});
}
function setupMainMenu() {
$('.sidebar-nav .nav-header').on('click', function() {
$(this).parents('.sidebar-nav').toggleClass('open');
setTimeout(function() {
$('.nano').nanoScroller();
}, 500); // replace with animationend event
});
$('.nano').nanoScroller();
$('#main-menu .nav-list > li a').append('<span class="pull-right"><i class="fa fa-inverse fa-arrow-circle-right"></i>&nbsp;</span>');
}
function selectMenuItem(url) {
$('#main-menu .nav-list > li').removeClass('active').each(function() {
var menu = $(this),
category = menu.parents('.sidebar-nav'),
href = menu.children('a').attr('href');
if (href && href.slice(1).indexOf(url) !== -1) {
category.addClass('open');
menu.addClass('active');
modifyBreadcrumb(category.find('.nav-header').text(), menu.text());
return false;
}
});
}
function modifyBreadcrumb() {
var caret = ' <i class="fa fa-angle-right"></i> ';
$('#breadcrumbs').html(caret + Array.prototype.slice.call(arguments).join(caret));
}
function getSearchIndex() {
$.getJSON(RELATIVE_PATH + '/templates/indexed.json', function (data) {
acpIndex = data;
for (var file in acpIndex) {
if (acpIndex.hasOwnProperty(file)) {
acpIndex[file] = acpIndex[file].replace(/<img/g, '<none'); // can't think of a better solution, see #2153
acpIndex[file] = $('<div class="search-container">' + acpIndex[file] + '</div>');
acpIndex[file].find('script').remove();
acpIndex[file] = acpIndex[file].text().toLowerCase().replace(/[ |\r|\n]+/g, ' ');
}
}
delete acpIndex['/admin/header.tpl'];
delete acpIndex['/admin/footer.tpl'];
setupACPSearch();
});
}
function setupACPSearch() {
var menu = $('#acp-search .dropdown-menu'),
routes = [],
input = $('#acp-search input'),
firstResult = null;
input.on('keyup', function() {
$('#acp-search .dropdown').addClass('open');
});
$('#acp-search').parents('form').on('submit', function(ev) {
var input = $(this).find('input'),
href = firstResult ? firstResult : RELATIVE_PATH + '/search/' + input.val();
ajaxify.go(href.replace(/^\//, ''));
setTimeout(function() {
$('#acp-search .dropdown').removeClass('open');
$(input).blur();
}, 150);
ev.preventDefault();
return false;
});
$('.sidebar-nav a').each(function(idx, link) {
routes.push($(link).attr('href'));
});
input.on('blur', function() {
$(this).val('').attr('placeholder', '/');
});
input.on('keyup focus', function() {
var $input = $(this),
value = $input.val().toLowerCase(),
menuItems = $('#acp-search .dropdown-menu').html('');
function toUpperCase(txt){
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
}
$input.attr('placeholder', '');
firstResult = null;
if (value.length >= 3) {
for (var file in acpIndex) {
if (acpIndex.hasOwnProperty(file)) {
var position = acpIndex[file].indexOf(value);
if (position !== -1) {
var href = file.replace('.tpl', ''),
title = href.replace(/^\/admin\//, '').split('/'),
description = acpIndex[file].substring(Math.max(0, position - 25), Math.min(acpIndex[file].length - 1, position + 25))
.replace(value, '<span class="search-match">' + value + '</span>');
for (var t in title) {
if (title.hasOwnProperty(t)) {
title[t] = title[t]
.replace('-', ' ')
.replace(/\w\S*/g, toUpperCase);
}
}
title = title.join(' > ');
href = RELATIVE_PATH + href;
firstResult = firstResult ? firstResult : href;
if ($.inArray(href, routes) !== -1) {
menuItems.append('<li role="presentation"><a role="menuitem" href="' + href + '">' + title + '<br /><small><code>...' + description + '...</code></small></a></li>');
}
}
}
}
if (menuItems.html() !== '') {
menuItems.append('<li role="presentation" class="divider"></li>');
}
}
if (value.length > 0) {
menuItems.append('<li role="presentation"><a role="menuitem" href="' + RELATIVE_PATH + '/search/' + value + '">Search the forum for <strong>' + value + '</strong></a></li>');
} else {
menuItems.append('<li role="presentation"><a role="menuitem" href="#">Start typing to see results...</a></li>');
}
});
}
});

@ -1,445 +0,0 @@
"use strict";
/*global define, ajaxify, app, socket, RELATIVE_PATH*/
define('forum/admin/general/dashboard', ['semver'], function(semver) {
var Admin = {},
intervals = {
rooms: false,
graphs: false
},
isMobile = false;
Admin.init = function() {
app.enterRoom('admin');
socket.emit('meta.rooms.getAll', Admin.updateRoomUsage);
isMobile = !/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
intervals.rooms = setInterval(function() {
if (app.isFocused && app.isConnected) {
socket.emit('meta.rooms.getAll', Admin.updateRoomUsage);
}
}, 5000);
$(window).on('action:ajaxify.start', function(ev, data) {
clearInterval(intervals.rooms);
clearInterval(intervals.graphs);
intervals.rooms = null;
intervals.graphs = null;
});
$('#logout-link').on('click', function() {
$.post(RELATIVE_PATH + '/logout', function() {
window.location.href = RELATIVE_PATH + '/';
});
});
$.get('https://api.github.com/repos/NodeBB/NodeBB/tags', function(releases) {
// Re-sort the releases, as they do not follow Semver (wrt pre-releases)
releases = releases.sort(function(a, b) {
a = a.name.replace(/^v/, '');
b = b.name.replace(/^v/, '');
return semver.lt(a, b) ? 1 : -1;
});
var version = $('#version').html(),
latestVersion = releases[0].name.slice(1),
checkEl = $('.version-check');
checkEl.html($('.version-check').html().replace('<i class="fa fa-spinner fa-spin"></i>', 'v' + latestVersion));
// Alter box colour accordingly
if (semver.eq(latestVersion, version)) {
checkEl.removeClass('alert-info').addClass('alert-success');
checkEl.append('<p>You are <strong>up-to-date</strong> <i class="fa fa-check"></i></p>');
} else if (semver.gt(latestVersion, version)) {
checkEl.removeClass('alert-info').addClass('alert-danger');
checkEl.append('<p>A new version (v' + latestVersion + ') has been released. Consider upgrading your NodeBB.</p>');
} else if (semver.gt(version, latestVersion)) {
checkEl.removeClass('alert-info').addClass('alert-warning');
checkEl.append('<p>You are running a <strong>development version</strong>! Unintended bugs may occur. <i class="fa fa-warning"></i></p>');
}
});
$('.restart').on('click', function() {
bootbox.confirm('Are you sure you wish to restart NodeBB?', function(confirm) {
if (confirm) {
app.alert({
alert_id: 'instance_restart',
type: 'info',
title: 'Restarting... <i class="fa fa-spin fa-refresh"></i>',
message: 'NodeBB is restarting.',
timeout: 5000
});
$(window).one('action:reconnected', function() {
app.alert({
alert_id: 'instance_restart',
type: 'success',
title: '<i class="fa fa-check"></i> Success',
message: 'NodeBB has successfully restarted.',
timeout: 5000
});
});
socket.emit('admin.restart');
}
});
});
$('.reload').on('click', function() {
app.alert({
alert_id: 'instance_reload',
type: 'info',
title: 'Reloading... <i class="fa fa-spin fa-refresh"></i>',
message: 'NodeBB is reloading.',
timeout: 5000
});
socket.emit('admin.reload', function(err) {
if (!err) {
app.alert({
alert_id: 'instance_reload',
type: 'success',
title: '<i class="fa fa-check"></i> Success',
message: 'NodeBB has successfully reloaded.',
timeout: 5000
});
} else {
app.alert({
alert_id: 'instance_reload',
type: 'danger',
title: '[[global:alert.error]]',
message: '[[error:reload-failed, ' + err.message + ']]'
});
}
});
});
setupGraphs();
};
Admin.updateRoomUsage = function(err, data) {
if (err) {
return app.alertError(err.message);
}
var html = '<div class="text-center pull-left">' +
'<div>'+ data.onlineRegisteredCount +'</div>' +
'<div>Users</div>' +
'</div>' +
'<div class="text-center pull-left">' +
'<div>'+ data.onlineGuestCount +'</div>' +
'<div>Guests</div>' +
'</div>' +
'<div class="text-center pull-left">' +
'<div>'+ (data.onlineRegisteredCount + data.onlineGuestCount) +'</div>' +
'<div>Total</div>' +
'</div>' +
'<div class="text-center pull-left">' +
'<div>'+ data.socketCount +'</div>' +
'<div>Connections</div>' +
'</div>';
var idle = data.socketCount - (data.users.home + data.users.topics + data.users.category);
updateRegisteredGraph(data.onlineRegisteredCount, data.onlineGuestCount);
updatePresenceGraph(data.users.home, data.users.topics, data.users.category, idle);
updateTopicsGraph(data.topics);
$('#active-users').html(html);
};
var graphs = {
traffic: null,
registered: null,
presence: null,
topics: null
};
var topicColors = ["#bf616a","#5B90BF","#d08770","#ebcb8b","#a3be8c","#96b5b4","#8fa1b3","#b48ead","#ab7967","#46BFBD"],
usedTopicColors = [];
// from chartjs.org
function lighten(col, amt) {
var usePound = false;
if (col[0] == "#") {
col = col.slice(1);
usePound = true;
}
var num = parseInt(col,16);
var r = (num >> 16) + amt;
if (r > 255) r = 255;
else if (r < 0) r = 0;
var b = ((num >> 8) & 0x00FF) + amt;
if (b > 255) b = 255;
else if (b < 0) b = 0;
var g = (num & 0x0000FF) + amt;
if (g > 255) g = 255;
else if (g < 0) g = 0;
return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
}
function getHoursArray() {
var currentHour = new Date().getHours(),
labels = [];
for (var i = currentHour, ii = currentHour - 12; i > ii; i--) {
var hour = i < 0 ? 24 + i : i;
labels.push(hour + ':00 ');
}
return labels.reverse();
}
function setupGraphs() {
var trafficCanvas = document.getElementById('analytics-traffic'),
registeredCanvas = document.getElementById('analytics-registered'),
presenceCanvas = document.getElementById('analytics-presence'),
topicsCanvas = document.getElementById('analytics-topics'),
trafficCtx = trafficCanvas.getContext('2d'),
registeredCtx = registeredCanvas.getContext('2d'),
presenceCtx = presenceCanvas.getContext('2d'),
topicsCtx = topicsCanvas.getContext('2d'),
trafficLabels = getHoursArray();
if (isMobile) {
Chart.defaults.global.showTooltips = false;
}
var data = {
labels: trafficLabels,
datasets: [
{
label: "Page Views",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [0,0,0,0,0,0,0,0,0,0,0,0]
},
{
label: "Unique Visitors",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [0,0,0,0,0,0,0,0,0,0,0,0]
}
]
};
trafficCanvas.width = $(trafficCanvas).parent().width(); // is this necessary
graphs.traffic = new Chart(trafficCtx).Line(data, {
responsive: true
});
graphs.registered = new Chart(registeredCtx).Doughnut([{
value: 1,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Registered Users"
},
{
value: 1,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Anonymous Users"
}], {
responsive: true
});
graphs.presence = new Chart(presenceCtx).Doughnut([{
value: 1,
color:"#F7464A",
highlight: "#FF5A5E",
label: "On homepage"
},
{
value: 1,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Reading posts"
},
{
value: 1,
color: "#FDB45C",
highlight: "#FFC870",
label: "Browsing topics"
},
{
value: 1,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Idle"
}], {
responsive: true
});
graphs.topics = new Chart(topicsCtx).Doughnut([], {responsive: true});
topicsCanvas.onclick = function(evt){
var obj = graphs.topics.getSegmentsAtEvent(evt);
window.open(RELATIVE_PATH + '/topic/' + obj[0].tid);
};
intervals.graphs = setInterval(updateTrafficGraph, 15000);
updateTrafficGraph();
$(window).on('resize', adjustPieCharts);
adjustPieCharts();
}
function adjustPieCharts() {
$('.pie-chart.legend-up').each(function() {
var $this = $(this);
if ($this.width() < 320) {
$this.addClass('compact');
} else {
$this.removeClass('compact');
}
});
}
function updateTrafficGraph() {
if (!app.isFocused || !app.isConnected) {
return;
}
socket.emit('admin.analytics.get', {graph: "traffic"}, function (err, data) {
for (var i = 0, ii = data.pageviews.length; i < ii; i++) {
graphs.traffic.datasets[0].points[i].value = data.pageviews[i];
graphs.traffic.datasets[1].points[i].value = data.uniqueVisitors[i];
}
var currentHour = new Date().getHours();
graphs.traffic.scale.xLabels = getHoursArray();
graphs.traffic.update();
});
}
function updateRegisteredGraph(registered, anonymous) {
graphs.registered.segments[0].value = registered;
graphs.registered.segments[1].value = anonymous;
graphs.registered.update();
}
function updatePresenceGraph(homepage, posts, topics, idle) {
graphs.presence.segments[0].value = homepage;
graphs.presence.segments[1].value = posts;
graphs.presence.segments[2].value = topics;
graphs.presence.segments[3].value = idle;
graphs.presence.update();
}
function updateTopicsGraph(topics) {
if (!Object.keys(topics).length) {
topics = {"0": {
title: "No users browsing",
value: 1
}};
}
var tids = Object.keys(topics),
segments = graphs.topics.segments;
function reassignExistingTopics() {
for (var i = 0, ii = segments.length; i < ii; i++ ) {
if (!segments[i]) {
continue;
}
var tid = segments[i].tid;
if ($.inArray(tid, tids) === -1) {
usedTopicColors.splice($.inArray(segments[i].color, usedTopicColors), 1);
graphs.topics.removeData(i);
} else {
graphs.topics.segments[i].value = topics[tid].value;
delete topics[tid];
}
}
}
function assignNewTopics() {
while (segments.length < 10 && tids.length > 0) {
var tid = tids.pop(),
data = topics[tid],
color = null;
if (!data) {
continue;
}
if (tid === '0') {
color = '#4D5360';
} else {
do {
for (var i = 0, ii = topicColors.length; i < ii; i++) {
var chosenColor = topicColors[i];
if ($.inArray(chosenColor, usedTopicColors) === -1) {
color = chosenColor;
usedTopicColors.push(color);
break;
}
}
} while (color === null && usedTopicColors.length < topicColors.length);
}
if (color) {
graphs.topics.addData({
value: data.value,
color: color,
highlight: lighten(color, 10),
label: data.title
});
segments[segments.length - 1].tid = tid;
}
}
}
function buildTopicsLegend() {
var legend = $('#topics-legend').html('');
for (var i = 0, ii = segments.length; i < ii; i++) {
var topic = segments[i],
label = topic.tid === '0' ? topic.label : '<a title="' + topic.label + '"href="' + RELATIVE_PATH + '/topic/' + topic.tid + '" target="_blank"> ' + topic.label + '</a>';
legend.append(
'<li>' +
'<div style="background-color: ' + topic.highlightColor + '; border-color: ' + topic.strokeColor + '"></div>' +
'<span>' + label + '</span>' +
'</li>');
}
}
reassignExistingTopics();
assignNewTopics();
buildTopicsLegend();
graphs.topics.update();
}
function buildTopicsLegend() {
}
return Admin;
});

@ -1,8 +0,0 @@
"use strict";
/*global define*/
define('forum/admin/general/languages', ['forum/admin/settings'], function(Settings) {
$(function() {
Settings.prepare();
});
});

@ -1,32 +0,0 @@
"use strict";
/* global define, socket */
define('forum/admin/general/sounds', ['sounds', 'settings'], function(Sounds, Settings) {
var SoundsAdmin = {};
SoundsAdmin.init = function() {
// Sounds tab
$('.sounds').find('button[data-action="play"]').on('click', function(e) {
e.preventDefault();
var fileName = $(this).parent().parent().find('select').val();
Sounds.playFile(fileName);
});
// Load Form Values
Settings.load('sounds', $('.sounds form'));
// Saving of Form Values
var saveEl = $('#save');
saveEl.on('click', function() {
Settings.save('sounds', $('.sounds form'), function() {
socket.emit('admin.fireEvent', {
name: 'event:sounds.reloadMapping'
});
app.alertSuccess('Settings Saved');
});
});
};
return SoundsAdmin;
});

@ -1,47 +0,0 @@
'use strict';
/* globals define, bootbox */
define(function() {
var iconSelect = {};
iconSelect.init = function(el, onModified) {
onModified = onModified || function() {};
var selected = el.attr('class').replace('fa-2x', '').replace('fa', '').replace(/\s+/g, '');
$('#icons .selected').removeClass('selected');
if (selected === '') {
selected = 'fa-doesnt-exist';
}
if (selected) {
$('#icons .fa-icons .fa.' + selected).parent().addClass('selected');
}
bootbox.confirm('<h2>Select an icon.</h2>' + $('#icons').html(), function(confirm) {
if (confirm) {
var iconClass = $('.bootbox .selected').attr('class');
var categoryIconClass = $('<div/>').addClass(iconClass).removeClass('fa').removeClass('selected').attr('class');
if (categoryIconClass === 'fa-doesnt-exist') {
categoryIconClass = '';
}
el.attr('class', 'fa fa-2x ' + categoryIconClass);
el.val(categoryIconClass);
el.attr('value', categoryIconClass);
onModified(el);
}
});
setTimeout(function() { //bootbox was rewritten for BS3 and I had to add this timeout for the previous code to work. TODO: to look into
$('.bootbox .fa-icons i').on('click', function() {
$('.bootbox .selected').removeClass('selected');
$(this).addClass('selected');
});
}, 500);
};
return iconSelect;
});

@ -1,391 +0,0 @@
"use strict";
/*global define, socket, app, bootbox, templates, ajaxify, RELATIVE_PATH*/
define('forum/admin/manage/categories', ['uploader', 'forum/admin/iconSelect'], function(uploader, iconSelect) {
var Categories = {};
Categories.init = function() {
var modified_categories = {};
function modified(el) {
var cid = $(el).parents('li').attr('data-cid');
if(cid) {
modified_categories[cid] = modified_categories[cid] || {};
modified_categories[cid][$(el).attr('data-name')] = $(el).val();
}
}
function save() {
if(Object.keys(modified_categories).length) {
socket.emit('admin.categories.update', modified_categories, function(err, result) {
if (err) {
return app.alertError(err.message);
}
if (result && result.length) {
app.alert({
title: 'Updated Categories',
message: 'Category IDs ' + result.join(', ') + ' was successfully updated.',
type: 'success',
timeout: 2000
});
}
});
modified_categories = {};
}
return false;
}
function update_blockclass(el) {
el.parentNode.parentNode.className = 'entry-row ' + el.value;
}
function updateCategoryOrders() {
var categories = $('.admin-categories #entry-container').children();
for(var i = 0; i<categories.length; ++i) {
var input = $(categories[i]).find('input[data-name="order"]');
input.val(i+1).attr('data-value', i+1);
modified(input);
}
}
$('#entry-container').sortable({
stop: function(event, ui) {
updateCategoryOrders();
},
distance: 10
});
$('.blockclass, .admin-categories form select').each(function() {
var $this = $(this);
$this.val($this.attr('data-value'));
});
function showCreateCategoryModal() {
$('#new-category-modal').modal();
}
function createNewCategory() {
var category = {
name: $('#inputName').val(),
description: $('#inputDescription').val(),
icon: $('#new-category-modal i').attr('value'),
bgColor: '#0059b2',
color: '#fff',
order: $('.admin-categories #entry-container').children().length + 1
};
socket.emit('admin.categories.create', category, function(err, data) {
if(err) {
return app.alertError(err.message);
}
app.alert({
alert_id: 'category_created',
title: 'Created',
message: 'Category successfully created!',
type: 'success',
timeout: 2000
});
$('#new-category-modal').modal('hide');
ajaxify.refresh();
});
}
function enableColorPicker(idx, inputEl) {
var $inputEl = $(inputEl),
previewEl = $inputEl.parents('[data-cid]').find('.preview-box');
admin.enableColorPicker($inputEl, function(hsb, hex) {
if ($inputEl.attr('data-name') === 'bgColor') {
previewEl.css('background', '#' + hex);
} else if ($inputEl.attr('data-name') === 'color') {
previewEl.css('color', '#' + hex);
}
modified($inputEl[0]);
});
}
function setupEditTargets() {
$('[data-edit-target]').on('click', function() {
var $this = $(this),
target = $($this.attr('data-edit-target'));
$this.addClass('hide');
target.removeClass('hide').on('blur', function() {
$this.removeClass('hide').children('span').html(this.value);
$(this).addClass('hide');
}).val($this.children('span').html());
target.focus();
});
}
$(function() {
var url = window.location.href,
parts = url.split('/'),
active = parts[parts.length - 1];
$('.nav-pills li').removeClass('active');
$('.nav-pills li a').each(function() {
var $this = $(this);
if ($this.attr('href').match(active)) {
$this.parent().addClass('active');
return false;
}
});
$('#addNew').on('click', showCreateCategoryModal);
$('#create-category-btn').on('click', createNewCategory);
$('#entry-container, #new-category-modal').on('click', '.icon', function(ev) {
iconSelect.init($(this).find('i'), modified);
});
$('.admin-categories form input, .admin-categories form select').on('change', function(ev) {
modified(ev.target);
});
$('.dropdown').on('click', '[data-disabled]', function(ev) {
var btn = $(this),
categoryRow = btn.parents('li'),
cid = categoryRow.attr('data-cid'),
disabled = btn.attr('data-disabled') === 'false' ? '1' : '0';
categoryRow.remove();
modified_categories[cid] = modified_categories[cid] || {};
modified_categories[cid].disabled = disabled;
save();
return false;
});
// Colour Picker
$('[data-name="bgColor"], [data-name="color"]').each(enableColorPicker);
$('.admin-categories').on('click', '.save', save);
$('.admin-categories').on('click', '.purge', function() {
var categoryRow = $(this).parents('li[data-cid]');
var cid = categoryRow.attr('data-cid');
bootbox.confirm('Do you really want to purge this category "' + categoryRow.find('#cid-' + cid + '-name').val() + '"?<br/><strong class="text-danger">Warning!</strong> All topics and posts in this category will be purged!', function(confirm) {
if (!confirm) {
return;
}
socket.emit('admin.categories.purge', cid, function(err) {
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('Category purged!');
categoryRow.remove();
});
});
});
$('.admin-categories').on('click', '.permissions', function() {
var cid = $(this).parents('li[data-cid]').attr('data-cid');
Categories.launchPermissionsModal(cid);
return false;
});
$('.admin-categories').on('click', '.upload-button', function() {
var inputEl = $(this),
cid = inputEl.parents('li[data-cid]').attr('data-cid');
uploader.open(RELATIVE_PATH + '/admin/category/uploadpicture', { cid: cid }, 0, function(imageUrlOnServer) {
inputEl.val(imageUrlOnServer);
var previewBox = inputEl.parents('li[data-cid]').find('.preview-box');
previewBox.css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')')
.css('background-size', 'cover');
modified(inputEl[0]);
});
});
$('.admin-categories').on('click', '.delete-image', function() {
var parent = $(this).parents('li[data-cid]'),
inputEl = parent.find('.upload-button'),
preview = parent.find('.preview-box'),
bgColor = parent.find('.category_bgColor').val();
inputEl.val('');
modified(inputEl[0]);
preview.css('background', bgColor);
$(this).addClass('hide').hide();
});
$('#revertChanges').on('click', function() {
ajaxify.refresh();
});
setupEditTargets();
$('button[data-action="setParent"]').on('click', function() {
var cid = $(this).parents('[data-cid]').attr('data-cid'),
modal = $('#setParent');
modal.find('select').val($(this).attr('data-parentCid'));
modal.attr('data-cid', cid).modal();
});
$('button[data-action="removeParent"]').on('click', function() {
var cid = $(this).parents('[data-cid]').attr('data-cid');
var payload= {};
payload[cid] = {
parentCid: 0
};
socket.emit('admin.categories.update', payload, function(err) {
if (err) {
return app.alertError(err.message);
}
ajaxify.go('admin/manage/categories/active');
});
});
$('#setParent [data-cid]').on('click', function() {
var modalEl = $('#setParent'),
parentCid = $(this).attr('data-cid'),
payload = {};
payload[modalEl.attr('data-cid')] = {
parentCid: parentCid
};
socket.emit('admin.categories.update', payload, function(err) {
modalEl.one('hidden.bs.modal', function() {
ajaxify.go('admin/manage/categories/active');
});
modalEl.modal('hide');
});
});
});
};
Categories.launchPermissionsModal = function(cid) {
var modal = $('#category-permissions-modal'),
searchEl = modal.find('#permission-search'),
resultsEl = modal.find('.search-results.users'),
groupsResultsEl = modal.find('.search-results.groups'),
searchDelay;
// Clear the search field and results
searchEl.val('');
resultsEl.html('');
searchEl.off().on('keyup', function() {
var searchEl = this,
liEl;
clearTimeout(searchDelay);
searchDelay = setTimeout(function() {
socket.emit('admin.categories.search', {
username: searchEl.value,
cid: cid
}, function(err, results) {
if(err) {
return app.alertError(err.message);
}
templates.parse('admin/partials/categories/users', {
users: results
}, function(html) {
resultsEl.html(html);
});
});
}, 250);
});
Categories.refreshPrivilegeList(cid);
resultsEl.off().on('click', '[data-priv]', function(e) {
var anchorEl = $(this),
uid = anchorEl.parents('li[data-uid]').attr('data-uid'),
privilege = anchorEl.attr('data-priv');
e.preventDefault();
e.stopPropagation();
socket.emit('admin.categories.setPrivilege', {
cid: cid,
uid: uid,
privilege: privilege,
set: !anchorEl.hasClass('active')
}, function(err) {
if (err) {
return app.alertError(err.message);
}
anchorEl.toggleClass('active', !anchorEl.hasClass('active'));
Categories.refreshPrivilegeList(cid);
});
});
modal.off().on('click', '.members li > img', function() {
searchEl.val($(this).attr('title'));
searchEl.keyup();
});
// User Groups and privileges
socket.emit('admin.categories.groupsList', cid, function(err, results) {
if(err) {
return app.alertError(err.message);
}
templates.parse('admin/partials/categories/groups', {
groups: results
}, function(html) {
groupsResultsEl.html(html);
});
});
groupsResultsEl.off().on('click', '[data-priv]', function(e) {
var anchorEl = $(this),
name = anchorEl.parents('li[data-name]').attr('data-name'),
privilege = anchorEl.attr('data-priv');
e.preventDefault();
e.stopPropagation();
socket.emit('admin.categories.setGroupPrivilege', {
cid: cid,
name: name,
privilege: privilege,
set: !anchorEl.hasClass('active')
}, function(err) {
if (!err) {
anchorEl.toggleClass('active');
}
});
});
modal.modal();
};
Categories.refreshPrivilegeList = function (cid) {
var modalEl = $('#category-permissions-modal'),
memberList = $('.members');
socket.emit('admin.categories.getPrivilegeSettings', cid, function(err, privilegeList) {
var membersLength = privilegeList.length,
liEl, x, userObj;
memberList.html('');
if (membersLength > 0) {
for(x = 0; x < membersLength; x++) {
userObj = privilegeList[x];
liEl = $('<li/>').attr('data-uid', userObj.uid).html('<img src="' + userObj.picture + '" title="' + userObj.username + '" />');
memberList.append(liEl);
}
} else {
liEl = $('<li/>').addClass('empty').html('None.');
memberList.append(liEl);
}
});
};
return Categories;
});

@ -1,68 +0,0 @@
"use strict";
/*global define, socket, app, admin, utils, bootbox, RELATIVE_PATH*/
define('forum/admin/manage/flags', ['forum/infinitescroll', 'admin/selectable'], function(infinitescroll, selectable) {
var Flags = {};
Flags.init = function() {
handleDismiss();
handleDelete();
handleInfiniteScroll();
};
function handleDismiss() {
$('.flags').on('click', '.dismiss', function() {
var btn = $(this);
var pid = btn.siblings('[data-pid]').attr('data-pid');
socket.emit('admin.dismissFlag', pid, function(err) {
done(err, btn);
});
});
}
function handleDelete() {
$('.flags').on('click', '.delete', function() {
var btn = $(this);
var pid = btn.siblings('[data-pid]').attr('data-pid');
var tid = btn.siblings('[data-pid]').attr('data-tid');
socket.emit('posts.delete', {pid: pid, tid: tid}, function(err) {
done(err, btn);
});
});
}
function done(err, btn) {
if (err) {
return app.alertError(err.messaage);
}
btn.parent().fadeOut(function() {
btn.remove();
});
if (!$('.flags [data-pid]').length) {
$('.post-container').text('No flagged posts!');
}
}
function handleInfiniteScroll() {
infinitescroll.init(function(direction) {
if (direction < 0 && !$('.flags').length) {
return;
}
infinitescroll.loadMore('admin.getMoreFlags', $('[data-next]').attr('data-next'), function(data, done) {
if (data.posts && data.posts.length) {
infinitescroll.parseAndTranslate('admin/manage/flags', 'posts', {posts: data.posts}, function(html) {
$('[data-next]').attr('data-next', data.next);
$('.post-container').append(html);
done();
});
} else {
done();
}
});
});
}
return Flags;
});

@ -1,263 +0,0 @@
"use strict";
/*global define, templates, socket, ajaxify, app, bootbox*/
define('forum/admin/manage/groups', ['forum/admin/iconSelect'], function(iconSelect) {
var Groups = {};
Groups.init = function() {
var yourid = ajaxify.variables.get('yourid'),
createModal = $('#create-modal'),
createGroupName = $('#create-group-name'),
create = $('#create'),
createModalGo = $('#create-modal-go'),
createGroupDesc = $('#create-group-desc'),
createModalError = $('#create-modal-error'),
groupDetailsModal = $('#group-details-modal'),
groupDetailsSearch = $('#group-details-search'),
groupDetailsSearchResults = $('#group-details-search-results'),
groupMembersEl = $('ul.current_members'),
formEl = groupDetailsModal.find('form'),
detailsModalSave = $('#details-modal-save'),
groupsList = $('#groups-list'),
groupIcon = $('#group-icon'),
changeGroupIcon = $('#change-group-icon'),
changeGroupName = $('#change-group-name'),
changeGroupDesc = $('#change-group-desc'),
changeGroupUserTitle = $('#change-group-user-title'),
changeGroupLabelColor = $('#change-group-label-color'),
groupIcon = $('#group-icon'),
groupLabelPreview = $('#group-label-preview'),
searchDelay;
// Tooltips
$('#groups-list .members li').tooltip();
createModal.on('keypress', function(e) {
switch(e.keyCode) {
case 13:
createModalGo.click();
break;
default:
break;
}
});
create.on('click', function() {
createModal.modal('show');
setTimeout(function() {
createGroupName.focus();
}, 250);
});
createModalGo.on('click', function() {
var submitObj = {
name: createGroupName.val(),
description: createGroupDesc.val()
},
errorText;
socket.emit('admin.groups.create', submitObj, function(err, data) {
if (err) {
switch (err) {
case 'group-exists':
errorText = '<strong>Please choose another name</strong><p>There seems to be a group with this name already.</p>';
break;
case 'name-too-short':
errorText = '<strong>Please specify a group name</strong><p>A group name is required for administrative purposes.</p>';
break;
default:
errorText = '<strong>Uh-Oh</strong><p>There was a problem creating your group. Please try again later!</p>';
break;
}
createModalError.html(errorText).removeClass('hide');
} else {
createModalError.addClass('hide');
createGroupName.val('');
createModal.on('hidden.bs.modal', function() {
ajaxify.go('admin/groups');
});
createModal.modal('hide');
}
});
});
formEl.keypress(function(e) {
switch(e.keyCode) {
case 13:
detailsModalSave.click();
break;
default:
break;
}
});
changeGroupUserTitle.keydown(function() {
setTimeout(function() {
groupLabelPreview.text(changeGroupUserTitle.val());
}, 0);
});
changeGroupLabelColor.keydown(function() {
setTimeout(function() {
groupLabelPreview.css('background', changeGroupLabelColor.val() || '#000000');
}, 0);
});
groupsList.on('click', 'button[data-action]', function() {
var el = $(this),
action = el.attr('data-action'),
groupName = el.parents('li[data-groupname]').attr('data-groupname');
switch (action) {
case 'delete':
bootbox.confirm('Are you sure you wish to delete this group?', function(confirm) {
if (confirm) {
socket.emit('admin.groups.delete', groupName, function(err, data) {
if(err) {
return app.alertError(err.message);
}
ajaxify.go('admin/groups');
});
}
});
break;
case 'members':
socket.emit('admin.groups.get', groupName, function(err, groupObj) {
changeGroupName.val(groupObj.name).prop('readonly', groupObj.system);
changeGroupDesc.val(groupObj.description);
changeGroupUserTitle.val(groupObj.userTitle);
groupIcon.attr('class', 'fa fa-2x ' + groupObj.icon).attr('value', groupObj.icon);
changeGroupLabelColor.val(groupObj.labelColor);
groupLabelPreview.css('background', groupObj.labelColor || '#000000').text(groupObj.userTitle);
groupMembersEl.empty();
if (groupObj.members.length > 0) {
for (var x = 0; x < groupObj.members.length; x++) {
var memberIcon = $('<li />')
.attr('data-uid', groupObj.members[x].uid)
.append($('<img />').attr('src', groupObj.members[x].picture))
.append($('<span />').html(groupObj.members[x].username));
groupMembersEl.append(memberIcon);
}
}
groupDetailsModal.attr('data-groupname', groupObj.name);
groupDetailsModal.modal('show');
});
break;
}
});
groupDetailsSearch.on('keyup', function() {
if (searchDelay) {
clearTimeout(searchDelay);
}
searchDelay = setTimeout(function() {
var searchText = groupDetailsSearch.val(),
foundUser;
socket.emit('admin.user.search', searchText, function(err, results) {
if (!err && results && results.users.length > 0) {
var numResults = results.users.length, x;
if (numResults > 4) {
numResults = 4;
}
groupDetailsSearchResults.empty();
for (x = 0; x < numResults; x++) {
foundUser = $('<li />');
foundUser
.attr({title: results.users[x].username, 'data-uid': results.users[x].uid})
.append($('<img />').attr('src', results.users[x].picture))
.append($('<span />').html(results.users[x].username));
groupDetailsSearchResults.append(foundUser);
}
} else {
groupDetailsSearchResults.html('<li>No Users Found</li>');
}
});
}, 200);
});
groupDetailsSearchResults.on('click', 'li[data-uid]', function() {
var userLabel = $(this),
uid = parseInt(userLabel.attr('data-uid'), 10),
groupName = groupDetailsModal.attr('data-groupname'),
members = [];
groupMembersEl.find('li[data-uid]').each(function() {
members.push(parseInt($(this).attr('data-uid'), 10));
});
if (members.indexOf(uid) === -1) {
socket.emit('admin.groups.join', {
groupName: groupName,
uid: uid
}, function(err, data) {
if (!err) {
groupMembersEl.append(userLabel.clone(true));
}
});
}
});
groupMembersEl.on('click', 'li[data-uid]', function() {
var uid = $(this).attr('data-uid'),
groupName = groupDetailsModal.attr('data-groupname');
socket.emit('admin.groups.get', groupName, function(err, groupObj){
if (!err){
bootbox.confirm('Are you sure you want to remove this user?', function(confirm) {
if (confirm){
socket.emit('admin.groups.leave', {
groupName: groupName,
uid: uid
}, function(err, data) {
if (!err) {
groupMembersEl.find('li[data-uid="' + uid + '"]').remove();
}
});
}
});
}
});
});
changeGroupIcon.on('click', function() {
iconSelect.init(groupIcon);
});
admin.enableColorPicker(changeGroupLabelColor, function(hsb, hex) {
groupLabelPreview.css('background-color', '#' + hex);
});
detailsModalSave.on('click', function() {
socket.emit('admin.groups.update', {
groupName: groupDetailsModal.attr('data-groupname'),
values: {
name: changeGroupName.val(),
userTitle: changeGroupUserTitle.val(),
description: changeGroupDesc.val(),
icon: groupIcon.attr('value'),
labelColor: changeGroupLabelColor.val()
}
}, function(err) {
if (!err) {
groupDetailsModal.on('hidden.bs.modal', function() {
ajaxify.go('admin/groups');
});
groupDetailsModal.modal('hide');
}
});
});
};
return Groups;
});

@ -1,110 +0,0 @@
"use strict";
/*global define, socket, app, admin, utils, bootbox, RELATIVE_PATH*/
define('forum/admin/manage/tags', ['forum/infinitescroll', 'admin/selectable'], function(infinitescroll, selectable) {
var Tags = {},
timeoutId = 0;
Tags.init = function() {
handleColorPickers();
selectable.enable('.tag-management', '.tag-row');
$('#tag-search').on('input propertychange', function() {
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = 0;
}
timeoutId = setTimeout(function() {
socket.emit('topics.searchAndLoadTags', {query: $('#tag-search').val()}, function(err, tags) {
if (err) {
return app.alertError(err.message);
}
infinitescroll.parseAndTranslate('admin/manage/tags', 'tags', {tags: tags}, function(html) {
$('.tag-list').html(html);
utils.makeNumbersHumanReadable(html.find('.human-readable-number'));
timeoutId = 0;
selectable.enable('.tag-management', '.tag-row');
});
});
}, 100);
});
$('#modify').on('click', function(ev) {
var tagsToModify = $('.tag-row.selected');
if (!tagsToModify.length) {
return;
}
var firstTag = $(tagsToModify[0]),
title = tagsToModify.length > 1 ? 'Editing multiple tags' : 'Editing ' + firstTag.find('.tag-item').text() + ' tag';
bootbox.dialog({
title: title,
message: firstTag.find('.tag-modal').html(),
buttons: {
success: {
label: "Save",
className: "btn-primary save",
callback: function() {
var modal = $('.bootbox'),
bgColor = modal.find('[data-name="bgColor"]').val(),
color = modal.find('[data-name="color"]').val();
tagsToModify.each(function(idx, tag) {
tag = $(tag);
tag.find('[data-name="bgColor"]').val(bgColor);
tag.find('[data-name="color"]').val(color);
tag.find('.tag-item').css('background-color', bgColor).css('color', color);
save(tag);
});
}
}
}
});
setTimeout(function() {
handleColorPickers();
}, 500); // bootbox made me do it.
});
};
function handleColorPickers() {
function enableColorPicker(idx, inputEl) {
var $inputEl = $(inputEl),
previewEl = $inputEl.parents('.tag-row').find('.tag-item');
admin.enableColorPicker($inputEl, function(hsb, hex) {
if ($inputEl.attr('data-name') === 'bgColor') {
previewEl.css('background-color', '#' + hex);
} else if ($inputEl.attr('data-name') === 'color') {
previewEl.css('color', '#' + hex);
}
});
}
$('[data-name="bgColor"], [data-name="color"]').each(enableColorPicker);
}
function save(tag) {
var data = {
tag: tag.attr('data-tag'),
bgColor : tag.find('[data-name="bgColor"]').val(),
color : tag.find('[data-name="color"]').val()
};
socket.emit('admin.tags.update', data, function(err) {
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('Tag Updated!');
});
}
return Tags;
});

@ -1,289 +0,0 @@
"use strict";
/* global socket, define, templates, bootbox, app, ajaxify, */
define('forum/admin/manage/users', ['admin/selectable'], function(selectable) {
var Users = {};
Users.init = function() {
var yourid = ajaxify.variables.get('yourid');
selectable.enable('#users-container', '.user-selectable');
function getSelectedUids() {
var uids = [];
$('#users-container .users-box .selected').each(function() {
uids.push($(this).parents('[data-uid]').attr('data-uid'));
});
return uids;
}
function update(className, state) {
$('#users-container .users-box .selected').siblings('.labels').find(className).each(function() {
$(this).toggleClass('hide', !state);
});
}
function unselectAll() {
$('#users-container .users-box .selected').removeClass('selected');
}
function removeSelected() {
$('#users-container .users-box .selected').remove();
}
function done(successMessage, className, flag) {
return function(err) {
if (err) {
return app.alertError(err.message);
}
app.alertSuccess(successMessage);
if (className) {
update(className, flag);
}
unselectAll();
};
}
$('.ban-user').on('click', function() {
var uids = getSelectedUids();
if (!uids.length) {
return false;
}
bootbox.confirm('Do you really want to ban?', function(confirm) {
if (confirm) {
socket.emit('admin.user.banUsers', uids, done('User(s) banned!', '.ban', true));
}
});
return false;
});
$('.unban-user').on('click', function() {
var uids = getSelectedUids();
if (!uids.length) {
return;
}
socket.emit('admin.user.unbanUsers', uids, done('User(s) unbanned!', '.ban', false));
return false;
});
$('.reset-lockout').on('click', function() {
var uids = getSelectedUids();
if (!uids.length) {
return;
}
socket.emit('admin.user.resetLockouts', uids, done('Lockout(s) reset!'));
return false;
});
$('.admin-user').on('click', function() {
var uids = getSelectedUids();
if (!uids.length) {
return;
}
if (uids.indexOf(yourid) !== -1) {
app.alertError('You can\'t remove yourself as Administrator!');
} else {
socket.emit('admin.user.makeAdmins', uids, done('User(s) are now administrators.', '.administrator', true));
}
return false;
});
$('.remove-admin-user').on('click', function() {
var uids = getSelectedUids();
if (!uids.length) {
return;
}
if (uids.indexOf(yourid.toString()) !== -1) {
app.alertError('You can\'t remove yourself as Administrator!');
} else {
bootbox.confirm('Do you really want to remove admins?', function(confirm) {
if (confirm) {
socket.emit('admin.user.removeAdmins', uids, done('User(s) are no longer administrators.', '.administrator', false));
}
});
}
return false;
});
$('.validate-email').on('click', function() {
var uids = getSelectedUids();
if (!uids.length) {
return;
}
bootbox.confirm('Do you want to validate email(s) of these user(s)?', function(confirm) {
if (confirm) {
socket.emit('admin.user.validateEmail', uids, done('Emails validated', '.notvalidated', false));
}
});
return false;
});
$('.delete-user').on('click', function() {
var uids = getSelectedUids();
if (!uids.length) {
return;
}
bootbox.confirm('<b>Warning!</b><br/>Do you really want to delete user(s)?<br/> This action is not reversable, all user data and content will be erased!', function(confirm) {
if (confirm) {
socket.emit('admin.user.deleteUsers', uids, function(err) {
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('User(s) Deleted!');
removeSelected();
unselectAll();
});
}
});
return false;
});
function handleUserCreate() {
var errorEl = $('#create-modal-error');
$('#createUser').on('click', function() {
$('#create-modal').modal('show');
$('#create-modal form')[0].reset();
errorEl.addClass('hide');
});
$('#create-modal-go').on('click', function() {
var username = $('#create-user-name').val(),
email = $('#create-user-email').val(),
password = $('#create-user-password').val(),
passwordAgain = $('#create-user-password-again').val();
if(password !== passwordAgain) {
return errorEl.html('<strong>Error</strong><p>Passwords must match!</p>').removeClass('hide');
}
var user = {
username: username,
email: email,
password: password
};
socket.emit('admin.user.createUser', user, function(err) {
if(err) {
return errorEl.html('<strong>Error</strong><p>' + err.message + '</p>').removeClass('hide');
}
$('#create-modal').modal('hide');
$('#create-modal').on('hidden.bs.modal', function() {
ajaxify.go('admin/users');
});
app.alertSuccess('User created!');
});
});
}
var timeoutId = 0,
loadingMoreUsers = false;
var url = window.location.href,
parts = url.split('/'),
active = parts[parts.length - 1];
$('.nav-pills li').removeClass('active');
$('.nav-pills li a').each(function() {
var $this = $(this);
if ($this.attr('href').match(active)) {
$this.parent().addClass('active');
return false;
}
});
$('#search-user').on('keyup', function() {
if (timeoutId !== 0) {
clearTimeout(timeoutId);
timeoutId = 0;
}
timeoutId = setTimeout(function() {
var username = $('#search-user').val();
$('.fa-spinner').removeClass('hidden');
socket.emit('admin.user.search', username, function(err, data) {
if (err) {
return app.alertError(err.message);
}
templates.parse('admin/manage/users', 'users', data, function(html) {
$('#users-container').html(html);
$('.fa-spinner').addClass('hidden');
if (data && data.users.length === 0) {
$('#user-notfound-notify').html('User not found!')
.show()
.addClass('label-danger')
.removeClass('label-success');
} else {
$('#user-notfound-notify').html(data.users.length + ' user' + (data.users.length > 1 ? 's' : '') + ' found! Search took ' + data.timing + ' ms.')
.show()
.addClass('label-success')
.removeClass('label-danger');
}
selectable.enable('#users-container', '.user-selectable');
});
});
}, 250);
});
handleUserCreate();
function onUsersLoaded(users) {
templates.parse('admin/manage/users', 'users', {users: users}, function(html) {
$('#users-container').append($(html));
});
}
function loadMoreUsers() {
var set = '';
if (active === 'latest') {
set = 'users:joindate';
} else if (active === 'sort-posts') {
set = 'users:postcount';
} else if (active === 'sort-reputation') {
set = 'users:reputation';
}
if (set) {
loadingMoreUsers = true;
socket.emit('user.loadMore', {
set: set,
after: $('#users-container').children().length
}, function(err, data) {
if (data && data.users.length) {
onUsersLoaded(data.users);
}
loadingMoreUsers = false;
});
}
}
$('#load-more-users-btn').on('click', loadMoreUsers);
$(window).off('scroll').on('scroll', function() {
var bottom = ($(document).height() - $(window).height()) * 0.9;
if ($(window).scrollTop() > bottom && !loadingMoreUsers) {
loadMoreUsers();
}
});
};
return Users;
});

@ -1,169 +0,0 @@
"use strict";
/*global define, app, socket, ajaxify, RELATIVE_PATH */
define('forum/admin/settings', ['uploader', 'sounds'], function(uploader, sounds) {
var Settings = {};
Settings.init = function() {
Settings.prepare();
};
Settings.prepare = function(callback) {
// Come back in 125ms if the config isn't ready yet
if (!app.config) {
setTimeout(function() {
Settings.prepare(callback);
}, 125);
return;
}
// Populate the fields on the page from the config
var fields = $('#content [data-field]'),
numFields = fields.length,
saveBtn = $('#save'),
revertBtn = $('#revert'),
x, key, inputType, field;
for (x = 0; x < numFields; x++) {
field = fields.eq(x);
key = field.attr('data-field');
inputType = field.attr('type');
if (field.is('input')) {
if (app.config[key]) {
switch (inputType) {
case 'text':
case 'hidden':
case 'password':
case 'textarea':
case 'number':
field.val(app.config[key]);
break;
case 'checkbox':
field.prop('checked', parseInt(app.config[key], 10) === 1);
break;
}
}
} else if (field.is('textarea')) {
if (app.config[key]) {
field.val(app.config[key]);
}
} else if (field.is('select')) {
if (app.config[key]) {
field.val(app.config[key]);
}
}
}
revertBtn.off('click').on('click', function(e) {
ajaxify.refresh();
});
saveBtn.off('click').on('click', function(e) {
e.preventDefault();
saveFields(fields, function onFieldsSaved(err) {
if (err) {
return app.alert({
alert_id: 'config_status',
timeout: 2500,
title: 'Changes Not Saved',
message: 'NodeBB encountered a problem saving your changes',
type: 'danger'
});
}
app.alert({
alert_id: 'config_status',
timeout: 2500,
title: 'Changes Saved',
message: 'Your changes to the NodeBB configuration have been saved.',
type: 'success'
});
});
});
handleUploads();
$('button[data-action="email.test"]').off('click').on('click', function() {
socket.emit('admin.email.test', function(err) {
app.alert({
alert_id: 'test_email_sent',
type: !err ? 'info' : 'danger',
title: 'Test Email Sent',
message: err ? err.message : '',
timeout: 2500
});
});
});
if (typeof callback === 'function') {
callback();
}
};
function handleUploads() {
$('#content input[data-action="upload"]').each(function() {
var uploadBtn = $(this);
uploadBtn.on('click', function() {
uploader.open(uploadBtn.attr('data-route'), {}, 0, function(image) {
$('#' + uploadBtn.attr('data-target')).val(image);
});
uploader.hideAlerts();
});
});
}
Settings.remove = function(key) {
socket.emit('admin.config.remove', key);
};
function saveFields(fields, callback) {
var data = {};
fields.each(function() {
var field = $(this);
var key = field.attr('data-field'),
value, inputType;
if (field.is('input')) {
inputType = field.attr('type');
switch (inputType) {
case 'text':
case 'password':
case 'hidden':
case 'textarea':
case 'number':
value = field.val();
break;
case 'checkbox':
value = field.prop('checked') ? '1' : '0';
break;
}
} else if (field.is('textarea') || field.is('select')) {
value = field.val();
}
data[key] = value;
});
socket.emit('admin.config.setMultiple', data, function(err) {
if (err) {
return callback(err);
}
if (app.config) {
for(var field in data) {
if (data.hasOwnProperty(field)) {
app.config[field] = data[field];
}
}
}
callback();
});
}
return Settings;
});

@ -1,351 +0,0 @@
"use strict";
/* global define, config, templates, app, utils, ajaxify, socket, translator */
define('forum/category', ['composer', 'forum/pagination', 'forum/infinitescroll', 'share', 'navigator', 'forum/categoryTools'], function(composer, pagination, infinitescroll, share, navigator, categoryTools) {
var Category = {};
$(window).on('action:ajaxify.start', function(ev, data) {
if(data && data.url.indexOf('category') !== 0) {
navigator.hide();
removeListeners();
}
});
function removeListeners() {
socket.removeListener('event:new_topic', Category.onNewTopic);
categoryTools.removeListeners();
}
Category.init = function() {
var cid = ajaxify.variables.get('category_id');
app.enterRoom('category_' + cid);
share.addShareHandlers(ajaxify.variables.get('category_name'));
$('#new_post').on('click', function () {
composer.newTopic(cid);
});
socket.on('event:new_topic', Category.onNewTopic);
categoryTools.init(cid);
enableInfiniteLoadingOrPagination();
if (!config.usePagination) {
navigator.init('#topics-container > .category-item', ajaxify.variables.get('topic_count'), Category.toTop, Category.toBottom, Category.navigatorCallback);
}
$('#topics-container').on('click', '.topic-title', function() {
var clickedTid = $(this).parents('li.category-item[data-tid]').attr('data-tid');
$('#topics-container li.category-item').each(function(index, el) {
if($(el).offset().top - $(window).scrollTop() > 0) {
localStorage.setItem('category:' + cid + ':bookmark', $(el).attr('data-tid'));
localStorage.setItem('category:' + cid + ':bookmark:clicked', clickedTid);
return false;
}
});
});
handleIgnoreWatch(cid);
};
function handleIgnoreWatch(cid) {
$('.watch, .ignore').on('click', function() {
var $this = $(this);
var command = $this.hasClass('watch') ? 'watch' : 'ignore';
socket.emit('categories.' + command, cid, function(err) {
if (err) {
return app.alertError(err.message);
}
$('.watch').toggleClass('hidden', command === 'watch');
$('.ignore').toggleClass('hidden', command === 'ignore');
});
});
}
Category.toTop = function() {
navigator.scrollTop(0);
};
Category.toBottom = function() {
socket.emit('categories.lastTopicIndex', ajaxify.variables.get('category_id'), function(err, index) {
navigator.scrollBottom(index);
});
};
Category.navigatorCallback = function(element, elementCount) {
return parseInt(element.attr('data-index'), 10) + 1;
};
$(window).on('action:popstate', function(ev, data) {
if(data.url.indexOf('category/') === 0) {
var cid = data.url.match(/^category\/(\d+)/);
if (cid && cid[1]) {
cid = cid[1];
}
if (!cid) {
return;
}
var bookmark = localStorage.getItem('category:' + cid + ':bookmark');
var clicked = localStorage.getItem('category:' + cid + ':bookmark:clicked');
if (!bookmark) {
return;
}
if(config.usePagination) {
socket.emit('topics.getTidPage', bookmark, function(err, page) {
if (err) {
return;
}
if(parseInt(page, 10) !== pagination.currentPage) {
pagination.loadPage(page);
} else {
Category.scrollToTopic(bookmark, clicked, 400);
}
});
} else {
socket.emit('topics.getTidIndex', bookmark, function(err, index) {
if (err) {
return;
}
if (index === 0) {
Category.highlightTopic(clicked);
return;
}
if (index < 0) {
index = 0;
}
$('#topics-container').empty();
loadTopicsAfter(index, function() {
Category.scrollToTopic(bookmark, clicked, 0);
});
});
}
}
});
Category.highlightTopic = function(tid) {
var highlight = $('#topics-container li.category-item[data-tid="' + tid + '"]');
if(highlight.length && !highlight.hasClass('highlight')) {
highlight.addClass('highlight');
setTimeout(function() {
highlight.removeClass('highlight');
}, 5000);
}
};
Category.scrollToTopic = function(tid, clickedTid, duration, offset) {
if(!tid) {
return;
}
if(!offset) {
offset = 0;
}
if($('#topics-container li.category-item[data-tid="' + tid + '"]').length) {
var cid = ajaxify.variables.get('category_id');
var scrollTo = $('#topics-container li.category-item[data-tid="' + tid + '"]');
if (cid && scrollTo.length) {
$('html, body').animate({
scrollTop: (scrollTo.offset().top - $('#header-menu').height() - offset) + 'px'
}, duration !== undefined ? duration : 400, function() {
Category.highlightTopic(clickedTid);
navigator.update();
});
}
}
};
function enableInfiniteLoadingOrPagination() {
if (!config.usePagination) {
infinitescroll.init(Category.loadMoreTopics);
} else {
navigator.hide();
pagination.init(ajaxify.variables.get('currentPage'), ajaxify.variables.get('pageCount'));
}
}
Category.onNewTopic = function(topic) {
$(window).trigger('filter:categories.new_topic', topic);
ajaxify.loadTemplate('category', function(categoryTemplate) {
var html = templates.parse(templates.getBlock(categoryTemplate, 'topics'), {
privileges: {editable: !!$('.thread-tools').length},
topics: [topic]
});
translator.translate(html, function(translatedHTML) {
var topic = $(translatedHTML),
container = $('#topics-container'),
topics = $('#topics-container').children('.category-item'),
numTopics = topics.length;
$('#topics-container, .category-sidebar').removeClass('hidden');
var noTopicsWarning = $('#category-no-topics');
if (noTopicsWarning.length) {
noTopicsWarning.remove();
ajaxify.widgets.render('category', window.location.pathname.slice(1));
}
if (numTopics > 0) {
for (var x = 0; x < numTopics; x++) {
var pinned = $(topics[x]).hasClass('pinned');
if (pinned) {
if(x === numTopics - 1) {
topic.insertAfter(topics[x]);
}
continue;
}
topic.insertBefore(topics[x]);
break;
}
} else {
container.append(topic);
}
topic.hide().fadeIn('slow');
socket.emit('categories.getPageCount', ajaxify.variables.get('category_id'), function(err, newPageCount) {
pagination.recreatePaginationLinks(newPageCount);
});
topic.find('span.timeago').timeago();
app.createUserTooltips();
updateTopicCount();
$(window).trigger('action:categories.new_topic.loaded');
});
});
};
function updateTopicCount() {
socket.emit('categories.getTopicCount', ajaxify.variables.get('category_id'), function(err, topicCount) {
if(err) {
return app.alertError(err.message);
}
navigator.setCount(topicCount);
});
}
Category.onTopicsLoaded = function(data, callback) {
if(!data || !data.topics.length) {
return;
}
function removeAlreadyAddedTopics(topics) {
return topics.filter(function(topic) {
return $('#topics-container li[data-tid="' + topic.tid +'"]').length === 0;
});
}
var after = null,
before = null;
function findInsertionPoint() {
if (!$('#topics-container .category-item[data-tid]').length) {
return;
}
var last = $('#topics-container .category-item[data-tid]').last();
var lastIndex = last.attr('data-index');
var firstIndex = data.topics[data.topics.length - 1].index;
if (firstIndex > lastIndex) {
after = last;
} else {
before = $('#topics-container .category-item[data-tid]').first();
}
}
data.topics = removeAlreadyAddedTopics(data.topics);
if(!data.topics.length) {
return;
}
findInsertionPoint();
ajaxify.loadTemplate('category', function(categoryTemplate) {
var html = templates.parse(templates.getBlock(categoryTemplate, 'topics'), data);
translator.translate(html, function(translatedHTML) {
var container = $('#topics-container'),
html = $(translatedHTML);
$('#topics-container, .category-sidebar').removeClass('hidden');
$('#category-no-topics').remove();
if(config.usePagination) {
container.empty().append(html);
} else {
if(after) {
html.insertAfter(after);
} else if(before) {
html.insertBefore(before);
} else {
container.append(html);
}
}
if (typeof callback === 'function') {
callback();
}
html.find('span.timeago').timeago();
app.createUserTooltips();
utils.makeNumbersHumanReadable(html.find('.human-readable-number'));
});
});
};
Category.loadMoreTopics = function(direction) {
if (!$('#topics-container').length || !$('#topics-container').children().length) {
return;
}
infinitescroll.calculateAfter(direction, '#topics-container .category-item[data-tid]', config.topicsPerPage, false, function(after, offset, el) {
loadTopicsAfter(after, function() {
if (direction < 0 && el) {
Category.scrollToTopic(el.attr('data-tid'), null, 0, offset);
}
});
});
};
function loadTopicsAfter(after, callback) {
if(!utils.isNumber(after) || (after === 0 && $('#topics-container li.category-item[data-index="0"]').length)) {
return;
}
$(window).trigger('action:categories.loading');
infinitescroll.loadMore('categories.loadMore', {
cid: ajaxify.variables.get('category_id'),
after: after
}, function (data, done) {
if (data.topics && data.topics.length) {
Category.onTopicsLoaded(data, function() {
done();
callback();
});
$('#topics-container').attr('data-nextstart', data.nextStart);
} else {
done();
}
$(window).trigger('action:categories.loaded');
});
}
return Category;
});

@ -1,205 +0,0 @@
'use strict';
/* globals define, app, translator, socket, bootbox, ajaxify */
define('forum/categoryTools', ['forum/topic/move', 'topicSelect'], function(move, topicSelect) {
var CategoryTools = {};
CategoryTools.init = function(cid) {
CategoryTools.cid = cid;
topicSelect.init(onTopicSelect);
$('.delete_thread').on('click', function(e) {
var tids = topicSelect.getSelectedTids();
categoryCommand(isAny(isTopicDeleted, tids) ? 'restore' : 'delete', tids);
return false;
});
$('.purge_thread').on('click', function() {
var tids = topicSelect.getSelectedTids();
categoryCommand('purge', tids);
return false;
});
$('.lock_thread').on('click', function() {
var tids = topicSelect.getSelectedTids();
if (tids.length) {
socket.emit(isAny(isTopicLocked, tids) ? 'topics.unlock' : 'topics.lock', {tids: tids, cid: CategoryTools.cid}, onCommandComplete);
}
return false;
});
$('.pin_thread').on('click', function() {
var tids = topicSelect.getSelectedTids();
if (tids.length) {
socket.emit(isAny(isTopicPinned, tids) ? 'topics.unpin' : 'topics.pin', {tids: tids, cid: CategoryTools.cid}, onCommandComplete);
}
return false;
});
$('.markAsUnreadForAll').on('click', function() {
var tids = topicSelect.getSelectedTids();
if (tids.length) {
socket.emit('topics.markAsUnreadForAll', tids, function(err) {
if(err) {
return app.alertError(err.message);
}
app.alertSuccess('[[topic:markAsUnreadForAll.success]]');
onCommandComplete();
});
}
return false;
});
$('.move_thread').on('click', function() {
var tids = topicSelect.getSelectedTids();
if (tids.length) {
move.init(tids, cid, onCommandComplete);
}
return false;
});
$('.move_all_threads').on('click', function() {
move.init(null, cid, function(err) {
ajaxify.refresh();
});
});
socket.on('event:topic_deleted', setDeleteState);
socket.on('event:topic_restored', setDeleteState);
socket.on('event:topic_purged', onTopicPurged);
socket.on('event:topic_locked', setLockedState);
socket.on('event:topic_unlocked', setLockedState);
socket.on('event:topic_pinned', setPinnedState);
socket.on('event:topic_unpinned', setPinnedState);
socket.on('event:topic_moved', onTopicMoved);
};
function categoryCommand(command, tids) {
if (!tids.length) {
return;
}
translator.translate('[[topic:thread_tools.' + command + '_confirm]]', function(msg) {
bootbox.confirm(msg, function(confirm) {
if (!confirm) {
return;
}
socket.emit('topics.' + command, {tids: tids, cid: CategoryTools.cid}, onCommandComplete);
});
});
}
CategoryTools.removeListeners = function() {
socket.removeListener('event:topic_deleted', setDeleteState);
socket.removeListener('event:topic_restored', setDeleteState);
socket.removeListener('event:topic_purged', onTopicPurged);
socket.removeListener('event:topic_locked', setLockedState);
socket.removeListener('event:topic_unlocked', setLockedState);
socket.removeListener('event:topic_pinned', setPinnedState);
socket.removeListener('event:topic_unpinned', setPinnedState);
socket.removeListener('event:topic_moved', onTopicMoved);
};
function closeDropDown() {
$('.thread-tools.open').find('.dropdown-toggle').trigger('click');
}
function onCommandComplete(err) {
if (err) {
return app.alertError(err.message);
}
closeDropDown();
topicSelect.unselectAll();
}
function onTopicSelect() {
var tids = topicSelect.getSelectedTids();
var isAnyDeleted = isAny(isTopicDeleted, tids);
var areAllDeleted = areAll(isTopicDeleted, tids);
var isAnyPinned = isAny(isTopicPinned, tids);
var isAnyLocked = isAny(isTopicLocked, tids);
$('.delete_thread span').translateHtml('<i class="fa fa-fw ' + (isAnyDeleted ? 'fa-history' : 'fa-trash-o') + '"></i> [[topic:thread_tools.' + (isAnyDeleted ? 'restore' : 'delete') + ']]');
$('.pin_thread').translateHtml('<i class="fa fa-fw fa-thumb-tack"></i> [[topic:thread_tools.' + (isAnyPinned ? 'unpin' : 'pin') + ']]');
$('.lock_thread').translateHtml('<i class="fa fa-fw fa-' + (isAnyLocked ? 'un': '') + 'lock"></i> [[topic:thread_tools.' + (isAnyLocked ? 'un': '') + 'lock]]');
$('.purge_thread').toggleClass('hidden', !areAllDeleted);
}
function isAny(method, tids) {
for(var i=0; i<tids.length; ++i) {
if(method(tids[i])) {
return true;
}
}
return false;
}
function areAll(method, tids) {
for(var i=0; i<tids.length; ++i) {
if(!method(tids[i])) {
return false;
}
}
return true;
}
function isTopicDeleted(tid) {
return getTopicEl(tid).hasClass('deleted');
}
function isTopicLocked(tid) {
return getTopicEl(tid).hasClass('locked');
}
function isTopicPinned(tid) {
return getTopicEl(tid).hasClass('pinned');
}
function getTopicEl(tid) {
return $('#topics-container li[data-tid="' + tid + '"]');
}
function setDeleteState(data) {
var topic = getTopicEl(data.tid);
topic.toggleClass('deleted', data.isDeleted);
topic.find('.fa-lock').toggleClass('hide', !data.isDeleted);
}
function setPinnedState(data) {
var topic = getTopicEl(data.tid);
topic.toggleClass('pinned', data.isPinned);
topic.find('.fa-thumb-tack').toggleClass('hide', !data.isPinned);
ajaxify.refresh();
}
function setLockedState(data) {
var topic = getTopicEl(data.tid);
topic.toggleClass('locked', data.isLocked);
topic.find('.fa-lock').toggleClass('hide', !data.isLocked);
}
function onTopicMoved(data) {
getTopicEl(data.tid).remove();
}
function onTopicPurged(tids) {
if (!tids) {
return;
}
for(var i=0; i<tids.length; ++i) {
getTopicEl(tids[i]).remove();
}
}
return CategoryTools;
});

@ -1,275 +0,0 @@
'use strict';
/* globals define, app, ajaxify, utils, socket, templates */
define('forum/chats', ['string', 'sounds', 'forum/infinitescroll'], function(S, sounds, infinitescroll) {
var Chats = {
initialised: false
};
var newMessage = false;
Chats.init = function() {
var containerEl = $('.expanded-chat ul');
if (!Chats.initialised) {
Chats.addSocketListeners();
Chats.addGlobalEventListeners();
}
Chats.addEventListeners();
Chats.resizeMainWindow();
Chats.scrollToBottom(containerEl);
Chats.setActive();
Chats.initialised = true;
};
Chats.getRecipientUid = function() {
return parseInt($('.expanded-chat').attr('data-uid'), 10);
};
Chats.isCurrentChat = function(uid) {
return Chats.getRecipientUid() === parseInt(uid, 10);
};
Chats.addEventListeners = function() {
var inputEl = $('.chat-input'),
sendEl = $('.expanded-chat button[data-action="send"]'),
popoutEl = $('[data-action="pop-out"]');
$('.chats-list').on('click', 'li', function(e) {
ajaxify.go('chats/' + utils.slugify($(this).attr('data-username')));
});
inputEl.on('keypress', function(e) {
if(e.which === 13) {
Chats.sendMessage(Chats.getRecipientUid(), inputEl);
}
});
inputEl.on('keyup', function() {
var val = !!$(this).val();
if ((val && $(this).attr('data-typing') === 'true') || (!val && $(this).attr('data-typing') === 'false')) {
return;
}
Chats.notifyTyping(Chats.getRecipientUid(), val);
$(this).attr('data-typing', val);
});
sendEl.on('click', function(e) {
Chats.sendMessage(Chats.getRecipientUid(), inputEl);
return false;
});
popoutEl.on('click', function() {
var username = $('.expanded-chat').attr('data-username'),
uid = Chats.getRecipientUid();
if (app.previousUrl && app.previousUrl.match(/chats/)) {
ajaxify.go('chats', function() {
app.openChat(username, uid);
}, true);
} else {
window.history.go(-1);
}
});
$('.recent-chats').on('scroll', function() {
var $this = $(this);
var bottom = ($this[0].scrollHeight - $this.height()) * 0.9;
if ($this.scrollTop() > bottom) {
loadMoreRecentChats();
}
});
$('.expanded-chat [data-since]').on('click', function() {
var since = $(this).attr('data-since');
$('.expanded-chat [data-since]').removeClass('selected');
$(this).addClass('selected');
loadChatSince(since);
return false;
});
};
function loadChatSince(since) {
var uid = Chats.getRecipientUid();
if (!uid) {
return;
}
socket.emit('modules.chats.get', {touid: uid, since: since}, function(err, messages) {
var chatContent = $('.expanded-chat .chat-content');
chatContent.find('.chat-message').remove();
Chats.parseMessage(messages, onMessagesParsed);
});
}
Chats.addGlobalEventListeners = function() {
$(window).on('resize', Chats.resizeMainWindow);
$(window).on('mousemove keypress click', function() {
if (newMessage) {
var recipientUid = Chats.getRecipientUid();
if (recipientUid) {
socket.emit('modules.chats.markRead', recipientUid);
newMessage = false;
}
}
});
};
function onMessagesParsed(html) {
var newMessage = $(html);
newMessage.insertBefore($('.user-typing'));
newMessage.find('span.timeago').timeago();
newMessage.find('img:not(".chat-user-image")').addClass('img-responsive');
Chats.scrollToBottom($('.expanded-chat .chat-content'));
}
Chats.addSocketListeners = function() {
socket.on('event:chats.receive', function(data) {
var typingNotifEl = $('.user-typing'),
containerEl = $('.expanded-chat ul');
if (Chats.isCurrentChat(data.withUid)) {
newMessage = data.self === 0;
data.message.self = data.self;
Chats.parseMessage(data.message, onMessagesParsed);
} else {
$('.chats-list li[data-uid="' + data.withUid + '"]').addClass('unread');
app.alternatingTitle('[[modules:chat.user_has_messaged_you, ' + data.message.fromUser.username + ']]');
}
});
socket.on('event:chats.userStartTyping', function(withUid) {
var typingNotifEl = $('.user-typing');
if (Chats.isCurrentChat(withUid)) {
typingNotifEl.removeClass('hide');
}
$('.chats-list li[data-uid="' + withUid + '"]').addClass('typing');
});
socket.on('event:chats.userStopTyping', function(withUid) {
var typingNotifEl = $('.user-typing');
if (Chats.isCurrentChat(withUid)) {
typingNotifEl.addClass('hide');
}
$('.chats-list li[data-uid="' + withUid + '"]').removeClass('typing');
});
socket.on('event:user_status_change', function(data) {
var userEl = $('.chats-list li[data-uid="' + data.uid +'"]');
if (userEl.length) {
var statusEl = userEl.find('.status');
translator.translate('[[global:' + data.status + ']]', function(translated) {
statusEl.attr('class', 'fa fa-circle status ' + data.status)
.attr('title', translated)
.attr('data-original-title', translated);
});
}
});
};
Chats.resizeMainWindow = function() {
var messagesList = $('.expanded-chat ul');
if (messagesList.length) {
var margin = $('.expanded-chat ul').outerHeight(true) - $('.expanded-chat ul').height(),
inputHeight = $('.chat-input').outerHeight(true),
fromTop = messagesList.offset().top;
messagesList.height($(window).height() - (fromTop + inputHeight + (margin * 4)));
}
};
Chats.notifyTyping = function(toUid, typing) {
socket.emit('modules.chats.user' + (typing ? 'Start' : 'Stop') + 'Typing', {
touid: toUid,
fromUid: app.uid
});
};
Chats.sendMessage = function(toUid, inputEl) {
var msg = S(inputEl.val()).stripTags().s;
if (msg.length) {
msg = msg +'\n';
socket.emit('modules.chats.send', {
touid:toUid,
message:msg
});
inputEl.val('');
sounds.play('chat-outgoing');
Chats.notifyTyping(toUid, false);
}
};
Chats.scrollToBottom = function(containerEl) {
if (containerEl.length) {
containerEl.scrollTop(
containerEl[0].scrollHeight - containerEl.height()
);
}
};
Chats.setActive = function() {
var recipientUid = Chats.getRecipientUid();
if (recipientUid) {
socket.emit('modules.chats.markRead', recipientUid);
$('.expanded-chat input').focus();
}
$('.chats-list li').removeClass('bg-primary');
$('.chats-list li[data-uid="' + recipientUid + '"]').addClass('bg-primary');
};
Chats.parseMessage = function(data, callback) {
templates.parse('partials/chat_message' + (Array.isArray(data) ? 's' : ''), {
messages: data
}, callback);
};
function loadMoreRecentChats() {
var recentChats = $('.recent-chats');
if (recentChats.attr('loading')) {
return;
}
recentChats.attr('loading', 1);
socket.emit('modules.chats.getRecentChats', {
after: recentChats.attr('data-nextstart')
}, function(err, data) {
if (err) {
return app.alertError(err.message);
}
if (data && data.users.length) {
onRecentChatsLoaded(data.users, function() {
recentChats.removeAttr('loading');
recentChats.attr('data-nextstart', data.nextStart);
});
} else {
recentChats.removeAttr('loading');
}
});
}
function onRecentChatsLoaded(users, callback) {
users = users.filter(function(user) {
return !$('.recent-chats li[data-uid=' + user.uid + ']').length;
});
if (!users.length) {
return callback();
}
infinitescroll.parseAndTranslate('chats', 'chats', {chats: users}, function(html) {
$('.recent-chats').append(html);
callback();
});
}
return Chats;
});

@ -1,69 +0,0 @@
define('forum/footer', ['notifications', 'chat'], function(Notifications, Chat) {
Notifications.prepareDOM();
Chat.prepareDOM();
translator.prepareDOM();
function updateUnreadTopicCount(err, count) {
if (err) {
return console.warn('Error updating unread count', err);
}
$('#unread-count')
.toggleClass('unread-count', count > 0)
.attr('data-content', count > 20 ? '20+' : count);
}
function updateUnreadChatCount(err, count) {
if (err) {
return console.warn('Error updating unread count', err);
}
$('#chat-count')
.toggleClass('unread-count', count > 0)
.attr('data-content', count > 20 ? '20+' : count);
}
function initUnreadTopics() {
var unreadTopics = {};
function onNewPost(data) {
if (data && data.posts && data.posts.length) {
var post = data.posts[0];
if (parseInt(post.uid, 10) !== parseInt(app.uid, 10) && !unreadTopics[post.topic.tid]) {
increaseUnreadCount();
markTopicsUnread(post.topic.tid);
unreadTopics[post.topic.tid] = true;
}
}
}
function increaseUnreadCount() {
var count = parseInt($('#unread-count').attr('data-content'), 10) + 1;
updateUnreadTopicCount(null, count);
}
function markTopicsUnread(tid) {
$('[data-tid="' + tid + '"]').addClass('unread');
}
$(window).on('action:ajaxify.end', function(ev, data) {
var tid = data.url.match(/^topic\/(\d+)/);
if (tid && tid[1]) {
delete unreadTopics[tid[1]];
}
});
socket.on('event:new_post', onNewPost);
}
socket.on('event:unread.updateCount', updateUnreadTopicCount);
socket.emit('user.getUnreadCount', updateUnreadTopicCount);
socket.on('event:unread.updateChatCount', updateUnreadChatCount);
socket.emit('user.getUnreadChatCount', updateUnreadChatCount);
initUnreadTopics();
});

@ -1,16 +0,0 @@
"use strict";
define('forum/groups/details', function() {
var Details = {};
Details.init = function() {
var memberListEl = $('.groups.details .members');
memberListEl.on('click', '[data-slug]', function() {
var slug = this.getAttribute('data-slug');
ajaxify.go('user/' + slug);
});
};
return Details;
});

@ -1,77 +0,0 @@
'use strict';
/* globals define, socket, app, templates, translator, ajaxify*/
define('forum/home', function() {
var home = {};
$(window).on('action:ajaxify.start', function(ev, data) {
if (data.url !== '') {
socket.removeListener('event:new_post', home.onNewPost);
}
});
home.init = function() {
app.enterRoom('home');
socket.removeListener('event:new_post', home.onNewPost);
socket.on('event:new_post', home.onNewPost);
$('.home .category-header').tooltip({
placement: 'bottom'
});
};
home.onNewPost = function(data) {
if (data && data.posts && data.posts.length && data.posts[0].topic) {
renderNewPost(data.posts[0].topic.cid, data.posts[0]);
}
};
function renderNewPost(cid, post) {
var category = $('.home .category-item[data-cid="' + cid + '"]');
var categoryBox = category.find('.category-box');
var numRecentReplies = category.attr('data-numRecentReplies');
if (!numRecentReplies || !parseInt(numRecentReplies, 10)) {
return;
}
var recentPosts = categoryBox.find('.post-preview');
var insertBefore = recentPosts.first();
parseAndTranslate([post], function(html) {
html.hide();
if(recentPosts.length === 0) {
html.appendTo(categoryBox);
} else {
html.insertBefore(recentPosts.first());
}
html.fadeIn();
app.createUserTooltips();
if (categoryBox.find('.post-preview').length > parseInt(numRecentReplies, 10)) {
recentPosts.last().remove();
}
$(window).trigger('action:posts.loaded');
});
}
function parseAndTranslate(posts, callback) {
ajaxify.loadTemplate('home', function(homeTemplate) {
var html = templates.parse(templates.getBlock(homeTemplate, 'posts'), {categories: {posts: posts}});
translator.translate(html, function(translatedHTML) {
translatedHTML = $(translatedHTML);
translatedHTML.find('img').addClass('img-responsive');
translatedHTML.find('span.timeago').timeago();
callback(translatedHTML);
});
});
}
return home;
});

@ -1,92 +0,0 @@
'use strict';
/* globals define, socket, ajaxify, translator, templates, app */
define('forum/infinitescroll', function() {
var scroll = {};
var callback;
var previousScrollTop = 0;
var loadingMore = false;
var topOffset = 0;
scroll.init = function(cb, _topOffest) {
callback = cb;
topOffset = _topOffest || 0;
$(window).off('scroll', onScroll).on('scroll', onScroll);
// if ($(document).height() === $(window).height()) {
// callback(1);
// }
};
function onScroll() {
var originalPostEl = $('li[data-index="0"]'),
top = $(window).height() * 0.15 + topOffset + (originalPostEl ? originalPostEl.outerHeight() : 0),
bottom = ($(document).height() - $(window).height()) * 0.85,
currentScrollTop = $(window).scrollTop();
if(currentScrollTop < top && currentScrollTop < previousScrollTop) {
callback(-1);
} else if (currentScrollTop > bottom && currentScrollTop > previousScrollTop) {
callback(1);
}
previousScrollTop = currentScrollTop;
}
scroll.loadMore = function(method, data, callback) {
if (loadingMore) {
return;
}
loadingMore = true;
socket.emit(method, data, function(err, data) {
if (err) {
loadingMore = false;
return app.alertError(err.message);
}
callback(data, function() {
loadingMore = false;
});
});
};
scroll.parseAndTranslate = function(template, blockName, data, callback) {
ajaxify.loadTemplate(template, function(templateHtml) {
var html = templates.parse(templates.getBlock(templateHtml, blockName), data);
translator.translate(html, function(translatedHTML) {
callback($(translatedHTML));
});
});
};
scroll.calculateAfter = function(direction, selector, count, reverse, callback) {
var after = 0,
offset = 0,
el = direction > 0 ? $(selector).last() : $(selector).first(),
increment;
count = reverse ? -count : count;
increment = reverse ? -1 : 1;
if (direction > 0) {
after = parseInt(el.attr('data-index'), 10) + increment;
} else {
after = parseInt(el.attr('data-index'), 10);
if (isNaN(after)) {
after = 0;
}
after -= count;
if (after < 0) {
after = 0;
}
if (el && el.offset()) {
offset = el.offset().top - $('#header-menu').offset().top + $('#header-menu').height();
}
}
callback(after, offset, el);
};
return scroll;
});

@ -1,39 +0,0 @@
"use strict";
/* global define, app, RELATIVE_PATH */
define('forum/login', function() {
var Login = {};
Login.init = function() {
var errorEl = $('#login-error-notify'),
submitEl = $('#login'),
formEl = $('#login-form');
submitEl.on('click', function(e) {
e.preventDefault();
if (!$('#username').val() || !$('#password').val()) {
translator.translate('[[error:invalid-username-or-password]]', function(translated) {
errorEl.find('p').text(translated)
errorEl.show();
});
} else {
errorEl.hide();
if (!submitEl.hasClass('disabled')) {
submitEl.addClass('disabled');
formEl.submit();
}
}
});
$('#login-error-notify button').on('click', function(e) {
e.preventDefault();
errorEl.hide();
});
$('#content #username').focus();
};
return Login;
});

@ -1,16 +0,0 @@
define('forum/notifications', function() {
var Notifications = {};
Notifications.init = function() {
var listEl = $('.notifications-list');
$('span.timeago').timeago();
// Allow the user to click anywhere in the LI
listEl.on('click', 'li', function(e) {
this.querySelector('a').click();
});
}
return Notifications;
});

@ -1,108 +0,0 @@
'use strict';
/*global define, utils, ajaxify, bootbox*/
define('forum/pagination', function() {
var pagination = {};
pagination.currentPage = 0;
pagination.pageCount = 0;
pagination.init = function(currentPage, pageCount) {
pagination.currentPage = parseInt(currentPage, 10);
pagination.pageCount = parseInt(pageCount, 10);
pagination.recreatePaginationLinks(pageCount);
$('.pagination')
.on('click', '.previous', function() {
return pagination.loadPage(pagination.currentPage - 1);
}).on('click', '.next', function() {
return pagination.loadPage(pagination.currentPage + 1);
}).on('click', '.select_page', function(e) {
e.preventDefault();
bootbox.prompt('Enter page number:', function(pageNum) {
pagination.loadPage(pageNum);
});
});
};
pagination.recreatePaginationLinks = function(newPageCount) {
pagination.pageCount = parseInt(newPageCount, 10);
var pagesToShow = determinePagesToShow();
var html = '';
for(var i=0; i<pagesToShow.length; ++i) {
if(i > 0) {
if (pagesToShow[i] - 1 !== pagesToShow[i-1]) {
html += '<li><a class="select_page" href="#">|</a></li>';
}
}
html += '<li class="page" data-page="' + pagesToShow[i] + '"><a href="#">' + pagesToShow[i] + '</a></li>';
}
$('.pagination li.page').remove();
$('.pagination li .select_page').parent().remove();
$(html).insertAfter($('.pagination li.previous'));
updatePageLinks();
};
function determinePagesToShow() {
var pagesToShow = [1];
if(pagination.pageCount !== 1) {
pagesToShow.push(pagination.pageCount);
}
var previous = pagination.currentPage - 1;
var next = pagination.currentPage + 1;
if(previous > 1 && pagesToShow.indexOf(previous) === -1) {
pagesToShow.push(previous);
}
if(next < pagination.pageCount && pagesToShow.indexOf(next) === -1) {
pagesToShow.push(next);
}
if(pagesToShow.indexOf(pagination.currentPage) === -1) {
pagesToShow.push(pagination.currentPage);
}
pagesToShow.sort(function(a, b) {
return parseInt(a, 10) - parseInt(b, 10);
});
return pagesToShow;
}
pagination.loadPage = function(page, callback) {
page = parseInt(page, 10);
if(!utils.isNumber(page) || page < 1 || page > pagination.pageCount) {
return false;
}
ajaxify.go(window.location.pathname.slice(1) + '?page=' + page, function() {
if (typeof callback === 'function') {
callback();
}
});
return true;
};
function updatePageLinks() {
$('.pagination').toggleClass('hide', pagination.pageCount === 0 || pagination.pageCount === 1);
$('.pagination .next').toggleClass('disabled', pagination.currentPage === pagination.pageCount);
$('.pagination .previous').toggleClass('disabled', pagination.currentPage === 1);
$('.pagination .page').removeClass('active');
$('.pagination .page[data-page="' + pagination.currentPage + '"]').addClass('active');
$('.pagination .page').each(function(index, element) {
var li = $(this);
var page = li.attr('data-page');
li.find('a').attr('href', window.location.pathname + '?page=' + page);
});
}
return pagination;
});

@ -1,19 +0,0 @@
'use strict';
/* globals define, app, socket*/
define('forum/popular', ['forum/recent', 'forum/infinitescroll'], function(recent, infinitescroll) {
var Popular = {};
Popular.init = function() {
app.enterRoom('recent_posts');
$('#new-topics-alert').on('click', function() {
$(this).addClass('hide');
});
recent.selectActivePill();
};
return Popular;
});

@ -1,140 +0,0 @@
'use strict';
/* globals define, app, socket, utils */
define('forum/recent', ['forum/infinitescroll'], function(infinitescroll) {
var Recent = {};
var newTopicCount = 0,
newPostCount = 0;
var active = '';
function getActiveSection() {
var url = window.location.href,
parts = url.split('/'),
active = parts[parts.length - 1];
return active;
}
$(window).on('action:ajaxify.start', function(ev, data) {
if(data.url.indexOf('recent') !== 0) {
Recent.removeListeners();
}
});
Recent.init = function() {
app.enterRoom('recent_posts');
Recent.watchForNewPosts();
active = Recent.selectActivePill();
$('#new-topics-alert').on('click', function() {
$(this).addClass('hide');
});
infinitescroll.init(Recent.loadMoreTopics);
};
Recent.selectActivePill = function() {
var active = getActiveSection();
$('.nav-pills li').removeClass('active');
$('.nav-pills li a').each(function() {
var $this = $(this);
if ($this.attr('href').match(active)) {
$this.parent().addClass('active');
return false;
}
});
return active;
};
Recent.watchForNewPosts = function () {
newPostCount = 0;
newTopicCount = 0;
Recent.removeListeners();
socket.on('event:new_topic', onNewTopic);
socket.on('event:new_post', onNewPost);
};
function onNewTopic(data) {
++newTopicCount;
Recent.updateAlertText();
}
function onNewPost(data) {
++newPostCount;
Recent.updateAlertText();
}
Recent.removeListeners = function() {
socket.removeListener('event:new_topic', onNewTopic);
socket.removeListener('event:new_post', onNewPost);
};
Recent.updateAlertText = function() {
var text = 'There';
if (newTopicCount > 1) {
text += ' are ' + newTopicCount + ' new topics';
} else if (newTopicCount === 1) {
text += ' is a new topic';
}
if (newPostCount > 1) {
text += (newTopicCount?' and ':' are ') + newPostCount + ' new posts';
} else if(newPostCount === 1) {
text += (newTopicCount?' and ':' is ') + ' a new post';
}
text += '. Click here to reload.';
$('#new-topics-alert').html(text).removeClass('hide').fadeIn('slow');
$('#category-no-topics').addClass('hide');
};
Recent.loadMoreTopics = function(direction) {
if(direction < 0 || !$('#topics-container').length) {
return;
}
infinitescroll.loadMore('topics.loadMoreRecentTopics', {
after: $('#topics-container').attr('data-nextstart'),
term: active
}, function(data, done) {
if (data.topics && data.topics.length) {
Recent.onTopicsLoaded('recent', data.topics, false, done);
$('#topics-container').attr('data-nextstart', data.nextStart);
} else {
done();
}
});
};
Recent.onTopicsLoaded = function(templateName, topics, showSelect, callback) {
topics = topics.filter(function(topic) {
return !$('#topics-container li[data-tid=' + topic.tid + ']').length;
});
if (!topics.length) {
return callback();
}
infinitescroll.parseAndTranslate(templateName, 'topics', {topics: topics, showSelect: showSelect}, function(html) {
$('#category-no-topics').remove();
$('#topics-container').append(html);
html.find('span.timeago').timeago();
app.createUserTooltips();
utils.makeNumbersHumanReadable(html.find('.human-readable-number'));
callback();
});
};
return Recent;
});

@ -1,198 +0,0 @@
'use strict';
/* globals define, app, utils, socket, config */
define('forum/register', function() {
var Register = {},
validationError = false,
successIcon = '<i class="fa fa-check"></i>';
function showError(element, msg) {
translator.translate(msg, function(msg) {
element.html(msg);
element.parent()
.removeClass('alert-success')
.addClass('alert-danger');
element.show();
});
validationError = true;
}
function showSuccess(element, msg) {
translator.translate(msg, function(msg) {
element.html(msg);
element.parent()
.removeClass('alert-danger')
.addClass('alert-success');
element.show();
});
}
function validateEmail(email, callback) {
callback = callback || function() {};
var email_notify = $('#email-notify');
if (!email) {
validationError = true;
return;
}
if (!utils.isEmailValid(email)) {
showError(email_notify, '[[error:invalid-email]]');
return;
}
socket.emit('user.emailExists', {
email: email
}, function(err, exists) {
if(err) {
return app.alertError(err.message);
}
if (exists) {
showError(email_notify, '[[error:email-taken]]');
} else {
showSuccess(email_notify, successIcon);
}
callback();
});
}
function validateUsername(username, callback) {
callback = callback || function() {};
var username_notify = $('#username-notify');
if (!username) {
validationError = true;
return;
}
if (username.length < config.minimumUsernameLength) {
showError(username_notify, '[[error:username-too-short]]');
} else if (username.length > config.maximumUsernameLength) {
showError(username_notify, '[[error:username-too-long]]');
} else if (!utils.isUserNameValid(username) || !utils.slugify(username)) {
showError(username_notify, '[[error:invalid-username]]');
} else {
socket.emit('user.exists', {
username: username
}, function(err, exists) {
if(err) {
return app.alertError(err.message);
}
if (exists) {
showError(username_notify, '[[error:username-taken]]');
} else {
showSuccess(username_notify, successIcon);
}
callback();
});
}
}
function validatePassword(password, password_confirm) {
if (!password) {
validationError = true;
return;
}
var password_notify = $('#password-notify'),
password_confirm_notify = $('#password-confirm-notify');
if (password.length < config.minimumPasswordLength) {
showError(password_notify, '[[user:change_password_error_length]]');
} else if (!utils.isPasswordValid(password)) {
showError(password_notify, '[[user:change_password_error]]');
} else {
showSuccess(password_notify, successIcon);
}
if (password !== password_confirm && password_confirm !== '') {
showError(password_confirm_notify, '[[user:change_password_error_match]]');
}
}
function validatePasswordConfirm(password, password_confirm) {
var password_notify = $('#password-notify'),
password_confirm_notify = $('#password-confirm-notify');
if (!password || password_notify.hasClass('alert-error')) {
return;
}
if (password !== password_confirm) {
showError(password_confirm_notify, '[[user:change_password_error_match]]');
} else {
showSuccess(password_confirm_notify, successIcon);
}
}
Register.init = function() {
var email = $('#email'),
username = $('#username'),
password = $('#password'),
password_confirm = $('#password-confirm'),
register = $('#register'),
agreeTerms = $('#agree-terms');
$('#referrer').val(app.previousUrl);
email.on('blur', function() {
validateEmail(email.val());
});
username.on('keyup', function() {
$('#yourUsername').html(this.value.length > 0 ? this.value : 'username');
});
username.on('blur', function() {
validateUsername(username.val());
});
password.on('blur', function() {
validatePassword(password.val(), password_confirm.val());
});
password_confirm.on('blur', function() {
validatePasswordConfirm(password.val(), password_confirm.val());
});
function validateForm(callback) {
validationError = false;
validatePassword(password.val(), password_confirm.val());
validatePasswordConfirm(password.val(), password_confirm.val());
validateEmail(email.val(), function() {
validateUsername(username.val(), callback);
});
}
register.on('click', function(e) {
var registerBtn = $(this);
e.preventDefault();
validateForm(function() {
if (!validationError) {
registerBtn.parents('form').trigger('submit');
}
});
});
if(agreeTerms.length) {
agreeTerms.on('click', function() {
if ($(this).prop('checked')) {
register.removeAttr('disabled');
} else {
register.attr('disabled', 'disabled');
}
});
register.attr('disabled', 'disabled');
}
};
return Register;
});

@ -1,28 +0,0 @@
define('forum/reset', function() {
var ResetPassword = {};
ResetPassword.init = function() {
var inputEl = $('#email'),
errorEl = $('#error'),
successEl = $('#success');
$('#reset').on('click', function() {
if (inputEl.val() && inputEl.val().indexOf('@') !== -1) {
socket.emit('user.reset.send', inputEl.val(), function(err, data) {
if(err) {
return app.alertError(err.message);
}
errorEl.addClass('hide').hide();
successEl.removeClass('hide').show();
inputEl.val('');
});
} else {
successEl.addClass('hide').hide();
errorEl.removeClass('hide').show();
}
});
};
return ResetPassword;
});

@ -1,55 +0,0 @@
define('forum/reset_code', function() {
var ResetCode = {};
ResetCode.init = function() {
var reset_code = ajaxify.variables.get('reset_code');
var resetEl = $('#reset'),
password = $('#password'),
repeat = $('#repeat'),
noticeEl = $('#notice');
resetEl.on('click', function() {
if (password.val().length < 6) {
$('#error').addClass('hide').hide();
noticeEl.find('strong').html('Invalid Password');
noticeEl.find('p').html('The password entered is too short, please pick a different password.');
noticeEl.removeClass('hide').css({display: 'block'});
} else if (password.value !== repeat.value) {
$('#error').hide();
noticeEl.find('strong').html('Invalid Password');
noticeEl.find('p').html('The two passwords you\'ve entered do not match.');
noticeEl.removeClass('hide').css({display: 'block'});
} else {
socket.emit('user.reset.commit', {
code: reset_code,
password: password.val()
}, function(err) {
if(err) {
return app.alertError(err.message);
}
$('#error').addClass('hide').hide();
$('#notice').addClass('hide').hide();
$('#success').removeClass('hide').addClass('show').show();
});
}
});
socket.emit('user.reset.valid', reset_code, function(err, valid) {
if(err) {
return app.alertError(err.message);
}
if (valid) {
resetEl.prop('disabled', false);
} else {
var formEl = $('#reset-form');
// Show error message
$('#error').show();
formEl.remove();
}
});
};
return ResetCode;
});

@ -1,35 +0,0 @@
define('forum/search', ['search'], function(searchModule) {
var Search = {};
Search.init = function() {
var searchQuery = $('#post-results').attr('data-search-query');
var regexes = [];
var searchTerms = searchQuery.split(' ');
for (var i=0; i<searchTerms.length; ++i) {
var regex = new RegExp(searchTerms[i], 'gi');
regexes.push({regex: regex, term: searchTerms[i]});
}
$('.search-result-text').each(function() {
var result = $(this);
var text = result.html();
for(var i=0; i<regexes.length; ++i) {
text = text.replace(regexes[i].regex, '<strong>' + regexes[i].term + '</strong>');
}
result.html(text).find('img').addClass('img-responsive');
});
$('#search-form input').val(searchQuery);
$('#mobile-search-form').off('submit').on('submit', function(e) {
e.preventDefault();
var input = $(this).find('input');
searchModule.query(input.val(), function() {
input.val('');
});
});
};
return Search;
});

@ -1,42 +0,0 @@
'use strict';
/* globals define, app, socket */
define('forum/tag', ['forum/recent', 'forum/infinitescroll'], function(recent, infinitescroll) {
var Tag = {};
Tag.init = function() {
app.enterRoom('tags');
if ($('body').height() <= $(window).height() && $('#topics-container').children().length >= 20) {
$('#load-more-btn').show();
}
$('#load-more-btn').on('click', function() {
loadMoreTopics();
});
infinitescroll.init(loadMoreTopics);
function loadMoreTopics(direction) {
if(direction < 0 || !$('#topics-container').length) {
return;
}
infinitescroll.loadMore('topics.loadMoreFromSet', {
set: 'tag:' + ajaxify.variables.get('tag') + ':topics',
after: $('#topics-container').attr('data-nextstart')
}, function(data, done) {
if (data.topics && data.topics.length) {
recent.onTopicsLoaded('tag', data.topics, false, done);
$('#topics-container').attr('data-nextstart', data.nextStart);
} else {
done();
$('#load-more-btn').hide();
}
});
}
};
return Tag;
});

@ -1,59 +0,0 @@
'use strict';
/* globals define, app, utils, socket */
define('forum/tags', ['forum/infinitescroll'], function(infinitescroll) {
var Tags = {};
var timeoutId = 0;
Tags.init = function() {
app.enterRoom('tags');
$('#tag-search').on('input propertychange', function() {
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = 0;
}
timeoutId = setTimeout(function() {
socket.emit('topics.searchAndLoadTags', {query: $('#tag-search').val()}, function(err, results) {
if (err) {
return app.alertError(err.message);
}
onTagsLoaded(results, true, function() {
timeoutId = 0;
});
});
}, 100);
});
infinitescroll.init(Tags.loadMoreTags);
};
Tags.loadMoreTags = function(direction) {
if(direction < 0 || !$('.tag-list').length) {
return;
}
infinitescroll.loadMore('topics.loadMoreTags', {
after: $('.tag-list').attr('data-nextstart')
}, function(data, done) {
if (data && data.tags && data.tags.length) {
onTagsLoaded(data.tags, false, done);
$('.tag-list').attr('data-nextstart', data.nextStart);
} else {
done();
}
});
};
function onTagsLoaded(tags, replace, callback) {
callback = callback || function() {};
infinitescroll.parseAndTranslate('tags', 'tags', {tags: tags}, function(html) {
$('.tag-list')[replace ? 'html' : 'append'](html);
utils.makeNumbersHumanReadable(html.find('.human-readable-number'));
callback();
});
}
return Tags;
});

@ -1,452 +0,0 @@
'use strict';
/* globals define, app, templates, translator, socket, bootbox, config, ajaxify, RELATIVE_PATH, utils */
var dependencies = [
'forum/pagination',
'forum/infinitescroll',
'forum/topic/threadTools',
'forum/topic/postTools',
'forum/topic/events',
'forum/topic/browsing',
'navigator'
];
define('forum/topic', dependencies, function(pagination, infinitescroll, threadTools, postTools, events, browsing, navigator) {
var Topic = {},
currentUrl = '';
$(window).on('action:ajaxify.start', function(ev, data) {
if(data.url.indexOf('topic') !== 0) {
navigator.hide();
$('.header-topic-title').find('span').text('').hide();
app.removeAlert('bookmark');
events.removeListeners();
socket.removeListener('event:new_post', onNewPost);
socket.removeListener('event:new_notification', onNewNotification);
}
});
Topic.init = function() {
var tid = ajaxify.variables.get('topic_id'),
thread_state = {
locked: ajaxify.variables.get('locked'),
deleted: ajaxify.variables.get('deleted'),
pinned: ajaxify.variables.get('pinned')
},
postCount = ajaxify.variables.get('postcount');
$(window).trigger('action:topic.loading');
app.enterRoom('topic_' + tid);
processPage($('.topic'));
showBottomPostBar();
postTools.init(tid, thread_state);
threadTools.init(tid, thread_state);
events.init();
handleSorting();
hidePostToolsForDeletedPosts();
enableInfiniteLoadingOrPagination();
addBlockQuoteHandler();
addBlockquoteEllipses($('.topic .post-content > blockquote'));
handleBookmark(tid);
navigator.init('.posts > .post-row', postCount, Topic.toTop, Topic.toBottom, Topic.navigatorCallback, Topic.calculateIndex);
socket.on('event:new_post', onNewPost);
socket.on('event:new_notification', onNewNotification);
$(window).on('scroll', updateTopicTitle);
$(window).trigger('action:topic.loaded');
socket.emit('topics.enter', tid);
};
Topic.toTop = function() {
navigator.scrollTop(0);
};
Topic.toBottom = function() {
socket.emit('topics.postcount', ajaxify.variables.get('topic_id'), function(err, postCount) {
if (config.topicPostSort !== 'oldest_to_newest') {
postCount = 1;
}
navigator.scrollBottom(postCount - 1);
});
};
function handleBookmark(tid) {
var bookmark = localStorage.getItem('topic:' + tid + ':bookmark');
var postIndex = getPostIndex();
if (postIndex) {
navigator.scrollToPost(postIndex - 1, true);
} else if (bookmark && (!config.usePagination || (config.usePagination && pagination.currentPage === 1)) && ajaxify.variables.get('postcount') > 1) {
app.alert({
alert_id: 'bookmark',
message: '[[topic:bookmark_instructions]]',
timeout: 0,
type: 'info',
clickfn : function() {
navigator.scrollToPost(parseInt(bookmark, 10), true);
},
closefn : function() {
localStorage.removeItem('topic:' + tid + ':bookmark');
}
});
}
}
function getPostIndex() {
var parts = window.location.pathname.split('/');
return parts[4] ? parseInt(parts[4], 10) : 0;
}
function handleSorting() {
var threadSort = $('.thread-sort');
threadSort.find('i').removeClass('fa-check');
var currentSetting = threadSort.find('a[data-sort="' + config.topicPostSort + '"]');
currentSetting.find('i').addClass('fa-check');
$('.thread-sort').on('click', 'a', function() {
var newSetting = $(this).attr('data-sort');
socket.emit('user.setTopicSort', newSetting, function(err) {
config.topicPostSort = newSetting;
ajaxify.go('topic/' + ajaxify.variables.get('topic_slug'));
});
});
}
function showBottomPostBar() {
if($('#post-container .post-row').length > 1 || !$('#post-container li[data-index="0"]').length) {
$('.bottom-post-bar').removeClass('hide');
}
}
function onNewPost(data) {
var tid = ajaxify.variables.get('topic_id');
if(data && data.posts && data.posts.length && data.posts[0].tid !== tid) {
return;
}
if(config.usePagination) {
return onNewPostPagination(data);
}
for (var i=0; i<data.posts.length; ++i) {
var postcount = $('.user_postcount_' + data.posts[i].uid);
postcount.html(parseInt(postcount.html(), 10) + 1);
}
socket.emit('topics.markAsRead', [tid]);
createNewPosts(data);
}
function onNewNotification(data) {
var tid = ajaxify.variables.get('topic_id');
if (data && data.tid && parseInt(data.tid, 10) === parseInt(tid, 10)) {
socket.emit('topics.markTopicNotificationsRead', tid);
}
}
function addBlockQuoteHandler() {
$('#post-container').on('click', 'blockquote .toggle', function() {
var blockQuote = $(this).parent('blockquote');
var toggle = $(this);
blockQuote.toggleClass('uncollapsed');
var collapsed = !blockQuote.hasClass('uncollapsed');
toggle.toggleClass('fa-angle-down', collapsed).toggleClass('fa-angle-up', !collapsed);
});
}
function addBlockquoteEllipses(blockquotes) {
blockquotes.each(function() {
var $this = $(this);
if ($this.find(':hidden:not(br)').length && !$this.find('.toggle').length) {
$this.append('<i class="fa fa-angle-down pointer toggle"></i>');
}
});
}
function enableInfiniteLoadingOrPagination() {
if(!config.usePagination) {
infinitescroll.init(loadMorePosts, $('#post-container .post-row[data-index="0"]').height());
} else {
navigator.hide();
pagination.init(parseInt(ajaxify.variables.get('currentPage'), 10), parseInt(ajaxify.variables.get('pageCount'), 10));
}
}
function hidePostToolsForDeletedPosts() {
$('#post-container li.deleted').each(function() {
postTools.toggle($(this).attr('data-pid'), true);
});
}
function updateTopicTitle() {
if($(window).scrollTop() > 50) {
$('.header-topic-title').find('span').text(ajaxify.variables.get('topic_name')).show();
} else {
$('.header-topic-title').find('span').text('').hide();
}
}
Topic.calculateIndex = function(index, elementCount) {
if (index !== 1 && config.topicPostSort !== 'oldest_to_newest') {
return elementCount - index + 2;
}
return index;
};
Topic.navigatorCallback = function(element, elementCount) {
var path = ajaxify.removeRelativePath(window.location.pathname.slice(1));
if (!path.startsWith('topic')) {
return 1;
}
var postIndex = parseInt(element.attr('data-index'), 10);
var index = postIndex + 1;
if (config.topicPostSort !== 'oldest_to_newest') {
if (postIndex === 0) {
index = 1;
} else {
index = Math.max(elementCount - postIndex + 1, 1);
}
}
var currentBookmark = localStorage.getItem('topic:' + ajaxify.variables.get('topic_id') + ':bookmark');
if (!currentBookmark || parseInt(postIndex, 10) >= parseInt(currentBookmark, 10)) {
localStorage.setItem('topic:' + ajaxify.variables.get('topic_id') + ':bookmark', postIndex);
app.removeAlert('bookmark');
}
if (!navigator.scrollActive) {
var parts = ajaxify.removeRelativePath(window.location.pathname.slice(1)).split('/');
var topicId = parts[1],
slug = parts[2];
var newUrl = 'topic/' + topicId + '/' + (slug ? slug : '');
if (postIndex > 0) {
newUrl += '/' + (postIndex + 1);
}
if (newUrl !== currentUrl) {
if (history.replaceState) {
var search = (window.location.search ? window.location.search : '');
history.replaceState({
url: newUrl + search
}, null, window.location.protocol + '//' + window.location.host + RELATIVE_PATH + '/' + newUrl + search);
}
currentUrl = newUrl;
}
}
return index;
};
function onNewPostPagination(data) {
var posts = data.posts;
socket.emit('topics.getPageCount', ajaxify.variables.get('topic_id'), function(err, newPageCount) {
pagination.recreatePaginationLinks(newPageCount);
if (pagination.currentPage === pagination.pageCount) {
createNewPosts(data);
} else if(data.posts && data.posts.length && parseInt(data.posts[0].uid, 10) === parseInt(app.uid, 10)) {
pagination.loadPage(pagination.pageCount);
}
});
}
function createNewPosts(data, callback) {
callback = callback || function() {};
if(!data || (data.posts && !data.posts.length)) {
return callback(false);
}
function removeAlreadyAddedPosts() {
data.posts = data.posts.filter(function(post) {
return $('#post-container li[data-pid="' + post.pid +'"]').length === 0;
});
}
var after = null,
before = null;
function findInsertionPoint() {
var firstPostTimestamp = parseInt(data.posts[0].timestamp, 10);
var firstPostVotes = parseInt(data.posts[0].votes, 10);
var firstPostPid = data.posts[0].pid;
var firstReply = $('#post-container li.post-row[data-index!="0"]').first();
var lastReply = $('#post-container li.post-row[data-index!="0"]').last();
if (config.topicPostSort === 'oldest_to_newest') {
if (firstPostTimestamp < parseInt(firstReply.attr('data-timestamp'), 10)) {
before = firstReply;
} else if(firstPostTimestamp >= parseInt(lastReply.attr('data-timestamp'), 10)) {
after = lastReply;
}
} else if(config.topicPostSort === 'newest_to_oldest') {
if (firstPostTimestamp > parseInt(firstReply.attr('data-timestamp'), 10)) {
before = firstReply;
} else if(firstPostTimestamp <= parseInt(lastReply.attr('data-timestamp'), 10)) {
after = lastReply;
}
} else if(config.topicPostSort === 'most_votes') {
if (firstPostVotes > parseInt(firstReply.attr('data-votes'), 10)) {
before = firstReply;
} else if(firstPostVotes < parseInt(firstReply.attr('data-votes'), 10)) {
after = lastReply;
} else {
if (firstPostPid > firstReply.attr('data-pid')) {
before = firstReply;
} else if(firstPostPid <= firstReply.attr('data-pid')) {
after = lastReply;
}
}
}
}
removeAlreadyAddedPosts();
if(!data.posts.length) {
return callback(false);
}
findInsertionPoint();
data.title = $('<div></div>').text(ajaxify.variables.get('topic_name')).html();
data.viewcount = ajaxify.variables.get('viewcount');
infinitescroll.parseAndTranslate('topic', 'posts', data, function(html) {
if(after) {
html.insertAfter(after);
} else if(before) {
// Save document height and position for future reference (about 5 lines down)
var height = $(document).height(),
scrollTop = $(document).scrollTop(),
originalPostEl = $('li[data-index="0"]');
// Insert the new post
html.insertBefore(before);
// If the user is not at the top of the page... (or reasonably so...)
if (scrollTop > originalPostEl.offset().top) {
// Now restore the relative position the user was on prior to new post insertion
$(document).scrollTop(scrollTop + ($(document).height() - height));
}
} else {
$('#post-container').append(html);
}
html.hide().fadeIn('slow');
addBlockquoteEllipses(html.find('.post-content > blockquote'));
$(window).trigger('action:posts.loaded');
onNewPostsLoaded(html, data.posts);
callback(true);
});
}
function onNewPostsLoaded(html, posts) {
var pids = [];
for(var i=0; i<posts.length; ++i) {
pids.push(posts[i].pid);
}
socket.emit('posts.getPrivileges', pids, function(err, privileges) {
if(err) {
return app.alertError(err.message);
}
for(i=0; i<pids.length; ++i) {
toggleModTools(pids[i], privileges[i]);
}
});
processPage(html);
}
function processPage(element) {
app.createUserTooltips();
app.replaceSelfLinks(element.find('a'));
utils.addCommasToNumbers(element.find('.formatted-number'));
utils.makeNumbersHumanReadable(element.find('.human-readable-number'));
element.find('span.timeago').timeago();
element.find('.post-content img:not(.emoji)').addClass('img-responsive').each(function() {
var $this = $(this);
if (!$this.parent().is('a')) {
$this.wrap('<a href="' + $this.attr('src') + '" target="_blank">');
}
});
postTools.updatePostCount();
showBottomPostBar();
}
function toggleModTools(pid, privileges) {
var postEl = $('.post-row[data-pid="' + pid + '"]');
postEl.find('.edit, .delete').toggleClass('hidden', !privileges.editable);
postEl.find('.move').toggleClass('hidden', !privileges.move);
postEl.find('.reply, .quote').toggleClass('hidden', !$('.post_reply').length);
var isSelfPost = parseInt(postEl.attr('data-uid'), 10) === parseInt(app.uid, 10);
postEl.find('.chat, .flag').toggleClass('hidden', isSelfPost || !app.uid);
}
function loadMorePosts(direction) {
if (!$('#post-container').length || navigator.scrollActive) {
return;
}
var reverse = config.topicPostSort === 'newest_to_oldest' || config.topicPostSort === 'most_votes';
infinitescroll.calculateAfter(direction, '#post-container .post-row[data-index!="0"]', config.postsPerPage, reverse, function(after, offset, el) {
loadPostsAfter(after);
});
}
function loadPostsAfter(after) {
var tid = ajaxify.variables.get('topic_id');
if (!utils.isNumber(tid) || !utils.isNumber(after) || (after === 0 && $('#post-container li.post-row[data-index="1"]').length)) {
return;
}
var indicatorEl = $('.loading-indicator');
if (!indicatorEl.is(':animated')) {
indicatorEl.fadeIn();
}
infinitescroll.loadMore('topics.loadMore', {
tid: tid,
after: after
}, function (data, done) {
indicatorEl.fadeOut();
if (data && data.posts && data.posts.length) {
createNewPosts(data, function(postsCreated) {
done();
});
hidePostToolsForDeletedPosts();
} else {
navigator.update();
done();
}
});
}
return Topic;
});

@ -1,95 +0,0 @@
'use strict';
/* globals define, app, translator, config, socket, ajaxify */
define('forum/topic/browsing', function() {
var Browsing = {};
Browsing.onUpdateUsersInRoom = function(data) {
if(data && data.room.indexOf('topic_' + ajaxify.variables.get('topic_id')) !== -1) {
for(var i=0; i<data.users.length; ++i) {
addUserIcon(data.users[i]);
}
getReplyingUsers();
}
};
Browsing.onUserEnter = function(data) {
var activeEl = $('.thread_active_users');
var user = activeEl.find('a[data-uid="' + data.uid + '"]');
if (!user.length && activeEl.children().length < 10) {
addUserIcon(data);
} else {
user.attr('data-count', parseInt(user.attr('data-count'), 10) + 1);
}
};
Browsing.onUserLeave = function(uid) {
var activeEl = $('.thread_active_users');
var user = activeEl.find('a[data-uid="' + uid + '"]');
if (user.length) {
var count = Math.max(0, parseInt(user.attr('data-count'), 10) - 1);
user.attr('data-count', count);
if (count <= 0) {
user.remove();
}
}
};
Browsing.onUserStatusChange = function(data) {
updateOnlineIcon($('.username-field[data-uid="' + data.uid + '"]'), data.status);
updateBrowsingUsers(data);
};
function updateOnlineIcon(el, status) {
translator.translate('[[global:' + status + ']]', function(translated) {
el.siblings('i')
.attr('class', 'fa fa-circle status ' + status)
.attr('title', translated)
.attr('data-original-title', translated);
});
}
function updateBrowsingUsers(data) {
var activeEl = $('.thread_active_users');
var user = activeEl.find('a[data-uid="'+ data.uid + '"]');
if (user.length && data.status === 'offline') {
user.parent().remove();
}
}
function addUserIcon(user) {
if (!user.userslug) {
return;
}
var activeEl = $('.thread_active_users');
var userEl = createUserIcon(user.uid, user.picture, user.userslug, user.username);
activeEl.append(userEl);
activeEl.find('a[data-uid] img').tooltip({
placement: 'top'
});
}
function createUserIcon(uid, picture, userslug, username) {
if(!$('.thread_active_users').find('[data-uid="' + uid + '"]').length) {
return $('<div class="inline-block"><a data-uid="' + uid + '" data-count="1" href="' + config.relative_path + '/user/' + userslug + '"><img title="' + username + '" src="'+ picture +'"/></a></div>');
}
}
function getReplyingUsers() {
var activeEl = $('.thread_active_users');
socket.emit('modules.composer.getUsersByTid', ajaxify.variables.get('topic_id'), function(err, uids) {
if (uids && uids.length) {
for(var x=0;x<uids.length;x++) {
activeEl.find('[data-uid="' + uids[x] + '"]').addClass('replying');
}
}
});
}
return Browsing;
});

@ -1,180 +0,0 @@
'use strict';
/* globals app, ajaxify, define, socket, translator, templates */
define('forum/topic/events', ['forum/topic/browsing', 'forum/topic/postTools', 'forum/topic/threadTools'], function(browsing, postTools, threadTools) {
var Events = {};
var events = {
'event:update_users_in_room': browsing.onUpdateUsersInRoom,
'event:user_enter': browsing.onUserEnter,
'event:user_leave': browsing.onUserLeave,
'event:user_status_change': browsing.onUserStatusChange,
'event:voted': updatePostVotesAndUserReputation,
'event:favourited': updateFavouriteCount,
'event:topic_deleted': toggleTopicDeleteState,
'event:topic_restored': toggleTopicDeleteState,
'event:topic_purged': onTopicPurged,
'event:topic_locked': threadTools.setLockedState,
'event:topic_unlocked': threadTools.setLockedState,
'event:topic_pinned': threadTools.setPinnedState,
'event:topic_unpinned': threadTools.setPinnedState,
'event:topic_moved': onTopicMoved,
'event:post_edited': onPostEdited,
'event:post_purged': onPostPurged,
'event:post_deleted': togglePostDeleteState,
'event:post_restored': togglePostDeleteState,
'posts.favourite': togglePostFavourite,
'posts.unfavourite': togglePostFavourite,
'posts.upvote': togglePostVote,
'posts.downvote': togglePostVote,
'posts.unvote': togglePostVote,
'event:topic.toggleReply': toggleReply,
};
Events.init = function() {
Events.removeListeners();
for(var eventName in events) {
if (events.hasOwnProperty(eventName)) {
socket.on(eventName, events[eventName]);
}
}
};
Events.removeListeners = function() {
for(var eventName in events) {
if (events.hasOwnProperty(eventName)) {
socket.removeListener(eventName, events[eventName]);
}
}
};
function updatePostVotesAndUserReputation(data) {
var votes = $('li[data-pid="' + data.post.pid + '"] .votes'),
reputationElements = $('.reputation[data-uid="' + data.post.uid + '"]');
votes.html(data.post.votes).attr('data-votes', data.post.votes);
reputationElements.html(data.user.reputation).attr('data-reputation', data.user.reputation);
}
function updateFavouriteCount(data) {
$('li[data-pid="' + data.post.pid + '"] .favouriteCount').html(data.post.reputation).attr('data-favourites', data.post.reputation);
}
function toggleTopicDeleteState(data) {
threadTools.setLockedState(data);
threadTools.setDeleteState(data);
}
function onTopicPurged(tid) {
ajaxify.go('category/' + ajaxify.variables.get('category_id'));
}
function onTopicMoved(data) {
if (data && data.tid > 0) {
ajaxify.go('topic/' + data.tid);
}
}
function onPostEdited(data) {
var editedPostEl = $('#content_' + data.pid),
editedPostTitle = $('#topic_title_' + data.pid);
if (editedPostTitle.length) {
editedPostTitle.fadeOut(250, function() {
editedPostTitle.html(data.title).fadeIn(250);
});
}
editedPostEl.fadeOut(250, function() {
editedPostEl.html(data.content);
editedPostEl.find('img').addClass('img-responsive');
app.replaceSelfLinks(editedPostEl.find('a'));
editedPostEl.fadeIn(250);
$(window).trigger('action:posts.edited');
});
if (data.tags && data.tags.length !== $('.tags').first().children().length) {
ajaxify.loadTemplate('partials/post_bar', function(postBarTemplate) {
var html = templates.parse(templates.getBlock(postBarTemplate, 'tags'), {
tags: data.tags
});
var tags = $('.tags');
tags.fadeOut(250, function() {
tags.html(html).fadeIn(250);
});
});
}
}
function onPostPurged(pid) {
$('#post-container li[data-pid="' + pid + '"]').fadeOut(500, function() {
$(this).remove();
});
}
function togglePostDeleteState(data) {
var postEl = $('#post-container li[data-pid="' + data.pid + '"]');
if (!postEl.length) {
return;
}
postEl.toggleClass('deleted');
var isDeleted = postEl.hasClass('deleted');
postTools.toggle(data.pid, isDeleted);
if (!app.isAdmin && parseInt(data.uid, 10) !== parseInt(app.uid, 10)) {
if (isDeleted) {
postEl.find('.post-content').translateHtml('[[topic:post_is_deleted]]');
} else {
postEl.find('.post-content').html(data.content);
}
}
postTools.updatePostCount();
}
function togglePostFavourite(data) {
var favBtn = $('li[data-pid="' + data.post.pid + '"] .favourite');
if (!favBtn.length) {
return;
}
favBtn.addClass('btn-warning')
.attr('data-favourited', data.isFavourited);
var icon = favBtn.find('i');
var className = icon.attr('class');
if (data.isFavourited ? className.indexOf('-o') !== -1 : className.indexOf('-o') === -1) {
icon.attr('class', data.isFavourited ? className.replace('-o', '') : className + '-o');
}
}
function togglePostVote(data) {
var post = $('li[data-pid="' + data.post.pid + '"]');
post.find('.upvote').toggleClass('btn-primary upvoted', data.upvote);
post.find('.downvote').toggleClass('btn-primary downvoted', data.downvote);
}
function toggleReply(data) {
$('.thread_active_users [data-uid="' + data.uid + '"]').toggleClass('replying', data.isReplying);
}
return Events;
});

@ -1,136 +0,0 @@
'use strict';
/* globals define, app, translator, socket */
define('forum/topic/fork', function() {
var Fork = {},
forkModal,
forkCommit,
pids = [];
Fork.init = function() {
$('.fork_thread').on('click', onForkThreadClicked);
};
function disableClicks() {
return false;
}
function disableClicksOnPosts() {
$('.post-row').on('click', 'button,a', disableClicks);
}
function enableClicksOnPosts() {
$('.post-row').off('click', 'button,a', disableClicks);
}
function onForkThreadClicked() {
forkModal = $('#fork-thread-modal');
forkCommit = forkModal.find('#fork_thread_commit');
pids.length = 0;
showForkModal();
showNoPostsSelected();
forkModal.find('.close,#fork_thread_cancel').on('click', closeForkModal);
forkModal.find('#fork-title').on('change', checkForkButtonEnable);
$('#post-container').on('click', 'li[data-pid]', function() {
togglePostSelection($(this));
});
disableClicksOnPosts();
forkCommit.on('click', createTopicFromPosts);
}
function showForkModal() {
forkModal.removeClass('hide')
.css('position', 'fixed')
.css('left', Math.max(0, (($(window).width() - $(forkModal).outerWidth()) / 2) + $(window).scrollLeft()) + 'px')
.css('top', '0px')
.css('z-index', '2000');
}
function createTopicFromPosts() {
socket.emit('topics.createTopicFromPosts', {
title: forkModal.find('#fork-title').val(),
pids: pids
}, function(err, newTopic) {
function fadeOutAndRemove(pid) {
$('#post-container li[data-pid="' + pid + '"]').fadeOut(500, function() {
$(this).remove();
});
}
if (err) {
return app.alertError(err.message);
}
app.alert({
timeout: 5000,
title: '[[global:alert.success]]',
message: '[[topic:fork_success]]',
type: 'success',
clickfn: function() {
ajaxify.go('topic/' + newTopic.slug);
}
});
for(var i=0; i<pids.length; ++i) {
fadeOutAndRemove(pids[i]);
}
closeForkModal();
});
}
function togglePostSelection(post) {
var newPid = post.attr('data-pid');
if(parseInt(post.attr('data-index'), 10) === 0) {
return;
}
if(newPid) {
var index = pids.indexOf(newPid);
if(index === -1) {
pids.push(newPid);
post.css('opacity', '0.5');
} else {
pids.splice(index, 1);
post.css('opacity', '1.0');
}
if(pids.length) {
pids.sort();
forkModal.find('#fork-pids').html(pids.toString());
} else {
showNoPostsSelected();
}
checkForkButtonEnable();
}
}
function showNoPostsSelected() {
forkModal.find('#fork-pids').translateHtml('[[topic:fork_no_pids]]');
}
function checkForkButtonEnable() {
if(forkModal.find('#fork-title').length && pids.length) {
forkCommit.removeAttr('disabled');
} else {
forkCommit.attr('disabled', true);
}
}
function closeForkModal() {
for(var i=0; i<pids.length; ++i) {
$('#post-container li[data-pid="' + pids[i] + '"]').css('opacity', 1);
}
forkModal.addClass('hide');
$('#post-container').off('click', 'li[data-pid]');
enableClicksOnPosts();
}
return Fork;
});

@ -1,100 +0,0 @@
'use strict';
/* globals define, app, socket */
define('forum/topic/move', function() {
var Move = {},
modal,
targetCid,
targetCategoryLabel;
Move.init = function(tids, currentCid, onComplete) {
modal = $('#move_thread_modal');
Move.tids = tids;
Move.currentCid = currentCid;
Move.onComplete = onComplete;
Move.moveAll = tids ? false : true;
modal.on('shown.bs.modal', onMoveModalShown);
$('#move-confirm').hide();
if (Move.moveAll || (tids && tids.length > 1)) {
modal.find('.modal-header h3').translateText('[[topic:move_topics]]');
}
modal.modal('show');
};
function onMoveModalShown() {
var loadingEl = $('#categories-loading');
if (!loadingEl.length) {
return;
}
socket.emit('categories.get', onCategoriesLoaded);
}
function onCategoriesLoaded(err, categories) {
if (err) {
return app.alertError(err.message);
}
renderCategories(categories);
modal.on('click', '.category-list li[data-cid]', function(e) {
selectCategory($(this));
});
$('#move_thread_commit').on('click', onCommitClicked);
}
function selectCategory(category) {
modal.find('#confirm-category-name').html(category.html());
$('#move-confirm').show();
targetCid = category.attr('data-cid');
targetCategoryLabel = category.html();
$('#move_thread_commit').prop('disabled', false);
}
function onCommitClicked() {
var commitEl = $('#move_thread_commit');
if (!commitEl.prop('disabled') && targetCid) {
commitEl.prop('disabled', true);
moveTopics();
}
}
function moveTopics() {
socket.emit(Move.moveAll ? 'topics.moveAll' : 'topics.move', {
tids: Move.tids,
cid: targetCid,
currentCid: Move.currentCid
}, function(err) {
modal.modal('hide');
$('#move_thread_commit').prop('disabled', false);
if(err) {
return app.alertError(err.message);
}
app.alertSuccess('[[topic:topic_move_success, ' + targetCategoryLabel + ']]');
if (typeof Move.onComplete === 'function') {
Move.onComplete();
}
});
}
function renderCategories(categories) {
templates.parse('partials/category_list', {categories: categories}, function(html) {
modal.find('.modal-body').prepend(html);
$('#categories-loading').remove();
});
}
return Move;
});

@ -1,322 +0,0 @@
'use strict';
/* globals define, app, translator, ajaxify, socket, bootbox */
define('forum/topic/postTools', ['composer', 'share', 'navigator'], function(composer, share, navigator) {
var PostTools = {},
topicName;
PostTools.init = function(tid, threadState) {
topicName = ajaxify.variables.get('topic_name');
addPostHandlers(tid, threadState);
share.addShareHandlers(topicName);
addVoteHandler();
};
PostTools.toggle = function(pid, isDeleted) {
var postEl = $('#post-container li[data-pid="' + pid + '"]');
postEl.find('.quote, .favourite, .post_reply, .chat').toggleClass('hidden', isDeleted);
postEl.find('.purge').toggleClass('hidden', !isDeleted);
postEl.find('.delete .i').toggleClass('fa-trash-o', !isDeleted).toggleClass('fa-history', isDeleted);
postEl.find('.delete span').translateHtml(isDeleted ? ' [[topic:restore]]' : ' [[topic:delete]]');
};
PostTools.updatePostCount = function() {
socket.emit('topics.postcount', ajaxify.variables.get('topic_id'), function(err, postCount) {
if (!err) {
$('.topic-post-count').html(postCount);
navigator.setCount(postCount);
}
});
};
function addVoteHandler() {
$('#post-container').on('mouseenter', '.post-row .votes', function() {
loadDataAndCreateTooltip($(this), 'posts.getUpvoters');
});
}
function loadDataAndCreateTooltip(el, method) {
var pid = el.parents('.post-row').attr('data-pid');
socket.emit(method, pid, function(err, data) {
if (!err) {
createTooltip(el, data);
}
});
}
function createTooltip(el, data) {
var usernames = data.usernames;
if (!usernames.length) {
return;
}
if (usernames.length + data.otherCount > 6) {
usernames = usernames.join(', ').replace(/,/g, '|');
translator.translate('[[topic:users_and_others, ' + usernames + ', ' + data.otherCount + ']]', function(translated) {
translated = translated.replace(/\|/g, ',');
el.attr('title', translated).tooltip('destroy').tooltip('show');
});
} else {
usernames = usernames.join(', ');
el.attr('title', usernames).tooltip('destroy').tooltip('show');
}
}
function addPostHandlers(tid, threadState) {
$('.topic').on('click', '.post_reply', function() {
if (!threadState.locked) {
onReplyClicked($(this), tid, topicName);
}
});
var postContainer = $('#post-container');
postContainer.on('click', '.quote', function() {
if (!threadState.locked) {
onQuoteClicked($(this), tid, topicName);
}
});
postContainer.on('click', '.favourite', function() {
favouritePost($(this), getData($(this), 'data-pid'));
});
postContainer.on('click', '.upvote', function() {
return toggleVote($(this), '.upvoted', 'posts.upvote');
});
postContainer.on('click', '.downvote', function() {
return toggleVote($(this), '.downvoted', 'posts.downvote');
});
postContainer.on('click', '.flag', function() {
flagPost(getData($(this), 'data-pid'));
});
postContainer.on('click', '.edit', function(e) {
composer.editPost(getData($(this), 'data-pid'));
});
postContainer.on('click', '.delete', function(e) {
deletePost($(this), tid);
});
postContainer.on('click', '.purge', function(e) {
purgePost($(this), tid);
});
postContainer.on('click', '.move', function(e) {
openMovePostModal($(this));
});
postContainer.on('click', '.chat', function(e) {
openChat($(this));
});
}
function onReplyClicked(button, tid, topicName) {
var selectionText = '',
selection = window.getSelection ? window.getSelection() : document.selection.createRange();
if ($(selection.baseNode).parents('.post-content').length > 0) {
var snippet = selection.toString();
if (snippet.length) {
selectionText = '> ' + snippet.replace(/\n/g, '\n> ') + '\n\n';
}
}
var username = getUserName(selectionText ? $(selection.baseNode) : button);
if (getData(button, 'data-uid') === '0') {
username = '';
}
if (selectionText.length) {
composer.addQuote(tid, ajaxify.variables.get('topic_slug'), getData(button, 'data-index'), getData(button, 'data-pid'), topicName, username, selectionText);
} else {
composer.newReply(tid, getData(button, 'data-pid'), topicName, username ? username + ' ' : '');
}
}
function onQuoteClicked(button, tid, topicName) {
var username = getUserName(button),
pid = getData(button, 'data-pid');
socket.emit('posts.getRawPost', pid, function(err, post) {
if(err) {
return app.alertError(err.message);
}
var quoted = '';
if(post) {
quoted = '> ' + post.replace(/\n/g, '\n> ') + '\n\n';
}
if($('.composer').length) {
composer.addQuote(tid, ajaxify.variables.get('topic_slug'), getData(button, 'data-index'), pid, topicName, username, quoted);
} else {
composer.newReply(tid, pid, topicName, '[[modules:composer.user_said, ' + username + ']]\n' + quoted);
}
});
}
function favouritePost(button, pid) {
var method = button.attr('data-favourited') === 'false' ? 'posts.favourite' : 'posts.unfavourite';
socket.emit(method, {
pid: pid,
room_id: app.currentRoom
}, function(err) {
if (err) {
app.alertError(err.message);
}
});
return false;
}
function toggleVote(button, className, method) {
var post = button.parents('.post-row'),
currentState = post.find(className).length;
socket.emit(currentState ? 'posts.unvote' : method , {
pid: post.attr('data-pid'),
room_id: app.currentRoom
}, function(err) {
if (err) {
app.alertError(err.message);
}
});
return false;
}
function getData(button, data) {
return button.parents('.post-row').attr(data);
}
function getUserName(button) {
var username = '',
post = button.parents('li[data-pid]');
if (post.length) {
username = post.attr('data-username').replace(/\s/g, '-');
}
if (post.length && post.attr('data-uid') !== '0') {
username = '@' + username;
}
return username;
}
function deletePost(button, tid) {
var pid = getData(button, 'data-pid'),
postEl = $('#post-container li[data-pid="' + pid + '"]'),
action = !postEl.hasClass('deleted') ? 'delete' : 'restore';
postAction(action, pid, tid);
}
function purgePost(button, tid) {
postAction('purge', getData(button, 'data-pid'), tid);
}
function postAction(action, pid, tid) {
translator.translate('[[topic:post_' + action + '_confirm]]', function(msg) {
bootbox.confirm(msg, function(confirm) {
if (!confirm) {
return;
}
socket.emit('posts.' + action, {
pid: pid,
tid: tid
}, function(err) {
if(err) {
app.alertError(err.message);
}
});
});
});
}
function openMovePostModal(button) {
var moveModal = $('#move-post-modal'),
moveBtn = moveModal.find('#move_post_commit'),
topicId = moveModal.find('#topicId');
showMoveModal();
moveModal.find('.close,#move_post_cancel').on('click', function() {
moveModal.addClass('hide');
});
topicId.on('change', function() {
if(topicId.val().length) {
moveBtn.removeAttr('disabled');
} else {
moveBtn.attr('disabled', true);
}
});
moveBtn.on('click', function() {
movePost(button.parents('.post-row'), getData(button, 'data-pid'), topicId.val());
});
}
function showMoveModal() {
$('#move-post-modal').removeClass('hide')
.css("position", "fixed")
.css("left", Math.max(0, (($(window).width() - $($('#move-post-modal')).outerWidth()) / 2) + $(window).scrollLeft()) + "px")
.css("top", "0px")
.css("z-index", "2000");
}
function movePost(post, pid, tid) {
socket.emit('topics.movePost', {pid: pid, tid: tid}, function(err) {
$('#move-post-modal').addClass('hide');
if(err) {
$('#topicId').val('');
return app.alertError(err.message);
}
post.fadeOut(500, function() {
post.remove();
});
$('#topicId').val('');
app.alertSuccess('[[topic:post_moved]]');
});
}
function flagPost(pid) {
translator.translate('[[topic:flag_confirm]]', function(message) {
bootbox.confirm(message, function(confirm) {
if (confirm) {
socket.emit('posts.flag', pid, function(err) {
if(err) {
return app.alertError(err.message);
}
app.alertSuccess('[[topic:flag_success]]');
});
}
});
});
}
function openChat(button) {
var post = button.parents('li.post-row');
app.openChat(post.attr('data-username'), post.attr('data-uid'));
button.parents('.btn-group').find('.dropdown-toggle').click();
return false;
}
return PostTools;
});

@ -1,169 +0,0 @@
'use strict';
/* globals define, app, translator, ajaxify, socket, bootbox */
define('forum/topic/threadTools', ['forum/topic/fork', 'forum/topic/move'], function(fork, move) {
var ThreadTools = {};
ThreadTools.init = function(tid, threadState) {
ThreadTools.threadState = threadState;
if (threadState.locked) {
ThreadTools.setLockedState({tid: tid, isLocked: true});
}
if (threadState.deleted) {
ThreadTools.setDeleteState({tid: tid, isDelete: true});
}
if (threadState.pinned) {
ThreadTools.setPinnedState({tid: tid, isPinned: true});
}
$('.delete_thread').on('click', function() {
topicCommand(threadState.deleted ? 'restore' : 'delete', tid);
return false;
});
$('.purge_thread').on('click', function() {
topicCommand('purge', tid);
return false;
});
$('.lock_thread').on('click', function() {
socket.emit(threadState.locked ? 'topics.unlock' : 'topics.lock', {tids: [tid], cid: ajaxify.variables.get('category_id')});
return false;
});
$('.pin_thread').on('click', function() {
socket.emit(threadState.pinned ? 'topics.unpin' : 'topics.pin', {tids: [tid], cid: ajaxify.variables.get('category_id')});
return false;
});
$('.markAsUnreadForAll').on('click', function() {
var btn = $(this);
socket.emit('topics.markAsUnreadForAll', [tid], function(err) {
if(err) {
return app.alertError(err.message);
}
app.alertSuccess('[[topic:markAsUnreadForAll.success]]');
btn.parents('.thread-tools.open').find('.dropdown-toggle').trigger('click');
});
return false;
});
$('.move_thread').on('click', function(e) {
move.init([tid], ajaxify.variables.get('category_id'));
return false;
});
fork.init();
$('.posts').on('click', '.follow', function() {
socket.emit('topics.follow', tid, function(err, state) {
if(err) {
return app.alert({
type: 'danger',
alert_id: 'topic_follow',
title: '[[global:please_log_in]]',
message: '[[topic:login_to_subscribe]]',
timeout: 5000
});
}
setFollowState(state);
app.alert({
alert_id: 'follow_thread',
message: state ? '[[topic:following_topic.message]]' : '[[topic:not_following_topic.message]]',
type: 'success',
timeout: 5000
});
});
return false;
});
};
function topicCommand(command, tid) {
translator.translate('[[topic:thread_tools.' + command + '_confirm]]', function(msg) {
bootbox.confirm(msg, function(confirm) {
if (confirm) {
socket.emit('topics.' + command, {tids: [tid], cid: ajaxify.variables.get('category_id')});
}
});
});
}
ThreadTools.setLockedState = function(data) {
var threadEl = $('#post-container');
if (parseInt(data.tid, 10) === parseInt(threadEl.attr('data-tid'), 10)) {
var isLocked = data.isLocked && !app.isAdmin;
$('.lock_thread').translateHtml('<i class="fa fa-fw fa-' + (data.isLocked ? 'un': '') + 'lock"></i> [[topic:thread_tools.' + (data.isLocked ? 'un': '') + 'lock]]');
translator.translate(isLocked ? '[[topic:locked]]' : '[[topic:reply]]', function(translated) {
var className = isLocked ? 'fa-lock' : 'fa-reply';
threadEl.find('.post_reply').html('<i class="fa ' + className + '"></i> ' + translated);
$('.topic-main-buttons .post_reply').attr('disabled', isLocked).html(isLocked ? '<i class="fa fa-lock"></i> ' + translated : translated);
});
threadEl.find('.quote, .edit, .delete').toggleClass('hidden', isLocked);
$('.topic-title i.fa-lock').toggleClass('hide', !data.isLocked);
ThreadTools.threadState.locked = data.isLocked;
}
};
ThreadTools.setDeleteState = function(data) {
var threadEl = $('#post-container');
if (parseInt(data.tid, 10) !== parseInt(threadEl.attr('data-tid'), 10)) {
return;
}
$('.delete_thread span').translateHtml('<i class="fa fa-fw ' + (data.isDelete ? 'fa-history' : 'fa-trash-o') + '"></i> [[topic:thread_tools.' + (data.isDelete ? 'restore' : 'delete') + ']]');
threadEl.toggleClass('deleted', data.isDelete);
ThreadTools.threadState.deleted = data.isDelete;
$('.purge_thread').toggleClass('hidden', !data.isDelete);
if (data.isDelete) {
translator.translate('[[topic:deleted_message]]', function(translated) {
$('<div id="thread-deleted" class="alert alert-warning">' + translated + '</div>').insertBefore(threadEl);
});
} else {
$('#thread-deleted').remove();
}
};
ThreadTools.setPinnedState = function(data) {
var threadEl = $('#post-container');
if (parseInt(data.tid, 10) === parseInt(threadEl.attr('data-tid'), 10)) {
translator.translate('<i class="fa fa-fw fa-thumb-tack"></i> [[topic:thread_tools.' + (data.isPinned ? 'unpin' : 'pin') + ']]', function(translated) {
$('.pin_thread').html(translated);
ThreadTools.threadState.pinned = data.isPinned;
});
$('.topic-title i.fa-thumb-tack').toggleClass('hide', !data.isPinned);
}
};
function setFollowState(state) {
var title = state ? '[[topic:unwatch.title]]' : '[[topic:watch.title]]';
var iconClass = state ? 'fa fa-eye-slash' : 'fa fa-eye';
var text = state ? '[[topic:unwatch]]' : '[[topic:watch]]';
var followEl = $('.posts .follow');
translator.translate(title, function(titleTranslated) {
followEl.attr('title', titleTranslated).find('i').attr('class', iconClass);
followEl.find('span').text(text);
translator.translate(followEl.html(), function(translated) {
followEl.html(translated);
});
});
}
return ThreadTools;
});

@ -1,151 +0,0 @@
'use strict';
/* globals define, app, socket */
define('forum/unread', ['forum/recent', 'topicSelect', 'forum/infinitescroll'], function(recent, topicSelect, infinitescroll) {
var Unread = {};
$(window).on('action:ajaxify.start', function(ev, data) {
if(data.url.indexOf('unread') !== 0) {
recent.removeListeners();
}
});
Unread.init = function() {
app.enterRoom('recent_posts');
$('#new-topics-alert').on('click', function() {
$(this).addClass('hide');
});
recent.watchForNewPosts();
$('#markSelectedRead').on('click', function() {
var tids = topicSelect.getSelectedTids();
if(!tids.length) {
return;
}
socket.emit('topics.markAsRead', tids, function(err) {
if(err) {
return app.alertError(err.message);
}
doneRemovingTids(tids);
});
});
$('#markAllRead').on('click', function() {
socket.emit('topics.markAllRead', function(err) {
if(err) {
return app.alertError(err.message);
}
app.alertSuccess('[[unread:topics_marked_as_read.success]]');
$('#topics-container').empty();
$('#category-no-topics').removeClass('hidden');
$('.markread').addClass('hidden');
});
});
$('.markread').on('click', '.category', function() {
function getCategoryTids(cid) {
var tids = [];
$('#topics-container .category-item[data-cid="' + cid + '"]').each(function() {
tids.push($(this).attr('data-tid'));
});
return tids;
}
var cid = $(this).attr('data-cid');
var tids = getCategoryTids(cid);
socket.emit('topics.markCategoryTopicsRead', cid, function(err) {
if(err) {
return app.alertError(err.message);
}
doneRemovingTids(tids);
});
});
socket.emit('categories.get', onCategoriesLoaded);
topicSelect.init();
if ($("body").height() <= $(window).height() && $('#topics-container').children().length >= 20) {
$('#load-more-btn').show();
}
$('#load-more-btn').on('click', function() {
loadMoreTopics();
});
infinitescroll.init(loadMoreTopics);
function loadMoreTopics(direction) {
if(direction < 0 || !$('#topics-container').length) {
return;
}
infinitescroll.loadMore('topics.loadMoreUnreadTopics', {
after: $('#topics-container').attr('data-nextstart')
}, function(data, done) {
if (data.topics && data.topics.length) {
recent.onTopicsLoaded('unread', data.topics, true, done);
$('#topics-container').attr('data-nextstart', data.nextStart);
} else {
done();
$('#load-more-btn').hide();
}
});
}
};
function doneRemovingTids(tids) {
removeTids(tids);
app.alertSuccess('[[unread:topics_marked_as_read.success]]');
if (!$('#topics-container').children().length) {
$('#category-no-topics').removeClass('hidden');
$('.markread').addClass('hidden');
}
}
function removeTids(tids) {
for(var i=0; i<tids.length; ++i) {
$('#topics-container .category-item[data-tid="' + tids[i] + '"]').remove();
}
}
function onCategoriesLoaded(err, categories) {
createCategoryLinks(categories);
}
function createCategoryLinks(categories) {
categories = categories.filter(function(category) {
return !category.disabled;
});
for(var i=0; i<categories.length; ++i) {
createCategoryLink(categories[i]);
}
}
function createCategoryLink(category) {
var link = $('<a role="menuitem" href="#"></a>');
if (category.icon) {
link.append('<i class="fa fa-fw ' + category.icon + '"></i> ' + category.name);
} else {
link.append(category.name);
}
$('<li role="presentation" class="category" data-cid="' + category.cid + '"></li>')
.append(link)
.appendTo($('.markread .dropdown-menu'));
}
return Unread;
});

@ -1,186 +0,0 @@
'use strict';
/* globals define, socket, app, ajaxify, templates, translator*/
define('forum/users', function() {
var Users = {};
var loadingMoreUsers = false;
Users.init = function() {
var active = getActiveSection();
$('.nav-pills li').removeClass('active');
$('.nav-pills li a').each(function() {
var $this = $(this);
if ($this.attr('href').match(active)) {
$this.parent().addClass('active');
return false;
}
});
handleSearch();
socket.removeListener('event:user_status_change', onUserStatusChange);
socket.on('event:user_status_change', onUserStatusChange);
$('#load-more-users-btn').on('click', loadMoreUsers);
$(window).off('scroll').on('scroll', function() {
var bottom = ($(document).height() - $(window).height()) * 0.9;
if ($(window).scrollTop() > bottom && !loadingMoreUsers) {
loadMoreUsers();
}
});
};
function loadMoreUsers() {
var set = '';
var activeSection = getActiveSection();
if (activeSection === 'latest') {
set = 'users:joindate';
} else if (activeSection === 'sort-posts') {
set = 'users:postcount';
} else if (activeSection === 'sort-reputation') {
set = 'users:reputation';
} else if (activeSection === 'online' || activeSection === 'users') {
set = 'users:online';
}
if (set) {
startLoading(set, $('#users-container').children('.registered-user').length);
}
}
function startLoading(set, after) {
loadingMoreUsers = true;
socket.emit('user.loadMore', {
set: set,
after: after
}, function(err, data) {
if (data && data.users.length) {
onUsersLoaded(data.users);
$('#load-more-users-btn').removeClass('disabled');
} else {
$('#load-more-users-btn').addClass('disabled');
}
loadingMoreUsers = false;
});
}
function onUsersLoaded(users) {
users = users.filter(function(user) {
return !$('.users-box[data-uid="' + user.uid + '"]').length;
});
ajaxify.loadTemplate('users', function(usersTemplate) {
var html = templates.parse(templates.getBlock(usersTemplate, 'users'), {users: users});
translator.translate(html, function(translated) {
$('#users-container').append(translated);
$('#users-container .anon-user').appendTo($('#users-container'));
});
});
}
function handleSearch() {
var timeoutId = 0;
var lastSearch = null;
$('#search-user').on('keyup', function() {
if (timeoutId !== 0) {
clearTimeout(timeoutId);
timeoutId = 0;
}
timeoutId = setTimeout(function() {
function reset() {
notify.html('<i class="fa fa-search"></i>');
notify.parent().removeClass('btn-warning label-warning btn-success label-success');
}
var username = $('#search-user').val();
var notify = $('#user-notfound-notify');
if (username === '') {
notify.html('<i class="fa fa-circle-o"></i>');
notify.parent().removeClass('btn-warning label-warning btn-success label-success');
return;
}
if (lastSearch === username) {
return;
}
lastSearch = username;
notify.html('<i class="fa fa-spinner fa-spin"></i>');
socket.emit('user.search', username, function(err, data) {
if (err) {
reset();
return app.alertError(err.message);
}
if (!data) {
reset();
return;
}
ajaxify.loadTemplate('users', function(usersTemplate) {
var html = templates.parse(templates.getBlock(usersTemplate, 'users'), data);
translator.translate(html, function(translated) {
$('#users-container').html(translated);
if (!data.users.length) {
translator.translate('[[error:no-user]]', function(translated) {
notify.html(translated);
notify.parent().addClass('btn-warning label-warning');
});
} else {
translator.translate('[[users:users-found-search-took, ' + data.users.length + ', ' + data.timing + ']]', function(translated) {
notify.html(translated);
notify.parent().addClass('btn-success label-success');
});
}
});
});
});
}, 250);
});
}
function onUserStatusChange(data) {
var section = getActiveSection();
if((section.indexOf('online') === 0 || section.indexOf('users') === 0)) {
updateUser(data);
}
}
function updateUser(data) {
if (data.status === 'offline') {
return;
}
var usersContainer = $('#users-container');
var userEl = usersContainer.find('li[data-uid="' + data.uid +'"]');
if (userEl.length) {
var statusEl = userEl.find('.status');
translator.translate('[[global:' + data.status + ']]', function(translated) {
statusEl.attr('class', 'fa fa-circle status ' + data.status)
.attr('title', translated)
.attr('data-original-title', translated);
});
}
}
function getActiveSection() {
var url = window.location.href,
parts = url.split('/');
return parts[parts.length - 1];
}
return Users;
});
Loading…
Cancel
Save