Page 1 of 2

[RELEASE] Sort Topics by Creation Date

Posted: Sat Nov 20, 2021 6:59 pm
by Expression
Hey everyone, long time lurker and brand new member of the forum. I was inspired by the user samfishercarl that made an anti-necro chrome extension, so I took it a little bit further and made something that will properly sort the topics (on the first page) by their creation date.

By default, this script is going to grab the first 5 pages of the On Video forum and sort them by their creation date. Then it will replace all existing topics on the front page with the ordered topics going up to page 5. You can change the number of pages this script will get by updating the numPages variable in the script. The higher this value is set, the longer it will take to load the page.

NOTE: This only works on the first page of On Video, going to page 2 will cause issues.

This tool runs in a chrome extension called Tampermonkey that will run javascript code when a webpage loads. Currently this tool only works for the On Video section of the forum since that's all I use, but it will probably work in other areas with some small modifications.

Installation instructions:
1. Install the Tampermonkey extension for chrome

2. Open up the Tampermonkey dashboard Image

3. Click the + button next to the Install Userscripts tab Image

4. Delete all of the existing code in this editor box Image

5. Paste code from below into the editor box and save the script

Code: Select all

// ==UserScript==
// @name         Milovana Sorter
// @version      0.3
// @description  Sort Milovana topics by creation date
// @author       Expression
// @match        https://milovana.com/forum/viewforum.php?f=25
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    function requestUrl(url) { /* send request to url and sends each post element to buildList processing */
        const http = new XMLHttpRequest();
        http.open("GET", url);
        http.send();
        http.onreadystatechange = function() {
            if(this.readyState == 4 && this.status == 200) {
                var temp_element = document.createElement("html");
                temp_element.innerHTML = http.responseText;
                var elementList = temp_element.getElementsByClassName("topiclist topics")[1].childNodes;
                elementList.forEach(buildList);
                }
            }
        }
    var post_arr = [];
    var display_arr = [];
    function getDate(el) { /* get date from element */
        for(var i = 0; i < el.length; i++) {
            for(var j = 0; j < el[i].children.length; j++) {
                if(el[i].children[j].nodeName == "TIME") {
                    return el[i].children[j].dateTime;
                }
            }
        }
        return "ERROR";
    }
    var count = 0;
    function buildList(el, idx, arr) { /* scrapes data from topics and stores it in post_arr or display_arr for sticky topics, immediately storing stickies retains their order at the top*/
        let match = /(?<=t\=)\d+(?=$)/;
        if(el.nodeType == 1) {
            try {
                count++;
                var className = el.className;
                var indexOffset = ((el.children[0].childNodes[1].children[0].className !== "list-inner") ? 1 : 0);
                var data = el.children[0].childNodes[1].children[0 + indexOffset].children;
                var url = data[0 + indexOffset].href;
                var postId = url.match(match)[0];
                var postDate = Date.parse(getDate(data));
                if(className.includes("sticky")) {
                    display_arr.push(el);
                } else {
                    post_arr.push([postDate, postId, el, className]);
                }
            } catch {
                return;
            }
        }
    }
    async function loop_requests() { /* requests first 5 pages of forum topics */
        var loopIncrement = 50;
        var numPages = 5;
        var count = 0;
        var req_url = "https://milovana.com/forum/viewforum.php?f=25&start=";
        for(var i = 0; i <= numPages; i++) {
            count++;
            var postFrom = i * loopIncrement;
            if(count > 100) {
                break;
            }
            var url = req_url + postFrom;
            await requestUrl(url);
        }
    }
    loop_requests();
    function replacePosts() { /* injects posts from an display_arr into the webpage */
        document.getElementsByClassName("topiclist topics")[1].innerHTML = "";
        for(var i = 0; i <= display_arr.length; i++) {
            try {
                document.getElementsByClassName("topiclist topics")[1].appendChild(display_arr[i]);
            } catch {}
        }
    }
    function getSortedElements() { /* sort elements in descending order by post date in post_arr and push them into display_arr */
        var sorted = post_arr.sort(function(a,b) {
            return a[0]-b[0]
        }).reverse();
        sorted.forEach(function(el, idx, arr) {
            display_arr.push(el[2]);
        });
        replacePosts(display_arr);
    }
    var timeout = setInterval(function() { /* check if post_arr can be sorted by checking its length */
        if(post_arr.length > 200) {
            getSortedElements();
            clearInterval(timeout);
        }
    }, 100);
})();

