X-Git-Url: https://git.pterodactylus.net/?p=Sone.git;a=blobdiff_plain;f=src%2Fmain%2Fresources%2Fstatic%2Fjavascript%2Fsone.js;h=6e7184e4c7ea4cc195592e24e2a90cb7f49c448a;hp=d60ee230157664d7d2b1711e233983362c518985;hb=8e4b0c79cea9367a42ecef1f2b610f675eb92a74;hpb=58eeba9b521b0a0094ac90a37fd88811c6a27376 diff --git a/src/main/resources/static/javascript/sone.js b/src/main/resources/static/javascript/sone.js index d60ee23..6e7184e 100644 --- a/src/main/resources/static/javascript/sone.js +++ b/src/main/resources/static/javascript/sone.js @@ -1,26 +1,23 @@ /* Sone JavaScript functions. */ -/* jQuery overrides. */ -oldGetJson = jQuery.prototype.getJSON; -jQuery.prototype.getJSON = function(url, data, successCallback, errorCallback) { - if (typeof errorCallback == "undefined") { - return oldGetJson(url, data, successCallback); - } - if (jQuery.isFunction(data)) { - errorCallback = successCallback; - successCallback = data; - data = null; - } - return jQuery.ajax({ - data: data, - error: errorCallback, - success: successCallback, - url: url - }); -} - -function isOnline() { - return $("#sone").hasClass("online"); +function ajaxGet(url, data, successCallback, errorCallback) { + (function(url, data, successCallback, errorCallback) { + $.ajax({"type": "GET", "url": url, "data": data, "dataType": "json", "success": function(data, textStatus, xmlHttpRequest) { + ajaxSuccess(); + if (typeof successCallback != "undefined") { + successCallback(data, textStatus); + } + }, "error": function(xmlHttpRequest, textStatus, errorThrown) { + if (xmlHttpRequest.status == 403) { + notLoggedIn = true; + } + if (typeof errorCallback != "undefined") { + errorCallback(); + } else { + ajaxError(); + } + }}); + })(url, data, successCallback, errorCallback); } function registerInputTextareaSwap(inputElement, defaultText, inputFieldName, optional, dontUseTextarea) { @@ -33,7 +30,7 @@ function registerInputTextareaSwap(inputElement, defaultText, inputFieldName, op inputField.val(defaultText); } }).hide().data("inputField", $(this)).val($(this).val()); - $(this).after(textarea); + $(this).data("textarea", textarea).after(textarea); (function(inputField, textarea) { inputField.focus(function() { $(this).hide().attr("disabled", "disabled"); @@ -66,11 +63,11 @@ function registerInputTextareaSwap(inputElement, defaultText, inputFieldName, op * @param element * The element to add a “comment” link to */ -function addCommentLink(postId, element, insertAfterThisElement) { +function addCommentLink(postId, author, element, insertAfterThisElement) { if (($(element).find(".show-reply-form").length > 0) || (getPostElement(element).find(".create-reply").length == 0)) { return; } - commentElement = (function(postId) { + commentElement = (function(postId, author) { separator = $(" · ").addClass("separator"); var commentElement = $("
Comment
").addClass("show-reply-form").click(function() { replyElement = $("#sone .post#" + postId + " .create-reply"); @@ -85,10 +82,13 @@ function addCommentLink(postId, element, insertAfterThisElement) { replyElement.removeClass("light"); }); })(replyElement); - replyElement.find("input.reply-input").focus(); + textArea = replyElement.find("input.reply-input").focus().data("textarea"); + if (author != getCurrentSoneId()) { + textArea.val(textArea.val() + "@sone://" + author + " "); + } }); return commentElement; - })(postId); + })(postId, author); $(insertAfterThisElement).after(commentElement.clone(true)); $(insertAfterThisElement).after(separator); } @@ -109,13 +109,11 @@ function getTranslation(key, callback) { callback(translations[key]); return; } - $.getJSON("getTranslation.ajax", {"key": key}, function(data, textStatus) { + ajaxGet("getTranslation.ajax", {"key": key}, function(data, textStatus) { if ((data != null) && data.success) { translations[key] = data.value; callback(data.value); } - }, function(xmlHttpRequest, textStatus, error) { - /* ignore error. */ }); } @@ -145,7 +143,7 @@ function filterSoneId(soneId) { * @param lastUpdated * The date and time of the last update (formatted for display) */ -function updateSoneStatus(soneId, name, status, modified, locked, lastUpdated) { +function updateSoneStatus(soneId, name, status, modified, locked, lastUpdated, lastUpdatedText) { $("#sone .sone." + filterSoneId(soneId)). toggleClass("unknown", status == "unknown"). toggleClass("idle", status == "idle"). @@ -155,7 +153,7 @@ function updateSoneStatus(soneId, name, status, modified, locked, lastUpdated) { $("#sone .sone." + filterSoneId(soneId) + " .lock").toggleClass("hidden", locked); $("#sone .sone." + filterSoneId(soneId) + " .unlock").toggleClass("hidden", !locked); if (lastUpdated != null) { - $("#sone .sone." + filterSoneId(soneId) + " .last-update span.time").text(lastUpdated); + $("#sone .sone." + filterSoneId(soneId) + " .last-update span.time").attr("title", lastUpdated).text(lastUpdatedText); } else { getTranslation("View.Sone.Text.UnknownDate", function(unknown) { $("#sone .sone." + filterSoneId(soneId) + " .last-update span.time").text(unknown); @@ -211,7 +209,7 @@ function enhanceDeleteButton(button, text, deleteCallback) { */ function enhanceDeletePostButton(button, postId, text) { enhanceDeleteButton(button, text, function() { - $.getJSON("deletePost.ajax", { "post": postId, "formPassword": getFormPassword() }, function(data, textStatus) { + ajaxGet("deletePost.ajax", { "post": postId, "formPassword": getFormPassword() }, function(data, textStatus) { if (data == null) { return; } @@ -243,7 +241,7 @@ function enhanceDeletePostButton(button, postId, text) { */ function enhanceDeleteReplyButton(button, replyId, text) { enhanceDeleteButton(button, text, function() { - $.getJSON("deleteReply.ajax", { "reply": replyId, "formPassword": $("#sone #formPassword").text() }, function(data, textStatus) { + ajaxGet("deleteReply.ajax", { "reply": replyId, "formPassword": $("#sone #formPassword").text() }, function(data, textStatus) { if (data == null) { return; } @@ -276,7 +274,7 @@ function getFormPassword() { */ function getSone(soneId) { return $("#sone .sone").filter(function(index) { - return $(".id").text() == soneId; + return $(".id", this).text() == soneId; }); } @@ -415,8 +413,19 @@ function getNotificationId(notificationElement) { return $(notificationElement).attr("id"); } +/** + * Returns the time the notification was last updated. + * + * @param notificationElement + * The notification element + * @returns The last update time of the notification + */ +function getNotificationLastUpdatedTime(notificationElement) { + return $(notificationElement).attr("lastUpdatedTime"); +} + function likePost(postId) { - $.getJSON("like.ajax", { "type": "post", "post" : postId, "formPassword": getFormPassword() }, function(data, textStatus) { + ajaxGet("like.ajax", { "type": "post", "post" : postId, "formPassword": getFormPassword() }, function(data, textStatus) { if ((data == null) || !data.success) { return; } @@ -429,7 +438,7 @@ function likePost(postId) { } function unlikePost(postId) { - $.getJSON("unlike.ajax", { "type": "post", "post" : postId, "formPassword": getFormPassword() }, function(data, textStatus) { + ajaxGet("unlike.ajax", { "type": "post", "post" : postId, "formPassword": getFormPassword() }, function(data, textStatus) { if ((data == null) || !data.success) { return; } @@ -442,9 +451,9 @@ function unlikePost(postId) { } function updatePostLikes(postId) { - $.getJSON("getLikes.ajax", { "type": "post", "post": postId }, function(data, textStatus) { + ajaxGet("getLikes.ajax", { "type": "post", "post": postId }, function(data, textStatus) { if ((data != null) && data.success) { - $("#sone .post#" + postId + " > .inner-part > .status-line .likes").toggleClass("hidden", data.likes == 0) + $("#sone .post#" + postId + " > .inner-part > .status-line .likes").toggleClass("hidden", data.likes == 0); $("#sone .post#" + postId + " > .inner-part > .status-line .likes span.like-count").text(data.likes); $("#sone .post#" + postId + " > .inner-part > .status-line .likes > span").attr("title", generateSoneList(data.sones)); } @@ -454,7 +463,7 @@ function updatePostLikes(postId) { } function likeReply(replyId) { - $.getJSON("like.ajax", { "type": "reply", "reply" : replyId, "formPassword": getFormPassword() }, function(data, textStatus) { + ajaxGet("like.ajax", { "type": "reply", "reply" : replyId, "formPassword": getFormPassword() }, function(data, textStatus) { if ((data == null) || !data.success) { return; } @@ -467,7 +476,7 @@ function likeReply(replyId) { } function unlikeReply(replyId) { - $.getJSON("unlike.ajax", { "type": "reply", "reply" : replyId, "formPassword": getFormPassword() }, function(data, textStatus) { + ajaxGet("unlike.ajax", { "type": "reply", "reply" : replyId, "formPassword": getFormPassword() }, function(data, textStatus) { if ((data == null) || !data.success) { return; } @@ -486,7 +495,7 @@ function unlikeReply(replyId) { * The ID of the Sone to trust */ function trustSone(soneId) { - $.getJSON("trustSone.ajax", { "formPassword" : getFormPassword(), "sone" : soneId }, function(data, textStatus) { + ajaxGet("trustSone.ajax", { "formPassword" : getFormPassword(), "sone" : soneId }, function(data, textStatus) { if ((data != null) && data.success) { updateTrustControls(soneId, data.trustValue); } @@ -500,7 +509,7 @@ function trustSone(soneId) { * The ID of the Sone to distrust */ function distrustSone(soneId) { - $.getJSON("distrustSone.ajax", { "formPassword" : getFormPassword(), "sone" : soneId }, function(data, textStatus) { + ajaxGet("distrustSone.ajax", { "formPassword" : getFormPassword(), "sone" : soneId }, function(data, textStatus) { if ((data != null) && data.success) { updateTrustControls(soneId, data.trustValue); } @@ -514,7 +523,7 @@ function distrustSone(soneId) { * The ID of the Sone to untrust */ function untrustSone(soneId) { - $.getJSON("untrustSone.ajax", { "formPassword" : getFormPassword(), "sone" : soneId }, function(data, textStatus) { + ajaxGet("untrustSone.ajax", { "formPassword" : getFormPassword(), "sone" : soneId }, function(data, textStatus) { if ((data != null) && data.success) { updateTrustControls(soneId, data.trustValue); } @@ -555,7 +564,7 @@ function updateTrustControls(soneId, trustValue) { */ function bookmarkPost(postId) { (function(postId) { - $.getJSON("bookmark.ajax", {"formPassword": getFormPassword(), "type": "post", "post": postId}, function(data, textStatus) { + ajaxGet("bookmark.ajax", {"formPassword": getFormPassword(), "type": "post", "post": postId}, function(data, textStatus) { if ((data != null) && data.success) { getPost(postId).find(".bookmark").toggleClass("hidden", true); getPost(postId).find(".unbookmark").toggleClass("hidden", false); @@ -571,7 +580,7 @@ function bookmarkPost(postId) { * The ID of the post to unbookmark */ function unbookmarkPost(postId) { - $.getJSON("unbookmark.ajax", {"formPassword": getFormPassword(), "type": "post", "post": postId}, function(data, textStatus) { + ajaxGet("unbookmark.ajax", {"formPassword": getFormPassword(), "type": "post", "post": postId}, function(data, textStatus) { if ((data != null) && data.success) { getPost(postId).find(".bookmark").toggleClass("hidden", false); getPost(postId).find(".unbookmark").toggleClass("hidden", true); @@ -580,9 +589,9 @@ function unbookmarkPost(postId) { } function updateReplyLikes(replyId) { - $.getJSON("getLikes.ajax", { "type": "reply", "reply": replyId }, function(data, textStatus) { + ajaxGet("getLikes.ajax", { "type": "reply", "reply": replyId }, function(data, textStatus) { if ((data != null) && data.success) { - $("#sone .reply#" + replyId + " .status-line .likes").toggleClass("hidden", data.likes == 0) + $("#sone .reply#" + replyId + " .status-line .likes").toggleClass("hidden", data.likes == 0); $("#sone .reply#" + replyId + " .status-line .likes span.like-count").text(data.likes); $("#sone .reply#" + replyId + " .status-line .likes > span").attr("title", generateSoneList(data.sones)); } @@ -605,7 +614,7 @@ function updateReplyLikes(replyId) { * parameters: success, error, replyId) */ function postReply(sender, postId, text, callbackFunction) { - $.getJSON("createReply.ajax", { "formPassword" : getFormPassword(), "sender": sender, "post" : postId, "text": text }, function(data, textStatus) { + ajaxGet("createReply.ajax", { "formPassword" : getFormPassword(), "sender": sender, "post" : postId, "text": text }, function(data, textStatus) { if (data == null) { /* TODO - show error */ return; @@ -633,7 +642,7 @@ function ajaxifySone(soneElement) { */ $(".follow", soneElement).submit(function() { var followElement = this; - $.getJSON("followSone.ajax", { "sone": getSoneId(this), "formPassword": getFormPassword() }, function() { + ajaxGet("followSone.ajax", { "sone": getSoneId(this), "formPassword": getFormPassword() }, function() { $(followElement).addClass("hidden"); $(followElement).parent().find(".unfollow").removeClass("hidden"); }); @@ -641,7 +650,7 @@ function ajaxifySone(soneElement) { }); $(".unfollow", soneElement).submit(function() { var unfollowElement = this; - $.getJSON("unfollowSone.ajax", { "sone": getSoneId(this), "formPassword": getFormPassword() }, function() { + ajaxGet("unfollowSone.ajax", { "sone": getSoneId(this), "formPassword": getFormPassword() }, function() { $(unfollowElement).addClass("hidden"); $(unfollowElement).parent().find(".follow").removeClass("hidden"); }); @@ -649,7 +658,7 @@ function ajaxifySone(soneElement) { }); $(".lock", soneElement).submit(function() { var lockElement = this; - $.getJSON("lockSone.ajax", { "sone" : getSoneId(this), "formPassword" : getFormPassword() }, function() { + ajaxGet("lockSone.ajax", { "sone" : getSoneId(this), "formPassword" : getFormPassword() }, function() { $(lockElement).addClass("hidden"); $(lockElement).parent().find(".unlock").removeClass("hidden"); }); @@ -657,7 +666,7 @@ function ajaxifySone(soneElement) { }); $(".unlock", soneElement).submit(function() { var unlockElement = this; - $.getJSON("unlockSone.ajax", { "sone" : getSoneId(this), "formPassword" : getFormPassword() }, function() { + ajaxGet("unlockSone.ajax", { "sone" : getSoneId(this), "formPassword" : getFormPassword() }, function() { $(unlockElement).addClass("hidden"); $(unlockElement).parent().find(".lock").removeClass("hidden"); }); @@ -666,7 +675,7 @@ function ajaxifySone(soneElement) { /* mark Sone as known when clicking it. */ $(soneElement).click(function() { - markSoneAsKnown(soneElement); + markSoneAsKnown(this); }); } @@ -750,14 +759,33 @@ function ajaxifyPost(postElement) { /* convert “show source” link into javascript function. */ $(postElement).find(".show-source").each(function() { $("a", this).click(function() { + post = getPostElement(this); + rawPostText = $(".post-text.raw-text", post); + rawPostText.toggleClass("hidden"); + if (rawPostText.hasClass("hidden")) { + $(".post-text.short-text", post).removeClass("hidden"); + $(".post-text.text", post).addClass("hidden"); + $(".expand-post-text", post).removeClass("hidden"); + } else { + $(".post-text.short-text", post).addClass("hidden"); + $(".post-text.text", post).addClass("hidden"); + $(".expand-post-text", post).addClass("hidden"); + } + return false; + }); + }); + + /* convert “show more” link into javascript function. */ + $(postElement).find(".expand-post-text").each(function() { + $(this).click(function() { $(".post-text.text", getPostElement(this)).toggleClass("hidden"); - $(".post-text.raw-text", getPostElement(this)).toggleClass("hidden"); + $(".post-text.short-text", getPostElement(this)).toggleClass("hidden"); return false; }); }); /* add “comment” link. */ - addCommentLink(getPostId(postElement), postElement, $(postElement).find(".post-status-line .time")); + addCommentLink(getPostId(postElement), getPostAuthor(postElement), postElement, $(postElement).find(".post-status-line .permalink-author")); /* process all replies. */ replyIds = []; @@ -817,13 +845,32 @@ function ajaxifyReply(replyElement) { }); }); })(replyElement); - addCommentLink(getPostId(replyElement), replyElement, $(replyElement).find(".reply-status-line .time")); + addCommentLink(getPostId(replyElement), getReplyAuthor(replyElement), replyElement, $(replyElement).find(".reply-status-line .permalink-author")); /* convert “show source” link into javascript function. */ $(replyElement).find(".show-reply-source").each(function() { $("a", this).click(function() { + reply = getReplyElement(this); + rawReplyText = $(".reply-text.raw-text", reply); + rawReplyText.toggleClass("hidden"); + if (rawReplyText.hasClass("hidden")) { + $(".reply-text.short-text", reply).removeClass("hidden"); + $(".reply-text.text", reply).addClass("hidden"); + $(".expand-reply-text", reply).removeClass("hidden"); + } else { + $(".reply-text.short-text", reply).addClass("hidden"); + $(".reply-text.text", reply).addClass("hidden"); + $(".expand-reply-text", reply).addClass("hidden"); + } + return false; + }); + }); + + /* convert “show more” link into javascript function. */ + $(replyElement).find(".expand-reply-text").each(function() { + $(this).click(function() { $(".reply-text.text", getReplyElement(this)).toggleClass("hidden"); - $(".reply-text.raw-text", getReplyElement(this)).toggleClass("hidden"); + $(".reply-text.short-text", getReplyElement(this)).toggleClass("hidden"); return false; }); }); @@ -859,19 +906,23 @@ function ajaxifyNotification(notification) { notification.find(".text").addClass("hidden"); } notification.find("form.mark-as-read button").click(function() { - $.getJSON("markAsKnown.ajax", {"formPassword": getFormPassword(), "type": $(":input[name=type]", this.form).val(), "id": $(":input[name=id]", this.form).val()}); + allIds = $(":input[name=id]", this.form).val().split(" "); + for (index = 0; index < allIds.length; index += 16) { + ids = allIds.slice(index, index + 16).join(" "); + ajaxGet("markAsKnown.ajax", {"formPassword": getFormPassword(), "type": $(":input[name=type]", this.form).val(), "id": ids}); + } }); notification.find("a[class^='link-']").each(function() { linkElement = $(this); if (linkElement.is("[href^='viewPost']")) { id = linkElement.attr("class").substr(5); if (hasPost(id)) { - linkElement.attr("href", "#post-" + id); + linkElement.attr("href", "#post-" + id).addClass("in-page-link"); } } }); notification.find("form.dismiss button").click(function() { - $.getJSON("dismissNotification.ajax", { "formPassword" : getFormPassword(), "notification" : notification.attr("id") }, function(data, textStatus) { + ajaxGet("dismissNotification.ajax", { "formPassword" : getFormPassword(), "notification" : notification.attr("id") }, function(data, textStatus) { /* dismiss in case of error, too. */ notification.slideUp(); }, function(xmlHttpRequest, textStatus, error) { @@ -911,8 +962,8 @@ function checkForRemovedSones(oldNotification, newNotification) { if (getNotificationId(oldNotification) != "new-sone-notification") { return; } - oldIds = getElementIds(oldNotification, ".sone-id"); - newIds = getElementIds(newNotification, ".sone-id"); + oldIds = getElementIds(oldNotification, ".new-sone-id"); + newIds = getElementIds(newNotification, ".new-sone-id"); $.each(oldIds, function(index, value) { if ($.inArray(value, newIds) == -1) { markSoneAsKnown(getSone(value), true); @@ -966,12 +1017,16 @@ function checkForRemovedReplies(oldNotification, newNotification) { } function getStatus() { - $.getJSON("getStatus.ajax", {"loadAllSones": isKnownSonesPage()}, function(data, textStatus) { + ajaxGet("getStatus.ajax", isViewSonePage() ? {"soneIds": getShownSoneId() } : {"loadAllSones": isKnownSonesPage()}, function(data, textStatus) { if ((data != null) && data.success) { /* process Sone information. */ $.each(data.sones, function(index, value) { - updateSoneStatus(value.id, value.name, value.status, value.modified, value.locked, value.lastUpdatedUnknown ? null : value.lastUpdated); + updateSoneStatus(value.id, value.name, value.status, value.modified, value.locked, value.lastUpdatedUnknown ? null : value.lastUpdated, value.lastUpdatedText); }); + notLoggedIn = !data.loggedIn; + if (!notLoggedIn) { + showOfflineMarker(!online); + } /* search for removed notifications. */ $("#sone #notification-area .notification").each(function() { notificationId = $(this).attr("id"); @@ -984,7 +1039,7 @@ function getStatus() { }); if (!foundNotification) { if (notificationId == "new-sone-notification") { - $(".sone-id", this).each(function(index, element) { + $(".new-sone-id", this).each(function(index, element) { soneId = $(this).text(); markSoneAsKnown(getSone(soneId), true); }); @@ -1009,25 +1064,16 @@ function getStatus() { } }); /* process notifications. */ + notificationIds = []; $.each(data.notifications, function(index, value) { oldNotification = getNotification(value.id); - notification = ajaxifyNotification(createNotification(value.id, value.text, value.dismissable)).hide(); - if (oldNotification.length != 0) { - if ((oldNotification.find(".short-text").length > 0) && (notification.find(".short-text").length > 0)) { - opened = oldNotification.is(":visible") && oldNotification.find(".short-text").hasClass("hidden"); - notification.find(".short-text").toggleClass("hidden", opened); - notification.find(".text").toggleClass("hidden", !opened); - } - checkForRemovedSones(oldNotification, notification); - checkForRemovedPosts(oldNotification, notification); - checkForRemovedReplies(oldNotification, notification); - oldNotification.replaceWith(notification.show()); - } else { - $("#sone #notification-area").append(notification); - notification.slideDown(); - setActivity(); + if ((oldNotification.length == 0) || (value.lastUpdatedTime > getNotificationLastUpdatedTime(oldNotification))) { + notificationIds.push(value.id); } }); + if (notificationIds.length > 0) { + loadNotifications(notificationIds); + } /* process new posts. */ $.each(data.newPosts, function(index, value) { loadNewPost(value.id, value.sone, value.recipient, value.time); @@ -1042,10 +1088,46 @@ function getStatus() { /* data.success was false, wait 30 seconds. */ setTimeout(getStatus, 30000); } - }, function(xmlHttpRequest, textStatus, error) { - /* something really bad happend, wait a minute. */ - setTimeout(getStatus, 60000); - }) + }, function() { + statusRequestQueued = false; + ajaxError(); + }); +} + +/** + * Requests multiple notifications from Sone and displays them. + * + * @param notificationIds + * Array of IDs of the notifications to load + */ +function loadNotifications(notificationIds) { + ajaxGet("getNotification.ajax", {"notifications": notificationIds.join(",")}, function(data, textStatus) { + if (!data || !data.success) { + // TODO - show error + return; + } + $.each(data.notifications, function(index, value) { + oldNotification = getNotification(value.id); + notification = ajaxifyNotification(createNotification(value.id, value.lastUpdatedTime, value.text, value.dismissable)).hide(); + if (oldNotification.length != 0) { + if ((oldNotification.find(".short-text").length > 0) && (notification.find(".short-text").length > 0)) { + opened = oldNotification.is(":visible") && oldNotification.find(".short-text").hasClass("hidden"); + notification.find(".short-text").toggleClass("hidden", opened); + notification.find(".text").toggleClass("hidden", !opened); + } + checkForRemovedSones(oldNotification, notification); + checkForRemovedPosts(oldNotification, notification); + checkForRemovedReplies(oldNotification, notification); + oldNotification.replaceWith(notification.show()); + } else { + $("#sone #notification-area").append(notification); + if (value.id.substring(0, 5) != "local") { + notification.slideDown(); + setActivity(); + } + } + }); + }); } /** @@ -1078,6 +1160,22 @@ function isIndexPage() { } /** + * Returns the current page of the selected pagination. If no pagination can be + * found with the given selector, {@code 1} is returned. + * + * @param paginationSelector + * The pagination selector + * @returns The current page of the pagination + */ +function getPage(paginationSelector) { + pagination = $(paginationSelector); + if (pagination.length > 0) { + return $(".current-page", paginationSelector).text(); + } + return 1; +} + +/** * Returns whether the current page is a “view Sone” page. * * @returns {Boolean} true if the current page is a “view Sone” @@ -1155,9 +1253,9 @@ function loadNewPost(postId, soneId, recipientId, time) { if (hasPost(postId)) { return; } - if (!isIndexPage()) { + if (!isIndexPage() || (getPage(".pagination-index") > 1)) { if (!isViewPostPage() || (getShownPostId() != postId)) { - if (!isViewSonePage() || ((getShownSoneId() != soneId) && (getShownSoneId() != recipientId))) { + if (!isViewSonePage() || ((getShownSoneId() != soneId) && (getShownSoneId() != recipientId)) || (getPage(".post-navigation") > 1)) { return; } } @@ -1165,12 +1263,12 @@ function loadNewPost(postId, soneId, recipientId, time) { if (getPostTime($("#sone .post").last()) > time) { return; } - $.getJSON("getPost.ajax", { "post" : postId }, function(data, textStatus) { + ajaxGet("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)))) { + if ((!isIndexPage() || (getPage(".pagination-index") > 1)) && !(isViewSonePage() && ((getShownSoneId() == data.post.sone) || (getShownSoneId() == data.post.recipient) || (getPage(".post-navigation") > 1)))) { return; } var firstOlderPost = null; @@ -1181,6 +1279,9 @@ function loadNewPost(postId, soneId, recipientId, time) { } }); newPost = $(data.post.html).addClass("hidden"); + if ($(".post-author-local", newPost).text() == "true") { + newPost.removeClass("new"); + } if (firstOlderPost != null) { newPost.insertBefore(firstOlderPost); } @@ -1199,7 +1300,7 @@ function loadNewReply(replyId, soneId, postId, postSoneId) { if (!hasPost(postId)) { return; } - $.getJSON("getReply.ajax", { "reply": replyId }, function(data, textStatus) { + ajaxGet("getReply.ajax", { "reply": replyId }, function(data, textStatus) { /* find post. */ if ((data != null) && data.success) { if (hasReply(data.reply.id)) { @@ -1214,6 +1315,14 @@ function loadNewReply(replyId, soneId, postId, postSoneId) { } }); newReply = $(data.reply.html).addClass("hidden"); + if ($(".reply-author-local", newReply).text() == "true") { + newReply.removeClass("new"); + (function(newReply) { + setTimeout(function() { + markReplyAsKnown(newReply, false); + }, 5000); + })(newReply); + } if (firstNewerReply != null) { newReply.insertBefore(firstNewerReply); } else { @@ -1243,11 +1352,10 @@ function loadNewReply(replyId, soneId, postId, postSoneId) { * request */ function markSoneAsKnown(soneElement, skipRequest) { - if ($(".new", soneElement).length > 0) { - if ((typeof skipRequest != "undefined") && !skipRequest) { - $.getJSON("maskAsKnown.ajax", {"formPassword": getFormPassword(), "type": "sone", "id": getSoneId(soneElement)}, function(data, textStatus) { - $(soneElement).removeClass("new"); - }); + if ($(soneElement).is(".new")) { + $(soneElement).removeClass("new"); + if ((typeof skipRequest == "undefined") || !skipRequest) { + ajaxGet("markAsKnown.ajax", {"formPassword": getFormPassword(), "type": "sone", "id": getSoneId(soneElement)}); } } } @@ -1255,15 +1363,15 @@ function markSoneAsKnown(soneElement, skipRequest) { function markPostAsKnown(postElements, skipRequest) { $(postElements).each(function() { postElement = this; - if ($(postElement).hasClass("new")) { + if ($(postElement).hasClass("new") || ((typeof skipRequest != "undefined") && !skipRequest)) { (function(postElement) { $(postElement).removeClass("new"); - $(".click-to-show", postElement).removeClass("new"); if ((typeof skipRequest == "undefined") || !skipRequest) { - $.getJSON("markAsKnown.ajax", {"formPassword": getFormPassword(), "type": "post", "id": getPostId(postElement)}); + ajaxGet("markAsKnown.ajax", {"formPassword": getFormPassword(), "type": "post", "id": getPostId(postElement)}); } })(postElement); } + $(".click-to-show", postElement).removeClass("new"); }); markReplyAsKnown($(postElements).find(".reply")); } @@ -1271,11 +1379,11 @@ function markPostAsKnown(postElements, skipRequest) { function markReplyAsKnown(replyElements, skipRequest) { $(replyElements).each(function() { replyElement = this; - if ($(replyElement).hasClass("new")) { + if ($(replyElement).hasClass("new") || ((typeof skipRequest != "undefined") && !skipRequest)) { (function(replyElement) { $(replyElement).removeClass("new"); if ((typeof skipRequest == "undefined") || !skipRequest) { - $.getJSON("markAsKnown.ajax", {"formPassword": getFormPassword(), "type": "reply", "id": getReplyId(replyElement)}); + ajaxGet("markAsKnown.ajax", {"formPassword": getFormPassword(), "type": "reply", "id": getReplyId(replyElement)}); } })(replyElement); } @@ -1313,7 +1421,7 @@ function updatePostTime(postId, timeText, refreshTime, tooltip) { * Comma-separated post IDs */ function updatePostTimes(postIds) { - $.getJSON("getTimes.ajax", { "posts" : postIds }, function(data, textStatus) { + ajaxGet("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); @@ -1350,7 +1458,7 @@ function updateReplyTime(replyId, timeText, refreshTime, tooltip) { * Comma-separated post IDs */ function updateReplyTimes(replyIds) { - $.getJSON("getTimes.ajax", { "replies" : replyIds }, function(data, textStatus) { + ajaxGet("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); @@ -1439,10 +1547,10 @@ function changeIcon(iconUrl) { * true if the notification can be dismissed by the * user */ -function createNotification(id, text, dismissable) { - notification = $("
").addClass("notification").attr("id", id); +function createNotification(id, lastUpdatedTime, text, dismissable) { + notification = $("
").addClass("notification").attr("id", id).attr("lastUpdatedTime", lastUpdatedTime); if (dismissable) { - dismissForm = $("#sone #notification-area #notification-dismiss-template").clone().removeClass("hidden").removeAttr("id") + dismissForm = $("#sone #notification-area #notification-dismiss-template").clone().removeClass("hidden").removeAttr("id"); dismissForm.find("input[name=notification]").val(id); notification.append(dismissForm); } @@ -1468,7 +1576,7 @@ function showNotificationDetails(notificationId) { * The ID of the field to delete */ function deleteProfileField(fieldId) { - $.getJSON("deleteProfileField.ajax", {"formPassword": getFormPassword(), "field": fieldId}, function(data, textStatus) { + ajaxGet("deleteProfileField.ajax", {"formPassword": getFormPassword(), "field": fieldId}, function(data, textStatus) { if (data && data.success) { $("#sone .profile-field#" + data.field.id).slideUp(); } @@ -1486,7 +1594,7 @@ function deleteProfileField(fieldId) { * Called when the renaming was successful */ function editProfileField(fieldId, newName, successFunction) { - $.getJSON("editProfileField.ajax", {"formPassword": getFormPassword(), "field": fieldId, "name": newName}, function(data, textStatus) { + ajaxGet("editProfileField.ajax", {"formPassword": getFormPassword(), "field": fieldId, "name": newName}, function(data, textStatus) { if (data && data.success) { successFunction(); } @@ -1504,7 +1612,7 @@ function editProfileField(fieldId, newName, successFunction) { * Function to call on success */ function moveProfileField(fieldId, direction, successFunction) { - $.getJSON("moveProfileField.ajax", {"formPassword": getFormPassword(), "field": fieldId, "direction": direction}, function(data, textStatus) { + ajaxGet("moveProfileField.ajax", {"formPassword": getFormPassword(), "field": fieldId, "direction": direction}, function(data, textStatus) { if (data && data.success) { successFunction(); } @@ -1535,11 +1643,53 @@ function moveProfileFieldDown(fieldId, successFunction) { moveProfileField(fieldId, "down", successFunction); } +var statusRequestQueued = true; + +/** + * Sets the status of the web interface as offline. + */ +function ajaxError() { + online = false; + showOfflineMarker(true); + if (!statusRequestQueued) { + setTimeout(getStatus, 5000); + statusRequestQueued = true; + } +} + +/** + * Sets the status of the web interface as online. + */ +function ajaxSuccess() { + online = true; + showOfflineMarker(!online || (initiallyLoggedIn && notLoggedIn)); +} + +/** + * Shows or hides the offline marker. + * + * @param visible + * {@code true} to display the offline marker, {@code false} to hide + * it + */ +function showOfflineMarker(visible) { + /* jQuery documentation says toggle() works the other way around?! */ + $("#sone #offline-marker").toggle(visible); + if (visible) { + $("#sone #main").addClass("offline"); + } else { + $("#sone #main").removeClass("offline"); + } +} + // // EVERYTHING BELOW HERE IS EXECUTED AFTER LOADING THE PAGE // var focus = true; +var online = true; +var initiallyLoggedIn = $("#sone #loggedIn").text() == "true"; +var notLoggedIn = !initiallyLoggedIn; $(document).ready(function() { @@ -1561,7 +1711,7 @@ $(document).ready(function() { } 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) { + ajaxGet("createPost.ajax", { "formPassword": getFormPassword(), "sender": sender, "text": text }, function(data, textStatus) { button.removeAttr("disabled"); }); $(this).find(":input[name=sender]").val(getCurrentSoneId()); @@ -1590,7 +1740,7 @@ $(document).ready(function() { $("#sone #post-message").submit(function() { 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 }); + ajaxGet("createPost.ajax", { "formPassword": getFormPassword(), "recipient": getShownSoneId(), "sender": sender, "text": text }); $(this).find(":input[name=sender]").val(getCurrentSoneId()); $(this).find(":input[name=text]:enabled").val("").blur(); $(this).find(".sender").hide(); @@ -1625,7 +1775,7 @@ $(document).ready(function() { allReplies = $(this).find(".reply"); if (allReplies.length > 2) { newHidden = false; - for (replyIndex = 0; replyIndex < (allReplies.length - 2); ++replyIndex) { + for (replyIndex = 0; !newHidden && (replyIndex < (allReplies.length - 2)); ++replyIndex) { $(allReplies[replyIndex]).addClass("hidden"); newHidden |= $(allReplies[replyIndex]).hasClass("new"); } @@ -1655,6 +1805,11 @@ $(document).ready(function() { ajaxifyNotification($(this)); }); + /* disable all permalinks. */ + $(".permalink").click(function() { + return false; + }); + /* activate status polling. */ setTimeout(getStatus, 5000); @@ -1664,6 +1819,6 @@ $(document).ready(function() { resetActivity(); }).blur(function() { focus = false; - }) + }); });