Skip to content

Threaded post support for NodeBB

Let's Build It
146 5 69.3k 1
  • odd i see this code in dev console, search better 🙂

    I see too li.pt-4.self-post.highlight.threaded I don’t have this

    EDIT :

    yes resolved by this code :

    .page-topic .topic .posts.timeline .timeline-event.highlight, .page-topic .topic .posts.timeline > [component="post/placeholder"].highlight, .page-topic .topic .posts.timeline > [component=post].highlight.threaded {
        border: 2px solid var(--bs-post-unread) !important;
        border-radius: var(--bs-border-radius);
    }
    
    li.pt-4.self-post.highlight.threaded {
        margin-left: 0rem !important;
      }
    

    – RESULT :

    blink2.gif

  • Here I am again Mark @phenomlab 😉

    I am contributing to this code to add a tooltip to the button.

    The position can be changed according to your wishes.
    For my part, I prefer to put it at the bottom because if we put it at the top it can be annoying.

    Tell me what you think about it ?

    function threaded() {
        $(document).ready(function () {
            // Check if the screen width is 1200px or more
            if ($(window).width() >= 1200) {
                // Check if the dropdown already exists
                if ($('#enableThreading').length === 0) {
                    var threadView = $('<div class="threads-wrapper"><i class="fa fa-fw fa-bars left"></i><form class="form"><div class="form-check form-switch sticky-tools-bar"> \
                        <input class="form-check-input" id="enableThreading" type="checkbox" data-field="enableThreading"> \
                        <label class=" d-none d-md-inline fw-semibold" for="enableThreading"><i class="fa fa-fw fa-bars-staggered right"></i></label> \
                    </div></form></div>');
                    $('.topic .sticky-tools ul [component="topic/browsing-users"]:last-of-type').append(threadView);
                    // Check if there's a stored state for the checkbox and update it
                    var storedState = localStorage.getItem('enableThreadingState');
                    if (storedState === 'true') {
                        $('#enableThreading').prop('checked', true);
                    }
                }
                
                // Add a tooltip to the button
                $('#enableThreading').tooltip({
                    title: 'Thread View On/Off', // Replace with your tooltip text
                    placement: 'Bottom', // Adjust the placement as needed
                    trigger: 'hover', // Show tooltip on hover
                });
                
                // Toggle the class 'threaded' on or off when the checkbox changes state
                $('#enableThreading').on('change', function () {
                    var isChecked = $(this).is(':checked');
                    if (isChecked) {
                        console.log('Thread view is active.');
                        $('ul[component="topic"]').addClass('threaded');
                        $('.posts-container').addClass('threaded');
                        $('ul[component="topic"]').addClass('threaded');
                        $('.post-container').addClass('threaded');
                        $('.timeline-event').addClass('threaded');
                        $('[component="post/footer"]').addClass('threaded');
                        $('[component="post"]').each(function () {
                            // Add the 'threaded' class to matching elements
                            if ($(this).hasClass('pt-4') || $(this).hasClass('self-post')) {
                                $(this).addClass('threaded');
                                $('.topic .sticky-tools').addClass('threaded');
                            }
                        });
                    } else {
                        console.log('Thread view is inactive.');
                        $('[component="post"]').removeClass('threaded');
                        $('ul[component="topic"]').removeClass('threaded');
                        $('.posts-container').removeClass('threaded');
                        $('ul[component="topic"]').removeClass('threaded');
                        $('.post-container').removeClass('threaded');
                        $('.timeline-event').removeClass('threaded');
                        $('[component="post/footer"]').removeClass('threaded');
                        $('.topic .sticky-tools').removeClass('threaded');
                    }
                    // Store the checkbox state in localStorage
                    localStorage.setItem('enableThreadingState', isChecked);
                });
                // Check for changes in the checkbox state when the page loads
                $('#enableThreading').trigger('change');
            }
        });
    }
    
    $(window).on('action:ajaxify.end', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.edited', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.loaded', function (data) {
        threaded();
    });
    

    CYA my friend

  • Here I am again Mark @phenomlab 😉

    I am contributing to this code to add a tooltip to the button.

    The position can be changed according to your wishes.
    For my part, I prefer to put it at the bottom because if we put it at the top it can be annoying.

    Tell me what you think about it ?

    function threaded() {
        $(document).ready(function () {
            // Check if the screen width is 1200px or more
            if ($(window).width() >= 1200) {
                // Check if the dropdown already exists
                if ($('#enableThreading').length === 0) {
                    var threadView = $('<div class="threads-wrapper"><i class="fa fa-fw fa-bars left"></i><form class="form"><div class="form-check form-switch sticky-tools-bar"> \
                        <input class="form-check-input" id="enableThreading" type="checkbox" data-field="enableThreading"> \
                        <label class=" d-none d-md-inline fw-semibold" for="enableThreading"><i class="fa fa-fw fa-bars-staggered right"></i></label> \
                    </div></form></div>');
                    $('.topic .sticky-tools ul [component="topic/browsing-users"]:last-of-type').append(threadView);
                    // Check if there's a stored state for the checkbox and update it
                    var storedState = localStorage.getItem('enableThreadingState');
                    if (storedState === 'true') {
                        $('#enableThreading').prop('checked', true);
                    }
                }
                
                // Add a tooltip to the button
                $('#enableThreading').tooltip({
                    title: 'Thread View On/Off', // Replace with your tooltip text
                    placement: 'Bottom', // Adjust the placement as needed
                    trigger: 'hover', // Show tooltip on hover
                });
                
                // Toggle the class 'threaded' on or off when the checkbox changes state
                $('#enableThreading').on('change', function () {
                    var isChecked = $(this).is(':checked');
                    if (isChecked) {
                        console.log('Thread view is active.');
                        $('ul[component="topic"]').addClass('threaded');
                        $('.posts-container').addClass('threaded');
                        $('ul[component="topic"]').addClass('threaded');
                        $('.post-container').addClass('threaded');
                        $('.timeline-event').addClass('threaded');
                        $('[component="post/footer"]').addClass('threaded');
                        $('[component="post"]').each(function () {
                            // Add the 'threaded' class to matching elements
                            if ($(this).hasClass('pt-4') || $(this).hasClass('self-post')) {
                                $(this).addClass('threaded');
                                $('.topic .sticky-tools').addClass('threaded');
                            }
                        });
                    } else {
                        console.log('Thread view is inactive.');
                        $('[component="post"]').removeClass('threaded');
                        $('ul[component="topic"]').removeClass('threaded');
                        $('.posts-container').removeClass('threaded');
                        $('ul[component="topic"]').removeClass('threaded');
                        $('.post-container').removeClass('threaded');
                        $('.timeline-event').removeClass('threaded');
                        $('[component="post/footer"]').removeClass('threaded');
                        $('.topic .sticky-tools').removeClass('threaded');
                    }
                    // Store the checkbox state in localStorage
                    localStorage.setItem('enableThreadingState', isChecked);
                });
                // Check for changes in the checkbox state when the page loads
                $('#enableThreading').trigger('change');
            }
        });
    }
    
    $(window).on('action:ajaxify.end', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.edited', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.loaded', function (data) {
        threaded();
    });
    

    CYA my friend

    @DownPW looks good to me 😀 I started to write this a few days ago, but got sidetracked and never finished it.

    Good job.

  • I forgot the screen 🙂

    image.png

  • I forgot the screen 🙂

    image.png

    @DownPW looks great.

  • And just modified this for better display (centered)

    .threads-wrapper {
        display: flex;
        position: relative;
        /* top: -2px; */
        top: 1px;
    }
    
  • And just modified this for better display (centered)

    .threads-wrapper {
        display: flex;
        position: relative;
        /* top: -2px; */
        top: 1px;
    }
    

    @DownPW yes, it was styled for this site because it uses heavily modified css.

  • @phenomlab

    I note, however, that here on Sudonix, our own posts and those of other users are not shifted (to the left). Only those of the author of the topics are.

    In the code you provide on Github, the author’s posts and those of others are shifted (to the left), only our own posts are not.

    I do not know if it’s normal.

    It actually seems logical to me that only our own posts are not shifted to just better identify our own posts

  • @phenomlab

    I note, however, that here on Sudonix, our own posts and those of other users are not shifted (to the left). Only those of the author of the topics are.

    In the code you provide on Github, the author’s posts and those of others are shifted (to the left), only our own posts are not.

    I do not know if it’s normal.

    It actually seems logical to me that only our own posts are not shifted to just better identify our own posts

    @DownPW Correct. The design in DEV and the code on Git reflects the points you raised, which is why it was developed from scratch in DEV and was not a copy of PROD. It’s a matter of personal taste 🙂 You can fairly easily change the cosmetic behavior to suit your needs - it’s not set in stone.

  • Here I am again Mark @phenomlab 😉

    I am contributing to this code to add a tooltip to the button.

    The position can be changed according to your wishes.
    For my part, I prefer to put it at the bottom because if we put it at the top it can be annoying.

    Tell me what you think about it ?

    function threaded() {
        $(document).ready(function () {
            // Check if the screen width is 1200px or more
            if ($(window).width() >= 1200) {
                // Check if the dropdown already exists
                if ($('#enableThreading').length === 0) {
                    var threadView = $('<div class="threads-wrapper"><i class="fa fa-fw fa-bars left"></i><form class="form"><div class="form-check form-switch sticky-tools-bar"> \
                        <input class="form-check-input" id="enableThreading" type="checkbox" data-field="enableThreading"> \
                        <label class=" d-none d-md-inline fw-semibold" for="enableThreading"><i class="fa fa-fw fa-bars-staggered right"></i></label> \
                    </div></form></div>');
                    $('.topic .sticky-tools ul [component="topic/browsing-users"]:last-of-type').append(threadView);
                    // Check if there's a stored state for the checkbox and update it
                    var storedState = localStorage.getItem('enableThreadingState');
                    if (storedState === 'true') {
                        $('#enableThreading').prop('checked', true);
                    }
                }
                
                // Add a tooltip to the button
                $('#enableThreading').tooltip({
                    title: 'Thread View On/Off', // Replace with your tooltip text
                    placement: 'Bottom', // Adjust the placement as needed
                    trigger: 'hover', // Show tooltip on hover
                });
                
                // Toggle the class 'threaded' on or off when the checkbox changes state
                $('#enableThreading').on('change', function () {
                    var isChecked = $(this).is(':checked');
                    if (isChecked) {
                        console.log('Thread view is active.');
                        $('ul[component="topic"]').addClass('threaded');
                        $('.posts-container').addClass('threaded');
                        $('ul[component="topic"]').addClass('threaded');
                        $('.post-container').addClass('threaded');
                        $('.timeline-event').addClass('threaded');
                        $('[component="post/footer"]').addClass('threaded');
                        $('[component="post"]').each(function () {
                            // Add the 'threaded' class to matching elements
                            if ($(this).hasClass('pt-4') || $(this).hasClass('self-post')) {
                                $(this).addClass('threaded');
                                $('.topic .sticky-tools').addClass('threaded');
                            }
                        });
                    } else {
                        console.log('Thread view is inactive.');
                        $('[component="post"]').removeClass('threaded');
                        $('ul[component="topic"]').removeClass('threaded');
                        $('.posts-container').removeClass('threaded');
                        $('ul[component="topic"]').removeClass('threaded');
                        $('.post-container').removeClass('threaded');
                        $('.timeline-event').removeClass('threaded');
                        $('[component="post/footer"]').removeClass('threaded');
                        $('.topic .sticky-tools').removeClass('threaded');
                    }
                    // Store the checkbox state in localStorage
                    localStorage.setItem('enableThreadingState', isChecked);
                });
                // Check for changes in the checkbox state when the page loads
                $('#enableThreading').trigger('change');
            }
        });
    }
    
    $(window).on('action:ajaxify.end', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.edited', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.loaded', function (data) {
        threaded();
    });
    

    CYA my friend

    @DownPW Maybe go one better perhaps, and toggle the on/off state depending on the switch selection (I’m doing that here)

    https://github.com/phenomlab/nodebb-harmony-threading/blob/main/functions%2Cjs

    Enabled

    9a9261ae-7730-4212-a650-04bf1d6807ba-image.png

    Disabled

    ce2cb828-32a9-4c95-905a-4b8f84a24bd0-image.png

  • it’s cool too ^^

  • it’s cool too ^^

  • this code does not work for me. No button

    EDIT:

    The code on github is OK, not the last share above

  • this code does not work for me. No button

    EDIT:

    The code on github is OK, not the last share above

    @DownPW said in Threading support for NodeBB:

    The code on github is OK, not the last share above

    Sorry - changed that to the Git link

  • Just don’t forget to comment out lines for browsing-users plugin

    I’m got screwed 😉

    Good work my friend

  • Just don’t forget to comment out lines for browsing-users plugin

    I’m got screwed 😉

    Good work my friend

    @DownPW This part?

    $('.topic .sticky-tools ul .hidden-xs').append(threadView);
    // If you have browsing users plugin, comment out the above line and uncomment the one below
    //$('.topic .sticky-tools ul [component="topic/browsing-users"]:last-of-type').append(threadView);
    

    Yes, I need to fix that! Thanks for the reminder.

  • For anyone else browsing here who has tried the code in git but wants it to look exactly like Sudonix, please note that this code is not public because it is heavily adapted to match the layout of this site. There are some Sudonix “clones” around so you can actually have this code if you really want it, but it comes with some conditions;

    1. You should consider buying me a coffee - see “Buy me a Coffee” link
    2. You have to provide a backlink to this site from your own - it needs to be visible and cannot be hidden - obviously, I can’t (and won’t) make you do this, but it’s courteous to recognize the original author - particularly when hundreds of hours were spent creating all of this eye candy 🙂
  • Hello @phenomlab

    I see this, when someone composes, it is displayed via the plugin like this (To the left of the Thread View button.). I do not know if it’s normal or if it is better to put it on the right like the others ?

    image.png

    or myself for example :

    33a99e14-13e5-4e67-beaa-25d02b39bb59-image.png

  • Hello @phenomlab

    I see this, when someone composes, it is displayed via the plugin like this (To the left of the Thread View button.). I do not know if it’s normal or if it is better to put it on the right like the others ?

    image.png

    or myself for example :

    33a99e14-13e5-4e67-beaa-25d02b39bb59-image.png

    @DownPW Mmmm - I thought that this would happen. In your js function, can you locate this line

    $('.topic .sticky-tools ul .hidden-xs').append(threadView);
    

    Replace it with

    $('.topic .sticky-tools ul.list-unstyled').append(threadView);
    

    51179c3a-e0cf-4f1f-a36b-79beb1655e88-image.png

    The issue here is that the hidden-xs class is being manipulated by js which forces the position and does not use relative. This new code should hopefully work around that. It will change the placement of the threaded toggle, but for the better I think. If this works, I’ll commit the code to git

  • @phenomlab

    I don’t use this line, I commented out this line as stipulated in the script

    $('.topic .sticky-tools ul .hidden-xs').append(threadView);
    

    But use this line :

    $('.topic .sticky-tools ul [component="topic/browsing-users"]:last-of-type').append(threadView);
    

    image.png

    maybe change for this ?

    $('.topic .sticky-tools ul.list-unstyled [component="topic/browsing-users"]:last-of-type').append(threadView);
    

