Skip to content

Threaded post support for NodeBB

Let's Build It
  • @DownPW any reason as to why you’ve defined background twice ?

    See

    background: var(--bs-body-bg);
    background: var(--bs-body navbar)!important;
    
  • I have just forget to delete the first but this nothing change.

  • @DownPW just curious 🤭

    The second would override the first anyway.

    I’m in transit currently and not in front of a pc but will review this as soon as I can.

  • i have a problem with my codes 😞

    image.png

  • phenomlabundefined phenomlab referenced this topic on
  • @phenomlab thank you Mark i did not read this one.

  • @cagatay no problems. Easily missed!!

  • @DownPW said in Threading support for NodeBB:

    I think I understand by reading the code that it is necessary to specify the classes chnaged in the function.js (with add .threaded) but I don’t really see how to add more

    Can you post the current function code you have?

  • sure :

    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);
                    }
                }
                // 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');
            }
        });
    }
    
    function threadedChat() {
        $(document).ready(function () {
            // Check if the screen width is 1200px or more
            if ($(window).width() >= 1200) {
                // Check if the dropdown already exists
                if ($('#enableThreadingChat').length === 0) {
                    var chatView = $('<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="enableThreadingChat" type="checkbox" data-field="enableThreading"> \
                        <label class=" d-none d-md-inline fw-semibold" for="enableThreadingChat"><span class="title-tooltip top" tooltip-text="Éditer Profil"><i class="fa fa-fw fa-bars-staggered right"></i></label> \
                    </div></form></div>');
                    $('[component="chat/header"]').prepend(chatView);
    
                    // Check if there's a stored state for the checkbox and update it
                    var storedState = localStorage.getItem('enableThreadingStateChat');
                    if (storedState === 'true') {
                        $('#enableThreadingChat').prop('checked', true);
                    }
                }
    
                // Toggle the class 'threaded' on or off when the checkbox changes state
                $('#enableThreadingChat').on('change', function () {
                    var isChecked = $(this).is(':checked');
                    if (isChecked) {
                        console.log('Thread view is active.');
                        $('[component="chat/message"]').each(function () {
                            // Add the 'threaded' class to matching elements
                            if ($(this).hasClass('chat-message')) {
                                $(this).addClass('threaded');
                            }
                        });
                    } else {
                        console.log('Thread view is inactive.');
                        $('[component="chat/message"]').removeClass('threaded');
                    }
    
                    // Store the checkbox state in localStorage
                    localStorage.setItem('enableThreadingStateChat', isChecked);
                });
    
                // Check for changes in the checkbox state when the page loads
                $('#enableThreadingChat').trigger('change');
            }
        });
    }
    
    
    $(window).on('action:chat.loaded', function(data) {
            threadedChat();
    });
    $(window).on('action:chat.received', function(data) {
            threadedChat();
    });
    $(window).on('action:ajaxify.end', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.edited', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.loaded', function (data) {
        threaded();
    });
    
  • @DownPW Thanks. You should remove the threadedChat function and these lines

    $(window).on('action:chat.loaded', function(data) {
            threadedChat();
    });
    $(window).on('action:chat.received', function(data) {
            threadedChat();
    });
    

    That code is not functional yet and is very experimental 🙂

    I’ll have a look at your DEV environment to make the code recommendations.

  • @DownPW I changed your CSS as it was lacking the actual .threaded class which is the target we add and remove

    .page-topic .topic .posts.timeline [component="topic/event"].timeline-event, .page-topic .topic .posts.timeline [component="topic/necro-post"].timeline-event.threaded {
        background: transparent !important;
        margin-bottom: 10px !important;
    }
    .page-topic .topic .posts.timeline .threaded:last-child .timeline-event:last-child,
    .page-topic .topic .posts.timeline .threaded:last-child>[component="post/placeholder"]:last-child,
    .page-topic .topic .posts.timeline .threaded:last-child>[component=post]:last-child {
        margin-left: 0.5rem !important;
    }
    

    Seems to work, but can you confirm?

  • nope

    Sorry I was on my way back from work @phenomlab

    So in fact I’m already going to try adding .threaded to the CSS code.

    When I activate Thread mode, everything is OK however when I deactivate Thread mode, certain classes remain and are not deleted

    For example here, without Thread mode, the background is not returned to vanilla and the same thing for the border-radius :

    0a214db5-6435-49dc-b04d-52842ba0b28d-image.png

  • @DownPW For clarity, I didn’t change all of the classes - only the two you posted last

    Threading off

    fe3562db-edee-4f63-a8aa-1eb59c1279ea-image.png

    Threading on

    a92e0031-cf0c-416e-a1f7-53a6cb3a6631-image.png

  • yep but these 2 class have problem, on your screens, with Threading Off, background color use –bs-body-navbar and not –bs-body-bg.
    And if you seen topi event is not transparent like vanilla

  • @DownPW That should make no difference?

    Just remove it from the class

    .page-topic .topic .posts.timeline .timeline-event, .page-topic .topic .posts.timeline > [component="post/placeholder"], .page-topic .topic .posts.timeline > [component=post] {
        border-left: none;
        transition: transform 0.3s ease !important;
        background: var(--bs-body-bg);
        /* background: var(--bs-body-navbar); */
        border-radius: var(--bs-border-radius);
    }
    

    9871c5b3-1b9b-415b-b848-0f663341fc09-image.png

  • that makes all the difference 🙂

    Vanilla is like this:

    image.png

  • @DownPW said in Threading support for NodeBB:

    And if you seen topi event is not transparent like vanilla

    It is for me

    6d89cea9-6311-48d1-8eea-07b7b827eafd-image.png

  • nope for me

    image.png

  • no return to vanilla background

    blink2.gif

    vanilla: bs-body-bg
    thread ON: bs-body-navbar

  • @DownPW Because your CSS has not been altered dude.

    ebe21e6c-5409-498f-a5dd-605403c52622-image.png

    Try now. It works for me?


