+/**
+ * Returns the notification hash. This hash is used in {@link #getStatus()} to
+ * determine whether the notifications changed and need to be reloaded.
+ */
+function getNotificationHash() {
+ return sone.find("#notification-area #notification-hash").text();
+}
+
+/**
+ * Sets the notification hash.
+ *
+ * @param notificationHash
+ * The new notification hash
+ */
+function setNotificationHash(notificationHash) {
+ sone.find("#notification-area #notification-hash").text(notificationHash);
+}
+
+/**
+ * Retrieves element IDs from notification elements.
+ *
+ * @param notification
+ * The notification element
+ * @param selector
+ * The selector of the element containing the ID as text
+ * @returns All extracted IDs
+ */
+function getElementIds(notification, selector) {
+ const elementIds = [];
+ $(selector, notification).each(function() {
+ elementIds.push($(this).text());
+ });
+ return elementIds;
+}
+
+/**
+ * Compares the given notification elements and calls {@link #markSoneAsKnown()}
+ * for every ID that is contained in the old notification but not in the new.
+ *
+ * @param oldNotification
+ * The old notification element
+ * @param newNotification
+ * The new notification element
+ */
+function checkForRemovedSones(oldNotification, newNotification) {
+ if (getNotificationId(oldNotification) !== "new-sone-notification") {
+ return;
+ }
+ const oldIds = getElementIds(oldNotification, ".new-sone-id");
+ const newIds = getElementIds(newNotification, ".new-sone-id");
+ $.each(oldIds, function(index, value) {
+ if ($.inArray(value, newIds) === -1) {
+ markSoneAsKnown(getSone(value), true);
+ }
+ });
+}
+
+/**
+ * Compares the given notification elements and calls {@link #markPostAsKnown()}
+ * for every ID that is contained in the old notification but not in the new.
+ *
+ * @param oldNotification
+ * The old notification element
+ * @param newNotification
+ * The new notification element
+ */
+function checkForRemovedPosts(oldNotification, newNotification) {
+ if (getNotificationId(oldNotification) !== "new-post-notification") {
+ return;
+ }
+ const oldIds = getElementIds(oldNotification, ".post-id");
+ const newIds = getElementIds(newNotification, ".post-id");
+ $.each(oldIds, function(index, value) {
+ if ($.inArray(value, newIds) === -1) {
+ markPostAsKnown(getPost(value), true);
+ }
+ });
+}
+
+/**
+ * Compares the given notification elements and calls
+ * {@link #markReplyAsKnown()} for every ID that is contained in the old
+ * notification but not in the new.
+ *
+ * @param oldNotification
+ * The old notification element
+ * @param newNotification
+ * The new notification element
+ */
+function checkForRemovedReplies(oldNotification, newNotification) {
+ if (getNotificationId(oldNotification) !== "new-reply-notification") {
+ return;
+ }
+ const oldIds = getElementIds(oldNotification, ".reply-id");
+ const newIds = getElementIds(newNotification, ".reply-id");
+ $.each(oldIds, function(index, value) {
+ if ($.inArray(value, newIds) === -1) {
+ markReplyAsKnown(getReply(value), true);
+ }
+ });
+}
+
+/**
+ * The URLs of not-loaded elements are part of the GET request’s URL. As
+ * both browsers and HTTP servers do have differing limits on URL length
+ * (the HTTP 1.1 RFC states 8000 bytes but most browsers only support up
+ * to 2000 bytes) we will return a random selection of not-loaded URLs we
+ * want to refresh the status from up until we are at approximately 1000
+ * bytes (as the rest of the URL also needs some space).
+ *
+ * @return An array of not-loaded element URLs that will have a total length
+ * of 1000 bytes or fewer
+ */
+function getRandomSelectionOfElementsToUpdate() {
+ const notLoadedElementUrls = $(".linked-element.not-loaded").map(function(_, element) {
+ return $(element).prop("title");
+ }).toArray();
+ shuffleArray(notLoadedElementUrls);
+ const selectedElementUrls = Array();
+ let currentCombinedStringLength = 0;
+ $(notLoadedElementUrls).each(function(_, elementUrl) {
+ if ((currentCombinedStringLength + elementUrl.length) <= 1000) {
+ selectedElementUrls.push(elementUrl);
+ currentCombinedStringLength += elementUrl.length;
+ }
+ });
+ return selectedElementUrls;
+}
+
+// shamelessly stolen from https://stackoverflow.com/a/12646864/43582
+function shuffleArray(array) {
+ for (let i = array.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ const temp = array[i];
+ array[i] = array[j];
+ array[j] = temp;
+ }
+}
+