1135 lines
39 KiB
JavaScript
1135 lines
39 KiB
JavaScript
/*****************************************************************************
|
|
* Gossamer Forum - Advanced web community
|
|
*
|
|
* Website : http://gossamer-threads.com/
|
|
* Support : http://gossamer-threads.com/scripts/support/
|
|
* Revision : $Id: gforum.js,v 1.89 2008/11/28 23:47:50 brewt Exp $
|
|
*
|
|
* Copyright (c) 2008 Gossamer Threads Inc. All Rights Reserved.
|
|
* Redistribution in part or in whole strictly prohibited. Please
|
|
* see LICENSE file for full details.
|
|
*****************************************************************************/
|
|
|
|
/**
|
|
* GForum is an object to create a separate name space for GForum javascript
|
|
* functions.
|
|
*
|
|
* Note: all parameters are set in include_common_head.html unless
|
|
* otherwise noted.
|
|
* @param staticUrl url of static build directory, from GForum/Config/Data
|
|
* @param url Base GForum url
|
|
* @param helpText help text for the current element on the page.
|
|
* @param social_media list of social media sites (not display names!)
|
|
* @param user_id the id of the user we want to deal with
|
|
* @param timezone_zones hash containing regions as keys with cities as values
|
|
* @param timezone_default the default timezone to display
|
|
* @param timezone_last_selected
|
|
* @param timezone_error_message message to display if ajax fails
|
|
* @param timezone_loading_message messate to display while loading time
|
|
*/
|
|
function GForum() {
|
|
this.staticUrl = '';
|
|
this.imageUrl = '';
|
|
this.gforum_url = '';
|
|
this.helpText = '';
|
|
// The following two vars get set in 'user_view.html'.
|
|
this.social_media = [];
|
|
this.user_id = '';
|
|
// The following 'timezone' vars are set in 'include_profile_display.html'.
|
|
this.timezone_zones = [];
|
|
this.timezone_default = '';
|
|
this.timezone_last_selected = [];
|
|
this.timezone_error_message = '';
|
|
this.timezone_loading_message = '';
|
|
|
|
this.password_strength_lang = [
|
|
'Weak',
|
|
'Good',
|
|
'Strong'
|
|
];
|
|
this.password_strength_levels = [
|
|
0,
|
|
40,
|
|
70
|
|
];
|
|
}
|
|
|
|
$(document).ready(function() {
|
|
// For the tooltip icon, we want to display a popup box of text
|
|
// further explaining whatever needs explaining. The help text needs
|
|
// to be assigned to the title attribute of the tooltip image.
|
|
$('.tooltip').hover(
|
|
function() {
|
|
var text = $(this).attr('title');
|
|
$(this).attr('title', '');
|
|
var id = $(this).attr('id');
|
|
var newId = id+'_tooltip';
|
|
|
|
// Create an info element after the tooltip icon with the help text
|
|
$('body').prepend('<div class="info" id="'+newId+'">'+text+'</div>');
|
|
GForum.showInfo(id, newId);
|
|
},
|
|
function() {
|
|
// Remove the tooltip text when we stop hovering over the icon
|
|
var id = '#'+$(this).attr('id')+'_tooltip';
|
|
var text = $(id).html();
|
|
$(id).hide().remove();
|
|
$(this).attr('title', text);
|
|
}
|
|
);
|
|
|
|
/*************************************************************************
|
|
* This binding affects the info/info-parent setup.
|
|
* With the info/info-parent setup, clicking on the info-parent causes
|
|
* the info div to become visible. This binding forces the info div to
|
|
* become invisible again if neither that div, nor it's info-parent
|
|
* has been clicked.
|
|
*************************************************************************/
|
|
$(document).bind("click", function(e) {
|
|
var target;
|
|
if (!e) { e = window.event; }
|
|
if (e.target) {
|
|
target = e.target;
|
|
} else if (e.srcElement) {
|
|
target = e.srcElement;
|
|
}
|
|
if (target.nodeType == 3) { // defeat Safari bug
|
|
target = target.parentNode;
|
|
}
|
|
|
|
/* hide all popups unless we've clicked on that div or it's parent */
|
|
if (target.className != 'info' && target.className != 'info-parent') {
|
|
$('.info').each(function() {
|
|
$(this).hide();
|
|
});
|
|
}
|
|
});
|
|
|
|
/*************************************************************************
|
|
* When we click on an item with the 'favourite' class, we submit an ajax
|
|
* request to the server, then we change the child elements in these ways:
|
|
*
|
|
* - update the favourites image icon
|
|
* - update the number of users who've favourited this item
|
|
*
|
|
* Because the ajax request is really simple, we just assume it will
|
|
* work and update the children regardless of the ajax response
|
|
*************************************************************************/
|
|
$(".favourite").click(function() {
|
|
var regex = /(\d+)$/;
|
|
var id = regex.exec($(this).attr('id'))[1];
|
|
|
|
// Get the action to perform
|
|
var action = '';
|
|
var add = 0;
|
|
if ($(this).hasClass('favourite_add')) {
|
|
action = 'add';
|
|
add = 1;
|
|
}
|
|
else {
|
|
action += 'remove';
|
|
add = -1;
|
|
}
|
|
|
|
// Toggle the action class
|
|
$(this).toggleClass('favourite_remove');
|
|
$(this).toggleClass('favourite_add');
|
|
|
|
// Save the favourite to the database
|
|
var url = GForum.url_get({ 'do': 'json_' + action + '_favourite', 'post_id': id });
|
|
$.post(url.url, url.params);
|
|
|
|
// Increase the favourited counter
|
|
var favourite_count_link = $('#favourite_' + id + '_link');
|
|
var favourite_count = parseInt(favourite_count_link.html().substr(1, favourite_count_link.html().length -1), 10) + add;
|
|
favourite_count_link.html('(' + favourite_count + ')');
|
|
|
|
if (favourite_count === 0) {
|
|
favourite_count_link.addClass('hide');
|
|
}
|
|
else {
|
|
favourite_count_link.removeClass('hide');
|
|
}
|
|
|
|
// Replace the favourite image
|
|
var image = $(this).find('img');
|
|
var img_url = image.attr('src');
|
|
var img_title;
|
|
if (action == 'add') {
|
|
img_url = img_url.replace('post-favoff', 'post-favon');
|
|
img_title = 'Remove Favourite';
|
|
}
|
|
else {
|
|
img_url = img_url.replace('post-favon', 'post-favoff');
|
|
img_title = 'Add Favourite';
|
|
}
|
|
image.attr('src', img_url);
|
|
image.attr('title', img_title);
|
|
|
|
return false;
|
|
});
|
|
});
|
|
|
|
GForum.prototype.init_help_text = function(text) {
|
|
GForum.helpText = text;
|
|
|
|
// We can set a 'help-text' element that contains a grayed-out
|
|
// string to indicate what default value should be entered.
|
|
// When we click on it, we remove the 'gray' class and any
|
|
// help text.
|
|
$('.help-text').bind("focus", function() {
|
|
if ($(this).val() == GForum.helpText) {
|
|
$(this).val('');
|
|
$(this).removeClass('gray');
|
|
}
|
|
});
|
|
|
|
// If we haven't entered any text for our 'help-text' input,
|
|
// then when it loses focus, we reset the help string and the
|
|
// grayed-out style.
|
|
$('.help-text').bind("blur", function() {
|
|
if ($(this).val() === '') {
|
|
$(this).val(GForum.helpText);
|
|
$(this).addClass('gray');
|
|
}
|
|
});
|
|
|
|
// If we haven't entered any text for our 'help-text' input,
|
|
// then when we hit 'escape' (ie., keycode 0), we reset the
|
|
// help string and the grayed-out style.
|
|
$('.help-text').bind("keypress", function(e) {
|
|
if (e.which === 0 && $(this).val() === '') {
|
|
$(this).val('');
|
|
$(this).addClass('gray');
|
|
$(this).val(GForum.helpText);
|
|
$(this).blur();
|
|
}
|
|
});
|
|
};
|
|
|
|
GForum.prototype.init_username_autocomplete = function () {
|
|
$('#autocomplete').autocomplete(
|
|
GForum.url_get({ 'do': 'json_user_list' }).url, {
|
|
lineSeparator: ',',
|
|
matchSubset: 0,
|
|
loadingClass: 'input text-area select ac_loading',
|
|
inputClass: 'profile-settings text',
|
|
onItemSelect: function() {$('#autocomplete').focus();}
|
|
}
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Initialize autocomplete for tags. Ie., when modifying a post and
|
|
* specifying tags for that post content, the tag input is handled
|
|
* via this function.
|
|
*/
|
|
GForum.prototype.init_tags = function() {
|
|
$('#autocomplete').autocomplete(
|
|
GForum.url_get({ 'do': 'json_tags' }).url, {
|
|
lineSeparator: ',',
|
|
onItemSelect: function() {
|
|
$('#autocomplete').focus();
|
|
GForum.add_tags($('#autocomplete'));
|
|
},
|
|
loadingClass: 'input text-area select ac_loading',
|
|
inputClass: 'profile-settings'
|
|
}
|
|
);
|
|
|
|
// If the user has entered tags, we can assume
|
|
// they want them added to the post.
|
|
$('#post_write_form').submit(function() {
|
|
GForum.add_tags($('#autocomplete'));
|
|
});
|
|
|
|
// Add entered tags when the 'Add' button is clicked, but also
|
|
// make sure to cancel the form submission
|
|
$('#autocomplete-submit').click(function() {
|
|
GForum.add_tags($('#autocomplete'));
|
|
return false;
|
|
});
|
|
|
|
// If we hit the enter key when typing in the tag text input
|
|
// area, then we want to add all tags in the text input to
|
|
// the active tag list.
|
|
$('#autocomplete').keypress(function(e) {
|
|
if (e.which == 13) {
|
|
GForum.add_tags($(this));
|
|
}
|
|
});
|
|
|
|
// Now if we click on the image next to the tag
|
|
// in the 'selected tags' div, that tag will be
|
|
// removed from the active selection.
|
|
$('#autocomplete-selected-items .remove-tag').click(function() {
|
|
GForum.remove_tag($(this));
|
|
return false;
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Initialize the timezone jquery setup.
|
|
* Set default select values and show the current time.
|
|
*/
|
|
GForum.prototype.init_timezone_select = function(zone_id, init_zone) {
|
|
$('#timezone_region').val(zone_id);
|
|
GForum.show_zone(zone_id, init_zone);
|
|
|
|
$('#timezone_region').change(function() {
|
|
GForum.show_zone($(this).val());
|
|
});
|
|
|
|
$('#user_timezone').change(function() {
|
|
GForum.timezone_last_selected[$('#timezone_region').val()] = $(this).val();
|
|
GForum.show_current_time($(this).val());
|
|
});
|
|
};
|
|
|
|
/**
|
|
* When a city/area has been selected, we need to perform an ajax request
|
|
* to get the actual date for that area.
|
|
*/
|
|
GForum.prototype.show_current_time = function(timezone) {
|
|
// First clear the div and set the temporary loading message.
|
|
$('#show_current_time').empty();
|
|
$('#show_current_time').append(GForum.timezone_loading_message);
|
|
|
|
// Now do the ajax call.
|
|
$.getJSON(GForum.url_get({ 'do': 'json_current_time' }).url, { 'timezone': timezone }, function(response) {
|
|
$('#show_current_time').empty();
|
|
if (!response.status) {
|
|
$('#show_current_time').append(GForum.timezone_error_message);
|
|
}
|
|
else {
|
|
$('#show_current_time').append(response.data);
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* When selecting which timezone the user is in, this function handles when
|
|
* a specific region is selected. When the region is selected, we want to
|
|
* get all cities/areas for that region and populate the 'city/area' select
|
|
* with those values.
|
|
*/
|
|
GForum.prototype.show_zone = function(region, init_zone) {
|
|
// For grammatical correctness, we append 's' to 'America' when creating the list.
|
|
region = region == 'Americas' ? 'America' : region;
|
|
|
|
// Remove the node since it's data has grown stale.
|
|
$('#user_timezone').empty();
|
|
|
|
// Cache the timezones locally.
|
|
var zones = GForum.timezone_zones[region];
|
|
|
|
// Append each timezone to the select object.
|
|
for (var zone in zones) {
|
|
if (typeof zone == 'string') {
|
|
// Set the default value and text for this select option.
|
|
var value = region + '/' + zones[zone];
|
|
var text = zones[zone].replace(/\//g, ' - ').replace(/_/g, ' ');
|
|
var selected = '';
|
|
|
|
if (zones[zone] == 'local') {
|
|
value = 'local';
|
|
text = GForum.timezone_default;
|
|
}
|
|
|
|
// Set this zone as selected if it's been selected.
|
|
if (init_zone && value == init_zone) {
|
|
selected = ' selected';
|
|
GForum.timezone_last_selected = $('#user_timezone').children().size();
|
|
}
|
|
else if (!init_zone && GForum.timezone_last_selected[region] && GForum.timezone_last_selected[region] == $('#user_timezone').children().size()) {
|
|
selected = ' selected';
|
|
}
|
|
|
|
// Append a new select option to thise select element.
|
|
$('#user_timezone').append('<option value="'+value+'"'+selected+'>'+text+'</option>');
|
|
}
|
|
}
|
|
|
|
// Update the current time being displayed.
|
|
if (!init_zone) {
|
|
GForum.show_current_time($('#user_timezone').val());
|
|
}
|
|
};
|
|
|
|
/**
|
|
* For hidden posts we load two versions of the given post. The default view
|
|
* is for the 'hidden' content, which basically just lets you 'click here' to
|
|
* show the actual post content. The link has a class of 'show_post', and
|
|
* this function handles hiding one and showing the other.
|
|
*/
|
|
GForum.prototype.init_hidden_posts = function() {
|
|
$('.show_post').click(function() {
|
|
if ($(this).attr('id').match(/_(\d+)$/)) {
|
|
var id = RegExp.$1;
|
|
$('#p' + id + '_hide').slideUp();
|
|
$('#p' + id).slideDown();
|
|
}
|
|
return false;
|
|
});
|
|
};
|
|
|
|
/**
|
|
* For a given form, if there are a set of inputs A and B such
|
|
* that some inputs from B must have the same value as some of those
|
|
* in group A, then this function follows that mapping to assign
|
|
* appropriate values.
|
|
*
|
|
* @input form_id the id of the form we are submitting.
|
|
* @input opts of the form: { mirrored_input_id: id_of_value_to_mirror }
|
|
* where we can have as many mirrors and original values as needed.
|
|
*/
|
|
GForum.prototype.init_mirror_inputs = function(form_id, opts) {
|
|
$('#'+form_id).submit(function() {
|
|
for (var name in opts) {
|
|
if (typeof name == 'string') {
|
|
$('#'+name).val($('#'+opts[name]).val());
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* When we use GForum.helpText to show default text in any input, this
|
|
* function is used to clear that default input on form submit.
|
|
* @param id id of the form containing the default help text.
|
|
*/
|
|
GForum.prototype.clear_help_on_submit = function(id) {
|
|
$('#'+id).submit(function() {
|
|
var text = $('#autocomplete').val();
|
|
if (text == GForum.helpText) {
|
|
$('#autocomplete').val('');
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* For use on the profile-view page.
|
|
* We do an ajax request for all the available media types. When we have
|
|
* a result, then we call this insert function to insert it into the DOM.
|
|
* @param media_type: currently 'flickr', 'youtube', 'delicious' or 'twitter'.
|
|
* @param item: the JSON object resulting from the AJAX query.
|
|
*/
|
|
GForum.prototype.social_media_insert = function(media_type, item) {
|
|
if (media_type == "flickr") {
|
|
$('#' + media_type + '_content').append('<div class="flickr"><a href="' + item.link + '"><img src="' + item["media:thumbnail"].url + '"/></a></div>');
|
|
}
|
|
else if (media_type == 'youtube') {
|
|
$('#' + media_type + '_content').append('<div class="youtube"><object width="150" height="150"><param name="movie" value="' + item.enclosure.url + '&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><embed src="' + item.enclosure.url + '&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="150" height="150"></embed></object></div>');
|
|
}
|
|
else if (media_type == 'delicious') {
|
|
$('#' + media_type + '_content').append('<div><a href="' + item.link + '">' + item.title + '</a></div>');
|
|
}
|
|
else if (media_type == 'twitter') {
|
|
date = item.pubDate.split(' ');
|
|
$('#' + media_type + '_content').append('<div><span>' + date[2] + ' ' + date[1] + ', ' + date[4] + '</span<span>' + item.title + '</span></div>');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Loads the social media data
|
|
* @param int user_id User_id to load the media for
|
|
*/
|
|
GForum.prototype.load_social_media = function(user_id) {
|
|
// Do the AJAX request
|
|
$.getJSON(GForum.url_get({ 'do': 'json_social_media_feed' }).url, { 'user_id': user_id }, function(json) {
|
|
var data = json.data;
|
|
|
|
$.each(json.data, function(media_name, media) {
|
|
// Remove the spinner icon
|
|
$('#' + media_name + '_spinner').remove();
|
|
|
|
if (media.success == '0') {
|
|
$('#' + media_name + '_error').html(media.message);
|
|
$('#' + media_name + '_error').show();
|
|
}
|
|
else {
|
|
var items;
|
|
if (media.data.feed.channel.item.constructor == Array) {
|
|
// We have multiple items
|
|
items = media.data.feed.channel.item;
|
|
}
|
|
else {
|
|
items[0] = media.data.feed.channel.item;
|
|
}
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
if (typeof items[i] == 'undefined') { break; }
|
|
GForum.social_media_insert(media_name, items[i]);
|
|
}
|
|
}
|
|
|
|
});
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Add tags from me to the element identified by '#autocomplete-selected-items'
|
|
* @param object me: text input containing string of tags to be entered
|
|
*/
|
|
GForum.prototype.add_tags = function (me) {
|
|
var tags = me.val().toLowerCase().replace(/^\s+/, '').replace(/\s+$/, '').split(/\s*,\s*/);
|
|
var $ac_tags = $('#autocomplete-tags');
|
|
|
|
// get all existing tags so we don't add duplicates
|
|
var unique_tags = {};
|
|
var current_tags = $ac_tags.val().split(/\s*,\s*/);
|
|
for (var i = 0; i < current_tags.length; i++) {
|
|
unique_tags[current_tags[i]] = 1;
|
|
}
|
|
|
|
for (var i = 0; i < tags.length; i++) {
|
|
var tag = tags[i];
|
|
if (!tag.length || unique_tags[tag]) {
|
|
continue;
|
|
}
|
|
|
|
unique_tags[tag] = 1;
|
|
|
|
// add the tag to the list of 'selected tags'
|
|
var $button = $('<div class="button-remove remove-tag" title="' + this.html_escape(tag) + '">' + this.html_escape(tag) + '</div>');
|
|
$button.click(function () {
|
|
GForum.remove_tag($(this));
|
|
return false;
|
|
});
|
|
$('#autocomplete-selected-items').append($button);
|
|
|
|
// add the tag to the hidden input
|
|
$ac_tags.val(($ac_tags.val() ? $ac_tags.val() + ',' : '') + tag);
|
|
}
|
|
|
|
// remove all tags from the input box so we know they've been 'added'
|
|
me.val('');
|
|
|
|
if ($ac_tags.val()) {
|
|
$('#autocomplete-selected').slideDown();
|
|
}
|
|
else {
|
|
$('#autocomplete-selected').slideUp();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Remove the clicked-upon tag from the active selection.
|
|
* @param object me: the tag element that has been clicked
|
|
*/
|
|
GForum.prototype.remove_tag = function (me) {
|
|
// remove the DOM element from the selected items element
|
|
var tag = me.attr('title');
|
|
me.remove();
|
|
|
|
var tags = $('#autocomplete-tags').val().split(/\s*,\s*/);
|
|
for (var i = 0; i < tags.length; i++) {
|
|
if (tags[i] == tag) {
|
|
tags.splice(i, 1);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
$('#autocomplete-tags').val(tags.join(','));
|
|
|
|
if (tags.length) {
|
|
$('#autocomplete-selected').slideDown();
|
|
}
|
|
else {
|
|
$('#autocomplete-selected').slideUp();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Show the child popup that is tied to the given parentId
|
|
* @param string parentId: Id of the parent object
|
|
* @param string thisId: Id of the element to show as a child
|
|
* @param int justifyRight: 1-> justify right, otherwise justify left
|
|
*/
|
|
GForum.prototype.showInfo = function (parentId, thisId, justifyRight) {
|
|
var offset = $('#'+parentId).offset();
|
|
if (justifyRight) {
|
|
$('#'+thisId).css('left', offset.left - $('#'+thisId).width());
|
|
}
|
|
else {
|
|
$('#'+thisId).css('left', offset.left);
|
|
}
|
|
$('#'+thisId).css('top', offset.top + $('#'+parentId).height());
|
|
$('#'+thisId).toggle();
|
|
};
|
|
|
|
/**
|
|
* Populates the post reports div
|
|
* @param int post_id Post id of post to process
|
|
* @param string action Ajax action to call
|
|
*
|
|
* @return false Returns false to avoid link submission
|
|
*/
|
|
GForum.prototype.postReportBoxGet = function (post_id, action) {
|
|
// Initialize the data store
|
|
if (typeof $('#post_report_' + post_id).data('open') == 'undefined') {
|
|
$('#post_report_' + post_id).data('open', 0);
|
|
$('#post_report_' + post_id).data('last_action', action);
|
|
}
|
|
|
|
if (!$('#post_report_' + post_id).data('open') || $('#post_report_' + post_id).data('last_action') != action) {
|
|
// Load the content of the post reports div
|
|
$.getJSON(GForum.url_get({ 'do': action }).url, { 'post_id': post_id }, function(json) {
|
|
$('#post_report_' + post_id).html(json.data.html);
|
|
});
|
|
|
|
$('#post_report_' + post_id).data('open', 1);
|
|
} else {
|
|
$('#post_report_' + post_id).data('open', 0);
|
|
}
|
|
|
|
// Open or close the post reports div
|
|
if ($('#post_report_' + post_id).data('open') || $('#post_report_' + post_id).data('last_action') == action) {
|
|
|
|
if ($('#post_report_' + post_id).data('open')) {
|
|
$('#post_report_' + post_id).show();
|
|
} else {
|
|
$('#post_report_' + post_id).hide();
|
|
}
|
|
}
|
|
|
|
$('#post_report_' + post_id).data('last_action', action);
|
|
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Preopens the post reports div in case a moderator selects a post report
|
|
* from the top navigation bar
|
|
*/
|
|
GForum.prototype.openPostReport = function() {
|
|
// Get the anchor from the url
|
|
var anchor = document.location.hash;
|
|
|
|
if (anchor.substr(1, 12) == 'post_report_') {
|
|
// Get the post id from the anchor
|
|
var post_id = anchor.substr(13);
|
|
|
|
// Fetch the content and open the post reports div
|
|
GForum.postReportBoxGet(post_id, 'json_post_reports_box_get');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Initializes the post report elements in the post reports div
|
|
* @param int post_id Post id to submit report for
|
|
* @param int max_message_length Maximal length for a post report
|
|
*/
|
|
GForum.prototype.initPostReportBox = function(post_id, max_message_length) {
|
|
$('#report_submit_' + post_id).click(function() { return GForum.submitPostReport(post_id); });
|
|
$('#report_message_' + post_id).keyup(function() { GForum.restrictPostReportLength(post_id, max_message_length); });
|
|
};
|
|
|
|
/**
|
|
* Initializes the post reports elements in the post reports div
|
|
* @param int post_id Post id to submit report for
|
|
*/
|
|
GForum.prototype.initPostReportsBox = function(post_id) {
|
|
// Assign the click functions for the moderation links
|
|
$('#post_reports_lock_' + post_id).click(function() { return GForum.moderatePostReports(post_id, 'lock'); });
|
|
$('#post_reports_mark_processed_' + post_id).click(function() { return GForum.moderatePostReports(post_id, 'mark_processed'); });
|
|
|
|
// Opens the PM dialog and initializes the PM receipient checkboxes
|
|
$('#post_reports_send_pm_' + post_id).click(function() {
|
|
$('#post_reports_pm_message_wrapper_' + post_id).slideToggle();
|
|
$('.post_reports_pm_user').toggleClass('hide');
|
|
$('.post_reports_sub_heading').toggleClass('hide');
|
|
|
|
return false;
|
|
});
|
|
|
|
// Checks/Unchecks all the PM receipients
|
|
$('#post_reports_pm_all_' + post_id).click(function() {
|
|
$('.post_reports_pm_user_checkbox_' + post_id).attr('checked', $(this).attr('checked') ? 'checked' : '');
|
|
});
|
|
|
|
// Checks/Unchecks all the PM receipients with the same name
|
|
$('.post_reports_pm_user_checkbox_' + post_id).click(function() {
|
|
var name = $(this).attr('name');
|
|
|
|
// Check/Uncheck unique checkboxes
|
|
var checked = 'checked';
|
|
if (!$(this).attr('checked')) {
|
|
checked = '';
|
|
}
|
|
$("input[name='" + name + "']").attr('checked', checked);
|
|
|
|
// Check/Uncheck the Send PM to all reporters box
|
|
var all_checked = 'checked';
|
|
$('.post_reports_pm_user_checkbox_' + post_id).each(function() {
|
|
if (!$(this).attr('checked')) {
|
|
all_checked = '';
|
|
}
|
|
});
|
|
$('#post_reports_pm_all_' + post_id).attr('checked', all_checked);
|
|
});
|
|
|
|
|
|
// Submits a private message to the users
|
|
$('#post_reports_submit_pm_' + post_id).click(function() {
|
|
GForum.postReportPrivateMessageSend(post_id);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* AJAX request to submit a post report
|
|
* @param int post_id Post id to submit report for
|
|
*
|
|
* @return false Returns false to avoid form submission
|
|
*/
|
|
GForum.prototype.submitPostReport = function(post_id) {
|
|
var data = {
|
|
'do': 'json_post_report_save',
|
|
'post_id': post_id,
|
|
'message': $('#report_message_' + post_id).val()
|
|
};
|
|
|
|
var url = GForum.url_get(data);
|
|
$.post(url.base_url, url.params, function(json) {
|
|
if (json.success == 1) {
|
|
$('#report_message_' + post_id).val('');
|
|
$('#report_error_' + post_id).text('');
|
|
$('#post_report_' + post_id).slideToggle();
|
|
$('#post_report_' + post_id).data('open', 0);
|
|
} else {
|
|
$('#report_error_' + post_id).show();
|
|
$('#report_error_' + post_id).text(json.message);
|
|
}
|
|
},
|
|
'json');
|
|
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Locks a post report or marks it as processed
|
|
* @param int post_id Post id to process reports for
|
|
* @param string action Action to perform (lock/mark_processed)
|
|
*
|
|
* @return false Returns false to avoid link submission
|
|
*/
|
|
GForum.prototype.moderatePostReports = function(post_id, action) {
|
|
var data = {
|
|
'do': 'json_post_reports_moderate',
|
|
'post_id': post_id,
|
|
'action': action
|
|
};
|
|
|
|
var url = GForum.url_get(data);
|
|
$.post(url.base_url, url.params, function(json) {
|
|
// Remove the spacer and the Reports link
|
|
if (action == 'mark_processed') {
|
|
$('#post_report_' + post_id).slideToggle();
|
|
$('#post_reports_link_' + post_id).remove();
|
|
$('#post_reports_count_' + post_id).remove();
|
|
} else if (action == 'lock') {
|
|
$('#post_reports_lock_' + post_id).replaceWith(json.data.lock_timeout);
|
|
}
|
|
},
|
|
'json');
|
|
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Restricts the length of the post reports message and shows remaining characters counter
|
|
* @param int post_id Post id of post to process
|
|
* @param int max_length Maximal length of the post reports message
|
|
*
|
|
* @return false Returns false to avoid link submission
|
|
*/
|
|
GForum.prototype.restrictPostReportLength = function(post_id, max_length) {
|
|
var report_message_remaining = max_length - $('#report_message_' + post_id).val().length;
|
|
|
|
if (report_message_remaining <= 0) {
|
|
report_message_remaining = 0;
|
|
var scroll_top = $('#report_message_' + post_id).scrollTop();
|
|
$('#report_message_' + post_id).val($('#report_message_' + post_id).val().substring(0, max_length));
|
|
$('#report_message_' + post_id).scrollTop(scroll_top);
|
|
}
|
|
|
|
$('#report_message_remaining_chars_' + post_id).text(report_message_remaining);
|
|
|
|
};
|
|
|
|
/**
|
|
* Sends a private message to the post reporters and the poster using an AJAX request
|
|
* @param int post_id Post id of post to process
|
|
*/
|
|
GForum.prototype.postReportPrivateMessageSend = function(post_id) {
|
|
var msg_input = $("textarea[name='post_reports_pm_message_" + post_id + "']");
|
|
var msg_body = msg_input.val();
|
|
|
|
// Create a unique indexed array containng all the users who get the message
|
|
var tmp_pm_users = [];
|
|
$('.post_reports_pm_user_checkbox_' + post_id).each(function() {
|
|
if ($(this).attr('checked')) {
|
|
tmp_pm_users[$(this).val()] = $(this).val();
|
|
}
|
|
});
|
|
|
|
if($('#post_reports_pm_poster').attr('checked')) {
|
|
tmp_pm_users[$('#post_reports_pm_poster').val()] = $('#post_reports_pm_poster').val();
|
|
}
|
|
|
|
// Remove the indexes from the array
|
|
var pm_users = [];
|
|
for (pm_user in tmp_pm_users) {
|
|
if(typeof pm_user == 'string') {
|
|
pm_users.push(pm_user);
|
|
}
|
|
}
|
|
|
|
var data = {
|
|
'do': 'json_post_reports_message_send',
|
|
'post_id': post_id,
|
|
'pm_users': pm_users,
|
|
'msg_body': msg_body
|
|
};
|
|
|
|
var url = GForum.url_get(data);
|
|
$.post(url.base_url, url.params, function(json) {
|
|
if (json.success) {
|
|
msg_input.val('');
|
|
$('#post_reports_pm_message_wrapper_' + post_id).slideToggle();
|
|
$('#reports_errors_' + post_id).text('');
|
|
$('.post_reports_pm_user').toggle();
|
|
} else {
|
|
$('#reports_errors_' + post_id).text(json.message);
|
|
$('#reports_errors_' + post_id).show();
|
|
}
|
|
},
|
|
"json");
|
|
};
|
|
|
|
/**
|
|
* Perform image maximum height/width resizing
|
|
* @param object img The image object
|
|
* @param int x (optional) Maximum image display width
|
|
* @param int y (optional) Maximum image display height
|
|
*/
|
|
GForum.prototype.resizeImage = function(img, x, y) {
|
|
x = x ? x : this.image_max_width;
|
|
y = y ? y : this.image_max_height;
|
|
var width = 0;
|
|
var height = 0;
|
|
if (x && x < img.width) {
|
|
width = x;
|
|
}
|
|
if (y && y < img.height) {
|
|
height = y;
|
|
}
|
|
if (width && height) {
|
|
if ((img.width > width && img.height <= height) || (img.width > width && img.height > height && width < height)) {
|
|
height = 0;
|
|
}
|
|
else {
|
|
width = 0;
|
|
}
|
|
}
|
|
if (width > 0) {
|
|
img.width = width;
|
|
}
|
|
if (height > 0) {
|
|
img.height = height;
|
|
}
|
|
if (width > 0 || height > 0) {
|
|
var $link = $('<a href="' + img.src + '" title="Click to view full sized image" target="_blank" />');
|
|
var $img = $(img);
|
|
$img.replaceWith($link);
|
|
$link.append($img);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Initializes the user profile google map
|
|
* @param hash data Contains the user location information and the default zoom level
|
|
*
|
|
* @return bool Status of localizing the position on the map
|
|
*/
|
|
GForum.prototype.init_google_map = function(data) {
|
|
// Initialize the map and add the controls
|
|
map = new GMap2($('#map_canvas').get(0));
|
|
map.addControl(new GSmallMapControl());
|
|
map.addControl(new GMenuMapTypeControl());
|
|
|
|
var point = '';
|
|
if (data.longitude !== '' && data.latitude !== '') {
|
|
// We use the longitude and latitude information to position the map
|
|
point = new GLatLng(data.latitude, data.longitude);
|
|
GForum.position_google_map(point, data.zoom_level);
|
|
return true;
|
|
} else if (data.location !== '') {
|
|
// We use the users location to position the map
|
|
geocoder = new GClientGeocoder();
|
|
return geocoder.getLatLng(data.location, function(point) {
|
|
if (point === null) {
|
|
// Google couldn't find the location remove the map
|
|
$('#map_canvas').remove();
|
|
return false;
|
|
}
|
|
|
|
GForum.position_google_map(point, data.zoom_level);
|
|
return true;
|
|
});
|
|
} else {
|
|
// This shouldn't happen remove the map
|
|
$('#map_canvas').remove();
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Centers the map and sets the marker
|
|
* @param object point Point to center and where to set the maker
|
|
* @param int zoom_level Zoom level of the map
|
|
*/
|
|
GForum.prototype.position_google_map = function(point, zoom_level) {
|
|
map.setCenter(point, zoom_level);
|
|
var marker = new GMarker(point);
|
|
map.addOverlay(marker);
|
|
};
|
|
|
|
/**
|
|
* Code to implement a check all checkbox. Also supports the usage of shift
|
|
* clicking to (un)select a range of checkboxes.
|
|
* @param string check_boxes The name attribute of all the checkboxes
|
|
* @param string check_all A css selector of the check all checkbox (eg. #check_all)
|
|
*/
|
|
GForum.prototype.init_check_all = function (check_boxes, check_all) {
|
|
var $check_all = $(check_all);
|
|
var $check_boxes = $('input[name=' + check_boxes + ']:checkbox');
|
|
if (!$check_all.length || !$check_boxes.length) {
|
|
return;
|
|
}
|
|
|
|
$check_all.click(function () {
|
|
$check_boxes.each(function (i, cb) {
|
|
cb.checked = $check_all.attr('checked');
|
|
});
|
|
});
|
|
$check_all.removeClass('hide');
|
|
|
|
var all_checked = true;
|
|
// The last (un)checked checkbox
|
|
var $last_checked;
|
|
$check_boxes.each(function (i, cb) {
|
|
var $cb = $(cb);
|
|
$cb.click(function (e) {
|
|
// Holding shift when clicking on a checkbox (un)selects everything from the previous box to the current one
|
|
var shift = e && e.shiftKey && $last_checked && $last_checked.val() != $cb.val();
|
|
// Used when 'shift' is true; 1 = first checkbox found, 2 = second checkbox found
|
|
var cb_found = 0;
|
|
// Whether or not the check all box should be (un)checked
|
|
var ac = true;
|
|
$check_boxes.each(function (j, cb) {
|
|
if (shift) {
|
|
if (cb.value == $cb.val() || cb.value == $last_checked.val()) {
|
|
++cb_found;
|
|
}
|
|
if (cb_found == 1) {
|
|
cb.checked = $last_checked.attr('checked');
|
|
}
|
|
}
|
|
|
|
if (!cb.checked) {
|
|
ac = false;
|
|
}
|
|
});
|
|
$check_all.attr('checked', ac);
|
|
$last_checked = $cb;
|
|
});
|
|
|
|
if (!$cb.attr('checked')) {
|
|
all_checked = false;
|
|
}
|
|
});
|
|
$check_all.attr('checked', all_checked);
|
|
};
|
|
|
|
/**
|
|
* Turns links that call functions which are POST request only into a form
|
|
* submission. It turns all links that contain the attribute rel="post-only"
|
|
* into post requests.
|
|
*/
|
|
GForum.prototype.init_post_only = function () {
|
|
$("a[rel*='post-only']").click(function (e) {
|
|
var href = $(this).attr('href');
|
|
|
|
var q = href.indexOf('?');
|
|
var action = q != -1 ? href.substr(0, q) : href;
|
|
var query = q != -1 ? href.substr(q + 1) : '';
|
|
var form = '<form action="' + GForum.html_escape(action) + '" method="post">';
|
|
|
|
var args = query.split(/[;&]/);
|
|
for (var i = 0; i < args.length; i++) {
|
|
if (args[i].match(/([^=]+)=(.*)/)) {
|
|
var key = unescape(RegExp.$1);
|
|
var val = unescape(RegExp.$2);
|
|
form += '<input type="hidden" name="' + GForum.html_escape(key) + '" value="' + GForum.html_escape(val) + '" />';
|
|
}
|
|
}
|
|
form += '</form>';
|
|
|
|
var $form = $(form);
|
|
$(document.body).append($form);
|
|
$form.submit();
|
|
|
|
return false;
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Initialize the password strength meter.
|
|
* @param string pass_input css selector to the password input
|
|
* @param string strength_text css selector to the text that will show the password strength
|
|
*/
|
|
GForum.prototype.init_password_strength = function (pass_input, strength_text) {
|
|
var $pass_input = $(pass_input);
|
|
var $strength_text = $(strength_text);
|
|
if (!$pass_input || !$pass_input.length || !$strength_text || !$strength_text.length) {
|
|
return;
|
|
}
|
|
|
|
$pass_input.keyup(function () {
|
|
var strength = 'None';
|
|
var pass = $pass_input.val();
|
|
if (pass.length) {
|
|
strength = GForum.password_strength(pass);
|
|
}
|
|
$strength_text.text(strength).attr('class', 'pass-strength-' + strength.replace(/\s/, '-').toLowerCase());
|
|
});
|
|
};
|
|
|
|
/**
|
|
* A simple password strength tester.
|
|
* @param string password the password to check
|
|
*/
|
|
GForum.prototype.password_strength = function (password) {
|
|
var N = 0;
|
|
if (password.match(/\d/)) {
|
|
N += 10;
|
|
}
|
|
if (password.match(/[a-z]/)) {
|
|
N += 26;
|
|
}
|
|
if (password.match(/[A-Z]/)) {
|
|
N += 26;
|
|
}
|
|
if (password.match(/[^a-zA-Z0-9]/)) {
|
|
N += 32;
|
|
}
|
|
|
|
// http://en.wikipedia.org/wiki/Password_strength
|
|
var entropy = password.length * Math.log(N) / Math.log(2);
|
|
|
|
var levels = this.password_strength_levels;
|
|
for (var i = levels.length - 1; i >= 0; i--) {
|
|
if (entropy >= levels[i]) {
|
|
return this.password_strength_lang[i];
|
|
}
|
|
}
|
|
return this.password_strength_lang[0];
|
|
}
|
|
|
|
/**
|
|
* Initialize the avatar selector.
|
|
* @param hash options The options for the avatar selector:
|
|
* carousel: css selector of the carousel div
|
|
* upload_input: css selector of the upload input (optional)
|
|
* selected_input: css selector of the hidden selected avatar input
|
|
* jCarouselLite options:
|
|
* btnPrev: css selector to the previous button
|
|
* btnNext: css selector to the next button
|
|
* scroll: the number of avatars to scroll (this should be less or equal to the visible option)
|
|
* visible: the number of avatars to show
|
|
* start: the avatar to initially show
|
|
* (you may also pass in any other jCarouselLite options)
|
|
*/
|
|
GForum.prototype.init_avatar_selector = function (options) {
|
|
$(options.upload_input).change(function () {
|
|
if ($(this).val()) {
|
|
// The user_icon input needs to be reset to an empty string for uploads to work
|
|
$(options.selected_input).val('');
|
|
$(options.carousel + ' img').removeClass('avatar_selected');
|
|
}
|
|
});
|
|
|
|
$(options.carousel + ' img').click(function () {
|
|
var $img = $(this);
|
|
var src = $img.attr('src');
|
|
|
|
$(options.carousel + ' img').removeClass('avatar_selected');
|
|
// When jCarousel is in circular mode, it makes a copy of the items, so you
|
|
// can't just add the class to the current item
|
|
$(options.carousel + " img[src='" + src + "']").addClass('avatar_selected');
|
|
|
|
var img = src.substr(GForum.imageUrl.length + 1);
|
|
if (img == 'avatars/no-avatar.gif') {
|
|
img = '';
|
|
}
|
|
$(options.selected_input).val(img);
|
|
});
|
|
|
|
$(options.carousel).jCarouselLite(options);
|
|
};
|
|
|
|
GForum.prototype.html_escape = function (text) {
|
|
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
};
|
|
|
|
GForum.prototype.html_unescape = function (text) {
|
|
return text.replace(/"/gi, '"').replace(/>/gi, '>').replace(/</gi, '<').replace(/&/gi, '&');
|
|
};
|
|
|
|
/**
|
|
* Parses GForum.url, breaks it into its components, merges params arg into query string and returns a hash containing:
|
|
* url - Complete url with merged query string (GET requests)
|
|
* base_url Base url without query string (POST requests)
|
|
* params Merged query string components (POST requests)
|
|
*
|
|
* @param params Parameters to merge into the query string
|
|
*
|
|
* @return Hash containing the url, base_url and params
|
|
*/
|
|
GForum.prototype.url_get = function(params) {
|
|
var url = GForum.gforum_url;
|
|
|
|
// Parse the url
|
|
var regex = /^(.*?)(?:\?(.*?))?(?:#(.*?))?$/;
|
|
var url_parts = regex.exec(url);
|
|
var base_url = url_parts[1];
|
|
var query_string = url_parts[2];
|
|
|
|
// Parse the query string and add the parameters to params
|
|
if(typeof query_string == 'string') {
|
|
$.each(query_string.split(';'), function () {
|
|
var pieces = this.split('=');
|
|
params[pieces[0]] = pieces[1];
|
|
});
|
|
}
|
|
|
|
// Create the new query_string
|
|
var query_string_pieces = [];
|
|
if(typeof params == 'object') {
|
|
$.each(params, function (key, value) {
|
|
query_string_pieces.push(key + '=' + value);
|
|
});
|
|
}
|
|
query_string = query_string_pieces.join(';');
|
|
|
|
url = base_url;
|
|
if (query_string) {
|
|
url += '?' + query_string;
|
|
}
|
|
|
|
return { 'url': url, 'base_url': base_url, 'params': params };
|
|
};
|
|
|
|
var GForum = new GForum();
|