/***************************************************************************** * 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('
'+text+'
'); 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(''); } } // 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('
'); } else if (media_type == 'youtube') { $('#' + media_type + '_content').append('
'); } else if (media_type == 'delicious') { $('#' + media_type + '_content').append('
' + item.title + '
'); } else if (media_type == 'twitter') { date = item.pubDate.split(' '); $('#' + media_type + '_content').append('
' + date[2] + ' ' + date[1] + ', ' + date[4] + '' + item.title + '
'); } }; /** * 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 = $('
' + this.html_escape(tag) + '
'); $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 = $(''); 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 = '
'; 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 += ''; } } 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, '"'); }; 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();