Before turning on topic sorter:
Image


After:
Image

Re: [RELEASE] Sort Topics by Creation Date

Posted: Sat Nov 20, 2021 10:42 pm
by doremi
Welcome to Milovana, Expression! :w00t:

Thanks for your contribution! Tampermonkey runs on other browsers too, so maybe your work will be compatible.

Expression wrote: Sat Nov 20, 2021 6:59 pm NOTE: This only works on the first page of On Video, going to page 2 will cause issues.
This reminds me of the time when Howie only developed an arm robot in The Big Bang Theory because it's only what he needed. Well, if in trouble, REBOOT!!! :lol:

Re: [RELEASE] Sort Topics by Creation Date

Posted: Sun Nov 21, 2021 5:16 am
by Sombre
Good job ! I was looking for this feature for a long time. Tired to see necro-posting bring back old subject to the top.

N.B : Apparently, it work only for the first page of "Video". Page 2 is not sorted.

Re: [RELEASE] Sort Topics by Creation Date

Posted: Sun Nov 21, 2021 6:33 am
by samfishercarl
Expression wrote: Sat Nov 20, 2021 6:59 pm NOTE: This only works on the first page of On Video, going to page 2 will cause issues.

Code: Select all

// ==UserScript==
// @name         Milovana Sorter
// @version      0.1
// @description  Sort Milovana topics by creation date
// @author       Expression
// @match        https://milovana.com/forum/viewforum.php?f=25*
// @grant        none
// ==/UserScript==

var active = document.getElementsByClassName("active")[0].innerText;
(function() {
    'use strict';
    var test = document.getElementsByClassName("topiclist topics")[1].childNodes;
    var req_url = "https://milovana.com/forum/viewforum.php?f=25&start=";
    function requestUrl(url) { /* send request to url */
        const http = new XMLHttpRequest();
        http.open("GET", url);
        http.send();
        http.onreadystatechange = function() {
            if(this.readyState == 4 && this.status == 200) {
                var temp_element = document.createElement("html");
                temp_element.innerHTML = http.responseText;
                var elementList = temp_element.getElementsByClassName("topiclist topics")[1].childNodes;
                elementList.forEach(buildList);
                }
            }
        }
    var post_arr = [];
    var display_arr = [];
    function getDate(el) { /* get date from element */
        for(var i = 0; i < el.length; i++) {
            if(el[i].nodeName == "TIME") {
                return el[i].dateTime;
            }
        }
        return "ERROR";
    }
    var count = 0;
    function buildList(el, idx, arr) { /* scrapes data from topics and stores it in post_arr or display_arr for sticky topics, immediately storing stickies retains their order at the top*/
        let match = /(?<=t\=)\d+(?=$)/;
        if(el.nodeType == 1) {
            try {
                count++;
                var className = el.className;
                var indexOffset = ((el.children[0].childNodes[1].children[0].className !== "list-inner") ? 1 : 0);
                var data = el.children[0].childNodes[1].children[0 + indexOffset].children;
                var url = data[0 + indexOffset].href;
                var postId = url.match(match)[0];
                var postDate = Date.parse(getDate(data[4 + indexOffset].children));
                if(className.includes("sticky")) {
                    display_arr.push(el);
                } else {
                    post_arr.push([postDate, postId, el, className]);
                }
            } catch {
                return;
            }
        }
    }
    async function loop_requests() { /* requests first 5 pages of forum topics */
        var loopIncrement = 50;
        var loopCount = 5;
        var count = 0;
        for(var i = 0; i < loopCount; i++) {
            count++;
            var postFrom = i * loopIncrement;
            if(count > 100) {
                break;
            }
            var url = req_url + postFrom;
            await requestUrl(url);
        }
    }
    loop_requests();
    function replacePosts() { /* injects posts from an display_arr into the webpage */
        var replace_list = document.getElementsByClassName("topiclist topics")[1].children;
		for(var j = 0; j < 50*(active-1); j++){
		display_arr.shift();
		}
        for(var i = 0; i < replace_list.length; i++) {
            var new_post = document.createElement("li");
            new_post.className = replace_list[i].className;
            new_post.innerHTML = display_arr.shift().innerHTML;
            replace_list[i].parentNode.replaceChild(new_post, replace_list[i]);
        }
    }
    function getSortedElements() { /* sort elements in descending order by post date in post_arr and push them into display_arr */
        var sorted = post_arr.sort(function(a,b) {
            return a[0]-b[0]
        }).reverse();
        sorted.forEach(function(el, idx, arr) {
            display_arr.push(el[2]);
        });
		
        replacePosts(display_arr);
    }
    var timeout = setInterval(function() { /* check if post_arr can be sorted by checking its length */
        if(post_arr.length > 200) {
            getSortedElements();
            clearInterval(timeout);
        }
    }, 100);
})();

