How nodebb loads pages?

Technical Support
  • Hi there,

    This question is not about a feature request or a problem report.
    I'm a new developer to nodejs and I would like to know how nodejs load the pages. When I click on a topic, I see a white opacity layer which overlay the screen. This mechanism is really well implemented, seems like all the new content is injected in the current page. Could someone tell me if that is just an animation loading delay or there is a particular mechanism that handle this?

    Thanks

  • It's a little difficult to explain, but at a high level, we're a single page app, which means when you click on an anchor, we request the JSON for the new page, render the html on the user browser, empty everything in #content, and inject it into #content. The overlay is a transition that makes this process a little smoother.

    We use a templating engine called Benchpress to render templates on both server and client-side.


Suggested Topics


  • 0 Votes
    8 Posts
    4k Views

    @insuusvenerati try running ./nodebb build and then start NodeBB

  • 0 Votes
    3 Posts
    1k Views

    @baris
    This worked perfectly. Thank you!

  • 1 Votes
    3 Posts
    2k Views

    @rod said in Sending emails via SMTP on Nodebb 1.0.x:

    Try the nodebb-plugin-emailer-local-bobo plugin. It will give you SMTP service.

    That worked. Thank you!

  • 0 Votes
    1 Posts
    872 Views

    GitHub - rauchg/slackin: Public Slack organizations made easy

    Public Slack organizations made easy. Contribute to rauchg/slackin development by creating an account on GitHub.

    favicon

    GitHub (github.com)

    I'm trying to add the badge it adds to a widget, but it doesn't load/can't find the script tag. Currently I'm using this:

    <script async defer src="https://slack.yourdomain.com/slackin.js"></script>

    Content of slackin.js

    (function(){ // give up and resort to `target=_blank` // if we're not modern enough if (!document.body.getBoundingClientRect || !document.body.querySelectorAll || !window.postMessage) { return; } // search for a script tag pointing to slackin.js function search(){ var replaced = 0; var scripts = document.querySelectorAll('script'); var script; for (var i = 0; i < scripts.length; i++) { script = scripts[i]; if (!script.src) continue; if (/\/slackin\.js(\?.*)?$/.test(script.src)) { // replace script with iframe replace(script); // we abort the search for subsequent // slackin.js executions to exhaust // the queue return true; } } } var LARGE; // boolean for large/small mode, from query param // replace the script tag with an iframe function replace(script){ var parent = script.parentNode; if (!parent) return; LARGE = /\?large/.test(script.src); var iframe = document.createElement('iframe'); var iframePath = '/iframe' + (LARGE ? '?large' : ''); iframe.src = script.src.replace(/\/slackin\.js.*/, iframePath); iframe.style.borderWidth = 0; iframe.className = '__slackin'; // a decent aproximation that we adjust later // once we have the knowledge of the actual // numbers of users, based on a user count // of 3 digits by 3 digits iframe.style.width = (LARGE ? 190 : 140) + 'px'; // height depends on target size iframe.style.height = (LARGE ? 30 : 20) + 'px'; // hidden by default to avoid flicker iframe.style.visibility = 'hidden'; parent.insertBefore(iframe, script); parent.removeChild(script); // setup iframe RPC iframe.onload = function(){ setup(iframe); }; } // setup an "RPC" channel between iframe and us function setup(iframe){ var id = Math.random() * (1 << 24) | 0; iframe.contentWindow.postMessage('slackin:' + id, '*'); window.addEventListener('message', function(e){ if (typeof e.data !== 'string') return; // show dialog upon click if ('slackin-click:' + id === e.data) { showDialog(iframe); } // update width var wp = 'slackin-width:' + id + ':'; if (wp === e.data.substr(0, wp.length)) { var width = e.data.substr(wp.length); iframe.style.width = width + 'px'; // ensure it's shown (since first time hidden) iframe.style.visibility = 'visible'; } // redirect to URL var redir = 'slackin-redirect:' + id + ':'; if (redir === e.data.substr(0, redir.length)) { location.href = e.data.substr(redir.length); } }); } // show the dialog around the iframe // by, yes, creating a new iframe var showing = false; function showDialog(iframe){ if (showing) return; showing = true; if (LARGE) { unitSize = '14px'; arrowHeight = 13; } else { unitSize = '10px'; arrowHeight = 9; } // container div var div = document.createElement('div'); div.className = '__slackin'; div.style.fontSize = unitSize; div.style.border = '.1em solid #D6D6D6'; div.style.padding = '0'; div.style.margin = '0'; div.style.lineHeight = '0'; div.style.backgroundColor = '#FAFAFA'; div.style.width = '25em'; div.style.height = '15.5em'; div.style.position = 'absolute'; div.style.left = '-10000px'; div.style.top = '-10000px'; div.style.borderRadius = '.4em'; div.style.padding = '.4em'; div.style.boxSizing = 'content-box'; // new iframe var ni = document.createElement('iframe'); ni.className = '__slackin'; ni.style.width = '25em'; ni.style.height = '15.5em'; ni.style.borderWidth = 0; ni.src = iframe.src.replace('iframe', 'iframe/dialog'); ni.onload = function(){ setup(ni); window.addEventListener('scroll', dposition); window.addEventListener('resize', dposition); position(); }; // arrows var a1 = document.createElement('div'); var a2 = document.createElement('div'); [a1, a2].forEach(function(a){ a.style.border = 'solid transparent'; a.style.pointerEvents = 'none'; a.style.width = '0'; a.style.height = '0'; a.style.margin = '0'; a.style.padding = '0'; a.style.position = 'absolute'; a.style.display = 'inline'; }); a1.style.borderColor = 'rgba(214, 214, 214, 0)'; a2.style.borderColor = 'rgba(250, 250, 250, 0)'; a1.style.borderWidth = '.7em'; a1.style.marginLeft = '-.65em'; a2.style.borderWidth = '.6em'; a2.style.marginLeft = '-.6em'; // append div.appendChild(a1); div.appendChild(a2); div.appendChild(ni); document.body.appendChild(div); function position(){ [div, a1, a2].forEach(function(el){ el.style.left = ''; el.style.right = ''; el.style.bottom = ''; el.style.top = ''; }); var divPos = div.getBoundingClientRect(); var iframePos = iframe.getBoundingClientRect(); var divHeight = divPos.height + arrowHeight; var st = document.body.scrollTop; var sl = document.body.scrollLeft; var iw = window.innerWidth; var ih = window.innerHeight; var iframeTop = iframePos.top + st; var iframeLeft = iframePos.left + sl; // position vertically / arrows if (st + iframePos.bottom + divHeight > st + ih) { div.style.top = (iframeTop - divHeight) + 'px'; a1.style.top = a2.style.top = '100%'; a1.style.borderBottomColor = 'rgba(214, 214, 214, 0)'; a2.style.borderBottomColor = 'rgba(250, 250, 250, 0)'; a1.style.borderTopColor = '#d6d6d6'; a2.style.borderTopColor = '#fafafa'; } else { div.style.top = (iframeTop + iframePos.height + arrowHeight) + 'px'; a1.style.bottom = a2.style.bottom = '100%'; a1.style.borderTopColor = 'rgba(214, 214, 214, 0)'; a2.style.borderTopColor = 'rgba(250, 250, 250, 0)'; a1.style.borderBottomColor = '#d6d6d6'; a2.style.borderBottomColor = '#fafafa'; } // position horizontally var left = iframePos.left + Math.round(iframePos.width / 2) - Math.round(divPos.width / 2); if (left < sl) left = sl; if (left + divPos.width > sl + iw) { left = sl + iw - divPos.width; } div.style.left = left + 'px'; a1.style.left = a2.style.left = (iframeLeft - left + Math.round(iframePos.width / 2)) + 'px'; } // debounced positionining var timer; function dposition(){ clearTimeout(timer); timer = setTimeout(position, 100); } function hide(){ showing = false; window.removeEventListener('scroll', dposition); window.removeEventListener('resize', dposition); document.body.removeChild(div); document.documentElement.removeEventListener('click', click, true); } function click(ev){ if ('__slackin' != ev.target.className) { hide(); } } document.documentElement.addEventListener('click', click, true); } var found = search(); if (!found) setTimeout(search, 5000); })();

    If anyone here could help me getting this to work in a widget, I would be really thankful!
    Thanks.

  • 0 Votes
    13 Posts
    3k Views

    Yeah its on my todo for tjs 1.0 🙂