Skip to content

Material View Support for Stock NodeBB

Unsolved Let's Build It
51 3 11.4k 1
  • Ha ha !!!

    In any case my code does not work correctly ๐Ÿ™‚

    @DownPW nothing we canโ€™t fix. Let me fire this up in dev and have a look.

  • @DownPW can you provide a screenshot of the layout you have? This would be useful as a guide.

  • โ€“ Home Page :

    โ€“ Recent, unread, etcโ€ฆ

    โ€“ Topic (without thread View)

  • It seems that the CSS class is added but that it does not work correctly when declared in the ACP.

    I wonder if we should not remove the resolution story and have the code applied regardless of the resolution used because Material mode can very well be used on Smartphones.

  • It seems that the CSS class is added but that it does not work correctly when declared in the ACP.

    I wonder if we should not remove the resolution story and have the code applied regardless of the resolution used because Material mode can very well be used on Smartphones.

    @DownPW On reviewing the screenshots again, this seems to be only an adjustment for the overall container width?

  • just background color, border etcโ€ฆ
    You have CSS I used for this result above in the topic

    but anyway, my code is not correct.

  • just background color, border etcโ€ฆ
    You have CSS I used for this result above in the topic

    but anyway, my code is not correct.

    @DownPW It doesnโ€™t work because you havenโ€™t defined anything here ๐Ÿ™‚

                    // Toggle CSS rules when the button is turned on or off
                    if (isChecked) {
                        console.log('Material Thread view is active.');
                        // Apply your CSS rules here
                    } else {
                        console.log('Material Thread view is inactive.');
                        // Remove the CSS rules here
                    }
    

    This is how I do it for the threads

    https://github.com/phenomlab/nodebb-harmony-chat-threading/blob/0cea943c2e7ab0f63d2b2eae38d64bc19b8242ec/functions.js#L22-L32

    Your CSS also needs to be more explicit. For example

    [component="category/topic"], [component="categories/category"] {
        margin-bottom: var(--bs-post-category-topic-margin);
        margin-bottom: 20px;
    }
    

    Would become

    [component="category/topic"].material, [component="categories/category"].material {
        margin-bottom: var(--bs-post-category-topic-margin);
        margin-bottom: 20px;
    }
    
  • I remenber I have already test this without good result.

    Maybe retest

  • I remenber I have already test this without good result.

    Maybe retest

    @DownPW Did you review the classes as I mentioned?

  • @DownPW Did you review the classes as I mentioned?

    @phenomlab said in Material View Support foir Stock NodeBB:

    @DownPW Did you review the classes as I mentioned?

    yes but added the wrong class name, itโ€™s better now.

    Iโ€™m here at the moment.

    JS :

    // ------------------------------------------
    // material View Mode
    // ------------------------------------------
    
    function material() {
        $(document).ready(function () {
            // Check if the screen width is 460px or more
            if ($(window).width() >= 460) {
                // Check if the custom thread view button already exists
                if ($('#materialThreadViewButton').length === 0) {
                    // Create the button for custom thread view mode with custom IDs
                    var threadViewButton = $('<div class="material-threads-wrapper"><form class="form"><div class="form-check form-switch material-threads-wrapper"> \
                        <input class="form-check-input" id="materialThreadViewButton" type="checkbox" data-field="materialThreadView"> \
                        <label class=" d-none d-md-inline fw-semibold" for="materialThreadViewButton"></label> \
                    </div></form></div>');
                    
                    // Append the button to the right sidebar
                    $('[component="sidebar/right"]').append(threadViewButton);
                }
                
                // Check if there's a stored state for the checkbox and update it
                var storedState = localStorage.getItem('materialThreadViewState');
                if (storedState === 'true') {
                    $('#materialThreadViewButton').prop('checked', true);
                }
                
                // Toggle the class 'material' on or off when the checkbox changes state
                $('#materialThreadViewButton').on('change', function () {
                    var isChecked = $(this).is(':checked');
                    var theTooltip = isChecked ? "Material Thread View Off" : "Material Thread View On"; // Update tooltip message
                    
                    // Toggle CSS rules when the button is turned on or off
                    if (isChecked) {
                        console.log('Material Thread view is active.');
                        // Apply your CSS rules here
                        $('[component=post]').addClass('material'); 
                        $('[component="category/topic"]').addClass('material'); 
                        $('[component="categories/category"]').addClass('material');
                    } else {
                        console.log('Material Thread view is inactive.');
                        // Remove the CSS rules here
                        $$('[component=post]').removeClass('material');
                        $('[component="category/topic"]').removeClass('material');
                        $('[component="categories/category"]').removeClass('material');
                    }
                    
                    // Store the checkbox state in localStorage
                    localStorage.setItem('materialThreadViewState', isChecked);
                    
                    // Update the tooltip title
                    $(this).attr('data-original-title', theTooltip).tooltip('dispose').tooltip({
                        placement: 'bottom',
                        title: theTooltip,
                        trigger: 'hover'
                    });
                });
    
                // Check for changes in the checkbox state when the page loads
                $('#materialThreadViewButton').trigger('change');
            }
        });
    }
    
    // Attach the material function to relevant events
    $(window).on('action:ajaxify.end', function (data) {
        material();
    });
    
    $(window).on('action:posts.edited', function (data) {
        material();
    });
    
    $(window).on('action:posts.loaded', function (data) {
        material();
    });
    

    CSS :

    .material-threads-wrapper {
        display: flex;
        left: 5px !important;
        position: relative !important;
    }
    
    @media (min-width:460px) {
    
    [component=post].material, [component="category/topic"].material, [component="categories/category"].material { 
        background: #F7F7F7 !important;
        border-radius: 0.375rem;
        margin-bottom: 20px;
        padding-left: 20px;
        border: 1px solid var(--bs-border-color);
    }
    
    }
    

    โ€“ There are quite a few things left, for example:

    • if we scan the recent or unread ones, the rest is not in the background :

    f3fe08cf-fbc1-4f47-8497-866557c4ec25-image.png

    • And the block + timeline in the topics :
      35beb3bc-8871-4689-b31c-cd2c489907a4-image.png

    I would also like to change the button which is not suitable for a vertical display

    For the moment, I havenโ€™t found for all of that but Iโ€™m looking for.

  • better with video :

    blink3.gif

  • better with video :

    blink3.gif

    @DownPW Youโ€™re missing a hook ๐Ÿ™‚

    Iโ€™ve added this

    $(window).on('action:topics.loaded', function (data) {
        material();
    });
    
    

    Works now !

  • @phenomlab said in Material View Support foir Stock NodeBB:

    @DownPW Did you review the classes as I mentioned?

    yes but added the wrong class name, itโ€™s better now.

    Iโ€™m here at the moment.

    JS :

    // ------------------------------------------
    // material View Mode
    // ------------------------------------------
    
    function material() {
        $(document).ready(function () {
            // Check if the screen width is 460px or more
            if ($(window).width() >= 460) {
                // Check if the custom thread view button already exists
                if ($('#materialThreadViewButton').length === 0) {
                    // Create the button for custom thread view mode with custom IDs
                    var threadViewButton = $('<div class="material-threads-wrapper"><form class="form"><div class="form-check form-switch material-threads-wrapper"> \
                        <input class="form-check-input" id="materialThreadViewButton" type="checkbox" data-field="materialThreadView"> \
                        <label class=" d-none d-md-inline fw-semibold" for="materialThreadViewButton"></label> \
                    </div></form></div>');
                    
                    // Append the button to the right sidebar
                    $('[component="sidebar/right"]').append(threadViewButton);
                }
                
                // Check if there's a stored state for the checkbox and update it
                var storedState = localStorage.getItem('materialThreadViewState');
                if (storedState === 'true') {
                    $('#materialThreadViewButton').prop('checked', true);
                }
                
                // Toggle the class 'material' on or off when the checkbox changes state
                $('#materialThreadViewButton').on('change', function () {
                    var isChecked = $(this).is(':checked');
                    var theTooltip = isChecked ? "Material Thread View Off" : "Material Thread View On"; // Update tooltip message
                    
                    // Toggle CSS rules when the button is turned on or off
                    if (isChecked) {
                        console.log('Material Thread view is active.');
                        // Apply your CSS rules here
                        $('[component=post]').addClass('material'); 
                        $('[component="category/topic"]').addClass('material'); 
                        $('[component="categories/category"]').addClass('material');
                    } else {
                        console.log('Material Thread view is inactive.');
                        // Remove the CSS rules here
                        $$('[component=post]').removeClass('material');
                        $('[component="category/topic"]').removeClass('material');
                        $('[component="categories/category"]').removeClass('material');
                    }
                    
                    // Store the checkbox state in localStorage
                    localStorage.setItem('materialThreadViewState', isChecked);
                    
                    // Update the tooltip title
                    $(this).attr('data-original-title', theTooltip).tooltip('dispose').tooltip({
                        placement: 'bottom',
                        title: theTooltip,
                        trigger: 'hover'
                    });
                });
    
                // Check for changes in the checkbox state when the page loads
                $('#materialThreadViewButton').trigger('change');
            }
        });
    }
    
    // Attach the material function to relevant events
    $(window).on('action:ajaxify.end', function (data) {
        material();
    });
    
    $(window).on('action:posts.edited', function (data) {
        material();
    });
    
    $(window).on('action:posts.loaded', function (data) {
        material();
    });
    

    CSS :

    .material-threads-wrapper {
        display: flex;
        left: 5px !important;
        position: relative !important;
    }
    
    @media (min-width:460px) {
    
    [component=post].material, [component="category/topic"].material, [component="categories/category"].material { 
        background: #F7F7F7 !important;
        border-radius: 0.375rem;
        margin-bottom: 20px;
        padding-left: 20px;
        border: 1px solid var(--bs-border-color);
    }
    
    }
    

    โ€“ There are quite a few things left, for example:

    • if we scan the recent or unread ones, the rest is not in the background :

    f3fe08cf-fbc1-4f47-8497-866557c4ec25-image.png

    • And the block + timeline in the topics :
      35beb3bc-8871-4689-b31c-cd2c489907a4-image.png

    I would also like to change the button which is not suitable for a vertical display

    For the moment, I havenโ€™t found for all of that but Iโ€™m looking for.

    @DownPW said in Material View Support foir Stock NodeBB:

    I would also like to change the button which is not suitable for a vertical display

    You could rotate it?

    .material-threads-wrapper {
        display: flex;
        left: 5px !important;
        position: relative !important;
        transform: rotate(45deg);
        margin-left: -2px;
        margin-top: 5px;
    }
    

    fc9f46cc-2235-47fe-a613-3baa9d5aa436-image.png

  • @DownPW could you pls share updated and enclosed codes for css and js?

  • @cagatay The code is not mature yet. There is still work to be done and phenomlab will have to validate it because I am not a developer

    @phenomlab said in Material View Support foir Stock NodeBB:

    You could rotate it?

    yep sure itโ€™s better ๐Ÿ™‚
    but I was thinking of a 2-state radio button like the form-switch because I believe Bootstrap offers it if I donโ€™t say bullsh*t.

  • @cagatay The code is not mature yet. There is still work to be done and phenomlab will have to validate it because I am not a developer

    @phenomlab said in Material View Support foir Stock NodeBB:

    You could rotate it?

    yep sure itโ€™s better ๐Ÿ™‚
    but I was thinking of a 2-state radio button like the form-switch because I believe Bootstrap offers it if I donโ€™t say bullsh*t.

    @DownPW said in Material View Support foir Stock NodeBB:

    but I was thinking of a 2-state radio button like the form-switch because I believe Bootstrap offers it if I donโ€™t say bullsh*t.

    Something like this?

    https://jsfiddle.net/milanandfriends/p9AaY/

  • yes maybe, I had thought about that but just one button not two but why not :

    image.png

    https://getbootstrap.com/docs/5.0/forms/checks-radios/

    Iโ€™m not closed off Iโ€™m trying to see what could be better.

  • see this @phenomlab

    the element is perfect regardless of the mode engaged but a refresh does not replace it correctly.
    A missing hook?

  • see this @phenomlab

    the element is perfect regardless of the mode engaged but a refresh does not replace it correctly.
    A missing hook?

    @DownPW No. More likely a CSS class is not being applied on load.

  • hmm that doesnโ€™t help me much ๐Ÿ™‚


