X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fresources%2Fstatic%2Fjavascript%2Fsone.js;h=86475e54368b4162f96a22edd97c92e3ebe1f50d;hb=e42a8f16b2ed6c3650cb288abbf48932ef63d97b;hp=acb1d466368e6d72e51f06f71366e7701bd439f3;hpb=0ac5c61faa54b62f29bf8c8e9903919315810c80;p=Sone.git diff --git a/src/main/resources/static/javascript/sone.js b/src/main/resources/static/javascript/sone.js index acb1d46..86475e5 100644 --- a/src/main/resources/static/javascript/sone.js +++ b/src/main/resources/static/javascript/sone.js @@ -37,7 +37,8 @@ function registerInputTextareaSwap(inputElement, defaultText, inputFieldName, op (function(inputField, textarea) { inputField.focus(function() { $(this).hide().attr("disabled", "disabled"); - textarea.show().focus(); + /* no, show(), âdisplay: blockâ is not what I need. */ + textarea.attr("style", "display: inline").focus(); }); if (inputField.val() == "") { inputField.addClass("default"); @@ -47,7 +48,9 @@ function registerInputTextareaSwap(inputElement, defaultText, inputFieldName, op textarea.show(); } $(inputField.get(0).form).submit(function() { + inputField.attr("disabled", "disabled"); if (!optional && (textarea.val() == "")) { + inputField.removeAttr("disabled").focus(); return false; } }); @@ -64,12 +67,12 @@ function registerInputTextareaSwap(inputElement, defaultText, inputFieldName, op * The element to add a âcommentâ link to */ function addCommentLink(postId, element, insertAfterThisElement) { - if ($(element).find(".show-reply-form").length > 0) { + if (($(element).find(".show-reply-form").length > 0) || (getPostElement(element).find(".create-reply").length == 0)) { return; } commentElement = (function(postId) { + separator = $(" · ").addClass("separator"); var commentElement = $("
true
if a post with the given ID already
+ * exists on the page, false
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} true
if a reply with the given ID already
+ * exists on the page, false
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;
}
$.getJSON("getPost.ajax", { "post" : postId }, function(data, textStatus) {
if ((data != null) && data.success) {
- if (data.post.id in loadedPosts) {
+ if (hasPost(data.post.id)) {
return;
}
- loadedPosts[data.post.id] = true;
if (!isIndexPage() && !(isViewSonePage() && ((getShownSoneId() == data.post.sone) || (getShownSoneId() == data.post.recipient)))) {
return;
}
@@ -698,27 +1028,28 @@ function loadNewPost(postId) {
newPost = $(data.post.html).addClass("hidden");
if (firstOlderPost != null) {
newPost.insertBefore(firstOlderPost);
- } else {
- $("#sone #posts").append(newPost);
}
ajaxifyPost(newPost);
+ updatePostTimes(data.post.id);
newPost.slideDown();
setActivity();
}
});
}
-function loadNewReply(replyId) {
- if (replyId in loadedReplies) {
+function loadNewReply(replyId, soneId, postId, postSoneId) {
+ if (hasReply(replyId)) {
+ return;
+ }
+ if (!hasPost(postId)) {
return;
}
$.getJSON("getReply.ajax", { "reply": replyId }, function(data, textStatus) {
/* find post. */
if ((data != null) && data.success) {
- if (data.reply.id in loadedReplies) {
+ if (hasReply(data.reply.id)) {
return;
}
- loadedReplies[data.reply.id] = true;
$("#sone .post#" + data.reply.postId).each(function() {
var firstNewerReply = null;
$(this).find(".replies .reply").each(function() {
@@ -738,6 +1069,7 @@ function loadNewReply(replyId) {
}
}
ajaxifyReply(newReply);
+ updateReplyTimes(data.reply.id);
newReply.slideDown();
setActivity();
return false;
@@ -746,14 +1078,28 @@ function loadNewReply(replyId) {
});
}
+/**
+ * Marks the given Sone as known if it is still new.
+ *
+ * @param soneElement
+ * The Sone to mark as known
+ */
+function markSoneAsKnown(soneElement) {
+ if ($(".new", soneElement).length > 0) {
+ $.getJSON("maskAsKnown.ajax", {"formPassword": getFormPassword(), "type": "sone", "id": getSoneId(soneElement)}, function(data, textStatus) {
+ $(soneElement).removeClass("new");
+ });
+ }
+}
+
function markPostAsKnown(postElements) {
$(postElements).each(function() {
postElement = this;
if ($(postElement).hasClass("new")) {
(function(postElement) {
- $.getJSON("markPostAsKnown.ajax", {"formPassword": getFormPassword(), "post": getPostId(postElement)}, function(data, textStatus) {
- $(postElement).removeClass("new");
- });
+ $(postElement).removeClass("new");
+ $(".click-to-show", postElement).removeClass("new");
+ $.getJSON("markAsKnown.ajax", {"formPassword": getFormPassword(), "type": "post", "id": getPostId(postElement)});
})(postElement);
}
});
@@ -765,18 +1111,97 @@ function markReplyAsKnown(replyElements) {
replyElement = this;
if ($(replyElement).hasClass("new")) {
(function(replyElement) {
- $.getJSON("markReplyAsKnown.ajax", {"formPassword": getFormPassword(), "reply": getReplyId(replyElement)}, function(data, textStatus) {
- $(replyElement).removeClass("new");
- });
+ $(replyElement).removeClass("new");
+ $.getJSON("markAsKnown.ajax", {"formPassword": getFormPassword(), "type": "reply", "id": getReplyId(replyElement)});
})(replyElement);
}
});
}
+/**
+ * Updates the time of the post with the given ID.
+ *
+ * @param postId
+ * The ID of the post to update
+ * @param timeText
+ * The text of the time to show
+ * @param refreshTime
+ * The refresh time after which to request a new time (in seconds)
+ * @param tooltip
+ * The tooltip to show
+ */
+function updatePostTime(postId, timeText, refreshTime, tooltip) {
+ if (!getPost(postId).is(":visible")) {
+ return;
+ }
+ getPost(postId).find(".post-status-line > .time a").html(timeText).attr("title", tooltip);
+ (function(postId, refreshTime) {
+ setTimeout(function() {
+ updatePostTimes(postId);
+ }, refreshTime * 1000);
+ })(postId, refreshTime);
+}
+
+/**
+ * Requests new rendered times for the posts with the given IDs.
+ *
+ * @param postIds
+ * Comma-separated post IDs
+ */
+function updatePostTimes(postIds) {
+ $.getJSON("getTimes.ajax", { "posts" : postIds }, function(data, textStatus) {
+ if ((data != null) && data.success) {
+ $.each(data.postTimes, function(index, value) {
+ updatePostTime(index, value.timeText, value.refreshTime, value.tooltip);
+ });
+ }
+ });
+}
+
+/**
+ * Updates the time of the reply with the given ID.
+ *
+ * @param postId
+ * The ID of the reply to update
+ * @param timeText
+ * The text of the time to show
+ * @param refreshTime
+ * The refresh time after which to request a new time (in seconds)
+ * @param tooltip
+ * The tooltip to show
+ */
+function updateReplyTime(replyId, timeText, refreshTime, tooltip) {
+ if (!getReply(replyId).is(":visible")) {
+ return;
+ }
+ getReply(replyId).find(".reply-status-line > .time").html(timeText).attr("title", tooltip);
+ (function(replyId, refreshTime) {
+ setTimeout(function() {
+ updateReplyTimes(replyId);
+ }, refreshTime * 1000);
+ })(replyId, refreshTime);
+}
+
+/**
+ * Requests new rendered times for the posts with the given IDs.
+ *
+ * @param postIds
+ * Comma-separated post IDs
+ */
+function updateReplyTimes(replyIds) {
+ $.getJSON("getTimes.ajax", { "replies" : replyIds }, function(data, textStatus) {
+ if ((data != null) && data.success) {
+ $.each(data.replyTimes, function(index, value) {
+ updateReplyTime(index, value.timeText, value.refreshTime, value.tooltip);
+ });
+ }
+ });
+}
+
function resetActivity() {
title = document.title;
if (title.indexOf('(') == 0) {
- document.title = title.substr(title.indexOf(' ') + 1);
+ setTitle(title.substr(title.indexOf(' ') + 1));
}
}
@@ -784,12 +1209,64 @@ function setActivity() {
if (!focus) {
title = document.title;
if (title.indexOf('(') != 0) {
- document.title = "(!) " + title;
+ setTitle("(!) " + title);
+ }
+ if (!iconBlinking) {
+ setTimeout(toggleIcon, 1500);
+ iconBlinking = true;
+ }
+ }
+}
+
+/**
+ * Sets the window title after a small delay to prevent race-condition issues.
+ *
+ * @param title
+ * The title to set
+ */
+function setTitle(title) {
+ setTimeout(function() {
+ document.title = title;
+ }, 50);
+}
+
+/** Whether the icon is currently showing activity. */
+var iconActive = false;
+
+/** Whether the icon is currently supposed to blink. */
+var iconBlinking = false;
+
+/**
+ * Toggles the icon. If the window has gained focus and the icon is still
+ * showing the activity state, it is returned to normal.
+ */
+function toggleIcon() {
+ if (focus) {
+ if (iconActive) {
+ changeIcon("images/icon.png");
+ iconActive = false;
}
+ iconBlinking = false;
+ } else {
+ iconActive = !iconActive;
+ changeIcon(iconActive ? "images/icon-activity.png" : "images/icon.png");
+ setTimeout(toggleIcon, 1500);
}
}
/**
+ * Changes the icon of the page.
+ *
+ * @param iconUrl
+ * The new URL of the icon
+ */
+function changeIcon(iconUrl) {
+ $("link[rel=icon]").remove();
+ $("head").append($("").attr("rel", "icon").attr("type", "image/png").attr("href", iconUrl));
+ $("iframe[id=icon-update]")[0].src += "";
+}
+
+/**
* Creates a new notification.
*
* @param id
@@ -811,6 +1288,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").removeClass("hidden");
+ $("#sone .notification#" + notificationId + " .short-text").addClass("hidden");
+}
+
+/**
+ * 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
//
@@ -822,29 +1384,62 @@ $(document).ready(function() {
/* this initializes the status update input field. */
getTranslation("WebInterface.DefaultText.StatusUpdate", function(defaultText) {
registerInputTextareaSwap("#sone #update-status .status-input", defaultText, "text", false, false);
+ $("#sone #update-status .select-sender").css("display", "inline");
+ $("#sone #update-status .sender").hide();
+ $("#sone #update-status .select-sender button").click(function() {
+ $("#sone #update-status .sender").show();
+ $("#sone #update-status .select-sender").hide();
+ return false;
+ });
$("#sone #update-status").submit(function() {
- text = $(this).find(":input:enabled").val();
- $.getJSON("createPost.ajax", { "formPassword": getFormPassword(), "text": text }, function(data, textStatus) {
+ button = $("button:submit", this);
+ button.attr("disabled", "disabled");
+ if ($(this).find(":input.default:enabled").length > 0) {
+ return false;
+ }
+ sender = $(this).find(":input[name=sender]").val();
+ text = $(this).find(":input[name=text]:enabled").val();
+ $.getJSON("createPost.ajax", { "formPassword": getFormPassword(), "sender": sender, "text": text }, function(data, textStatus) {
if ((data != null) && data.success) {
- loadNewPost(data.postId);
+ loadNewPost(data.postId, data.sone, data.recipient);
}
+ button.removeAttr("disabled");
});
- $(this).find(":input:enabled").val("").blur();
+ $(this).find(":input[name=sender]").val(getCurrentSoneId());
+ $(this).find(":input[name=text]:enabled").val("").blur();
+ $(this).find(".sender").hide();
+ $(this).find(".select-sender").show();
return false;
});
});
+ /* ajaxify the search input field. */
+ getTranslation("WebInterface.DefaultText.Search", function(defaultText) {
+ registerInputTextareaSwap("#sone #search input[name=query]", defaultText, "query", false, true);
+ });
+
/* ajaxify input field on âview Soneâ page. */
getTranslation("WebInterface.DefaultText.Message", function(defaultText) {
registerInputTextareaSwap("#sone #post-message input[name=text]", defaultText, "text", false, false);
+ $("#sone #post-message .select-sender").css("display", "inline");
+ $("#sone #post-message .sender").hide();
+ $("#sone #post-message .select-sender button").click(function() {
+ $("#sone #post-message .sender").show();
+ $("#sone #post-message .select-sender").hide();
+ return false;
+ });
$("#sone #post-message").submit(function() {
- text = $(this).find(":input:enabled").val();
- $.getJSON("createPost.ajax", { "formPassword": getFormPassword(), "recipient": getShownSoneId(), "text": text }, function(data, textStatus) {
+ sender = $(this).find(":input[name=sender]").val();
+ text = $(this).find(":input[name=text]:enabled").val();
+ $.getJSON("createPost.ajax", { "formPassword": getFormPassword(), "recipient": getShownSoneId(), "sender": sender, "text": text }, function(data, textStatus) {
if ((data != null) && data.success) {
- loadNewPost(data.postId);
+ loadNewPost(data.postId, getCurrentSoneId());
}
});
- $(this).find(":input:enabled").val("").blur();
+ $(this).find(":input[name=sender]").val(getCurrentSoneId());
+ $(this).find(":input[name=text]:enabled").val("").blur();
+ $(this).find(".sender").hide();
+ $(this).find(".select-sender").show();
return false;
});
});
@@ -861,6 +1456,13 @@ $(document).ready(function() {
});
});
+ /* update post times. */
+ postIds = [];
+ $("#sone .post").each(function() {
+ postIds.push(getPostId(this));
+ });
+ updatePostTimes(postIds.join(","));
+
/* hides all replies but the latest two. */
if (!isViewPostPage()) {
getTranslation("WebInterface.ClickToShow.Replies", function(text) {
@@ -889,41 +1491,8 @@ $(document).ready(function() {
});
}
- /*
- * convert all âfollowâ, âunfollowâ, âlockâ, and âunlockâ links to something
- * nicer.
- */
- $("#sone .follow").submit(function() {
- var followElement = this;
- $.getJSON("followSone.ajax", { "sone": getSoneId(this), "formPassword": getFormPassword() }, function() {
- $(followElement).addClass("hidden");
- $(followElement).parent().find(".unfollow").removeClass("hidden");
- });
- return false;
- });
- $("#sone .unfollow").submit(function() {
- var unfollowElement = this;
- $.getJSON("unfollowSone.ajax", { "sone": getSoneId(this), "formPassword": getFormPassword() }, function() {
- $(unfollowElement).addClass("hidden");
- $(unfollowElement).parent().find(".follow").removeClass("hidden");
- });
- return false;
- });
- $("#sone .lock").submit(function() {
- var lockElement = this;
- $.getJSON("lockSone.ajax", { "sone" : getSoneId(this), "formPassword" : getFormPassword() }, function() {
- $(lockElement).addClass("hidden");
- $(lockElement).parent().find(".unlock").removeClass("hidden");
- });
- return false;
- });
- $("#sone .unlock").submit(function() {
- var unlockElement = this;
- $.getJSON("unlockSone.ajax", { "sone" : getSoneId(this), "formPassword" : getFormPassword() }, function() {
- $(unlockElement).addClass("hidden");
- $(unlockElement).parent().find(".lock").removeClass("hidden");
- });
- return false;
+ $("#sone .sone").each(function() {
+ ajaxifySone($(this));
});
/* process all existing notifications, ajaxify dismiss buttons. */