Related Topics
  • Material View Support for Stock NodeBB

    Unsolved Let's Build It
    51
    15 Votes
    51 Posts
    3k Views

    Oh yes, that’s what’s super cool, I learn something every day. Afterwards I start from so low in JS

  • Threaded chat support for NodeBB

    Let's Build It
    35
    19 Votes
    35 Posts
    2k 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

  • Nodebb design

    Solved General
    2
    1 Votes
    2 Posts
    282 Views

    @Panda said in Nodebb design:

    One negative is not being so good for SEO as more Server side rendered forums, if web crawlers dont run the JS to read the forum.

    From recollection, Google and Bing have the capability to read and process JS, although it’s not in the same manner as a physical person will consume content on a page. It will be seen as plain text, but will be indexed. However, it’s important to note that Yandex and Baidu will not render JS, although seeing as Google has a 90% share of the content available on the web in terms of indexing, this isn’t something you’ll likely lose sleep over.

    @Panda said in Nodebb design:

    The “write api” is preferred for server-to-server interactions.

    This is mostly based around overall security - you won’t typically want a client machine changing database elements or altering data. This is why you have “client-side” which could be DOM manipulation etc, and “server-side” which performs more complex operations as it can communicate directly with the database whereas the client cannot (and if it can, then you have a serious security flaw). Reading from the API is perfectly acceptable on the client-side, but not being able to write.

    A paradigm here would be something like SNMP. This protocol exists as a UDP (UDP is very efficient, as it is “fire and forget” and does not wait for a response like TCP does) based service which reads performance data from a remote source, thus enabling an application to parse that data for use in a monitoring application. In all cases, SNMP access should be “RO” (Read Only) and not RW (Read Write). It is completely feasible to assume complete control over a firewall for example by having RW access to SNMP and then exposing it to the entire internet with a weak passphrase.

    You wouldn’t do it (at least, I hope you wouldn’t) and the same ethic applies to server-side rendering and the execution of commands.

  • Setup OGProxy for use in NodeBB

    Moved Let's Build It
    110
    21 Votes
    110 Posts
    11k 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

  • Header Menu After Upgrading V3.1.1

    Solved Customisation
    2
    2 Votes
    2 Posts
    188 Views

    @cagatay this relates to a change the css classes used for the brand header meaning it will now float to the left instead of right.

    If you’d like to retain the original behavior, you can add this css class

    [data-widget-area="brand-header"] { justify-content: end; display: flex; }

    Further information here

    https://community.nodebb.org/topic/17090/manual-build-a-custom-header-in-harmony/19?_=1684069325296

  • 11 Votes
    14 Posts
    831 Views

    @dave1904 excellent news. Thanks for the feedback

  • Rotating homepage icons, gifs?

    Solved Configure
    2
    3 Votes
    2 Posts
    237 Views

    @eveh It’s not a GIF, no. It’s actually a webp file so made much smaller, and uses keyframes to control the rotation on hover. You can easily make your own though 🙂

    The CSS for that is as below

    @keyframes rotate180 { from { transform: rotate(0deg); } to { transform: rotate(180deg); } } @keyframes rotate0 { from { transform: rotate(180deg); } to { transform: rotate(0deg); } }

    Your milage may vary on the CSS below, as it’s custom for Sudonix, but this is the class that is used to control the rotate

    .header .forum-logo, img.forum-logo.head { max-height: 50px; width: auto; height: 30px; margin-top: 9px; max-width: 150px; min-width: 32px; display: inline-block; animation-name: rotate180, rotate0; animation-duration: 1000ms; animation-delay: 0s, 1000ms; animation-iteration-count: 1; animation-timing-function: linear; transition: transform 1000ms ease-in-out; }
  • background color of the footer area

    Solved Customisation
    7
    7 Votes
    7 Posts
    499 Views

    @phenomlab thank you very much 🙂