fix for the first 5 pages :)

BTW this can now be scaled up by changing the value on line 62 (loopCount = 5) so you could sort the first 10 pages if you wanted at the cost of script runtime.

Re: [RELEASE] Sort Topics by Creation Date

Posted: Sun Nov 21, 2021 6:53 am
by samfishercarl
Just updated forgot a *

Re: [RELEASE] Sort Topics by Creation Date

Posted: Sun Nov 21, 2021 7:36 am
by Expression
samfishercarl wrote: Sun Nov 21, 2021 6:33 am
Expression wrote: Sat Nov 20, 2021 6:59 pm NOTE: This only works on the first page of On Video, going to page 2 will cause issues.
snipped code block

fix for the first 5 pages :)

BTW this can now be scaled up by changing the value on line 62 (loopCount = 5) so you could sort the first 10 pages if you wanted at the cost of script runtime.
Thanks so much for this! Taking more inspiration from you, I've made an update to the script that takes all 5 pages (by default, you can change it in the script with the numPages variable) and puts them in a single page ordered by creation date. I'll put the code here and update the original post.

Code: Select all

// ==UserScript==
// @name         Milovana Sorter
// @version      0.2
// @description  Sort Milovana topics by creation date
// @author       Expression
// @match        https://milovana.com/forum/viewforum.php?f=25
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    function requestUrl(url) { /* send request to url and sends each post element to buildList processing */
        const http = new XMLHttpRequest();
        http.open("GET", url);
        http.send();
        http.onreadystatechange = function() {
            if(this.readyState == 4 && this.status == 200) {
                var temp_element = document.createElement("html");
                temp_element.innerHTML = http.responseText;
                var elementList = temp_element.getElementsByClassName("topiclist topics")[1].childNodes;
                elementList.forEach(buildList);
                }
            }
        }
    var post_arr = [];
    var display_arr = [];
    function getDate(el) { /* get date from element */
        for(var i = 0; i < el.length; i++) {
            if(el[i].nodeName == "TIME") {
                return el[i].dateTime;
            }
        }
        return "ERROR";
    }
    var count = 0;
    function buildList(el, idx, arr) { /* scrapes data from topics and stores it in post_arr or display_arr for sticky topics, immediately storing stickies retains their order at the top*/
        let match = /(?<=t\=)\d+(?=$)/;
        if(el.nodeType == 1) {
            try {
                count++;
                var className = el.className;
                var indexOffset = ((el.children[0].childNodes[1].children[0].className !== "list-inner") ? 1 : 0);
                var data = el.children[0].childNodes[1].children[0 + indexOffset].children;
                var url = data[0 + indexOffset].href;
                var postId = url.match(match)[0];
                var postDate = Date.parse(getDate(data[4 + indexOffset].children));
                if(className.includes("sticky")) {
                    display_arr.push(el);
                } else {
                    post_arr.push([postDate, postId, el, className]);
                }
            } catch {
                return;
            }
        }
    }
    async function loop_requests() { /* requests first 5 pages of forum topics */
        var loopIncrement = 50;
        var numPages = 5;
        var count = 0;
        var req_url = "https://milovana.com/forum/viewforum.php?f=25&start=";
        for(var i = 0; i <= numPages; i++) {
            count++;
            var postFrom = i * loopIncrement;
            if(count > 100) {
                break;
            }
            var url = req_url + postFrom;
            await requestUrl(url);
        }
    }
    loop_requests();
    function replacePosts() { /* injects posts from an display_arr into the webpage */
        document.getElementsByClassName("topiclist topics")[1].innerHTML = "";
        for(var i = 0; i <= display_arr.length; i++) {
            try {
                document.getElementsByClassName("topiclist topics")[1].appendChild(display_arr[i]);
            } catch {}
        }
    }
    function getSortedElements() { /* sort elements in descending order by post date in post_arr and push them into display_arr */
        var sorted = post_arr.sort(function(a,b) {
            return a[0]-b[0]
        }).reverse();
        sorted.forEach(function(el, idx, arr) {
            display_arr.push(el[2]);
        });
        replacePosts(display_arr);
    }
    var timeout = setInterval(function() { /* check if post_arr can be sorted by checking its length */
        if(post_arr.length > 200) {
            getSortedElements();
            clearInterval(timeout);
        }
    }, 100);
})();