Related Topics
  • What’s going on with NodeBB?

    Performance nodebb script die
    20
    8 Votes
    20 Posts
    2k Views
    @cagatay The most reliable way to upgrade Node.js on Ubuntu depends on how you originally installed it. Method 1: Using NVM (Recommended) If you already use Node Version Manager (NVM), upgrading is simple. NVM allows you to keep both versions and switch between them if needed. Install Node 22: nvm install 22 Switch to Node 22: nvm use 22 Set it as your default: nvm alias default 22 Verify the change: node -v Method 2: Using NodeSource (PPA) If you installed Node.js via apt using the NodeSource repository, you need to update the repository script to point to the new version. Remove the old NodeSource list (optional but cleaner): sudo rm /etc/apt/sources.list.d/nodesource.list Download and run the NodeSource setup script for Node 22: curl -fsSL [https://deb.nodesource.com/setup_22.x](https://deb.nodesource.com/setup_22.x) | sudo -E bash - Install/Upgrade Node.js: sudo apt-get install -y nodejs Verify the installation: node -v Method 3: Using the ‘n’ Package If you have npm installed, you can use the n interactive manager. Clear the npm cache: sudo npm cache clean -f Install the ‘n’ helper: sudo npm install -g n Install Node 22: sudo n 22 Update your shell: hash -r Troubleshooting Permission Denied: If you see permission errors using Method 2 or 3, ensure you are using sudo. Path Issues: If node -v still shows version 20 after upgrading via NVM, restart your terminal or run source ~/.bashrc. Conflicts: Avoid mixing these methods. If you switch from apt to nvm, it is best to sudo apt remove nodejs first to avoid path conflicts.
  • Threaded chat support for NodeBB

    Let's Build It threaded chat code
    35
    1
    19 Votes
    35 Posts
    9k Views
    @DownPW said in Threaded chat support for NodeBB: Better like this : add shadow and border-left on self answer Of course - you style to your own requirements and taste I’ll commit that CSS we discussed yesterday also
  • Difficult to move posts now, on mobile.

    Bugs nodebb
    16
    1
    5 Votes
    16 Posts
    4k Views
    @DownPW Yes, it is. It’s set far too low meaning other elements with a higher preference will sit over the top of it.
  • 21 Votes
    110 Posts
    34k Views
    @crazycells said in Setup OGProxy for use in NodeBB: are they cached for each user separately? No. It’s a shared cache @crazycells said in Setup OGProxy for use in NodeBB: additionally, this is also handling youtube videos etc, right? No. This is handled by nodebb-plugin-ns-embed
  • 11 Votes
    14 Posts
    4k Views
    @dave1904 excellent news. Thanks for the feedback
  • background color of the footer area

    Solved Customisation nodebb
    7
    1
    7 Votes
    7 Posts
    2k Views
    @phenomlab thank you very much
  • NodeBB templates

    Locked Chitchat themes templates nodebb
    12
    4 Votes
    12 Posts
    3k Views
    Placing this here for reference https://sudonix.com/topic/216/nodebb-js-script-css-theme-switcher Further information and posts can be found at this link
  • 0 Votes
    9 Posts
    2k Views
    @downpw I’m inclined to agree with this. There isn’t much else you can do, and provided it works with no odd looking artefacts in other browsers, then ok. The :before and :after are pseudo classes and very well supported across all browsers (except perhaps Internet Exploder, but who uses that these days ?)