1 /* Sone JavaScript functions. */
4 return $("#sone").hasClass("online");
7 function registerInputTextareaSwap(inputSelector, defaultText, inputFieldName, optional, dontUseTextarea) {
8 $(inputSelector).each(function() {
9 textarea = $(dontUseTextarea ? "<input type=\"text\" name=\"" + inputFieldName + "\">" : "<textarea name=\"" + inputFieldName + "\"></textarea>").blur(function() {
10 if ($(this).val() == "") {
12 inputField = $(this).data("inputField");
13 inputField.show().removeAttr("disabled").addClass("default");
14 inputField.val(defaultText);
16 }).hide().data("inputField", $(this)).val($(this).val());
17 $(this).after(textarea);
18 (function(inputField, textarea) {
19 inputField.focus(function() {
20 $(this).hide().attr("disabled", "disabled");
21 textarea.show().focus();
23 if (inputField.val() == "") {
24 inputField.addClass("default");
25 inputField.val(defaultText);
27 inputField.hide().attr("disabled", "disabled");
30 $(inputField.get(0).form).submit(function() {
31 if (!optional && (textarea.val() == "")) {
35 })($(this), textarea);
39 /* hide all the “create reply” forms until a link is clicked. */
40 function addCommentLinks() {
44 $("#sone .post").each(function() {
45 postId = $(this).attr("id");
46 addCommentLink(postId, $(this));
51 * Adds a “comment” link to all status lines contained in the given element.
56 * The element to add a “comment” link to
58 function addCommentLink(postId, element) {
59 commentElement = (function(postId) {
60 var commentElement = $("<div><span>Comment</span></div>").addClass("show-reply-form").click(function() {
61 replyElement = $("#sone .post#" + postId + " .create-reply");
62 replyElement.removeClass("hidden");
63 replyElement.removeClass("light");
64 (function(replyElement) {
65 replyElement.find("input.reply-input").blur(function() {
66 if ($(this).hasClass("default")) {
67 replyElement.addClass("light");
70 replyElement.removeClass("light");
73 replyElement.find("input.reply-input").focus();
75 return commentElement;
77 element.find(".create-reply").addClass("hidden");
78 element.find(".status-line .time").each(function() {
79 $(this).after(commentElement.clone(true));
84 * Retrieves the translation for the given key and calls the callback function.
85 * The callback function takes a single parameter, the translated string.
88 * The key of the translation string
90 * The callback function
92 function getTranslation(key, callback) {
93 $.getJSON("ajax/getTranslation.ajax", {"key": key}, function(data, textStatus) {
99 * Fires off an AJAX request to retrieve the current status of a Sone.
104 * <code>true</code> if the Sone is local, <code>false</code>
107 function getSoneStatus(soneId, local) {
108 $.getJSON("ajax/getSoneStatus.ajax", {"sone": soneId}, function(data, textStatus) {
109 updateSoneStatus(soneId, data.name, data.status, data.modified, data.lastUpdated);
112 if (local || data.modified || (data.status == "downloading") || (data.status == "inserting")) {
115 setTimeout(function() {
116 getSoneStatus(soneId, local);
117 }, updateInterval * 1000);
122 * Filters the given Sone ID, replacing all “~” characters by an underscore.
125 * The Sone ID to filter
126 * @returns The filtered Sone ID
128 function filterSoneId(soneId) {
129 return soneId.replace(/[^a-zA-Z0-9-]/g, "_");
133 * Updates the status of the given Sone.
136 * The ID of the Sone to update
138 * The status of the Sone (“idle”, “unknown”, “inserting”,
141 * Whether the Sone is modified
143 * The date and time of the last update (formatted for display)
145 function updateSoneStatus(soneId, name, status, modified, lastUpdated) {
146 $("#sone .sone." + filterSoneId(soneId)).
147 toggleClass("unknown", status == "unknown").
148 toggleClass("idle", status == "idle").
149 toggleClass("inserting", status == "inserting").
150 toggleClass("downloading", status == "downloading").
151 toggleClass("modified", modified);
152 $("#sone .sone." + filterSoneId(soneId) + " .last-update span.time").text(lastUpdated);
153 $("#sone .sone." + filterSoneId(soneId) + " .profile-link a").text(name);
156 var watchedSones = {};
159 * Watches this Sone for updates to its status.
162 * The ID of the Sone to watch
164 * <code>true</code> if the Sone is local, <code>false</code>
167 function watchSone(soneId, local) {
168 if (watchedSones[soneId]) {
171 watchedSones[soneId] = true;
173 setTimeout(function() {
174 getSoneStatus(soneId, local);
180 * Enhances a “delete” button so that the confirmation is done on the same page.
183 * The selector of the button
185 * The text to show on the button
186 * @param deleteCallback
187 * The callback that actually deletes something
189 function enhanceDeleteButton(buttonId, text, deleteCallback) {
190 button = $(buttonId);
192 newButton = $("<button></button>").addClass("confirm").hide().text(text).click(function() {
193 $(this).fadeOut("slow");
196 }).insertAfter(button);
197 (function(button, newButton) {
198 button.click(function() {
199 button.fadeOut("slow", function() {
200 newButton.fadeIn("slow");
201 $(document).one("click", function() {
202 if (this != newButton.get(0)) {
203 newButton.fadeOut(function() {
211 })(button, newButton);
216 * Enhances a post’s “delete” button.
219 * The selector of the button
221 * The ID of the post to delete
223 * The text to replace the button with
225 function enhanceDeletePostButton(buttonId, postId, text) {
226 enhanceDeleteButton(buttonId, text, function() {
227 $.getJSON("ajax/deletePost.ajax", { "post": postId, "formPassword": $("#sone #formPassword").text() }, function(data, textStatus) {
229 $("#sone .post#" + postId).slideUp();
230 } else if (data.error == "invalid-post-id") {
231 alert("Invalid post ID given!");
232 } else if (data.error == "auth-required") {
233 alert("You need to be logged in.");
234 } else if (data.error == "not-authorized") {
235 alert("You are not allowed to delete this post.");
242 * Enhances a reply’s “delete” button.
245 * The selector of the button
247 * The ID of the reply to delete
249 * The text to replace the button with
251 function enhanceDeleteReplyButton(buttonId, replyId, text) {
252 enhanceDeleteButton(buttonId, text, function() {
253 $.getJSON("ajax/deleteReply.ajax", { "reply": replyId, "formPassword": $("#sone #formPassword").text() }, function(data, textStatus) {
255 $("#sone .reply#" + replyId).slideUp();
256 } else if (data.error == "invalid-reply-id") {
257 alert("Invalid reply ID given!");
258 } else if (data.error == "auth-required") {
259 alert("You need to be logged in.");
260 } else if (data.error == "not-authorized") {
261 alert("You are not allowed to delete this reply.");
267 function getFormPassword() {
268 return $("#sone #formPassword").text();
271 function getSoneElement(element) {
272 return $(element).parents(".sone");
276 * Generates a list of Sones by concatening the names of the given sones with a
277 * new line character (“\n”).
280 * The sones to format
281 * @returns {String} The created string
283 function generateSoneList(sones) {
285 $.each(sones, function() {
286 if (soneList != "") {
289 soneList += this.name;
295 * Returns the ID of the Sone that this element belongs to.
298 * The element to locate the matching Sone ID for
299 * @returns The ID of the Sone, or undefined
301 function getSoneId(element) {
302 return getSoneElement(element).find(".id").text();
305 function getPostElement(element) {
306 return $(element).parents(".post");
309 function getPostId(element) {
310 return getPostElement(element).attr("id");
313 function getReplyElement(element) {
314 return $(element).parents(".reply");
317 function getReplyId(element) {
318 return getReplyElement(element).attr("id");
321 function likePost(postId) {
322 $.getJSON("ajax/like.ajax", { "type": "post", "post" : postId, "formPassword": getFormPassword() }, function() {
323 $("#sone .post#" + postId + " > .inner-part > .status-line .like").addClass("hidden");
324 $("#sone .post#" + postId + " > .inner-part > .status-line .unlike").removeClass("hidden");
325 updatePostLikes(postId);
329 function unlikePost(postId) {
330 $.getJSON("ajax/unlike.ajax", { "type": "post", "post" : postId, "formPassword": getFormPassword() }, function() {
331 $("#sone .post#" + postId + " > .inner-part > .status-line .unlike").addClass("hidden");
332 $("#sone .post#" + postId + " > .inner-part > .status-line .like").removeClass("hidden");
333 updatePostLikes(postId);
337 function updatePostLikes(postId) {
338 $.getJSON("ajax/getLikes.ajax", { "type": "post", "post": postId }, function(data, textStatus) {
340 $("#sone .post#" + postId + " > .inner-part > .status-line .likes").toggleClass("hidden", data.likes == 0)
341 $("#sone .post#" + postId + " > .inner-part > .status-line .likes span.like-count").text(data.likes);
342 $("#sone .post#" + postId + " > .inner-part > .status-line .likes > span").attr("title", generateSoneList(data.sones));
347 function likeReply(replyId) {
348 $.getJSON("ajax/like.ajax", { "type": "reply", "reply" : replyId, "formPassword": getFormPassword() }, function() {
349 $("#sone .reply#" + replyId + " .status-line .like").addClass("hidden");
350 $("#sone .reply#" + replyId + " .status-line .unlike").removeClass("hidden");
351 updateReplyLikes(replyId);
355 function unlikeReply(replyId) {
356 $.getJSON("ajax/unlike.ajax", { "type": "reply", "reply" : replyId, "formPassword": getFormPassword() }, function() {
357 $("#sone .reply#" + replyId + " .status-line .unlike").addClass("hidden");
358 $("#sone .reply#" + replyId + " .status-line .like").removeClass("hidden");
359 updateReplyLikes(replyId);
363 function updateReplyLikes(replyId) {
364 $.getJSON("ajax/getLikes.ajax", { "type": "reply", "reply": replyId }, function(data, textStatus) {
366 $("#sone .reply#" + replyId + " .status-line .likes").toggleClass("hidden", data.likes == 0)
367 $("#sone .reply#" + replyId + " .status-line .likes span.like-count").text(data.likes);
368 $("#sone .reply#" + replyId + " .status-line .likes > span").attr("title", generateSoneList(data.sones));
374 * Posts a reply and calls the given callback when the request finishes.
377 * The ID of the post the reply refers to
380 * @param callbackFunction
381 * The callback function to call when the request finishes (takes 3
382 * parameters: success, error, replyId)
384 function postReply(postId, text, callbackFunction) {
385 $.getJSON("ajax/createReply.ajax", { "formPassword" : getFormPassword(), "post" : postId, "text": text }, function(data, textStatus) {
387 callbackFunction(true, null, data.reply);
389 callbackFunction(false, data.error);
395 * Requests information about the reply with the given ID.
398 * The ID of the reply
399 * @param callbackFunction
400 * A callback function (parameters soneId, soneName, replyTime,
401 * replyDisplayTime, text, html)
403 function getReply(replyId, callbackFunction) {
404 $.getJSON("ajax/getReply.ajax", { "reply" : replyId }, function(data, textStatus) {
406 callbackFunction(data.soneId, data.soneName, data.time, data.displayTime, data.text, data.html);