Re: [RELEASE] Sort Topics by Creation Date

Posted: Sun Nov 21, 2021 8:31 am
by samfishercarl
Expression wrote: Sun Nov 21, 2021 7:36 am
Thanks so much for this!

No problem!


puts them in a single page ordered by creation date. I'll put the code here and update the original post.

That is a neat idea!

Re: [RELEASE] Sort Topics by Creation Date

Posted: Sun Nov 21, 2021 4:30 pm
by samfishercarl
Guilherme_1988 wrote: Sun Nov 21, 2021 4:14 pm This extension works on Firefox? Opera installs Chrome extensions but since i don´t use Chrome (too much RAM usage) and use more Firefox (Opera is for downloading archives on Mega, Firefox stops when download mega archives here), that´s why the question.
I have not tried, but i believe the extension is available on all browsers and the code is just javascript so it should run on any browser as long as you have the extension installed

Re: [RELEASE] Sort Topics by Creation Date

Posted: Sun Nov 21, 2021 7:08 pm
by Sombre
I think it work yes. If you use Tampermonkey.

I tried on violentmonkey, it didn't work. I needed to put Tampermonkey.

Re: [RELEASE] Sort Topics by Creation Date

Posted: Sun Nov 21, 2021 8:10 pm
by Expression
Guilherme_1988 wrote: Sun Nov 21, 2021 4:14 pm This extension works on Firefox? Opera installs Chrome extensions but since i don´t use Chrome (too much RAM usage) and use more Firefox (Opera is for downloading archives on Mega, Firefox stops when download mega archives here), that´s why the question.
I just tested this script in Firefox using the Greasemonkey extension and it appears to work exactly as expected. Similar procedure as adding it to Tampermonkey:

1. Open up the Greasemonkey menu, then click New user script

Image

2. Delete all existing code in the window that opens, then paste in the code from the original post and save.

Image

Re: [RELEASE] Sort Topics by Creation Date

Posted: Mon Nov 22, 2021 11:51 am
by Hades-
Must have script! No more missing new releases and threads.
Most forums have sort option by default, but if I need to install scripts, I'm fine with it.
:thankyou: @Expression and @samfishercarl :thankyou:

Re: [RELEASE] Sort Topics by Creation Date

Posted: Mon Nov 22, 2021 2:17 pm
by Sombre
Hades- wrote: Mon Nov 22, 2021 11:51 am Must have script! No more missing new releases and threads.
Most forums have sort option by default, but if I need to install scripts, I'm fine with it.
:thankyou: @Expression and @samfishercarl :thankyou:
Andyp can't add this feature, he would need to add a mod for the forum. It's a pain in the ass.

Re: [RELEASE] Sort Topics by Creation Date

Posted: Tue Nov 23, 2021 7:38 pm
by CantoFan123
I installed this on firefox and it was very easy! Thanks so much!

Re: [RELEASE] Sort Topics by Creation Date

