Merge branch 'profile-fields' into next
[Sone.git] / src / main / resources / static / javascript / sone.js
index 3646f73..2d6c8ec 100644 (file)
@@ -449,16 +449,18 @@ function ajaxifyPost(postElement) {
                inputField = $(this.form).find(":input:enabled").get(0);
                postId = getPostId(this);
                text = $(inputField).val();
-               $(inputField).val("");
-               postReply(postId, text, function(success, error, replyId) {
-                       if (success) {
-                               loadNewReply(replyId);
-                               markPostAsKnown(getPostElement(inputField));
-                               $("#sone .post#" + postId + " .create-reply").addClass("hidden");
-                       } else {
-                               alert(error);
-                       }
-               });
+               (function(postId, text, inputField) {
+                       postReply(postId, text, function(success, error, replyId) {
+                               if (success) {
+                                       $(inputField).val("");
+                                       loadNewReply(replyId, getCurrentSoneId(), postId);
+                                       markPostAsKnown(getPostElement(inputField));
+                                       $("#sone .post#" + postId + " .create-reply").addClass("hidden");
+                               } else {
+                                       alert(error);
+                               }
+                       });
+               })(postId, text, inputField);
                return false;
        });
 
@@ -498,7 +500,10 @@ function ajaxifyPost(postElement) {
        });
 
        /* mark everything as known on click. */