Related Topics
  • NodeBB Twitter / X embeds

    Let's Build It twitter script
    34
    21 Votes
    34 Posts
    6k Views
    @phenomlab said: @DownPW thanks for spotting (and fixing) this issue. I admittedly threw this together quickly for @jac some time ago, and it hasnโ€™t had any love since. If OK with you, Iโ€™ll merge these changes into the github repository? No problem dude
  • 5 Votes
    4 Posts
    2k Views
    @DownPW thanks. I forgot about that.
  • Threaded post support for NodeBB

    Let's Build It threading nodebb
    146
    3
    50 Votes
    146 Posts
    53k Views
    Updated git for above change https://github.com/phenomlab/nodebb-harmony-threading/commit/14a4e277521d83d219065ffb14154fd5f5cfac69
  • Coding question: fetch vs $.ajax call from Shopify

    Solved Performance javascript
    4
    3 Votes
    4 Posts
    1k Views
    @Panda You should be able to use {% javscript %} as shown in this video - itโ€™s quite the watch, but very educational, and provides insight as to how this works - see below screenshot for an example [image: 1690282186734-cdb160e9-d955-498c-b921-982db2986e2b-image.png]
  • 21 Votes
    110 Posts
    28k 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
    3k Views
    @dave1904 excellent news. Thanks for the feedback
  • Detect if user is admin

    General nodebb javascript code
    2
    0 Votes
    2 Posts
    1k Views
    @pwsincd I think you can use userData.isAdmin = isAdmin; if Iโ€™m not mistaken - see https://community.nodebb.org/topic/15128/how-to-hide-whitelist-user-field-only-to-owner-or-admin?_=1648802303112 for an example
  • [NODEBB] Help for my custom CSS

    Solved Customisation nodebb css bugfix
    237
    49 Votes
    237 Posts
    80k Views
    @baris said: You should change your selectors so it doesnโ€™t look at the entire document. You probably only want to apply fancybox to stuff inside the #content element which is what changes when the user navigates around the page. So use $('#content a').... for your selectors then the forum logo in the header wonโ€™t be selected. I modified the JS Fancybox code now and this code and it seem better // --------------------------------------------- // Fancybox Media Reader (Without Website Logo) // --------------------------------------------- if (top.location.pathname !== '/login') { $(window).on('action:posts.loaded', function(data) { console.log("Polling DOM for lazyLoaded images to apply Fancybox"); $(document).ready(function() { $('#content a').not('.forum-logo').not(".avatar").not(".emoji").not(".bmac-noanimate").each(function() { $('#content a[href*=".jpg"], #content a[href*=".jpeg"], #content a[href*=".png"], #content a[href*=".gif"], #content a[href*=".webp"]').addClass("noanimate"); }); }); }); } if (top.location.pathname !== '/login') { $(document).ready(function() { $(window).on('action:ajaxify.end', function(data) { $('#content a').not('.logo').not(".avatar").not(".emoji").not(".bmac-noanimate").each(function() { $('#content a[href*=".jpg"], #content a[href*=".jpeg"], #content a[href*=".png"], #content a[href*=".gif"], #content a[href*=".webp"]').addClass("noanimate"); data.preventDefault() // Strip out the images contained inside blockquotes as this looks nasty :) $('#content blockquote img').remove(); }); Fancybox.bind( '#content a[href*=".jpg"], #content a[href*=".jpeg"], #content a[href*=".png"], #content a[href*=".gif"], #content a[href*=".webp"]', { groupAll: true, } ); }); }); } // Chat fancybox - fires when chat module loaded and AJAX calls new chat $(document).ready(function() { $(window).on('action:chat.loaded', function(data) { // >>> Se limiter au contenu principal uniquement <<< $('#content img').not('.forum-logo').not(".avatar").not(".emoji").not(".bmac-noanimate").each(function() { var newHref = $(this).attr("src"); $(this).wrap("<a class='fancybox' href='" + newHref + "'/>"); $('#content a[href*=".jpg"], #content a[href*=".jpeg"], #content a[href*=".png"], #content a[href*=".gif"], #content a[href*=".webp"]').addClass("noanimate"); data.preventDefault(); // Strip out the images contained inside blockquotes as this looks nasty :) $('#content blockquote img').remove(); }); Fancybox.bind( '#content a[href*=".jpg"], #content a[href*=".jpeg"], #content a[href*=".png"], #content a[href*=".gif"], #content a[href*=".webp"]', { groupAll: true, } ); }); }); For the logo, I must use overflow: visible !important; on [component="brand/logo"] /* --- Logo --- */ [component="brand/logo"] { max-height: 50px; width: auto; height: auto; max-width: 100%; display: block; object-fit: contain; object-position: left center; overflow: visible !important; } Better result !!