Posted: Fri Nov 26, 2021 12:22 am
by lestrian
Expression wrote: Sun Nov 21, 2021 7:36 am ...
This code has some bug. I installed it in tampermonkey on chrome, and it looks like it works fine, but it only shows posts from Nov 24 and earlier. It misses the post made today on Nov 26.

Re: [RELEASE] Sort Topics by Creation Date

Posted: Fri Nov 26, 2021 2:48 am
by Expression
lestrian wrote: Fri Nov 26, 2021 12:22 am
Expression wrote: Sun Nov 21, 2021 7:36 am ...
This code has some bug. I installed it in tampermonkey on chrome, and it looks like it works fine, but it only shows posts from Nov 24 and earlier. It misses the post made today on Nov 26.
Thanks for letting me know, looks like the HTML of topics change when they receive a reply. Here's the code that correctly handles new posts without replies. Original post will also have this same code.

Code: Select all

// ==UserScript==
// @name         Milovana Sorter
// @version      0.3
// @description  Sort Milovana topics by creation date
// @author       Expression
// @match        https://milovana.com/forum/viewforum.php?f=25
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    function requestUrl(url) { /* send request to url and sends each post element to buildList processing */
        const http = new XMLHttpRequest();
        http.open("GET", url);
        http.send();
        http.onreadystatechange = function() {
            if(this.readyState == 4 && this.status == 200) {
                var temp_element = document.createElement("html");
                temp_element.innerHTML = http.responseText;
                var elementList = temp_element.getElementsByClassName("topiclist topics")[1].childNodes;
                elementList.forEach(buildList);
                }
            }
        }
    var post_arr = [];
    var display_arr = [];
    function getDate(el) { /* get date from element */
        for(var i = 0; i < el.length; i++) {
            for(var j = 0; j < el[i].children.length; j++) {
                if(el[i].children[j].nodeName == "TIME") {
                    return el[i].children[j].dateTime;
                }
            }
        }
        return "ERROR";
    }
    var count = 0;
    function buildList(el, idx, arr) { /* scrapes data from topics and stores it in post_arr or display_arr for sticky topics, immediately storing stickies retains their order at the top*/
        let match = /(?<=t\=)\d+(?=$)/;
        if(el.nodeType == 1) {
            try {
                count++;
                var className = el.className;
                var indexOffset = ((el.children[0].childNodes[1].children[0].className !== "list-inner") ? 1 : 0);
                var data = el.children[0].childNodes[1].children[0 + indexOffset].children;
                var url = data[0 + indexOffset].href;
                var postId = url.match(match)[0];
                var postDate = Date.parse(getDate(data));
                if(className.includes("sticky")) {
                    display_arr.push(el);
                } else {
                    post_arr.push([postDate, postId, el, className]);
                }
            } catch {
                return;
            }
        }
    }
    async function loop_requests() { /* requests first 5 pages of forum topics */
        var loopIncrement = 50;
        var numPages = 5;
        var count = 0;
        var req_url = "https://milovana.com/forum/viewforum.php?f=25&start=";
        for(var i = 0; i <= numPages; i++) {
            count++;
            var postFrom = i * loopIncrement;
            if(count > 100) {
                break;
            }
            var url = req_url + postFrom;
            await requestUrl(url);
        }
    }
    loop_requests();
    function replacePosts() { /* injects posts from an display_arr into the webpage */
        document.getElementsByClassName("topiclist topics")[1].innerHTML = "";
        for(var i = 0; i <= display_arr.length; i++) {
            try {
                document.getElementsByClassName("topiclist topics")[1].appendChild(display_arr[i]);
            } catch {}
        }
    }
    function getSortedElements() { /* sort elements in descending order by post date in post_arr and push them into display_arr */
        var sorted = post_arr.sort(function(a,b) {
            return a[0]-b[0]
        }).reverse();
        sorted.forEach(function(el, idx, arr) {
            display_arr.push(el[2]);
        });
        replacePosts(display_arr);
    }
    var timeout = setInterval(function() { /* check if post_arr can be sorted by checking its length */
        if(post_arr.length > 200) {
            getSortedElements();
            clearInterval(timeout);
        }
    }, 100);
})();