Show and manage linked elements in web interface
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 7 Apr 2017 20:55:54 +0000 (22:55 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 8 Apr 2017 13:22:57 +0000 (15:22 +0200)
src/main/resources/static/css/sone.css
src/main/resources/static/javascript/sone.js
src/main/resources/templates/linked/image.html
src/main/resources/templates/linked/notLoaded.html
src/test/kotlin/net/pterodactylus/sone/template/LinkedElementRenderFilterTest.kt

index 34dad50..7392483 100644 (file)
@@ -444,7 +444,7 @@ textarea {
        margin-top: 1ex;
 }
 
-#sone .post .linked-element {
+#sone .post .linked-element.loaded .image {
        display: inline-block;
        border: solid 1px black;
        width: 160px;
@@ -515,7 +515,7 @@ textarea {
        margin-top: 1ex;
 }
 
-#sone .post .reply .linked-element {
+#sone .post .reply .linked-element.loaded .image {
        display: inline-block;
        border: solid 1px black;
        width: 120px;
index 7ef585d..a003780 100644 (file)
@@ -1194,7 +1194,13 @@ function checkForRemovedReplies(oldNotification, newNotification) {
 }
 
 function getStatus() {
-       ajaxGet("getStatus.ajax", isViewSonePage() ? {"soneIds": getShownSoneId() } : isKnownSonesPage() ? {"soneIds": getShownSoneIds() } : {}, function(data, textStatus) {
+       var parameters = isViewSonePage() ? {"soneIds": getShownSoneId() } : isKnownSonesPage() ? {"soneIds": getShownSoneIds() } : {};
+       $.extend(parameters, {
+               "elements": JSON.stringify($(".linked-element.not-loaded").map(function () {
+                       return $(this).attr("title");
+               }).toArray())
+       });
+       ajaxGet("getStatus.ajax", parameters, function(data, textStatus) {
                if ((data != null) && data.success) {
                        /* process Sone information. */
                        $.each(data.sones, function(index, value) {
@@ -1216,6 +1222,9 @@ function getStatus() {
                                        loadNewReply(value.id, value.sone, value.post, value.postSone);
                                });
                        }
+                       if (data.linkedElements) {
+                               loadLinkedElements(data.linkedElements)
+                       }
                        /* do it again in 5 seconds. */
                        setTimeout(getStatus, 5000);
                } else {
@@ -1520,6 +1529,37 @@ function loadNewReply(replyId, soneId, postId, postSoneId) {
        });
 }
 
+function loadLinkedElements(links) {
+       var failedElements = links.filter(function(element) {
+               return element.failed;
+       });
+       if (failedElements.length > 0) {
+               failedElements.forEach(function(element) {
+                       $(getLinkedElement(element.link)).remove()
+               });
+       }
+       var loadedElements = links.filter(function(element) {
+               return !element.loading && !element.failed;
+       });
+       if (loadedElements.length > 0) {
+               ajaxGet("getLinkedElement.ajax", {
+                       "elements": JSON.stringify(loadedElements.map(function(element) {
+                               return element.link;
+                       }))
+               }, function (data, textStatus) {
+                       if ((data != null) && (data.success)) {
+                               data.linkedElements.forEach(function (linkedElement) {
+                                       $(getLinkedElement(linkedElement.link)).replaceWith(linkedElement.html);
+                               });
+                       }
+               });
+       }
+}
+
+function getLinkedElement(link) {
+       return $(".linked-element[title='" + link + "']")[0]
+}
+
 /**
  * Marks the given Sone as known if it is still new.
  *
index 17fa28a..d7fef5a 100644 (file)
@@ -1 +1 @@
-<a href="/<% link|html>"><span class="linked-element" title="<% link|html>" style="background-image: url('/<% link|html>')"></span></a>
+<span class="linked-element loaded" title="<%link|html>"><a href="/<% link|html>"><span class="image" style="background-image: url('/<% link|html>')"></span></a></span>
index 87ee516..4a2d977 100644 (file)
@@ -1 +1 @@
-<span class="linked-element" title="<% link|html>" style="background-image: url('images/loading-animation.gif')"></span>
+<span class="linked-element not-loaded" title="<% link|html>"/>
index e8e7fc3..c3e26c0 100644 (file)
@@ -34,26 +34,28 @@ class LinkedElementRenderFilterTest {
        }
 
        @Test
-       fun `filter renders loading animation for not loaded elements`() {
+       fun `filter renders empty span for not loaded elements`() {
                val html = filter.format(null, LinkedElement("KSK@gpl.png", loading = true), emptyMap<String, Any?>()) as String
                val spanNode = Jsoup.parseBodyFragment(html).body().child(0)
                assertThat(spanNode.nodeName(), `is`("span"))
-               assertThat(spanNode.attr("class"), `is`("linked-element"))
+               assertThat(spanNode.attr("class"), `is`("linked-element not-loaded"))
                assertThat(spanNode.attr("title"), `is`("KSK@gpl.png"))
-               assertThat(spanNode.attr("style"), `is`("background-image: url('images/loading-animation.gif')"))
+               assertThat(spanNode.hasAttr("style"), `is`(false))
+               assertThat(spanNode.children().isEmpty(), `is`(true))
        }
 
        @Test
        fun `filter can render linked images`() {
                val html = filter.format(null, LinkedElement("KSK@gpl.png"), emptyMap<String, Any?>()) as String
-               val linkNode = Jsoup.parseBodyFragment(html).body().child(0)
+               val outerSpanNode = Jsoup.parseBodyFragment(html).body().child(0)
+               assertThat(outerSpanNode.nodeName(), `is`("span"))
+               assertThat(outerSpanNode.attr("class"), `is`("linked-element loaded"))
+               assertThat(outerSpanNode.attr("title"), `is`("KSK@gpl.png"))
+               val linkNode = outerSpanNode.child(0)
                assertThat(linkNode.nodeName(), `is`("a"))
                assertThat(linkNode.attr("href"), `is`("/KSK@gpl.png"))
-               val spanNode = linkNode.child(0)
-               assertThat(spanNode.nodeName(), `is`("span"))
-               assertThat(spanNode.attr("class"), `is`("linked-element"))
-               assertThat(spanNode.attr("title"), `is`("KSK@gpl.png"))
-               assertThat(spanNode.attr("style"), `is`("background-image: url('/KSK@gpl.png')"))
+               val innerSpanNode = linkNode.child(0)
+               assertThat(innerSpanNode.attr("style"), `is`("background-image: url('/KSK@gpl.png')"))
        }
 
        @Test