-       $(postElement).click(function() {
+       $(postElement).click(function(event) {
+               if ($(event.target).hasClass("click-to-show")) {
+                       return false;
+               }
                markPostAsKnown(this);
        });
 
@@ -534,7 +539,7 @@ function ajaxifyReply(replyElement) {
 
        /* mark post and all replies as known on click. */
        $(replyElement).click(function() {
-               markPostAsKnown(getPostElement(replyElement));
+               markPostAsKnown(getPostElement(this));
        });
 }
 
@@ -583,11 +588,11 @@ function getStatus() {
                        });
                        /* process new posts. */
                        $.each(data.newPosts, function(index, value) {
-                               loadNewPost(value);
+                               loadNewPost(value.id, value.sone, value.recipient, value.time);
                        });
                        /* process new replies. */
                        $.each(data.newReplies, function(index, value) {
-                               loadNewReply(value);
+                               loadNewReply(value.id, value.sone, value.post, value.postSone);
                        });
                        /* do it again in 5 seconds. */
                        setTimeout(getStatus, 5000);
@@ -602,6 +607,16 @@ function getStatus() {
 }
 
 /**
+ * Returns the ID of the currently logged in Sone.
+ *
+ * @return The ID of the current Sone, or an empty string if no Sone is logged
+ *         in
+ */
+function getCurrentSoneId() {
+       return $("#currentSoneId").text();
+}
+
+/**
  * Returns the content of the page-id attribute.
  *
  * @returns The page ID
@@ -670,16 +685,49 @@ function isKnownSonesPage() {
        return getPageId() == "known-sones";
 }
 
-var loadedPosts = {};
-var loadedReplies = {};
+/**
+ * Returns whether a post with the given ID exists on the current page.
+ *
+ * @param postId
+ *            The post ID to check for
+ * @returns {Boolean} <code>true</code> if a post with the given ID already
+ *          exists on the page, <code>false</code> otherwise
+ */
+function hasPost(postId) {
+       return $(".post#" + postId).length > 0;
+}
 
-function loadNewPost(postId) {
-       if (postId in loadedPosts) {
+/**
+ * Returns whether a reply with the given ID exists on the current page.
+ *
+ * @param replyId
+ *            The reply ID to check for
+ * @returns {Boolean} <code>true</code> if a reply with the given ID already
+ *          exists on the page, <code>false</code> otherwise
+ */
+function hasReply(replyId) {
+       return $("#sone .reply#" + replyId).length > 0;
+}
+
+function loadNewPost(postId, soneId, recipientId, time) {
+       if (hasPost(postId)) {
+               return;
+       }
+       if (!isIndexPage()) {
+               if (!isViewPostPage() || (getShownPostId() != postId)) {
+                       if (!isViewSonePage() || ((getShownSoneId() != soneId) && (getShownSoneId() != recipientId))) {
+                               return;
+                       }
+               }
+       }
+       if (getPostTime($("#sone .post").last()) > time) {
                return;
        }
-       loadedPosts[postId] = true;
        $.getJSON("getPost.ajax", { "post" : postId }, function(data, textStatus) {
                if ((data != null) && data.success) {
+                       if (hasPost(data.post.id)) {
+                               return;
+                       }
                        if (!isIndexPage() && !(isViewSonePage() && ((getShownSoneId() == data.post.sone) || (getShownSoneId() == data.post.recipient)))) {
                                return;
                        }
@@ -693,8 +741,6 @@ function loadNewPost(postId) {
                        newPost = $(data.post.html).addClass("hidden");
                        if (firstOlderPost != null) {
                                newPost.insertBefore(firstOlderPost);
-                       } else {
-                               $("#sone #posts").append(newPost);
                        }
                        ajaxifyPost(newPost);
                        newPost.slideDown();
@@ -703,14 +749,19 @@ function loadNewPost(postId) {
        });
 }
 
-function loadNewReply(replyId) {
-       if (replyId in loadedReplies) {
+function loadNewReply(replyId, soneId, postId, postSoneId) {
+       if (hasReply(replyId)) {
+               return;
+       }
+       if (!hasPost(postId)) {
                return;
        }
-       loadedReplies[replyId] = true;
        $.getJSON("getReply.ajax", { "reply": replyId }, function(data, textStatus) {
                /* find post. */
                if ((data != null) && data.success) {
+                       if (hasReply(data.reply.id)) {
+                               return;
+                       }
                        $("#sone .post#" + data.reply.postId).each(function() {
                                var firstNewerReply = null;
                                $(this).find(".replies .reply").each(function() {
@@ -732,6 +783,7 @@ function loadNewReply(replyId) {
                                ajaxifyReply(newReply);
                                newReply.slideDown();
                                setActivity();
+                               return false;
                        });
                }
        });
@@ -744,6 +796,7 @@ function markPostAsKnown(postElements) {
                        (function(postElement) {
                                $.getJSON("markPostAsKnown.ajax", {"formPassword": getFormPassword(), "post": getPostId(postElement)}, function(data, textStatus) {
                                        $(postElement).removeClass("new");
+                                       $(".click-to-show", postElement).removeClass("new");
                                });
                        })(postElement);
                }
@@ -802,6 +855,91 @@ function createNotification(id, text, dismissable) {
        return notification;
 }
 
+/**
+ * Shows the details of the notification with the given ID.
+ *
+ * @param notificationId
+ *            The ID of the notification
+ */
+function showNotificationDetails(notificationId) {
+       $("#sone .notification#" + notificationId + " .text").show();
+       $("#sone .notification#" + notificationId + " .short-text").hide();
+}
+
+/**
+ * Deletes the field with the given ID from the profile.
+ *
+ * @param fieldId
+ *            The ID of the field to delete
+ */
+function deleteProfileField(fieldId) {
+       $.getJSON("deleteProfileField.ajax", {"formPassword": getFormPassword(), "field": fieldId}, function(data, textStatus) {
+               if (data && data.success) {
+                       $("#sone .profile-field#" + data.field.id).slideUp();
+               }
+       });
+}
+
+/**
+ * Renames a profile field.
+ *
+ * @param fieldId
+ *            The ID of the field to rename
+ * @param newName
+ *            The new name of the field
+ * @param successFunction
+ *            Called when the renaming was successful
+ */
+function editProfileField(fieldId, newName, successFunction) {
+       $.getJSON("editProfileField.ajax", {"formPassword": getFormPassword(), "field": fieldId, "name": newName}, function(data, textStatus) {
+               if (data && data.success) {
+                       successFunction();
+               }
+       });
+}
+
+/**
+ * Moves the profile field with the given ID one slot in the given direction.
+ *
+ * @param fieldId
+ *            The ID of the field to move
+ * @param direction
+ *            The direction to move in (“up” or “down”)
+ * @param successFunction
+ *            Function to call on success
+ */
+function moveProfileField(fieldId, direction, successFunction) {
+       $.getJSON("moveProfileField.ajax", {"formPassword": getFormPassword(), "field": fieldId, "direction": direction}, function(data, textStatus) {
+               if (data && data.success) {
+                       successFunction();
+               }
+       });
+}
+
+/**
+ * Moves the profile field with the given ID up one slot.
+ *
+ * @param fieldId
+ *            The ID of the field to move
+ * @param successFunction
+ *            Function to call on success
+ */
+function moveProfileFieldUp(fieldId, successFunction) {
+       moveProfileField(fieldId, "up", successFunction);
+}
+
+/**
+ * Moves the profile field with the given ID down one slot.
+ *
+ * @param fieldId
+ *            The ID of the field to move
+ * @param successFunction
+ *            Function to call on success
+ */
+function moveProfileFieldDown(fieldId, successFunction) {
+       moveProfileField(fieldId, "down", successFunction);
+}
+
 //
 // EVERYTHING BELOW HERE IS EXECUTED AFTER LOADING THE PAGE
 //
@@ -814,10 +952,13 @@ $(document).ready(function() {
        getTranslation("WebInterface.DefaultText.StatusUpdate", function(defaultText) {
                registerInputTextareaSwap("#sone #update-status .status-input", defaultText, "text", false, false);
                $("#sone #update-status").submit(function() {
+                       if ($(this).find(":input.default:enabled").length > 0) {
+                               return false;
+                       }
                        text = $(this).find(":input:enabled").val();
                        $.getJSON("createPost.ajax", { "formPassword": getFormPassword(), "text": text }, function(data, textStatus) {
                                if ((data != null) && data.success) {
-                                       loadNewPost(data.postId);
+                                       loadNewPost(data.postId, getCurrentSoneId());
                                }
                        });
                        $(this).find(":input:enabled").val("").blur();
@@ -832,7 +973,7 @@ $(document).ready(function() {
                        text = $(this).find(":input:enabled").val();
                        $.getJSON("createPost.ajax", { "formPassword": getFormPassword(), "recipient": getShownSoneId(), "text": text }, function(data, textStatus) {
                                if ((data != null) && data.success) {
-                                       loadNewPost(data.postId);
+                                       loadNewPost(data.postId, getCurrentSoneId());
                                }
                        });
                        $(this).find(":input:enabled").val("").blur();