Merge branch 'master' of github.com:ipetepete/NodeBB

v1.18.x
Peter Peterson 12 years ago
commit 3968877b1e

@ -76,6 +76,9 @@ var ajaxify = {};
templates.flush();
templates.load_template(function () {
exec_body_scripts(content);
require(['forum/' + tpl_url], function(script) {
if (script && script.init) script.init();
});
if (callback) {
callback();

@ -1,85 +1,92 @@
(function() {
var yourid = templates.get('yourid'),
theirid = templates.get('theirid'),
isFollowing = templates.get('isFollowing');
define(['forum/accountheader'], function(header) {
var Account = {};
$(document).ready(function() {
var username = $('.account-username a').html();
app.enter_room('user/' + theirid);
Account.init = function() {
header.init();
app.addCommasToNumbers();
var yourid = templates.get('yourid'),
theirid = templates.get('theirid'),
isFollowing = templates.get('isFollowing');
var followBtn = $('#follow-btn');
var unfollowBtn = $('#unfollow-btn');
$(document).ready(function() {
var username = $('.account-username a').html();
app.enter_room('user/' + theirid);
if (yourid !== theirid) {
if (isFollowing) {
followBtn.hide();
unfollowBtn.show();
} else {
followBtn.show();
unfollowBtn.hide();
}
} else {
followBtn.hide();
unfollowBtn.hide();
}
app.addCommasToNumbers();
followBtn.on('click', function() {
socket.emit('api:user.follow', {
uid: theirid
}, function(success) {
if (success) {
var followBtn = $('#follow-btn');
var unfollowBtn = $('#unfollow-btn');
if (yourid !== theirid) {
if (isFollowing) {
followBtn.hide();
unfollowBtn.show();
app.alertSuccess('You are now following ' + username + '!');
} else {
app.alertError('There was an error following' + username + '!');
}
});
return false;
});
unfollowBtn.on('click', function() {
socket.emit('api:user.unfollow', {
uid: theirid
}, function(success) {
if (success) {
followBtn.show();
unfollowBtn.hide();
app.alertSuccess('You are no longer following ' + username + '!');
} else {
app.alertError('There was an error unfollowing ' + username + '!');
}
} else {
followBtn.hide();
unfollowBtn.hide();
}
followBtn.on('click', function() {
socket.emit('api:user.follow', {
uid: theirid
}, function(success) {
if (success) {
followBtn.hide();
unfollowBtn.show();
app.alertSuccess('You are now following ' + username + '!');
} else {
app.alertError('There was an error following' + username + '!');
}
});
return false;
});
return false;
});
$('.user-recent-posts .topic-row').on('click', function() {
ajaxify.go($(this).attr('topic-url'));
});
unfollowBtn.on('click', function() {
socket.emit('api:user.unfollow', {
uid: theirid
}, function(success) {
if (success) {
followBtn.show();
unfollowBtn.hide();
app.alertSuccess('You are no longer following ' + username + '!');
} else {
app.alertError('There was an error unfollowing ' + username + '!');
}
});
return false;
});
var onlineStatus = $('.account-online-status');
$('.user-recent-posts .topic-row').on('click', function() {
ajaxify.go($(this).attr('topic-url'));
});
function handleUserOnline(data) {
if (data.online) {
onlineStatus.find('span span').text('online');
onlineStatus.find('i').attr('class', 'icon-circle');
} else {
onlineStatus.find('span span').text('offline');
onlineStatus.find('i').attr('class', 'icon-circle-blank');
}
}
socket.on('api:user.isOnline', Account.handleUserOnline);
socket.on('api:user.isOnline', handleUserOnline);
socket.emit('api:user.isOnline', theirid, Account.handleUserOnline);
socket.emit('api:user.isOnline', theirid, handleUserOnline);
socket.on('event:new_post', function(data) {
var html = templates.prepare(templates['account'].blocks['posts']).parse(data);
$('.user-recent-posts').prepend(html);
});
socket.on('event:new_post', function(data) {
var html = templates.prepare(templates['account'].blocks['posts']).parse(data);
$('.user-recent-posts').prepend(html);
});
};
});
Account.handleUserOnline = function(data) {
var onlineStatus = $('.account-online-status');
if (data.online) {
onlineStatus.find('span span').text('online');
onlineStatus.find('i').attr('class', 'icon-circle');
} else {
onlineStatus.find('span span').text('offline');
onlineStatus.find('i').attr('class', 'icon-circle-blank');
}
};
}());
return Account;
});

@ -1,88 +1,258 @@
var gravatarPicture = templates.get('gravatarpicture');
var uploadedPicture = templates.get('uploadedpicture');
define(['forum/accountheader'], function(header) {
var AccountEdit = {};
$(document).ready(function() {
AccountEdit.init = function() {
header.init();
var gravatarPicture = templates.get('gravatarpicture');
var uploadedPicture = templates.get('uploadedpicture');
$('#uploadForm').submit(function() {
AccountEdit.status('uploading the file ...');
$('#uploadForm').submit(function() {
status('uploading the file ...');
$('#upload-progress-bar').css('width', '0%');
$('#upload-progress-box').show();
$('#upload-progress-box').removeClass('hide');
$('#upload-progress-bar').css('width', '0%');
$('#upload-progress-box').show();
$('#upload-progress-box').removeClass('hide');
if (!$('#userPhotoInput').val()) {
AccountEdit.error('select an image to upload!');
return false;
}
$(this).find('#imageUploadCsrf').val($('#csrf_token').val());
if (!$('#userPhotoInput').val()) {
error('select an image to upload!');
return false;
}
$(this).find('#imageUploadCsrf').val($('#csrf_token').val());
$(this).ajaxSubmit({
error: function(xhr) {
AccountEdit.error('Error: ' + xhr.status);
},
$(this).ajaxSubmit({
uploadProgress: function(event, position, total, percent) {
console.log(percent);
$('#upload-progress-bar').css('width', percent + '%');
},
error: function(xhr) {
error('Error: ' + xhr.status);
},
uploadProgress: function(event, position, total, percent) {
console.log(percent);
$('#upload-progress-bar').css('width', percent + '%');
},
success: function(response) {
if (response.error) {
AccountEdit.error(response.error);
return;
}
var imageUrlOnServer = response.path;
success: function(response) {
if (response.error) {
error(response.error);
return;
$('#user-current-picture').attr('src', imageUrlOnServer);
$('#user-uploaded-picture').attr('src', imageUrlOnServer);
uploadedPicture = imageUrlOnServer;
setTimeout(function() {
AccountEdit.hideAlerts();
$('#upload-picture-modal').modal('hide');
}, 750);
socket.emit('api:updateHeader', {
fields: ['username', 'picture', 'userslug']
});
AccountEdit.success('File uploaded successfully!');
}
});
var imageUrlOnServer = response.path;
return false;
});
$('#user-current-picture').attr('src', imageUrlOnServer);
$('#user-uploaded-picture').attr('src', imageUrlOnServer);
var selectedImageType = '';
$('#submitBtn').on('click', function() {
var userData = {
uid: $('#inputUID').val(),
email: $('#inputEmail').val(),
fullname: $('#inputFullname').val(),
website: $('#inputWebsite').val(),
birthday: $('#inputBirthday').val(),
location: $('#inputLocation').val(),
signature: $('#inputSignature').val()
};
socket.emit('api:user.updateProfile', userData, function(err, data) {
if (data.success) {
app.alertSuccess('Your profile has been updated successfully!');
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;
}
} else {
app.alertError('There was an error updating your profile! ' + err.error);
}
});
return false;
});
$('#changePictureBtn').on('click', function() {
selectedImageType = '';
AccountEdit.updateImages();
uploadedPicture = imageUrlOnServer;
$('#change-picture-modal').modal('show');
$('#change-picture-modal').removeClass('hide');
setTimeout(function() {
hideAlerts();
$('#upload-picture-modal').modal('hide');
}, 750);
return false;
});
$('#gravatar-box').on('click', function() {
$('#gravatar-box .icon-ok').show();
$('#uploaded-box .icon-ok').hide();
selectedImageType = 'gravatar';
});
socket.emit('api:updateHeader', {
fields: ['username', 'picture', 'userslug']
});
success('File uploaded successfully!');
$('#uploaded-box').on('click', function() {
$('#gravatar-box .icon-ok').hide();
$('#uploaded-box .icon-ok').show();
selectedImageType = 'uploaded';
});
$('#savePictureChangesBtn').on('click', function() {
$('#change-picture-modal').modal('hide');
if (selectedImageType) {
AccountEdit.changeUserPicture(selectedImageType);
if (selectedImageType == 'gravatar')
$('#user-current-picture').attr('src', gravatarPicture);
else if (selectedImageType == 'uploaded')
$('#user-current-picture').attr('src', uploadedPicture);
}
});
$('#upload-picture-modal').on('hide', function() {
$('#userPhotoInput').val('');
});
$('#uploadPictureBtn').on('click', function() {
$('#change-picture-modal').modal('hide');
$('#upload-picture-modal').modal('show');
$('#upload-picture-modal').removeClass('hide');
AccountEdit.hideAlerts();
return false;
});
$('#pictureUploadSubmitBtn').on('click', function() {
$('#uploadForm').submit();
});
return false;
});
(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;
function onPasswordChanged() {
passwordvalid = utils.isPasswordValid(password.val());
if (password.val().length < config.minimumPasswordLength) {
password_notify.html('Password too short');
password_notify.attr('class', 'alert alert-danger');
password_notify.removeClass('hide');
} else if (!passwordvalid) {
password_notify.html('Invalid password');
password_notify.attr('class', 'alert alert-danger');
password_notify.removeClass('hide');
} else {
password_notify.html('OK!');
password_notify.attr('class', 'alert alert-success');
password_notify.removeClass('hide');
}
onPasswordConfirmChanged();
}
function onPasswordConfirmChanged() {
if (password_notify.hasClass('alert-danger') || !password_confirm.val()) {
password_confirm_notify.addClass('hide');
return;
}
if (password.val() !== password_confirm.val()) {
password_confirm_notify.html('Passwords must match!');
password_confirm_notify.attr('class', 'alert alert-danger');
password_confirm_notify.removeClass('hide');
passwordsmatch = false;
} else {
password_confirm_notify.html('OK!');
password_confirm_notify.attr('class', 'alert alert-success');
password_confirm_notify.removeClass('hide');
passwordsmatch = true;
}
}
password.on('blur', onPasswordChanged);
password_confirm.on('blur', onPasswordConfirmChanged);
function hideAlerts() {
$('#changePasswordBtn').on('click', function() {
if (passwordvalid && passwordsmatch && currentPassword.val()) {
socket.emit('api:user.changePassword', {
'currentPassword': currentPassword.val(),
'newPassword': password.val()
}, function(err) {
currentPassword.val('');
password.val('');
password_confirm.val('');
password_notify.addClass('hide');
password_confirm_notify.addClass('hide');
passwordsmatch = false;
passwordvalid = false;
if (err) {
app.alertError(err.error);
return;
}
app.alertSuccess('Your password is updated!');
});
}
return false;
});
}());
};
AccountEdit.hideAlerts = function() {
$('#alert-status').addClass('hide');
$('#alert-success').addClass('hide');
$('#alert-error').addClass('hide');
$('#upload-progress-box').addClass('hide');
}
function status(message) {
hideAlerts();
AccountEdit.status = function(message) {
AccountEdit.hideAlerts();
$('#alert-status').text(message).removeClass('hide');
}
function success(message) {
hideAlerts();
AccountEdit.success = function(message) {
AccountEdit.hideAlerts();
$('#alert-success').text(message).removeClass('hide');
}
function error(message) {
hideAlerts();
AccountEdit.error = function(message) {
AccountEdit.hideAlerts();
$('#alert-error').text(message).removeClass('hide');
}
function changeUserPicture(type) {
AccountEdit.changeUserPicture = function(type) {
var userData = {
type: type
};
@ -94,40 +264,10 @@ $(document).ready(function() {
});
}
var selectedImageType = '';
$('#submitBtn').on('click', function() {
var userData = {
uid: $('#inputUID').val(),
email: $('#inputEmail').val(),
fullname: $('#inputFullname').val(),
website: $('#inputWebsite').val(),
birthday: $('#inputBirthday').val(),
location: $('#inputLocation').val(),
signature: $('#inputSignature').val()
};
socket.emit('api:user.updateProfile', userData, function(err, data) {
if (data.success) {
app.alertSuccess('Your profile has been updated successfully!');
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;
}
} else {
app.alertError('There was an error updating your profile! ' + err.error);
}
});
return false;
});
function updateImages() {
AccountEdit.updateImages = function() {
var currentPicture = $('#user-current-picture').attr('src');
var gravatarPicture = templates.get('gravatarpicture');
var uploadedPicture = templates.get('uploadedpicture');
if (gravatarPicture) {
$('#user-gravatar-picture').attr('src', gravatarPicture);
@ -153,139 +293,5 @@ $(document).ready(function() {
$('#uploaded-box .icon-ok').hide();
}
$('#changePictureBtn').on('click', function() {
selectedImageType = '';
updateImages();
$('#change-picture-modal').modal('show');
$('#change-picture-modal').removeClass('hide');
return false;
});
$('#gravatar-box').on('click', function() {
$('#gravatar-box .icon-ok').show();
$('#uploaded-box .icon-ok').hide();
selectedImageType = 'gravatar';
});
$('#uploaded-box').on('click', function() {
$('#gravatar-box .icon-ok').hide();
$('#uploaded-box .icon-ok').show();
selectedImageType = 'uploaded';
});
$('#savePictureChangesBtn').on('click', function() {
$('#change-picture-modal').modal('hide');
if (selectedImageType) {
changeUserPicture(selectedImageType);
if (selectedImageType == 'gravatar')
$('#user-current-picture').attr('src', gravatarPicture);
else if (selectedImageType == 'uploaded')
$('#user-current-picture').attr('src', uploadedPicture);
}
});
$('#upload-picture-modal').on('hide', function() {
$('#userPhotoInput').val('');
});
$('#uploadPictureBtn').on('click', function() {
$('#change-picture-modal').modal('hide');
$('#upload-picture-modal').modal('show');
$('#upload-picture-modal').removeClass('hide');
hideAlerts();
return false;
});
$('#pictureUploadSubmitBtn').on('click', function() {
$('#uploadForm').submit();
});
(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;
function onPasswordChanged() {
passwordvalid = utils.isPasswordValid(password.val());
if (password.val().length < config.minimumPasswordLength) {
password_notify.html('Password too short');
password_notify.attr('class', 'alert alert-danger');
password_notify.removeClass('hide');
} else if (!passwordvalid) {
password_notify.html('Invalid password');
password_notify.attr('class', 'alert alert-danger');
password_notify.removeClass('hide');
} else {
password_notify.html('OK!');
password_notify.attr('class', 'alert alert-success');
password_notify.removeClass('hide');
}
onPasswordConfirmChanged();
}
function onPasswordConfirmChanged() {
if (password_notify.hasClass('alert-danger') || !password_confirm.val()) {
password_confirm_notify.addClass('hide');
return;
}
if (password.val() !== password_confirm.val()) {
password_confirm_notify.html('Passwords must match!');
password_confirm_notify.attr('class', 'alert alert-danger');
password_confirm_notify.removeClass('hide');
passwordsmatch = false;
} else {
password_confirm_notify.html('OK!');
password_confirm_notify.attr('class', 'alert alert-success');
password_confirm_notify.removeClass('hide');
passwordsmatch = true;
}
}
password.on('blur', onPasswordChanged);
password_confirm.on('blur', onPasswordConfirmChanged);
$('#changePasswordBtn').on('click', function() {
if (passwordvalid && passwordsmatch && currentPassword.val()) {
socket.emit('api:user.changePassword', {
'currentPassword': currentPassword.val(),
'newPassword': password.val()
}, function(err) {
currentPassword.val('');
password.val('');
password_confirm.val('');
password_notify.addClass('hide');
password_confirm_notify.addClass('hide');
passwordsmatch = false;
passwordvalid = false;
if (err) {
app.alertError(err.error);
return;
}
app.alertSuccess('Your password is updated!');
});
}
return false;
});
}());
return AccountEdit;
});

@ -1,24 +1,11 @@
(function() {
var yourid = templates.get('yourid'),
theirid = templates.get('theirid');
define(function() {
var AccountHeader = {};
AccountHeader.init = function() {
var yourid = templates.get('yourid'),
theirid = templates.get('theirid');
function createMenu() {
var userslug = $('.account-username-box').attr('data-userslug');
var links = $('<div class="account-sub-links inline-block pull-right">\
<span id="settingsLink" class="pull-right"><a href="/user/' + userslug + '/settings">settings</a></span>\
<span id="favouritesLink" class="pull-right"><a href="/user/' + userslug + '/favourites">favourites</a></span>\
<span class="pull-right"><a href="/user/' + userslug + '/followers">followers</a></span>\
<span class="pull-right"><a href="/user/' + userslug + '/following">following</a></span>\
<span id="editLink" class="pull-right"><a href="/user/' + userslug + '/edit">edit</a></span>\
</div>');
$('.account-username-box').append(links);
}
$(document).ready(function() {
createMenu();
AccountHeader.createMenu();
var editLink = $('#editLink');
var settingsLink = $('#settingsLink');
@ -37,6 +24,20 @@
return false;
}
});
});
}
AccountHeader.createMenu = function() {
var userslug = $('.account-username-box').attr('data-userslug');
var links = $('<div class="account-sub-links inline-block pull-right">\
<span id="settingsLink" class="pull-right"><a href="/user/' + userslug + '/settings">settings</a></span>\
<span id="favouritesLink" class="pull-right"><a href="/user/' + userslug + '/favourites">favourites</a></span>\
<span class="pull-right"><a href="/user/' + userslug + '/followers">followers</a></span>\
<span class="pull-right"><a href="/user/' + userslug + '/following">following</a></span>\
<span id="editLink" class="pull-right"><a href="/user/' + userslug + '/edit">edit</a></span>\
</div>');
$('.account-username-box').append(links);
}
}());
return AccountHeader;
});

@ -1,19 +1,25 @@
$(document).ready(function() {
define(['forum/accountheader'], function(header) {
var AccountSettings = {};
$('#submitBtn').on('click', function() {
AccountSettings.init = function() {
header.init();
var settings = {
showemail: $('#showemailCheckBox').is(':checked') ? 1 : 0
};
$('#submitBtn').on('click', function() {
socket.emit('api:user.saveSettings', settings, function(success) {
if (success) {
app.alertSuccess('Settings saved!');
} else {
app.alertError('There was an error saving settings!');
}
var settings = {
showemail: $('#showemailCheckBox').is(':checked') ? 1 : 0
};
socket.emit('api:user.saveSettings', settings, function(success) {
if (success) {
app.alertSuccess('Settings saved!');
} else {
app.alertError('There was an error saving settings!');
}
});
return false;
});
return false;
});
};
});
return AccountSettings;
});

@ -1,139 +1,144 @@
var modified_categories = {};
define(function() {
var Categories = {};
function modified(el) {
var cid = $(el).parents('li').attr('data-cid');
Categories.init = function() {
var modified_categories = {};
modified_categories[cid] = modified_categories[cid] || {};
modified_categories[cid][$(el).attr('data-name')] = $(el).val();
}
function modified(el) {
var cid = $(el).parents('li').attr('data-cid');
function save() {
socket.emit('api:admin.categories.update', modified_categories);
modified_categories = {};
}
function select_icon(el) {
var selected = el.attr('class').replace(' icon-2x', '');
jQuery('#icons .selected').removeClass('selected');
if (selected)
jQuery('#icons .' + selected).parent().addClass('selected');
bootbox.confirm('<h2>Select an icon.</h2>' + document.getElementById('icons').innerHTML, function(confirm) {
if (confirm) {
var iconClass = jQuery('.bootbox .selected').children(':first').attr('class');
el.attr('class', iconClass + ' icon-2x');
el.val(iconClass);
modified(el);
modified_categories[cid] = modified_categories[cid] || {};
modified_categories[cid][$(el).attr('data-name')] = $(el).val();
}
});
setTimeout(function() { //bootbox was rewritten for BS3 and I had to add this timeout for the previous code to work. TODO: to look into
jQuery('.bootbox .col-md-3').on('click', function() {
jQuery('.bootbox .selected').removeClass('selected');
jQuery(this).addClass('selected');
});
}, 500);
}
function update_blockclass(el) {
el.parentNode.parentNode.className = 'entry-row ' + el.value;
}
jQuery('#entry-container').sortable();
jQuery('.blockclass').each(function() {
jQuery(this).val(this.getAttribute('data-value'));
});
//DRY Failure. this needs to go into an ajaxify onready style fn. Currently is copy pasted into every single function so after ACP is off the ground fix asap
(function() {
function showCreateCategoryModal() {
$('#new-category-modal').modal();
}
function createNewCategory() {
var category = {
name: $('#inputName').val(),
description: $('#inputDescription').val(),
icon: $('#new-category-modal i').attr('value'),
blockclass: $('#inputBlockclass').val()
};
socket.emit('api:admin.categories.create', category, function(err, data) {
if (!err) {
app.alert({
alert_id: 'category_created',
title: 'Created',
message: 'Category successfully created!',
type: 'success',
timeout: 2000
});
function save() {
socket.emit('api:admin.categories.update', modified_categories);
modified_categories = {};
}
var html = templates.prepare(templates['admin/categories'].blocks['categories']).parse({
categories: [data]
});
$('#entry-container').append(html);
function select_icon(el) {
var selected = el.attr('class').replace(' icon-2x', '');
jQuery('#icons .selected').removeClass('selected');
if (selected)
jQuery('#icons .' + selected).parent().addClass('selected');
$('#new-category-modal').modal('hide');
}
});
}
jQuery('document').ready(function() {
var url = window.location.href,
parts = url.split('/'),
active = parts[parts.length - 1];
bootbox.confirm('<h2>Select an icon.</h2>' + document.getElementById('icons').innerHTML, function(confirm) {
if (confirm) {
var iconClass = jQuery('.bootbox .selected').children(':first').attr('class');
el.attr('class', iconClass + ' icon-2x');
el.val(iconClass);
jQuery('.nav-pills li').removeClass('active');
jQuery('.nav-pills li a').each(function() {
if (this.getAttribute('href').match(active)) {
jQuery(this.parentNode).addClass('active');
return false;
}
});
modified(el);
}
});
jQuery('#save').on('click', save);
jQuery('#addNew').on('click', showCreateCategoryModal);
jQuery('#create-category-btn').on('click', createNewCategory);
setTimeout(function() { //bootbox was rewritten for BS3 and I had to add this timeout for the previous code to work. TODO: to look into
jQuery('.bootbox .col-md-3').on('click', function() {
jQuery('.bootbox .selected').removeClass('selected');
jQuery(this).addClass('selected');
});
}, 500);
}
jQuery('#entry-container').on('click', '.icon', function(ev) {
select_icon($(this).find('i'));
});
jQuery('.blockclass').on('change', function(ev) {
update_blockclass(ev.target);
});
function update_blockclass(el) {
el.parentNode.parentNode.className = 'entry-row ' + el.value;
}
jQuery('.category_name, .category_description, .blockclass').on('change', function(ev) {
modified(ev.target);
jQuery('#entry-container').sortable();
jQuery('.blockclass').each(function() {
jQuery(this).val(this.getAttribute('data-value'));
});
jQuery('.entry-row button').each(function(index, element) {
var disabled = $(element).attr('data-disabled');
if (disabled == "0" || disabled == "")
$(element).html('Disable');
else
$(element).html('Enable');
});
//DRY Failure. this needs to go into an ajaxify onready style fn. Currently is copy pasted into every single function so after ACP is off the ground fix asap
function showCreateCategoryModal() {
$('#new-category-modal').modal();
}
jQuery('.entry-row button').on('click', function(ev) {
var btn = jQuery(this);
var categoryRow = btn.parents('li');
var cid = categoryRow.attr('data-cid');
function createNewCategory() {
var category = {
name: $('#inputName').val(),
description: $('#inputDescription').val(),
icon: $('#new-category-modal i').attr('value'),
blockclass: $('#inputBlockclass').val()
};
socket.emit('api:admin.categories.create', category, function(err, data) {
if (!err) {
app.alert({
alert_id: 'category_created',
title: 'Created',
message: 'Category successfully created!',
type: 'success',
timeout: 2000
});
var html = templates.prepare(templates['admin/categories'].blocks['categories']).parse({
categories: [data]
});
$('#entry-container').append(html);
$('#new-category-modal').modal('hide');
}
});
}
var disabled = btn.html() == "Disable" ? "1" : "0";
categoryRow.remove();
modified_categories[cid] = modified_categories[cid] || {};
modified_categories[cid]['disabled'] = disabled;
jQuery('document').ready(function() {
var url = window.location.href,
parts = url.split('/'),
active = parts[parts.length - 1];
jQuery('.nav-pills li').removeClass('active');
jQuery('.nav-pills li a').each(function() {
if (this.getAttribute('href').match(active)) {
jQuery(this.parentNode).addClass('active');
return false;
}
});
jQuery('#save').on('click', save);
jQuery('#addNew').on('click', showCreateCategoryModal);
jQuery('#create-category-btn').on('click', createNewCategory);
jQuery('#entry-container').on('click', '.icon', function(ev) {
select_icon($(this).find('i'));
});
jQuery('.blockclass').on('change', function(ev) {
update_blockclass(ev.target);
});
jQuery('.category_name, .category_description, .blockclass').on('change', function(ev) {
modified(ev.target);
});
jQuery('.entry-row button').each(function(index, element) {
var disabled = $(element).attr('data-disabled');
if (disabled == "0" || disabled == "")
$(element).html('Disable');
else
$(element).html('Enable');
});
jQuery('.entry-row button').on('click', function(ev) {
var btn = jQuery(this);
var categoryRow = btn.parents('li');
var cid = categoryRow.attr('data-cid');
var disabled = btn.html() == "Disable" ? "1" : "0";
categoryRow.remove();
modified_categories[cid] = modified_categories[cid] || {};
modified_categories[cid]['disabled'] = disabled;
save();
return false;
});
save();
return false;
});
};
});
}());
return Categories;
});

@ -1,121 +1,44 @@
var nodebb_admin = (function(nodebb_admin) {
nodebb_admin.config = undefined;
nodebb_admin.prepare = function() {
// Come back in 500ms if the config isn't ready yet
if (nodebb_admin.config === undefined) {
setTimeout(function() {
nodebb_admin.prepare();
}, 500);
return;
}
// Populate the fields on the page from the config
var fields = document.querySelectorAll('#content [data-field]'),
numFields = fields.length,
saveBtn = document.getElementById('save'),
x, key, inputType;
for (x = 0; x < numFields; x++) {
key = fields[x].getAttribute('data-field');
inputType = fields[x].getAttribute('type');
if (fields[x].nodeName === 'INPUT') {
if (nodebb_admin.config[key]) {
switch (inputType) {
case 'text':
case 'textarea':
case 'number':
fields[x].value = nodebb_admin.config[key];
break;
case 'checkbox':
fields[x].checked = nodebb_admin.config[key] === '1' ? true : false;
break;
}
}
} else if (fields[x].nodeName === 'TEXTAREA') {
if (nodebb_admin.config[key]) fields[x].value = nodebb_admin.config[key];
jQuery('document').ready(function() {
// On menu click, change "active" state
var menuEl = document.querySelector('.sidebar-nav'),
liEls = menuEl.querySelectorAll('li')
parentEl = null;
menuEl.addEventListener('click', function(e) {
parentEl = e.target.parentNode;
if (parentEl.nodeName === 'LI') {
for (var x = 0, numLis = liEls.length; x < numLis; x++) {
if (liEls[x] !== parentEl) jQuery(liEls[x]).removeClass('active');
else jQuery(parentEl).addClass('active');
}
}
}, false);
});
saveBtn.addEventListener('click', function(e) {
var key, value;
e.preventDefault();
for (x = 0; x < numFields; x++) {
key = fields[x].getAttribute('data-field');
if (fields[x].nodeName === 'INPUT') {
inputType = fields[x].getAttribute('type');
switch (inputType) {
case 'text':
case 'number':
value = fields[x].value;
break;
case 'checkbox':
value = fields[x].checked ? '1' : '0';
break;
}
} else if (fields[x].nodeName === 'TEXTAREA') {
value = fields[x].value;
}
socket.emit('api:config.set', {
key: key,
value: value
});
}
socket.once('api:config.get', function(config) {
require(['forum/admin/settings'], function(Settings) {
Settings.config = config;
});
});
socket.emit('api:config.get');
socket.on('api:config.set', function(data) {
if (data.status === 'ok') {
app.alert({
alert_id: 'config_status',
timeout: 2500,
title: 'Changes Saved',
message: 'Your changes to the NodeBB configuration have been saved.',
type: 'success'
});
} else {
app.alert({
alert_id: 'config_status',
timeout: 2500,
title: 'Changes Not Saved',
message: 'NodeBB encountered a problem saving your changes',
type: 'danger'
});
}
nodebb_admin.remove = function(key) {
socket.emit('api:config.remove', key);
}
jQuery('document').ready(function() {
// On menu click, change "active" state
var menuEl = document.querySelector('.sidebar-nav'),
liEls = menuEl.querySelectorAll('li')
parentEl = null;
menuEl.addEventListener('click', function(e) {
parentEl = e.target.parentNode;
if (parentEl.nodeName === 'LI') {
for (var x = 0, numLis = liEls.length; x < numLis; x++) {
if (liEls[x] !== parentEl) jQuery(liEls[x]).removeClass('active');
else jQuery(parentEl).addClass('active');
}
}
}, false);
});
socket.once('api:config.get', function(config) {
nodebb_admin.config = config;
});
socket.emit('api:config.get');
socket.on('api:config.set', function(data) {
if (data.status === 'ok') {
app.alert({
alert_id: 'config_status',
timeout: 2500,
title: 'Changes Saved',
message: 'Your changes to the NodeBB configuration have been saved.',
type: 'success'
});
} else {
app.alert({
alert_id: 'config_status',
timeout: 2500,
title: 'Changes Not Saved',
message: 'NodeBB encountered a problem saving your changes',
type: 'danger'
});
}
});
return nodebb_admin;
}(nodebb_admin || {}));
});

@ -1,194 +1,200 @@
$(document).ready(function() {
var createEl = document.getElementById('create'),
createModal = $('#create-modal'),
createSubmitBtn = document.getElementById('create-modal-go'),
createNameEl = $('#create-group-name'),
detailsModal = $('#group-details-modal'),
detailsSearch = detailsModal.find('#group-details-search'),
searchResults = detailsModal.find('#group-details-search-results'),
groupMembersEl = detailsModal.find('ul.current_members'),
detailsModalSave = detailsModal.find('.btn-primary'),
searchDelay = undefined,
listEl = $('#groups-list');
createEl.addEventListener('click', function() {
createModal.modal('show');
setTimeout(function() {
createNameEl.focus();
}, 250);
}, false);
createSubmitBtn.addEventListener('click', function() {
var submitObj = {
name: createNameEl.val(),
description: $('#create-group-desc').val()
},
errorEl = $('#create-modal-error'),
errorText;
socket.emit('api: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 grou 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;
define(function() {
var Groups = {};
Groups.init = function() {
var createEl = document.getElementById('create'),
createModal = $('#create-modal'),
createSubmitBtn = document.getElementById('create-modal-go'),
createNameEl = $('#create-group-name'),
detailsModal = $('#group-details-modal'),
detailsSearch = detailsModal.find('#group-details-search'),
searchResults = detailsModal.find('#group-details-search-results'),
groupMembersEl = detailsModal.find('ul.current_members'),
detailsModalSave = detailsModal.find('.btn-primary'),
searchDelay = undefined,
listEl = $('#groups-list');
createEl.addEventListener('click', function() {
createModal.modal('show');
setTimeout(function() {
createNameEl.focus();
}, 250);
}, false);
createSubmitBtn.addEventListener('click', function() {
var submitObj = {
name: createNameEl.val(),
description: $('#create-group-desc').val()
},
errorEl = $('#create-modal-error'),
errorText;
socket.emit('api: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 grou 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;
}
errorEl.html(errorText).removeClass('hide');
} else {
createModal.modal('hide');
errorEl.addClass('hide');
createNameEl.val('');
ajaxify.go('admin/groups');
}
});
});
errorEl.html(errorText).removeClass('hide');
} else {
createModal.modal('hide');
errorEl.addClass('hide');
createNameEl.val('');
ajaxify.go('admin/groups');
listEl.on('click', 'button[data-action]', function() {
var action = this.getAttribute('data-action'),
gid = $(this).parents('li[data-gid]').attr('data-gid');
switch (action) {
case 'delete':
bootbox.confirm('Are you sure you wish to delete this group?', function(confirm) {
if (confirm) {
socket.emit('api:groups.delete', gid, function(err, data) {
if (data === 'OK') ajaxify.go('admin/groups');
});
}
});
break;
case 'members':
socket.emit('api:groups.get', gid, function(err, groupObj) {
var formEl = detailsModal.find('form'),
nameEl = formEl.find('#change-group-name'),
descEl = formEl.find('#change-group-desc'),
memberIcon = document.createElement('li'),
numMembers = groupObj.members.length,
membersFrag = document.createDocumentFragment(),
memberIconImg, x;
nameEl.val(groupObj.name);
descEl.val(groupObj.description);
// Member list
memberIcon.innerHTML = '<img /><span></span>';
memberIconImg = memberIcon.querySelector('img');
memberIconLabel = memberIcon.querySelector('span');
if (numMembers > 0) {
for (x = 0; x < numMembers; x++) {
memberIconImg.src = groupObj.members[x].picture;
memberIconLabel.innerHTML = groupObj.members[x].username;
memberIcon.setAttribute('data-uid', groupObj.members[x].uid);
membersFrag.appendChild(memberIcon.cloneNode(true));
}
groupMembersEl.html('');
groupMembersEl[0].appendChild(membersFrag);
}
detailsModal.attr('data-gid', groupObj.gid);
detailsModal.modal('show');
});
break;
}
});
});
listEl.on('click', 'button[data-action]', function() {
var action = this.getAttribute('data-action'),
gid = $(this).parents('li[data-gid]').attr('data-gid');
switch (action) {
case 'delete':
bootbox.confirm('Are you sure you wish to delete this group?', function(confirm) {
if (confirm) {
socket.emit('api:groups.delete', gid, function(err, data) {
if (data === 'OK') ajaxify.go('admin/groups');
});
}
});
break;
case 'members':
socket.emit('api:groups.get', gid, function(err, groupObj) {
var formEl = detailsModal.find('form'),
nameEl = formEl.find('#change-group-name'),
descEl = formEl.find('#change-group-desc'),
memberIcon = document.createElement('li'),
numMembers = groupObj.members.length,
membersFrag = document.createDocumentFragment(),
memberIconImg, x;
nameEl.val(groupObj.name);
descEl.val(groupObj.description);
// Member list
memberIcon.innerHTML = '<img /><span></span>';
memberIconImg = memberIcon.querySelector('img');
memberIconLabel = memberIcon.querySelector('span');
if (numMembers > 0) {
for (x = 0; x < numMembers; x++) {
memberIconImg.src = groupObj.members[x].picture;
memberIconLabel.innerHTML = groupObj.members[x].username;
memberIcon.setAttribute('data-uid', groupObj.members[x].uid);
membersFrag.appendChild(memberIcon.cloneNode(true));
detailsSearch.on('keyup', function() {
var searchEl = this;
if (searchDelay) clearTimeout(searchDelay);
searchDelay = setTimeout(function() {
var searchText = searchEl.value,
resultsEl = document.getElementById('group-details-search-results'),
foundUser = document.createElement('li'),
foundUserImg, foundUserLabel;
foundUser.innerHTML = '<img /><span></span>';
foundUserImg = foundUser.getElementsByTagName('img')[0];
foundUserLabel = foundUser.getElementsByTagName('span')[0];
socket.emit('api:admin.user.search', searchText, function(err, results) {
if (!err && results && results.length > 0) {
var numResults = results.length,
resultsSlug = document.createDocumentFragment(),
x;
if (numResults > 4) numResults = 4;
for (x = 0; x < numResults; x++) {
foundUserImg.src = results[x].picture;
foundUserLabel.innerHTML = results[x].username;
foundUser.setAttribute('title', results[x].username);
foundUser.setAttribute('data-uid', results[x].uid);
resultsSlug.appendChild(foundUser.cloneNode(true));
}
groupMembersEl.html('');
groupMembersEl[0].appendChild(membersFrag);
}
detailsModal.attr('data-gid', groupObj.gid);
detailsModal.modal('show');
resultsEl.innerHTML = '';
resultsEl.appendChild(resultsSlug);
} else resultsEl.innerHTML = '<li>No Users Found</li>';
});
break;
}
});
detailsSearch.on('keyup', function() {
var searchEl = this;
if (searchDelay) clearTimeout(searchDelay);
searchDelay = setTimeout(function() {
var searchText = searchEl.value,
resultsEl = document.getElementById('group-details-search-results'),
foundUser = document.createElement('li'),
foundUserImg, foundUserLabel;
foundUser.innerHTML = '<img /><span></span>';
foundUserImg = foundUser.getElementsByTagName('img')[0];
foundUserLabel = foundUser.getElementsByTagName('span')[0];
socket.emit('api:admin.user.search', searchText, function(err, results) {
if (!err && results && results.length > 0) {
var numResults = results.length,
resultsSlug = document.createDocumentFragment(),
x;
if (numResults > 4) numResults = 4;
for (x = 0; x < numResults; x++) {
foundUserImg.src = results[x].picture;
foundUserLabel.innerHTML = results[x].username;
foundUser.setAttribute('title', results[x].username);
foundUser.setAttribute('data-uid', results[x].uid);
resultsSlug.appendChild(foundUser.cloneNode(true));
}
}, 200);
});
resultsEl.innerHTML = '';
resultsEl.appendChild(resultsSlug);
} else resultsEl.innerHTML = '<li>No Users Found</li>';
});
}, 200);
});
searchResults.on('click', 'li[data-uid]', function() {
var userLabel = this,
uid = parseInt(this.getAttribute('data-uid')),
gid = detailsModal.attr('data-gid'),
members = [];
searchResults.on('click', 'li[data-uid]', function() {
var userLabel = this,
uid = parseInt(this.getAttribute('data-uid')),
gid = detailsModal.attr('data-gid'),
members = [];
groupMembersEl.find('li[data-uid]').each(function() {
members.push(parseInt(this.getAttribute('data-uid')));
});
groupMembersEl.find('li[data-uid]').each(function() {
members.push(parseInt(this.getAttribute('data-uid')));
if (members.indexOf(uid) === -1) {
socket.emit('api:groups.join', {
gid: gid,
uid: uid
}, function(err, data) {
if (!err) {
groupMembersEl.append(userLabel.cloneNode(true));
}
});
}
});
if (members.indexOf(uid) === -1) {
socket.emit('api:groups.join', {
groupMembersEl.on('click', 'li[data-uid]', function() {
var uid = this.getAttribute('data-uid'),
gid = detailsModal.attr('data-gid');
socket.emit('api:groups.leave', {
gid: gid,
uid: uid
}, function(err, data) {
if (!err) {
groupMembersEl.append(userLabel.cloneNode(true));
groupMembersEl.find('li[data-uid="' + uid + '"]').remove();
}
});
}
});
groupMembersEl.on('click', 'li[data-uid]', function() {
var uid = this.getAttribute('data-uid'),
gid = detailsModal.attr('data-gid');
socket.emit('api:groups.leave', {
gid: gid,
uid: uid
}, function(err, data) {
if (!err) {
groupMembersEl.find('li[data-uid="' + uid + '"]').remove();
}
});
});
detailsModalSave.on('click', function() {
var formEl = detailsModal.find('form'),
nameEl = formEl.find('#change-group-name'),
descEl = formEl.find('#change-group-desc'),
gid = detailsModal.attr('data-gid');
socket.emit('api:groups.update', {
gid: gid,
values: {
name: nameEl.val(),
description: descEl.val()
}
}, function(err) {
if (!err) {
detailsModal.modal('hide');
ajaxify.go('admin/groups');
}
detailsModalSave.on('click', function() {
var formEl = detailsModal.find('form'),
nameEl = formEl.find('#change-group-name'),
descEl = formEl.find('#change-group-desc'),
gid = detailsModal.attr('data-gid');
socket.emit('api:groups.update', {
gid: gid,
values: {
name: nameEl.val(),
description: descEl.val()
}
}, function(err) {
if (!err) {
detailsModal.modal('hide');
ajaxify.go('admin/groups');
}
});
});
});
};
return Groups;
});

@ -1,25 +1,28 @@
define(function() {
var Admin = {};
(function() {
Admin.init = function() {
ajaxify.register_events(['api:get_all_rooms']);
socket.on('api:get_all_rooms', function(data) {
ajaxify.register_events(['api:get_all_rooms']);
socket.on('api:get_all_rooms', function(data) {
var active_users = document.getElementById('active_users'),
total = 0;
active_users.innerHTML = '';
var active_users = document.getElementById('active_users'),
total = 0;
active_users.innerHTML = '';
for (var room in data) {
if (room !== '') {
var count = data[room].length;
total += count;
active_users.innerHTML = active_users.innerHTML + "<div class='alert alert-success'><strong>" + room + "</strong> " + count + " active user" + (count > 1 ? "s" : "") + "</div>";
for (var room in data) {
if (room !== '') {
var count = data[room].length;
total += count;
active_users.innerHTML = active_users.innerHTML + "<div class='alert alert-success'><strong>" + room + "</strong> " + count + " active user" + (count > 1 ? "s" : "") + "</div>";
}
}
}
document.getElementById('connections').innerHTML = total;
});
document.getElementById('connections').innerHTML = total;
});
app.enter_room('admin');
socket.emit('api:get_all_rooms');
app.enter_room('admin');
socket.emit('api:get_all_rooms');
};
}());
return Admin;
});

@ -1,7 +1,5 @@
var nodebb_admin = nodebb_admin || {};
(function() {
var plugins = {
define(function() {
var Plugins = {
init: function() {
var pluginsList = $('.plugins'),
numPlugins = pluginsList[0].querySelectorAll('li').length,
@ -31,8 +29,5 @@ var nodebb_admin = nodebb_admin || {};
}
};
jQuery(document).ready(function() {
nodebb_admin.plugins = plugins;
nodebb_admin.plugins.init();
});
})();
return Plugins;
});

@ -0,0 +1,81 @@
define(function() {
var Settings = {};
Settings.config = {};
Settings.init = function() {
Settings.prepare();
};
Settings.prepare = function() {
// Come back in 500ms if the config isn't ready yet
if (Settings.config === undefined) {
setTimeout(function() {
Settings.prepare();
}, 500);
return;
}
// Populate the fields on the page from the config
var fields = document.querySelectorAll('#content [data-field]'),
numFields = fields.length,
saveBtn = document.getElementById('save'),
x, key, inputType;
for (x = 0; x < numFields; x++) {
key = fields[x].getAttribute('data-field');
inputType = fields[x].getAttribute('type');
if (fields[x].nodeName === 'INPUT') {
if (Settings.config[key]) {
switch (inputType) {
case 'text':
case 'textarea':
case 'number':
fields[x].value = Settings.config[key];
break;
case 'checkbox':
fields[x].checked = Settings.config[key] === '1' ? true : false;
break;
}
}
} else if (fields[x].nodeName === 'TEXTAREA') {
if (Settings.config[key]) fields[x].value = Settings.config[key];
}
}
saveBtn.addEventListener('click', function(e) {
var key, value;
e.preventDefault();
for (x = 0; x < numFields; x++) {
key = fields[x].getAttribute('data-field');
if (fields[x].nodeName === 'INPUT') {
inputType = fields[x].getAttribute('type');
switch (inputType) {
case 'text':
case 'number':
value = fields[x].value;
break;
case 'checkbox':
value = fields[x].checked ? '1' : '0';
break;
}
} else if (fields[x].nodeName === 'TEXTAREA') {
value = fields[x].value;
}
socket.emit('api:config.set', {
key: key,
value: value
});
}
});
};
Settings.remove = function(key) {
socket.emit('api:config.remove', key);
};
return Settings;
});

@ -1,8 +1,91 @@
var nodebb_admin = (function(nodebb_admin) {
define(function() {
var Themes = {};
var themes = {};
Themes.init = function() {
var scriptEl = document.createElement('script');
scriptEl.src = 'http://api.bootswatch.com/3/?callback=bootswatchListener';
document.body.appendChild(scriptEl);
themes.render = function(bootswatch) {
var bootstrapThemeContainer = document.querySelector('#bootstrap_themes'),
installedThemeContainer = document.querySelector('#installed_themes'),
themeEvent = function(e) {
if (e.target.hasAttribute('data-action')) {
switch (e.target.getAttribute('data-action')) {
case 'preview':
var cssSrc = $(e.target).parents('li').attr('data-css'),
cssEl = document.getElementById('base-theme');
cssEl.href = cssSrc;
break;
case 'use':
var parentEl = $(e.target).parents('li'),
cssSrc = parentEl.attr('data-css'),
cssName = parentEl.attr('data-theme');
socket.emit('api:config.set', {
key: 'theme:id',
value: 'bootswatch:' + cssName
});
socket.emit('api:config.set', {
key: 'theme:src',
value: cssSrc
});
break;
}
}
};
bootstrapThemeContainer.addEventListener('click', themeEvent);
installedThemeContainer.addEventListener('click', themeEvent);
var revertEl = document.getElementById('revert_theme');
revertEl.addEventListener('click', function() {
bootbox.confirm('Are you sure you wish to remove the custom theme and restore the NodeBB default theme?', function(confirm) {
if (confirm) {
require(['forum/admin/settings'], function(Settings) {
Settings.remove('theme:id');
Settings.remove('theme:src');
});
}
});
}, false);
// Installed Themes
socket.emit('api:admin.themes.getInstalled', function(themes) {
var instListEl = document.getElementById('installed_themes'),
themeFrag = document.createDocumentFragment(),
liEl = document.createElement('li');
if (themes.length > 0) {
for (var x = 0, numThemes = themes.length; x < numThemes; x++) {
liEl.setAttribute('data-theme', themes[x].id);
liEl.setAttribute('data-css', themes[x].src);
liEl.innerHTML = '<img src="' + themes[x].screenshot + '" />' +
'<div>' +
'<div class="pull-right">' +
'<button class="btn btn-primary" data-action="use">Use</button> ' +
'<button class="btn btn-default" data-action="preview">Preview</button>' +
'</div>' +
'<h4>' + themes[x].name + '</h4>' +
'<p>' +
themes[x].description +
(themes[x].url ? ' (<a href="' + themes[x].url + '">Homepage</a>)' : '') +
'</p>' +
'</div>' +
'<div class="clear">';
themeFrag.appendChild(liEl.cloneNode(true));
}
} else {
// No themes found
liEl.className = 'no-themes';
liEl.innerHTML = 'No installed themes found';
themeFrag.appendChild(liEl);
}
instListEl.innerHTML = '';
instListEl.appendChild(themeFrag);
});
}
Themes.render = function(bootswatch) {
var themeFrag = document.createDocumentFragment(),
themeEl = document.createElement('li'),
themeContainer = document.querySelector('#bootstrap_themes'),
@ -28,91 +111,5 @@ var nodebb_admin = (function(nodebb_admin) {
themeContainer.appendChild(themeFrag);
}
nodebb_admin.themes = themes;
return nodebb_admin;
}(nodebb_admin || {}));
(function() {
var scriptEl = document.createElement('script');
scriptEl.src = 'http://api.bootswatch.com/3/?callback=nodebb_admin.themes.render';
document.body.appendChild(scriptEl);
var bootstrapThemeContainer = document.querySelector('#bootstrap_themes'),
installedThemeContainer = document.querySelector('#installed_themes'),
themeEvent = function(e) {
if (e.target.hasAttribute('data-action')) {
switch (e.target.getAttribute('data-action')) {
case 'preview':
var cssSrc = $(e.target).parents('li').attr('data-css'),
cssEl = document.getElementById('base-theme');
cssEl.href = cssSrc;
break;
case 'use':
var parentEl = $(e.target).parents('li'),
cssSrc = parentEl.attr('data-css'),
cssName = parentEl.attr('data-theme');
socket.emit('api:config.set', {
key: 'theme:id',
value: 'bootswatch:' + cssName
});
socket.emit('api:config.set', {
key: 'theme:src',
value: cssSrc
});
break;
}
}
};
bootstrapThemeContainer.addEventListener('click', themeEvent);
installedThemeContainer.addEventListener('click', themeEvent);
var revertEl = document.getElementById('revert_theme');
revertEl.addEventListener('click', function() {
bootbox.confirm('Are you sure you wish to remove the custom theme and restore the NodeBB default theme?', function(confirm) {
if (confirm) {
nodebb_admin.remove('theme:id');
nodebb_admin.remove('theme:src');
}
});
}, false);
// Installed Themes
socket.emit('api:admin.themes.getInstalled', function(themes) {
var instListEl = document.getElementById('installed_themes'),
themeFrag = document.createDocumentFragment(),
liEl = document.createElement('li');
if (themes.length > 0) {
for (var x = 0, numThemes = themes.length; x < numThemes; x++) {
liEl.setAttribute('data-theme', themes[x].id);
liEl.setAttribute('data-css', themes[x].src);
liEl.innerHTML = '<img src="' + themes[x].screenshot + '" />' +
'<div>' +
'<div class="pull-right">' +
'<button class="btn btn-primary" data-action="use">Use</button> ' +
'<button class="btn btn-default" data-action="preview">Preview</button>' +
'</div>' +
'<h4>' + themes[x].name + '</h4>' +
'<p>' +
themes[x].description +
(themes[x].url ? ' (<a href="' + themes[x].url + '">Homepage</a>)' : '') +
'</p>' +
'</div>' +
'<div class="clear">';
themeFrag.appendChild(liEl.cloneNode(true));
}
} else {
// No themes found
liEl.className = 'no-themes';
liEl.innerHTML = 'No installed themes found';
themeFrag.appendChild(liEl);
}
instListEl.innerHTML = '';
instListEl.appendChild(themeFrag);
});
})();
return Themes;
});

@ -1,127 +1,133 @@
$(document).ready(function() {
var topicsListEl = document.querySelector('.topics'),
loadMoreEl = document.getElementById('topics_loadmore');
$(topicsListEl).on('click', '[data-action]', function() {
var $this = $(this),
action = this.getAttribute('data-action'),
tid = $this.parents('[data-tid]').attr('data-tid');
switch (action) {
case 'pin':
if (!$this.hasClass('active')) socket.emit('api:topic.pin', {
tid: tid
define(function() {
var Topics = {};
Topics.init = function() {
var topicsListEl = document.querySelector('.topics'),
loadMoreEl = document.getElementById('topics_loadmore');
$(topicsListEl).on('click', '[data-action]', function() {
var $this = $(this),
action = this.getAttribute('data-action'),
tid = $this.parents('[data-tid]').attr('data-tid');
switch (action) {
case 'pin':
if (!$this.hasClass('active')) socket.emit('api:topic.pin', {
tid: tid
});
else socket.emit('api:topic.unpin', {
tid: tid
});
break;
case 'lock':
if (!$this.hasClass('active')) socket.emit('api:topic.lock', {
tid: tid
});
else socket.emit('api:topic.unlock', {
tid: tid
});
break;
case 'delete':
if (!$this.hasClass('active')) socket.emit('api:topic.delete', {
tid: tid
});
else socket.emit('api:topic.restore', {
tid: tid
});
break;
}
});
loadMoreEl.addEventListener('click', function() {
if (this.className.indexOf('disabled') === -1) {
var topics = document.querySelectorAll('.topics li[data-tid]'),
lastTid = parseInt(topics[topics.length - 1].getAttribute('data-tid'));
this.innerHTML = '<i class="icon-refresh icon-spin"></i> Retrieving topics';
socket.emit('api:admin.topics.getMore', {
limit: 10,
after: lastTid
}, function(topics) {
var btnEl = document.getElementById('topics_loadmore');
topics = JSON.parse(topics);
if (topics.length > 0) {
var html = templates.prepare(templates['admin/topics'].blocks['topics']).parse({
topics: topics
}),
topicsListEl = document.querySelector('.topics');
topicsListEl.innerHTML += html;
btnEl.innerHTML = 'Load More Topics';
} else {
// Exhausted all topics
btnEl.className += ' disabled';
btnEl.innerHTML = 'No more topics';
}
});
else socket.emit('api:topic.unpin', {
tid: tid
});
break;
case 'lock':
if (!$this.hasClass('active')) socket.emit('api:topic.lock', {
tid: tid
});
else socket.emit('api:topic.unlock', {
tid: tid
});
break;
case 'delete':
if (!$this.hasClass('active')) socket.emit('api:topic.delete', {
tid: tid
});
else socket.emit('api:topic.restore', {
tid: tid
});
break;
}
}, false);
// Resolve proper button state for all topics
var topicEls = topicsListEl.querySelectorAll('li'),
numTopics = topicEls.length;
for (var x = 0; x < numTopics; x++) {
if (topicEls[x].getAttribute('data-pinned') === '1') topicEls[x].querySelector('[data-action="pin"]').className += ' active';
if (topicEls[x].getAttribute('data-locked') === '1') topicEls[x].querySelector('[data-action="lock"]').className += ' active';
if (topicEls[x].getAttribute('data-deleted') === '1') topicEls[x].querySelector('[data-action="delete"]').className += ' active';
topicEls[x].removeAttribute('data-pinned');
topicEls[x].removeAttribute('data-locked');
topicEls[x].removeAttribute('data-deleted');
}
});
loadMoreEl.addEventListener('click', function() {
if (this.className.indexOf('disabled') === -1) {
var topics = document.querySelectorAll('.topics li[data-tid]'),
lastTid = parseInt(topics[topics.length - 1].getAttribute('data-tid'));
this.innerHTML = '<i class="icon-refresh icon-spin"></i> Retrieving topics';
socket.emit('api:admin.topics.getMore', {
limit: 10,
after: lastTid
}, function(topics) {
var btnEl = document.getElementById('topics_loadmore');
topics = JSON.parse(topics);
if (topics.length > 0) {
var html = templates.prepare(templates['admin/topics'].blocks['topics']).parse({
topics: topics
}),
topicsListEl = document.querySelector('.topics');
topicsListEl.innerHTML += html;
btnEl.innerHTML = 'Load More Topics';
} else {
// Exhausted all topics
btnEl.className += ' disabled';
btnEl.innerHTML = 'No more topics';
}
});
}
}, false);
// Resolve proper button state for all topics
var topicEls = topicsListEl.querySelectorAll('li'),
numTopics = topicEls.length;
for (var x = 0; x < numTopics; x++) {
if (topicEls[x].getAttribute('data-pinned') === '1') topicEls[x].querySelector('[data-action="pin"]').className += ' active';
if (topicEls[x].getAttribute('data-locked') === '1') topicEls[x].querySelector('[data-action="lock"]').className += ' active';
if (topicEls[x].getAttribute('data-deleted') === '1') topicEls[x].querySelector('[data-action="delete"]').className += ' active';
topicEls[x].removeAttribute('data-pinned');
topicEls[x].removeAttribute('data-locked');
topicEls[x].removeAttribute('data-deleted');
}
});
socket.on('api:topic.pin', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
$(btnEl).addClass('active');
}
});
socket.on('api:topic.unpin', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
$(btnEl).removeClass('active');
}
});
socket.on('api:topic.lock', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="lock"]');
$(btnEl).addClass('active');
}
});
socket.on('api:topic.unlock', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="lock"]');
$(btnEl).removeClass('active');
}
});
socket.on('api:topic.delete', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
$(btnEl).addClass('active');
}
});
socket.on('api:topic.restore', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
$(btnEl).removeClass('active');
}
socket.on('api:topic.pin', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
$(btnEl).addClass('active');
}
});
socket.on('api:topic.unpin', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
$(btnEl).removeClass('active');
}
});
socket.on('api:topic.lock', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="lock"]');
$(btnEl).addClass('active');
}
});
socket.on('api:topic.unlock', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="lock"]');
$(btnEl).removeClass('active');
}
});
socket.on('api:topic.delete', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
$(btnEl).addClass('active');
}
});
socket.on('api:topic.restore', function(response) {
if (response.status === 'ok') {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
$(btnEl).removeClass('active');
}
});
};
return Topics;
});

@ -1,170 +1,174 @@
(function() {
var yourid = templates.get('yourid');
function isUserAdmin(element) {
var parent = $(element).parents('.users-box');
return (parent.attr('data-admin') !== "0");
}
function isUserBanned(element) {
var parent = $(element).parents('.users-box');
return (parent.attr('data-banned') !== "" && parent.attr('data-banned') !== "0");
}
function getUID(element) {
var parent = $(element).parents('.users-box');
return parent.attr('data-uid');
}
function updateUserButtons() {
jQuery('.ban-btn').each(function(index, element) {
var banBtn = $(element);
var uid = getUID(banBtn);
if (isUserAdmin(banBtn) || uid === yourid)
banBtn.addClass('disabled');
else if (isUserBanned(banBtn))
banBtn.addClass('btn-warning');
else
banBtn.removeClass('btn-warning');
define(function() {
var Users = {};
});
}
Users.init = function() {
var yourid = templates.get('yourid');
function initUsers() {
function isUserAdmin(element) {
var parent = $(element).parents('.users-box');
return (parent.attr('data-admin') !== "0");
}
updateUserButtons();
function isUserBanned(element) {
var parent = $(element).parents('.users-box');
return (parent.attr('data-banned') !== "" && parent.attr('data-banned') !== "0");
}
$('#users-container').on('click', '.ban-btn', function() {
var banBtn = $(this);
var isAdmin = isUserAdmin(banBtn);
var isBanned = isUserBanned(banBtn);
var parent = banBtn.parents('.users-box');
var uid = getUID(banBtn);
function getUID(element) {
var parent = $(element).parents('.users-box');
return parent.attr('data-uid');
}
if (!isAdmin) {
if (isBanned) {
socket.emit('api:admin.user.unbanUser', uid);
function updateUserButtons() {
jQuery('.ban-btn').each(function(index, element) {
var banBtn = $(element);
var uid = getUID(banBtn);
if (isUserAdmin(banBtn) || uid === yourid)
banBtn.addClass('disabled');
else if (isUserBanned(banBtn))
banBtn.addClass('btn-warning');
else
banBtn.removeClass('btn-warning');
parent.attr('data-banned', 0);
} else {
bootbox.confirm('Do you really want to ban "' + parent.attr('data-username') + '"?', function(confirm) {
if (confirm) {
socket.emit('api:admin.user.banUser', uid);
banBtn.addClass('btn-warning');
parent.attr('data-banned', 1);
}
});
}
}
return false;
});
}
});
}
jQuery('document').ready(function() {
function initUsers() {
var timeoutId = 0,
loadingMoreUsers = false;
updateUserButtons();
var url = window.location.href,
parts = url.split('/'),
active = parts[parts.length - 1];
$('#users-container').on('click', '.ban-btn', function() {
var banBtn = $(this);
var isAdmin = isUserAdmin(banBtn);
var isBanned = isUserBanned(banBtn);
var parent = banBtn.parents('.users-box');
var uid = getUID(banBtn);
if (!isAdmin) {
if (isBanned) {
socket.emit('api:admin.user.unbanUser', uid);
banBtn.removeClass('btn-warning');
parent.attr('data-banned', 0);
} else {
bootbox.confirm('Do you really want to ban "' + parent.attr('data-username') + '"?', function(confirm) {
if (confirm) {
socket.emit('api:admin.user.banUser', uid);
banBtn.addClass('btn-warning');
parent.attr('data-banned', 1);
}
});
}
}
jQuery('.nav-pills li').removeClass('active');
jQuery('.nav-pills li a').each(function() {
if (this.getAttribute('href').match(active)) {
jQuery(this.parentNode).addClass('active');
return false;
}
});
});
}
jQuery('#search-user').on('keyup', function() {
if (timeoutId !== 0) {
clearTimeout(timeoutId);
timeoutId = 0;
}
timeoutId = setTimeout(function() {
var username = $('#search-user').val();
jQuery('document').ready(function() {
jQuery('.icon-spinner').removeClass('none');
socket.emit('api:admin.user.search', username);
var timeoutId = 0,
loadingMoreUsers = false;
}, 250);
});
var url = window.location.href,
parts = url.split('/'),
active = parts[parts.length - 1];
initUsers();
socket.removeAllListeners('api:admin.user.search');
socket.on('api:admin.user.search', function(data) {
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
users: data
}),
userListEl = document.querySelector('.users');
userListEl.innerHTML = html;
jQuery('.icon-spinner').addClass('none');
if (data && data.length === 0) {
$('#user-notfound-notify').html('User not found!')
.show()
.addClass('label-danger')
.removeClass('label-success');
} else {
$('#user-notfound-notify').html(data.length + ' user' + (data.length > 1 ? 's' : '') + ' found!')
.show()
.addClass('label-success')
.removeClass('label-danger');
}
jQuery('.nav-pills li').removeClass('active');
jQuery('.nav-pills li a').each(function() {
if (this.getAttribute('href').match(active)) {
jQuery(this.parentNode).addClass('active');
return false;
}
});
jQuery('#search-user').on('keyup', function() {
if (timeoutId !== 0) {
clearTimeout(timeoutId);
timeoutId = 0;
}
timeoutId = setTimeout(function() {
var username = $('#search-user').val();
jQuery('.icon-spinner').removeClass('none');
socket.emit('api:admin.user.search', username);
}, 250);
});
initUsers();
});
function onUsersLoaded(users) {
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
users: users
socket.removeAllListeners('api:admin.user.search');
socket.on('api:admin.user.search', function(data) {
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
users: data
}),
userListEl = document.querySelector('.users');
userListEl.innerHTML = html;
jQuery('.icon-spinner').addClass('none');
if (data && data.length === 0) {
$('#user-notfound-notify').html('User not found!')
.show()
.addClass('label-danger')
.removeClass('label-success');
} else {
$('#user-notfound-notify').html(data.length + ' user' + (data.length > 1 ? 's' : '') + ' found!')
.show()
.addClass('label-success')
.removeClass('label-danger');
}
initUsers();
});
$('#users-container').append(html);
updateUserButtons();
}
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';
function onUsersLoaded(users) {
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
users: users
});
$('#users-container').append(html);
updateUserButtons();
}
if (set) {
loadingMoreUsers = true;
socket.emit('api:users.loadMore', {
set: set,
after: $('#users-container').children().length
}, function(data) {
if (data.users.length) {
onUsersLoaded(data.users);
}
loadingMoreUsers = false;
});
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('api:users.loadMore', {
set: set,
after: $('#users-container').children().length
}, function(data) {
if (data.users.length) {
onUsersLoaded(data.users);
}
loadingMoreUsers = false;
});
}
}
}
$('#load-more-users-btn').on('click', loadMoreUsers);
$('#load-more-users-btn').on('click', loadMoreUsers);
$(window).off('scroll').on('scroll', function() {
var bottom = ($(document).height() - $(window).height()) * 0.9;
$(window).off('scroll').on('scroll', function() {
var bottom = ($(document).height() - $(window).height()) * 0.9;
if ($(window).scrollTop() > bottom && !loadingMoreUsers) {
loadMoreUsers();
}
});
if ($(window).scrollTop() > bottom && !loadingMoreUsers) {
loadMoreUsers();
}
});
});
});
};
}());
return Users;
});

@ -1,41 +1,86 @@
(function () {
var cid = templates.get('category_id'),
room = 'category_' + cid,
twitterEl = document.getElementById('twitter-intent'),
facebookEl = document.getElementById('facebook-share'),
googleEl = document.getElementById('google-share'),
twitter_url = templates.get('twitter-intent-url'),
facebook_url = templates.get('facebook-share-url'),
google_url = templates.get('google-share-url'),
loadingMoreTopics = false;
app.enter_room(room);
twitterEl.addEventListener('click', function () {
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
return false;
}, false);
facebookEl.addEventListener('click', function () {
window.open(facebook_url, '_blank', 'width=626,height=436,scrollbars=no,status=no');
return false;
}, false);
googleEl.addEventListener('click', function () {
window.open(google_url, '_blank', 'width=500,height=570,scrollbars=no,status=no');
return false;
}, false);
var new_post = document.getElementById('new_post');
new_post.onclick = function () {
require(['composer'], function (cmp) {
cmp.push(0, cid);
define(function () {
var Category = {};
Category.init = function() {
var cid = templates.get('category_id'),
room = 'category_' + cid,
twitterEl = document.getElementById('twitter-intent'),
facebookEl = document.getElementById('facebook-share'),
googleEl = document.getElementById('google-share'),
twitter_url = templates.get('twitter-intent-url'),
facebook_url = templates.get('facebook-share-url'),
google_url = templates.get('google-share-url'),
loadingMoreTopics = false;
app.enter_room(room);
twitterEl.addEventListener('click', function () {
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
return false;
}, false);
facebookEl.addEventListener('click', function () {
window.open(facebook_url, '_blank', 'width=626,height=436,scrollbars=no,status=no');
return false;
}, false);
googleEl.addEventListener('click', function () {
window.open(google_url, '_blank', 'width=500,height=570,scrollbars=no,status=no');
return false;
}, false);
var new_post = document.getElementById('new_post');
new_post.onclick = function () {
require(['composer'], function (cmp) {
cmp.push(0, cid);
});
}
ajaxify.register_events([
'event:new_topic'
]);
socket.on('event:new_topic', Category.onNewTopic);
socket.emit('api:categories.getRecentReplies', cid);
socket.on('api:categories.getRecentReplies', function (posts) {
if (!posts || posts.length === 0) {
return;
}
var recent_replies = document.getElementById('category_recent_replies');
recent_replies.innerHTML = '';
var frag = document.createDocumentFragment(),
li = document.createElement('li');
for (var i = 0, numPosts = posts.length; i < numPosts; i++) {
li.setAttribute('data-pid', posts[i].pid);
li.innerHTML = '<a href="/user/' + posts[i].userslug + '"><img title="' + posts[i].username + '" style="width: 48px; height: 48px; /*temporary*/" class="img-rounded" src="' + posts[i].picture + '" class="" /></a>' +
'<a href="/topic/' + posts[i].topicSlug + '#' + posts[i].pid + '">' +
'<p>' +
posts[i].content +
'</p>' +
'<p class="meta"><strong>' + posts[i].username + '</strong></span> -<span class="timeago" title="' + posts[i].relativeTime + '"></span></p>' +
'</a>';
frag.appendChild(li.cloneNode(true));
recent_replies.appendChild(frag);
}
$('#category_recent_replies span.timeago').timeago();
});
}
ajaxify.register_events([
'event:new_topic'
]);
$(window).off('scroll').on('scroll', function (ev) {
var bottom = ($(document).height() - $(window).height()) * 0.9;
function onNewTopic(data) {
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
Category.loadMoreTopics(cid);
}
});
};
Category.onNewTopic = function(data) {
var html = templates.prepare(templates['category'].blocks['topics']).parse({
topics: [data]
}),
@ -64,40 +109,7 @@
$('#topics-container span.timeago').timeago();
}
socket.on('event:new_topic', onNewTopic);
socket.emit('api:categories.getRecentReplies', cid);
socket.on('api:categories.getRecentReplies', function (posts) {
if (!posts || posts.length === 0) {
return;
}
var recent_replies = document.getElementById('category_recent_replies');
recent_replies.innerHTML = '';
var frag = document.createDocumentFragment(),
li = document.createElement('li');
for (var i = 0, numPosts = posts.length; i < numPosts; i++) {
li.setAttribute('data-pid', posts[i].pid);
li.innerHTML = '<a href="/user/' + posts[i].userslug + '"><img title="' + posts[i].username + '" style="width: 48px; height: 48px; /*temporary*/" class="img-rounded" src="' + posts[i].picture + '" class="" /></a>' +
'<a href="/topic/' + posts[i].topicSlug + '#' + posts[i].pid + '">' +
'<p>' +
posts[i].content +
'</p>' +
'<p class="meta"><strong>' + posts[i].username + '</strong></span> -<span class="timeago" title="' + posts[i].relativeTime + '"></span></p>' +
'</a>';
frag.appendChild(li.cloneNode(true));
recent_replies.appendChild(frag);
}
$('#category_recent_replies span.timeago').timeago();
});
function onTopicsLoaded(topics) {
Category.onTopicsLoaded = function(topics) {
var html = templates.prepare(templates['category'].blocks['topics']).parse({
topics: topics
@ -113,26 +125,18 @@
}
function loadMoreTopics(cid) {
Category.loadMoreTopics = function(cid) {
loadingMoreTopics = true;
socket.emit('api:category.loadMore', {
cid: cid,
after: $('#topics-container').children().length
}, function (data) {
if (data.topics.length) {
onTopicsLoaded(data.topics);
Category.onTopicsLoaded(data.topics);
}
loadingMoreTopics = false;
});
}
$(window).off('scroll').on('scroll', function (ev) {
var bottom = ($(document).height() - $(window).height()) * 0.9;
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
loadMoreTopics(cid);
}
});
})();
return Category;
});

@ -1,7 +1,13 @@
(function() {
$(document).ready(function() {
define(['forum/accountheader'], function(header) {
var AccountHeader = {};
AccountHeader.init = function() {
header.init();
$('.user-favourite-posts .topic-row').on('click', function() {
ajaxify.go($(this).attr('topic-url'));
});
});
}());
};
return AccountHeader;
});

@ -1,18 +1,20 @@
(function() {
define(['forum/accountheader'], function(header) {
var Followers = {};
var yourid = templates.get('yourid'),
theirid = templates.get('theirid'),
followersCount = templates.get('followersCount');
Followers.init = function() {
header.init();
$(document).ready(function() {
var yourid = templates.get('yourid'),
theirid = templates.get('theirid'),
followersCount = templates.get('followersCount');
if (parseInt(followersCount, 10) === 0) {
$('#no-followers-notice').removeClass('hide');
}
app.addCommasToNumbers();
});
if (parseInt(followersCount, 10) === 0) {
$('#no-followers-notice').removeClass('hide');
}
app.addCommasToNumbers();
};
}());
return Followers;
});

@ -1,10 +1,12 @@
(function() {
define(['forum/accountheader'], function(header) {
var Following = {};
var yourid = templates.get('yourid'),
theirid = templates.get('theirid'),
followingCount = templates.get('followingCount');
Following.init = function() {
header.init();
$(document).ready(function() {
var yourid = templates.get('yourid'),
theirid = templates.get('theirid'),
followingCount = templates.get('followingCount');
if (parseInt(followingCount, 10) === 0) {
$('#no-following-notice').removeClass('hide');
@ -34,7 +36,7 @@
}
app.addCommasToNumbers();
});
};
}());
return Following;
});

@ -1,60 +1,66 @@
(function() {
// Alternate Logins
var altLoginEl = document.querySelector('.alt-logins');
altLoginEl.addEventListener('click', function(e) {
var target;
switch (e.target.nodeName) {
case 'LI':
target = e.target;
break;
case 'I':
target = e.target.parentNode;
break;
}
if (target) {
document.location.href = target.getAttribute('data-url');
}
});
$('#login').on('click', function() {
var loginData = {
'username': $('#username').val(),
'password': $('#password').val(),
'_csrf': $('#csrf-token').val()
};
$.ajax({
type: "POST",
url: RELATIVE_PATH + '/login',
data: loginData,
success: function(data, textStatus, jqXHR) {
if (!data.success) {
define(function() {
var Login = {};
Login.init = function() {
// Alternate Logins
var altLoginEl = document.querySelector('.alt-logins');
altLoginEl.addEventListener('click', function(e) {
var target;
switch (e.target.nodeName) {
case 'LI':
target = e.target;
break;
case 'I':
target = e.target.parentNode;
break;
}
if (target) {
document.location.href = target.getAttribute('data-url');
}
});
$('#login').on('click', function() {
var loginData = {
'username': $('#username').val(),
'password': $('#password').val(),
'_csrf': $('#csrf-token').val()
};
$.ajax({
type: "POST",
url: RELATIVE_PATH + '/login',
data: loginData,
success: function(data, textStatus, jqXHR) {
if (!data.success) {
$('#login-error-notify').show();
} else {
$('#login-error-notify').hide();
if(app.previousUrl.indexOf('/reset/') != -1)
window.location.replace(RELATIVE_PATH + "/?loggedin");
else
window.location.replace(app.previousUrl + "?loggedin");
app.loadConfig();
}
},
error: function(data, textStatus, jqXHR) {
$('#login-error-notify').show();
} else {
$('#login-error-notify').hide();
if(app.previousUrl.indexOf('/reset/') != -1)
window.location.replace(RELATIVE_PATH + "/?loggedin");
else
window.location.replace(app.previousUrl + "?loggedin");
app.loadConfig();
}
},
error: function(data, textStatus, jqXHR) {
$('#login-error-notify').show();
},
dataType: 'json',
async: true,
timeout: 2000
},
dataType: 'json',
async: true,
timeout: 2000
});
return false;
});
return false;
});
$('#login-error-notify button').on('click', function() {
$('#login-error-notify').hide();
return false;
});
$('#login-error-notify button').on('click', function() {
$('#login-error-notify').hide();
return false;
});
document.querySelector('#content input').focus();
};
document.querySelector('#content input').focus();
}());
return Login;
});

@ -1,40 +1,56 @@
(function() {
var loadingMoreTopics = false;
define(function() {
var Recent = {};
app.enter_room('recent_posts');
Recent.newTopicCount = 0;
Recent.newPostCount = 0;
Recent.loadingMoreTopics = false;
ajaxify.register_events([
'event:new_topic',
'event:new_post'
]);
Recent.init = function() {
app.enter_room('recent_posts');
var newTopicCount = 0,
newPostCount = 0;
ajaxify.register_events([
'event:new_topic',
'event:new_post'
]);
$('#new-topics-alert').on('click', function() {
$(this).hide();
});
$('#new-topics-alert').on('click', function() {
$(this).hide();
});
socket.on('event:new_topic', function(data) {
++Recent.newTopicCount;
Recent.updateAlertText();
socket.on('event:new_topic', function(data) {
});
socket.on('event:new_post', function(data) {
++Recent.newPostCount;
Recent.updateAlertText();
});
++newTopicCount;
updateAlertText();
$(window).off('scroll').on('scroll', function() {
var bottom = ($(document).height() - $(window).height()) * 0.9;
});
if ($(window).scrollTop() > bottom && !Recent.loadingMoreTopics) {
Recent.loadMoreTopics();
}
});
};
function updateAlertText() {
Recent.updateAlertText = function() {
var text = '';
if (newTopicCount > 1)
text = 'There are ' + newTopicCount + ' new topics';
else if (newTopicCount === 1)
if (Recent.newTopicCount > 1)
text = 'There are ' + Recent.newTopicCount + ' new topics';
else if (Recent.newTopicCount === 1)
text = 'There is 1 new topic';
else
text = 'There are no new topics';
if (newPostCount > 1)
text += ' and ' + newPostCount + ' new posts.';
else if (newPostCount === 1)
if (Recent.newPostCount > 1)
text += ' and ' + Recent.newPostCount + ' new posts.';
else if (Recent.newPostCount === 1)
text += ' and 1 new post.';
else
text += ' and no new posts.';
@ -44,12 +60,7 @@
$('#new-topics-alert').html(text).fadeIn('slow');
}
socket.on('event:new_post', function(data) {
++newPostCount;
updateAlertText();
});
function onTopicsLoaded(topics) {
Recent.onTopicsLoaded = function(topics) {
var html = templates.prepare(templates['recent'].blocks['topics']).parse({
topics: topics
@ -61,25 +72,17 @@
container.append(html);
}
function loadMoreTopics() {
loadingMoreTopics = true;
Recent.loadMoreTopics = function() {
Recent.loadingMoreTopics = true;
socket.emit('api:topics.loadMoreRecentTopics', {
after: $('#topics-container').children().length
}, function(data) {
if (data.topics && data.topics.length) {
onTopicsLoaded(data.topics);
Recent.onTopicsLoaded(data.topics);
}
loadingMoreTopics = false;
Recent.loadingMoreTopics = false;
});
}
$(window).off('scroll').on('scroll', function() {
var bottom = ($(document).height() - $(window).height()) * 0.9;
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
loadMoreTopics();
}
});
})();
return Recent;
});

@ -1,154 +1,159 @@
(function() {
var username = $('#username'),
password = $('#password'),
password_confirm = $('#password-confirm'),
register = $('#register'),
emailEl = $('#email'),
username_notify = $('#username-notify'),
email_notify = $('#email-notify'),
password_notify = $('#password-notify'),
password_confirm_notify = $('#password-confirm-notify'),
validationError = false,
successIcon = '<i class="icon icon-ok"></i>';
$('#referrer').val(app.previousUrl);
function showError(element, msg) {
element.html(msg);
element.parent()
.removeClass('alert-success')
.addClass('alert-danger');
element.show();
validationError = true;
}
function showSuccess(element, msg) {
element.html(msg);
element.parent()
.removeClass('alert-danger')
.addClass('alert-success');
element.show();
}
function validateEmail() {
if (!emailEl.val()) {
define(function() {
var Register = {};
Register.init = function() {
var username = $('#username'),
password = $('#password'),
password_confirm = $('#password-confirm'),
register = $('#register'),
emailEl = $('#email'),
username_notify = $('#username-notify'),
email_notify = $('#email-notify'),
password_notify = $('#password-notify'),
password_confirm_notify = $('#password-confirm-notify'),
validationError = false,
successIcon = '<i class="icon icon-ok"></i>';
$('#referrer').val(app.previousUrl);
function showError(element, msg) {
element.html(msg);
element.parent()
.removeClass('alert-success')
.addClass('alert-danger');
element.show();
validationError = true;
return;
}
if (!utils.isEmailValid(emailEl.val())) {
showError(email_notify, 'Invalid email address.');
} else
socket.emit('user.email.exists', {
email: emailEl.val()
});
}
emailEl.on('blur', function() {
validateEmail();
});
function validateUsername() {
if (!username.val()) {
validationError = true;
return;
}
if (username.val().length < config.minimumUsernameLength) {
showError(username_notify, 'Username too short!');
} else if (username.val().length > config.maximumUsernameLength) {
showError(username_notify, 'Username too long!');
} else if (!utils.isUserNameValid(username.val())) {
showError(username_notify, 'Invalid username!');
} else {
socket.emit('user.exists', {
username: username.val()
});
}
}
username.on('keyup', function() {
jQuery('#yourUsername').html(this.value.length > 0 ? this.value : 'username');
});
username.on('blur', function() {
validateUsername();
});
function validatePassword() {
if (!password.val()) {
validationError = true;
return;
}
if (password.val().length < config.minimumPasswordLength) {
showError(password_notify, 'Password too short!');
} else if (!utils.isPasswordValid(password.val())) {
showError(password_notify, 'Invalid password!');
} else {
showSuccess(password_notify, successIcon);
function showSuccess(element, msg) {
element.html(msg);
element.parent()
.removeClass('alert-danger')
.addClass('alert-success');
element.show();
}
if (password.val() !== password_confirm.val() && password_confirm.val() !== '') {
showError(password_confirm_notify, 'Passwords must match!');
function validateEmail() {
if (!emailEl.val()) {
validationError = true;
return;
}
if (!utils.isEmailValid(emailEl.val())) {
showError(email_notify, 'Invalid email address.');
} else
socket.emit('user.email.exists', {
email: emailEl.val()
});
}
}
$(password).on('blur', function() {
validatePassword();
});
function validatePasswordConfirm() {
if (!password.val() || password_notify.hasClass('alert-error')) {
return;
emailEl.on('blur', function() {
validateEmail();
});
function validateUsername() {
if (!username.val()) {
validationError = true;
return;
}
if (username.val().length < config.minimumUsernameLength) {
showError(username_notify, 'Username too short!');
} else if (username.val().length > config.maximumUsernameLength) {
showError(username_notify, 'Username too long!');
} else if (!utils.isUserNameValid(username.val())) {
showError(username_notify, 'Invalid username!');
} else {
socket.emit('user.exists', {
username: username.val()
});
}
}
if (password.val() !== password_confirm.val()) {
showError(password_confirm_notify, 'Passwords must match!');
} else {
showSuccess(password_confirm_notify, successIcon);
username.on('keyup', function() {
jQuery('#yourUsername').html(this.value.length > 0 ? this.value : 'username');
});
username.on('blur', function() {
validateUsername();
});
function validatePassword() {
if (!password.val()) {
validationError = true;
return;
}
if (password.val().length < config.minimumPasswordLength) {
showError(password_notify, 'Password too short!');
} else if (!utils.isPasswordValid(password.val())) {
showError(password_notify, 'Invalid password!');
} else {
showSuccess(password_notify, successIcon);
}
if (password.val() !== password_confirm.val() && password_confirm.val() !== '') {
showError(password_confirm_notify, 'Passwords must match!');
}
}
}
$(password_confirm).on('blur', function() {
validatePasswordConfirm();
});
$(password).on('blur', function() {
validatePassword();
});
ajaxify.register_events(['user.exists', 'user.email.exists']);
function validatePasswordConfirm() {
if (!password.val() || password_notify.hasClass('alert-error')) {
return;
}
socket.on('user.exists', function(data) {
if (data.exists === true) {
showError(username_notify, 'Username already taken!');
} else {
showSuccess(username_notify, successIcon);
if (password.val() !== password_confirm.val()) {
showError(password_confirm_notify, 'Passwords must match!');
} else {
showSuccess(password_confirm_notify, successIcon);
}
}
});
socket.on('user.email.exists', function(data) {
if (data.exists === true) {
showError(email_notify, 'Email address already taken!');
} else {
showSuccess(email_notify, successIcon);
$(password_confirm).on('blur', function() {
validatePasswordConfirm();
});
ajaxify.register_events(['user.exists', 'user.email.exists']);
socket.on('user.exists', function(data) {
if (data.exists === true) {
showError(username_notify, 'Username already taken!');
} else {
showSuccess(username_notify, successIcon);
}
});
socket.on('user.email.exists', function(data) {
if (data.exists === true) {
showError(email_notify, 'Email address already taken!');
} else {
showSuccess(email_notify, successIcon);
}
});
// Alternate Logins
$('.alt-logins li').on('click', function(e) {
document.location.href = $(this).attr('data-url');
});
function validateForm() {
validationError = false;
validateEmail();
validateUsername();
validatePassword();
validatePasswordConfirm();
return validationError;
}
});
// Alternate Logins
$('.alt-logins li').on('click', function(e) {
document.location.href = $(this).attr('data-url');
});
function validateForm() {
validationError = false;
validateEmail();
validateUsername();
validatePassword();
validatePasswordConfirm();
return validationError;
}
register.on('click', function(e) {
if (validateForm()) e.preventDefault();
});
register.on('click', function(e) {
if (validateForm()) e.preventDefault();
});
};
}());
return Register;
});

@ -1,41 +1,47 @@
(function() {
var inputEl = document.getElementById('email'),
errorEl = document.getElementById('error'),
errorTextEl = errorEl.querySelector('p');
define(function() {
var ResetPassword = {};
document.getElementById('reset').onclick = function() {
if (inputEl.value.length > 0 && inputEl.value.indexOf('@') !== -1) {
socket.emit('user:reset.send', {
email: inputEl.value
});
} else {
jQuery('#success').hide();
jQuery(errorEl).show();
errorTextEl.innerHTML = 'Please enter a valid email';
}
};
ResetPassword.init = function() {
var inputEl = document.getElementById('email'),
errorEl = document.getElementById('error'),
errorTextEl = errorEl.querySelector('p');
document.getElementById('reset').onclick = function() {
if (inputEl.value.length > 0 && inputEl.value.indexOf('@') !== -1) {
socket.emit('user:reset.send', {
email: inputEl.value
});
} else {
jQuery('#success').hide();
jQuery(errorEl).show();
errorTextEl.innerHTML = 'Please enter a valid email';
}
};
ajaxify.register_events(['user.send_reset']);
ajaxify.register_events(['user.send_reset']);
socket.on('user.send_reset', function(data) {
var submitEl = document.getElementById('reset');
socket.on('user.send_reset', function(data) {
var submitEl = document.getElementById('reset');
if (data.status === 'ok') {
jQuery('#error').hide();
jQuery('#success').show();
jQuery('#success p').html('An email has been dispatched to "' + data.email + '" with instructions on setting a new password.');
inputEl.value = '';
} else {
jQuery('#success').hide();
jQuery(errorEl).show();
switch (data.message) {
case 'invalid-email':
errorTextEl.innerHTML = 'The email you put in (<span>' + data.email + '</span>) is not registered with us. Please try again.';
break;
case 'send-failed':
errorTextEl.innerHTML = 'There was a problem sending the reset code. Please try again later.';
break;
if (data.status === 'ok') {
jQuery('#error').hide();
jQuery('#success').show();
jQuery('#success p').html('An email has been dispatched to "' + data.email + '" with instructions on setting a new password.');
inputEl.value = '';
} else {
jQuery('#success').hide();
jQuery(errorEl).show();
switch (data.message) {
case 'invalid-email':
errorTextEl.innerHTML = 'The email you put in (<span>' + data.email + '</span>) is not registered with us. Please try again.';
break;
case 'send-failed':
errorTextEl.innerHTML = 'There was a problem sending the reset code. Please try again later.';
break;
}
}
}
});
}());
});
};
return ResetPassword;
});

@ -1,52 +1,58 @@
(function() {
var reset_code = templates.get('reset_code');
var resetEl = document.getElementById('reset'),
password = document.getElementById('password'),
repeat = document.getElementById('repeat'),
noticeEl = document.getElementById('notice');
resetEl.addEventListener('click', function() {
if (password.value.length < 6) {
$('#error').hide();
noticeEl.querySelector('strong').innerHTML = 'Invalid Password';
noticeEl.querySelector('p').innerHTML = 'The password entered is too short, please pick a different password.';
noticeEl.style.display = 'block';
} else if (password.value !== repeat.value) {
$('#error').hide();
noticeEl.querySelector('strong').innerHTML = 'Invalid Password';
noticeEl.querySelector('p').innerHTML = 'The two passwords you\'ve entered do not match.';
noticeEl.style.display = 'block';
} else {
socket.emit('user:reset.commit', {
code: reset_code,
password: password.value
});
}
}, false);
// Enable the form if the code is valid
socket.emit('user:reset.valid', {
code: reset_code
});
ajaxify.register_events(['user:reset.valid', 'user:reset.commit']);
socket.on('user:reset.valid', function(data) {
if ( !! data.valid) resetEl.disabled = false;
else {
var formEl = document.getElementById('reset-form');
// Show error message
$('#error').show();
formEl.parentNode.removeChild(formEl);
}
})
socket.on('user:reset.commit', function(data) {
if (data.status === 'ok') {
$('#error').hide();
$('#notice').hide();
$('#success').show();
}
});
}());
define(function() {
var ResetCode = {};
ResetCode.init = function() {
var reset_code = templates.get('reset_code');
var resetEl = document.getElementById('reset'),
password = document.getElementById('password'),
repeat = document.getElementById('repeat'),
noticeEl = document.getElementById('notice');
resetEl.addEventListener('click', function() {
if (password.value.length < 6) {
$('#error').hide();
noticeEl.querySelector('strong').innerHTML = 'Invalid Password';
noticeEl.querySelector('p').innerHTML = 'The password entered is too short, please pick a different password.';
noticeEl.style.display = 'block';
} else if (password.value !== repeat.value) {
$('#error').hide();
noticeEl.querySelector('strong').innerHTML = 'Invalid Password';
noticeEl.querySelector('p').innerHTML = 'The two passwords you\'ve entered do not match.';
noticeEl.style.display = 'block';
} else {
socket.emit('user:reset.commit', {
code: reset_code,
password: password.value
});
}
}, false);
// Enable the form if the code is valid
socket.emit('user:reset.valid', {
code: reset_code
});
ajaxify.register_events(['user:reset.valid', 'user:reset.commit']);
socket.on('user:reset.valid', function(data) {
if ( !! data.valid) resetEl.disabled = false;
else {
var formEl = document.getElementById('reset-form');
// Show error message
$('#error').show();
formEl.parentNode.removeChild(formEl);
}
})
socket.on('user:reset.commit', function(data) {
if (data.status === 'ok') {
$('#error').hide();
$('#notice').hide();
$('#success').show();
}
});
};
return ResetCode;
});

@ -1,6 +1,7 @@
(function() {
define(function() {
var Search = {};
$(document).ready(function() {
Search.init = function() {
var searchQuery = $('#topics-container').attr('data-search-query');
$('.search-result-text').each(function() {
@ -21,4 +22,5 @@
});
});
})();
return Search;
});

File diff suppressed because it is too large Load Diff

@ -1,114 +1,119 @@
(function() {
var loadingMoreTopics = false;
app.enter_room('recent_posts');
ajaxify.register_events([
'event:new_topic',
'event:new_post'
]);
var newTopicCount = 0,
newPostCount = 0;
$('#new-topics-alert').on('click', function() {
$(this).hide();
});
socket.on('event:new_topic', function(data) {
++newTopicCount;
updateAlertText();
});
function updateAlertText() {
var text = '';
if (newTopicCount > 1)
text = 'There are ' + newTopicCount + ' new topics';
else if (newTopicCount === 1)
text = 'There is 1 new topic';
else
text = 'There are no new topics';
if (newPostCount > 1)
text += ' and ' + newPostCount + ' new posts.';
else if (newPostCount === 1)
text += ' and 1 new post.';
else
text += ' and no new posts.';
text += ' Click here to reload.';
$('#new-topics-alert').html(text).fadeIn('slow');
}
socket.on('event:new_post', function(data) {
++newPostCount;
updateAlertText();
});
$('#mark-allread-btn').on('click', function() {
var btn = $(this);
socket.emit('api:topics.markAllRead', {}, function(success) {
if (success) {
btn.remove();
$('#topics-container').empty();
$('#category-no-topics').removeClass('hidden');
app.alertSuccess('All topics marked as read!');
$('#numUnreadBadge')
.removeClass('badge-important')
.addClass('badge-inverse')
.html('0');
} else {
app.alertError('There was an error marking topics read!');
}
define(function() {
var Unread = {};
Unread.init = function() {
var loadingMoreTopics = false;
app.enter_room('recent_posts');
ajaxify.register_events([
'event:new_topic',
'event:new_post'
]);
var newTopicCount = 0,
newPostCount = 0;
$('#new-topics-alert').on('click', function() {
$(this).hide();
});
});
function onTopicsLoaded(topics) {
var html = templates.prepare(templates['unread'].blocks['topics']).parse({
topics: topics
}),
container = $('#topics-container');
$('#category-no-topics').remove();
container.append(html);
}
function loadMoreTopics() {
loadingMoreTopics = true;
socket.emit('api:topics.loadMoreUnreadTopics', {
after: parseInt($('#topics-container').attr('data-next-start'), 10)
}, function(data) {
if (data.topics && data.topics.length) {
onTopicsLoaded(data.topics);
$('#topics-container').attr('data-next-start', data.nextStart);
} else {
$('#load-more-btn').hide();
}
loadingMoreTopics = false;
socket.on('event:new_topic', function(data) {
++newTopicCount;
updateAlertText();
});
}
$(window).off('scroll').on('scroll', function() {
var bottom = ($(document).height() - $(window).height()) * 0.9;
function updateAlertText() {
var text = '';
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
loadMoreTopics();
if (newTopicCount > 1)
text = 'There are ' + newTopicCount + ' new topics';
else if (newTopicCount === 1)
text = 'There is 1 new topic';
else
text = 'There are no new topics';
if (newPostCount > 1)
text += ' and ' + newPostCount + ' new posts.';
else if (newPostCount === 1)
text += ' and 1 new post.';
else
text += ' and no new posts.';
text += ' Click here to reload.';
$('#new-topics-alert').html(text).fadeIn('slow');
}
socket.on('event:new_post', function(data) {
++newPostCount;
updateAlertText();
});
$('#mark-allread-btn').on('click', function() {
var btn = $(this);
socket.emit('api:topics.markAllRead', {}, function(success) {
if (success) {
btn.remove();
$('#topics-container').empty();
$('#category-no-topics').removeClass('hidden');
app.alertSuccess('All topics marked as read!');
$('#numUnreadBadge')
.removeClass('badge-important')
.addClass('badge-inverse')
.html('0');
} else {
app.alertError('There was an error marking topics read!');
}
});
});
function onTopicsLoaded(topics) {
var html = templates.prepare(templates['unread'].blocks['topics']).parse({
topics: topics
}),
container = $('#topics-container');
$('#category-no-topics').remove();
container.append(html);
}
});
function loadMoreTopics() {
loadingMoreTopics = true;
socket.emit('api:topics.loadMoreUnreadTopics', {
after: parseInt($('#topics-container').attr('data-next-start'), 10)
}, function(data) {
if (data.topics && data.topics.length) {
onTopicsLoaded(data.topics);
$('#topics-container').attr('data-next-start', data.nextStart);
} else {
$('#load-more-btn').hide();
}
loadingMoreTopics = false;
});
}
if ($("body").height() <= $(window).height() && $('#topics-container').children().length >= 20)
$('#load-more-btn').show();
$(window).off('scroll').on('scroll', function() {
var bottom = ($(document).height() - $(window).height()) * 0.9;
$('#load-more-btn').on('click', function() {
loadMoreTopics();
});
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
loadMoreTopics();
}
});
if ($("body").height() <= $(window).height() && $('#topics-container').children().length >= 20)
$('#load-more-btn').show();
$('#load-more-btn').on('click', function() {
loadMoreTopics();
});
};
})();
return Unread;
});

@ -1,6 +1,7 @@
(function() {
define(function() {
var Users = {};
$(document).ready(function() {
Users.init = function() {
var timeoutId = 0;
var loadingMoreUsers = false;
@ -131,6 +132,7 @@
loadMoreUsers();
}
});
});
};
}());
return Users;
});

@ -97,7 +97,4 @@
<input type="hidden" template-variable="yourid" value="{yourid}" />
<input type="hidden" template-variable="theirid" value="{theirid}" />
<input type="hidden" template-type="boolean" template-variable="isFollowing" value="{isFollowing}" />
<script type="text/javascript" src="{relative_path}/src/forum/account.js"></script>
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
<input type="hidden" template-type="boolean" template-variable="isFollowing" value="{isFollowing}" />

@ -174,9 +174,3 @@
</div>
</div>
<input type="hidden" template-variable="gravatarpicture" value="{gravatarpicture}" />
<input type="hidden" template-variable="uploadedpicture" value="{uploadedpicture}" />
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
<script type="text/javascript" src="{relative_path}/src/forum/accountedit.js"></script>

@ -26,6 +26,3 @@
<a id="submitBtn" href="#" class="btn btn-primary">Save changes</a>
</div>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
<script type="text/javascript" src="{relative_path}/src/forum/accountsettings.js"></script>

@ -101,5 +101,3 @@
<div class="col-md-3"><i class="icon-adn"></i></div><div class="col-md-3"><i class="icon-android"></i></div><div class="col-md-3"><i class="icon-apple"></i></div><div class="col-md-3"><i class="icon-bitbucket"></i></div><div class="col-md-3"><i class="icon-bitbucket-sign"></i></div><div class="col-md-3"><i class="icon-bitcoin"></i></div><div class="col-md-3"><i class="icon-btc"></i></div><div class="col-md-3"><i class="icon-css3"></i></div><div class="col-md-3"><i class="icon-dribbble"></i></div><div class="col-md-3"><i class="icon-dropbox"></i></div><div class="col-md-3"><i class="icon-facebook"></i></div><div class="col-md-3"><i class="icon-facebook-sign"></i></div><div class="col-md-3"><i class="icon-flickr"></i></div><div class="col-md-3"><i class="icon-foursquare"></i></div><div class="col-md-3"><i class="icon-github"></i></div><div class="col-md-3"><i class="icon-github-alt"></i></div><div class="col-md-3"><i class="icon-github-sign"></i></div><div class="col-md-3"><i class="icon-gittip"></i></div><div class="col-md-3"><i class="icon-google-plus"></i></div><div class="col-md-3"><i class="icon-google-plus-sign"></i></div><div class="col-md-3"><i class="icon-html5"></i></div><div class="col-md-3"><i class="icon-instagram"></i></div><div class="col-md-3"><i class="icon-linkedin"></i></div><div class="col-md-3"><i class="icon-linkedin-sign"></i></div><div class="col-md-3"><i class="icon-linux"></i></div><div class="col-md-3"><i class="icon-maxcdn"></i></div><div class="col-md-3"><i class="icon-pinterest"></i></div><div class="col-md-3"><i class="icon-pinterest-sign"></i></div><div class="col-md-3"><i class="icon-renren"></i></div><div class="col-md-3"><i class="icon-skype"></i></div><div class="col-md-3"><i class="icon-stackexchange"></i></div><div class="col-md-3"><i class="icon-trello"></i></div><div class="col-md-3"><i class="icon-tumblr"></i></div><div class="col-md-3"><i class="icon-tumblr-sign"></i></div><div class="col-md-3"><i class="icon-twitter"></i></div><div class="col-md-3"><i class="icon-twitter-sign"></i></div><div class="col-md-3"><i class="icon-vk"></i></div><div class="col-md-3"><i class="icon-weibo"></i></div><div class="col-md-3"><i class="icon-windows"></i></div><div class="col-md-3"><i class="icon-xing"></i></div><div class="col-md-3"><i class="icon-xing-sign"></i></div><div class="col-md-3"><i class="icon-youtube"></i></div><div class="col-md-3"><i class="icon-youtube-play"></i></div><div class="col-md-3"><i class="icon-youtube-sign"></i></div>
<div class="col-md-3"><i class="icon-ambulance"></i></div><div class="col-md-3"><i class="icon-h-sign"></i></div><div class="col-md-3"><i class="icon-hospital"></i></div><div class="col-md-3"><i class="icon-medkit"></i></div><div class="col-md-3"><i class="icon-plus-sign-alt"></i></div><div class="col-md-3"><i class="icon-stethoscope"></i></div><div class="col-md-3"><i class="icon-user-md"></i></div>
</div></div></div>
<script type="text/javascript" src="{relative_path}/src/forum/admin/categories.js"></script>

@ -17,10 +17,7 @@
<button class="btn btn-lg btn-primary" id="save">Save</button>
<script>
var loadDelay = setInterval(function() {
if (nodebb_admin) {
nodebb_admin.prepare();
clearInterval(loadDelay);
}
}, 500);
require(['forum/admin/settings'], function(Settings) {
Settings.prepare();
});
</script>

@ -9,7 +9,7 @@
</div>
<script type="text/javascript">
$.getScript(RELATIVE_PATH + '/src/forum/admin/footer.js');
require(['forum/admin/footer']);
</script>
</body>

@ -17,10 +17,7 @@
<button class="btn btn-lg btn-primary" id="save">Save</button>
<script>
var loadDelay = setInterval(function() {
if (nodebb_admin) {
nodebb_admin.prepare();
clearInterval(loadDelay);
}
}, 500);
require(['forum/admin/settings'], function(Settings) {
Settings.prepare();
});
</script>

@ -96,5 +96,3 @@
</div>
</div>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/admin/groups.js"></script>

@ -7,7 +7,6 @@
var RELATIVE_PATH = "{relative_path}";
</script>
<link id="base-theme" href="{relative_path}/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="{relative_path}/vendor/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet" media="screen">
<link rel="stylesheet" href="{relative_path}/vendor/fontawesome/css/font-awesome.min.css">
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript" src="{relative_path}/vendor/bootstrap/js/bootstrap.min.js"></script>
@ -25,7 +24,10 @@
<script>
require.config({
baseUrl: "{relative_path}/src/modules",
waitSeconds: 3
waitSeconds: 3,
paths: {
"forum": '../forum'
}
});
</script>
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">

@ -18,5 +18,3 @@
</p>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/admin/index.js"></script>

@ -24,10 +24,7 @@
<button class="btn btn-lg btn-primary" id="save" checked>Save</button>
<script>
var loadDelay = setInterval(function() {
if (nodebb_admin) {
nodebb_admin.prepare();
clearInterval(loadDelay);
}
}, 500);
require(['forum/admin/settings'], function(Settings) {
Settings.prepare();
});
</script>

@ -21,5 +21,3 @@
Full documentation regarding plugin authoring can be found in the <a target="_blank" href="https://github.com/designcreateplay/NodeBB/wiki/Writing-Plugins-for-NodeBB">NodeBB Wiki</a>.
</p>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/admin/plugins.js"></script>

@ -83,10 +83,7 @@
<button class="btn btn-lg btn-primary" id="save">Save</button>
<script>
var loadDelay = setInterval(function() {
if (nodebb_admin) {
nodebb_admin.prepare();
clearInterval(loadDelay);
}
}, 500);
require(['forum/admin/settings'], function(Settings) {
Settings.prepare();
});
</script>

@ -23,4 +23,10 @@
<button class="btn btn-warning" id="revert_theme">Revert</button> This will remove any custom theme applied to your NodeBB, and restore the base theme.
</p>
<script type="text/javascript" src="{relative_path}/src/forum/admin/themes.js"></script>
<script>
var bootswatchListener = function(data) {
require(['forum/admin/themes'], function(t) {
t.render(data);
});
}
</script>

@ -22,5 +22,3 @@
<div class="text-center">
<button id="topics_loadmore" class="btn btn-primary btn-lg">Load More Topics</button>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/admin/topics.js"></script>

@ -17,10 +17,7 @@
<button class="btn btn-lg btn-primary" id="save">Save</button>
<script>
var loadDelay = setInterval(function() {
if (nodebb_admin) {
nodebb_admin.prepare();
clearInterval(loadDelay);
}
}, 500);
require(['forum/admin/settings'], function(Settings) {
Settings.prepare();
});
</script>

@ -42,6 +42,3 @@
<button id="load-more-users-btn" class="btn btn-primary">Load More</button>
</div>
<input type="hidden" template-variable="yourid" value="{yourid}" />
<script type="text/javascript" src="{relative_path}/src/forum/admin/users.js"></script>

@ -96,6 +96,4 @@
<input type="hidden" template-variable="category_id" value="{category_id}" />
<input type="hidden" template-variable="twitter-intent-url" value="{twitter-intent-url}" />
<input type="hidden" template-variable="facebook-share-url" value="{facebook-share-url}" />
<input type="hidden" template-variable="google-share-url" value="{google-share-url}" />
<script type="text/javascript" src="{relative_path}/src/forum/category.js"></script>
<input type="hidden" template-variable="google-share-url" value="{google-share-url}" />

@ -22,6 +22,3 @@
</div>
</div>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
<script type="text/javascript" src="{relative_path}/src/forum/favourites.js"></script>

@ -34,6 +34,3 @@
<input type="hidden" template-variable="yourid" value="{yourid}" />
<input type="hidden" template-variable="theirid" value="{theirid}" />
<input type="hidden" template-variable="followersCount" value="{followersCount}" />
<script type="text/javascript" src="{relative_path}/src/forum/followers.js"></script>
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>

@ -35,6 +35,3 @@
<input type="hidden" template-variable="yourid" value="{yourid}" />
<input type="hidden" template-variable="theirid" value="{theirid}" />
<input type="hidden" template-variable="followingCount" value="{followingCount}" />
<script type="text/javascript" src="{relative_path}/src/forum/following.js"></script>
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>

@ -53,7 +53,7 @@
</footer>
<script>
$.getScript(RELATIVE_PATH + '/src/forum/footer.js');
require(['forum/footer']);
</script>
</body>

@ -15,8 +15,14 @@
<script>
require.config({
baseUrl: "{relative_path}/src/modules",
waitSeconds: 3
waitSeconds: 3,
paths: {
"forum": '../forum'
}
});
requirejs.onError = function(err) {
console.log(err);
}
</script>
<link rel="stylesheet" type="text/css" href="{relative_path}/css/nodebb.css" />

@ -60,5 +60,3 @@
</div>
</div>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/login.js"></script>

@ -49,5 +49,3 @@
</ul>
</div>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/recent.js"></script>

@ -80,5 +80,3 @@
</div>
</div>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/register.js"></script>

@ -26,5 +26,3 @@
<button class="btn btn-primary btn-block btn-lg" id="reset" type="submit">Reset Password</button>
</form>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/reset.js"></script>

@ -34,6 +34,3 @@
</form>
</div>
<input type="hidden" template-variable="reset_code" value="{reset_code}" />
<script type="text/javascript" src="{relative_path}/src/forum/reset_code.js"></script>

@ -53,5 +53,3 @@
</ul>
</div>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/search.js"></script>

@ -199,7 +199,3 @@
<input type="hidden" template-variable="pinned" value="{pinned}" />
<input type="hidden" template-variable="topic_name" value="{topic_name}" />
<input type="hidden" template-variable="postcount" value="{postcount}" />
<script type="text/javascript" src="{relative_path}/src/forum/topic.js"></script>

@ -54,5 +54,3 @@
</div>
</div>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/unread.js"></script>

@ -45,5 +45,3 @@
<button id="load-more-users-btn" class="btn btn-primary">[[users:load_more]]</button>
</div>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/users.js"></script>

@ -135,22 +135,22 @@ var express = require('express'),
app.use(function (req, res, next) {
res.status(404);
// respond with html page
if (req.accepts('html')) {
if (path.dirname(req.url) === '/src/forum') {
// Handle missing client-side scripts
res.type('text/javascript').send(200, '');
} else if (req.accepts('html')) {
// respond with html page
winston.warn('Route requested but not found: ' + req.url);
res.redirect(nconf.get('relative_path') + '/404');
return;
}
// respond with json
if (req.accepts('json')) {
res.send({
} else if (req.accepts('json')) {
// respond with json
res.json({
error: 'Not found'
});
return;
} else {
// default to plain-text. send()
res.type('txt').send('Not found');
}
// default to plain-text. send()
res.type('txt').send('Not found');
});
app.use(function (err, req, res, next) {

Loading…
Cancel
Save