Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Free Nodelet freed

by tye (Sage)
on Oct 14, 2004 at 16:22 UTC ( [id://399250] : monkdiscuss . print w/replies, xml ) Need Help??

You can now rush to Nodelet Settings and add the "Free Nodelet" to your list of nodelets. Once you've done that, how to use it should be obvious. But note that most changes to settings take one extra page load before you see the effect, so click the node ID number at the top of the page (for example) after you make a change if it appears that the change didn't "take".

For those who don't want to just try it, the Free Nodelet lets you put any HTML in it. It processes PM-style links (things in square brackets) but otherwise doesn't touch your HTML. You can even include JavaScript, bizarre CSS, forms, iframes, stuff to copy/paste etc. in it (though you should avoid having JavaScript enabled when visiting PerlMonks until home nodes get properly filtered and some CSS belongs in your CSS settings and not in the Free Nodelet, but you are free to try whatever you like).

If you try to stuff 60kB of data into your Free Nodelet (or any of the other text areas on User Settings and the related 'Settings' pages), you'll likely mess up your settings (and you are a freak).

Later I'll post instructions for how to add a link to your Free Nodelet such that clicking the link adds to your Free Nodelet a link to whatever node you are viewing (so you can use the Free Nodelet like the Personal Nodelet).

Note that PM-style CODE tags don't work in the Free Nodelet. I'm not yet sure if this is a bug or a feature.


- tye        

Replies are listed 'Best First'.
Free Nodelet Hack: RAT collapse all
by jZed (Prior) on Oct 14, 2004 at 19:58 UTC
    Add the code below to your free nodelet and you'll be able to toggle between collapse all and expand all in Recently Active Threads. You can collapse them all, then expand only the threads you are interested in with the (+/-) link for that thread. Collapse_all is very fast, Expand_all takes a moment or two.
    <script language="javascript"><!-- var expandState="expanded"; function toggle_all(){ expandState = (expandState=='expanded') ? 'collapsed' : 'expanded' ; var elements = document.getElementsByTagName('ul'); var elnum; for(elnum=0;elnum<elements.length;elnum++){ var lb = "\x5B"; var rb = "\x5D" var el = eval("elements"+lb+"elnum"+rb); el.className = expandState; } } //--></script> <p> <a href="javascript:toggle_all()">Expand/Collapse All</a> </p>
    Thanks cLive++ for the evil string eval.
      If you add the following snippet to your Free Nodelet, you'll have a way to clear all the radiobuttons on the current page.
      <script language="javascript"><!-- function clear_all_radios(){ var lb = "\x5B"; var rb = "\x5D" var elements = document.getElementsByTagName('input'); var elnum; for(elnum=0;elnum<elements.length;elnum++){ var el = eval("elements"+lb+"elnum"+rb); if ( el.type == 'radio') { el.checked = false; } } } //--></script> <p><a href="javascript:clear_all_radios()">Clear All Radiobuttons</a>< +/p>

      Thanks to jZed for the parent node, upon which this code is based.

      See also: planetscape's Free Nodelet Hack: Check or Clear all "Delete" Message Checkboxes in Your Message Inbox

Re: Free Nodelet freed
by jZed (Prior) on Oct 14, 2004 at 17:17 UTC
    Great idea, thanks. The square brackets thing without code tags makes javascript pretty unusable - no way to use square brackets in javascript, so no javascript arrays.
      eval is your friend (using the word friend in its loosest form :)
      <script language="javascript"> var arr = new Array('one','two'); var lb = "\x5B"; var rb = "\x5D" var code = "alert(\"Second element is \"+arr"+lb+"1"+rb+")"; eval(code); </script>


      cLive ;-)

        This might be simpler:
        // Hack around mangling of left square bracket by PerlMonks. function get_item(a, i) { return eval("a\x5Bi]"); } function set_item(a, i, v) { return eval("a\x5Bi] = v"); }
        var a = new Array(5); set_item(a, 2, "Hello World\n"); alert(get_item(a, 2));

        Update: Never mind. New useful escapes documented here.

      Code tags wouldn't help. CODE tags just turn [ into &#91; (among other things, of course).

      - tye        

Free Nodelet Hack: 'Newest Nodes' Menubar
by jdporter (Chancellor) on Feb 24, 2006 at 16:43 UTC

    The Free Nodelet can have javascript in it. This can be used to modify how your PerlMonks pages appear and behave. Also, the Free Nodelet, unlike any other nodelets or node, is allowed to have virtually any HTML in it. (This is because no matter what nasty code you might put in your Free Nodelet, the only person it affects is you. :-)

    I've taken advantage of this freedom to display a condensed list of "newest nodes" links across the top of every PerlMonks page. Here is a screenshot (126kb) of my PerlMonks experience.

    The links themselves come from the RSS feeds at, filtered through a CGI script I wrote which converts the RSS XML to HTML. My script takes several parameters which control the HTML generation.

    I embed this small fragment of HTML in my PerlMonks web page using <iframe...>. You don't see the iframe border in the screenshot, because I've set its frameBorder attribute to 0. You'll notice that some of the page style (css) propagates into the iframe, but not all.

    In order to place the iframe in the exact web page location I desire, I use javascript running in the Free Nodelet.

    So — if you'd just like to include a list like this in your Free Nodelet and skip the javascript part, simply go to Free Nodelet Settings and insert the following code in the HTML textarea:

    <iframe width="400" height=240 src=" +.cgi?feeds=top&max=12"> </iframe>
    This will put a 'newest nodes' link list in your Free Nodelet. (Of course, you'll want to have your Free Nodelet enabled in Nodelet Settings.)

    In the example above, 'top' is the name of the feed. Here is the list of available feeds:

    	top	all	cufp	note	poem	user	snippet
    	perlnews	usergroup	perlquestion
    	bookreview	qandasection	obfuscated
    	sourcecode	scratchpad	monkdiscuss
    	perltutorial	perlmeditation	categorized_question
    (This is similar to, but not quite the same as, the list for the Newest Nodes XML Ticker.)
    You can actually have more than one feed in the output listing — simply give more than one feed name, separated by commas. For example, pmrss.cgi?feeds=perlquestion,perlmeditation,monkdiscuss&max=12
    You can also override the link count maximum on a feed-by-feed basis: put a number after the feed name, separated by a colon. For example, pmrss.cgi?feeds=perlmeditation,monkdiscuss:4&max=12
    If you leave off the max= parameter, the limit used by in its rss feeds will apply. I don't know what that limit might be, but the list of links is never very long.

    Now — if you'd like to duplicate what I've done, as shown in the screenshot above, you'll want to add code like the following in your Free Nodelet:

    function add_nn_iframe() { var tbl = document.getElementById('titlebar-bottom'); var hr = document.createElement('hr'); var tbl2 = document.createElement('table'); var row = document.createElement('tr'); var cel = document.createElement('td'); var ifr = document.createElement('iframe'); tbl2.width = "100%"; ifr.src = " +:4,snippet&max=8"; ifr.width = "100%"; ifr.height = 64; ifr.border = 0; ifr.frameBorder = 0; ifr.margin = 0; cel.width = "100%"; cel.align = "center"; cel.appendChild(ifr); row.appendChild(cel); tbl2.appendChild(row); tbl.parentNode.insertBefore(hr,tbl.nextSibling); tbl.parentNode.insertBefore(tbl2,hr); } add_nn_iframe();

    Also note the image I've embedded in my Free Nodelet. ;-)

    We're building the house of the future together.

    (<script type="text/javascript"> stuff I'm storing here temporarily</script>)
Re: Free Nodelet freed
by ambrus (Abbot) on Oct 14, 2004 at 19:14 UTC

    I thought you could add any html to the Personal Nodelet too (I now have a form in it). So is this just a variant of the Personal Nodelet?

    I however still like the idea, as now I can have two personal nodelets, one on the top of the nodelet bar for important links, and one near the bottom.

      No, actually this is what tye originally meant when he mentioned the personal nodelet should be changed. I was in a gee-whiz mode and put together the Personal Nodelet on different principles. PN is basically a list of tiny pm-html snippets that are manipulatable as such so you can reorder, limit the list etc. The Free Nodelet is just a single html string that doesn't go through normal PM tag filtering. I think the only real difference is that you have the controls on Personal Nodelet Settings and PN can display code tags, wheras the "Free Nodelet" is just what it says Free. :-)

      In some respects when tye put this together I thought maybe I should remove the PN, but what you just said seems to make me think that on the contrary there is a place for both. I think that PN is more suited to link collecting, and the free nodelet to more stylized stuff so they seem to complement each other.


        First they ignore you, then they laugh at you, then they fight you, then you win.
        -- Gandhi


        A big difference for me that you don't mention is that I adjust the Free Nodelet by pasting the contents into my favorite editor (or other tool), changing anything in any way I like, and then pasting the results back into User Settings. So I can do a global search/replace easily or I can write a tiny snippet of Perl code to sort a list of links in the middle of my free nodelet by node ID and paste the now-sorted list back in. That is more than just being free to add anything I want to it.

        - tye        

        They have different merits. The various Add to foo links on the PN make it nice for on-site bookmark management, whereas the FN’s unconstrained content makes it nice as a sort of cross between homenode and scratchpad that’s always available. (I know about FN templating, but really, the PN does much of the same out of the box, and I’m getting cranky in my old age and expecting more things to Just Work.)

        Makeshifts last the longest.

Free Nodelet Hack: Hide/Display Nodelet Bar On Demand
by jdporter (Chancellor) on May 03, 2006 at 21:30 UTC

    I like to have my Nodelet bar (column? table?) nice and wide, most of the time, partly because it makes the nodelets shorter, and thus I have to scroll less to read them. (I keep the most dynamic ones at the top.) The downside is that the main body of the node is squeezed. This not only makes it taller, but often causes ugly line wrapping, especially in embedded HTML tables. So, sometimes I really want to get my Nodelet column out of the way, and just view the main node body in its full glory. So I thought:

    How can I hide (toggle off) the Nodelet bar as needed?

    The following code does just that. Simply plunk it into your Free Nodelet Settings. It makes two checkboxes near the top right corner of your page, labeled 'Hide Main Body' and 'Hide Nodelets'. When one or the other part of the page is hidden, the remaining visible part expands to fill the entire width of the window.

    // add toggles to hide/show nodelets and main_content { var tbl = document.getElementById('titlebar-bottom'); var cel = document.createElement('td'); tbl.rows[0].appendChild(cel); cel.width = "20%"; cel.align = "right"; // add toggle to hide/show main_content txt = document.createTextNode( 'Hide Main Body' ); cel.appendChild(txt); chk = document.createElement('input'); cel.appendChild(chk); chk.type = 'checkbox'; = 'hide_mainbody'; = 'hide_mainbody'; chk.onclick = function(){ var chk = document.getElementById('hide_mainbody'); var state = chk.checked ? 'none' : 'table-cell'; element_of_tag_and_class('td','main_content').style.display = +state; } // add toggle to hide/show nodelets var txt = document.createTextNode( 'Hide Nodelets' ); cel.appendChild(txt); var chk = document.createElement('input'); cel.appendChild(chk); chk.type = 'checkbox'; = 'hide_nodelets'; = 'hide_nodelets'; chk.onclick = function(){ var chk = document.getElementById('hide_nodelets'); var state = chk.checked ? 'none' : 'table-cell'; element_of_tag_and_class('td','nodelets').style.display = stat +e; } } // presumes only one. returns first found. function element_of_tag_and_class(tagname,classname) { var elems = document.getElementsByTagName(tagname); var i; for ( i = 0; i < elems.length; i++ ) { if ( elems[i].className == classname ) { return( elems[i] ); } } }
    We're building the house of the future together.

      There are lots of cool nodelets, and normally I like to have almost all of them turned on. Problem is, that makes each page take noticeably longer to load. So sometimes I wish I could have just a bare-bones set of nodelets active.

      Fortunately, PerlMonks gives you two nodelet configurations, as you can see by going to your Nodelet Settings: there's your FrontPage nodelets, and your non-FrontPage nodelets. But using Nodelet Settings to toggle quickly between them is just not convenient!

      So I came up with the following code to go in my Free Nodelet. (Note that if you use this you'll definitely want Free Nodelet to be enabled in both your FrontPage and non-FrontPage nodelet sets.)

      <script language="javascript"><!-- // the value of _redir must be a node ID! if ( "`_redir`" != "`" + "_redir" + "`" ) { "?node_id=`_redir`"; } //--></script> [href://?node_id=25185;_redir=`id`;setfpeqnonfp=1|FP nodelets] | [href://?node_id=25185;_redir=`id`;clrfpeqnonfp=1|main nodelets]

      Each link makes a submission to Nodelet Settings — to enable and disable Use my frontpage nodelets everywhere, respectively — and then "redirects" back to the node you were viewing when you clicked. Note that only the node ID of the current node is remembered; any other URI arguments are dropped.

      This technique is based on ideas in subthread Re: Free Nodelet Hack: Add parent & root links to nodes in 'Nodes You Wrote' (or anywhere). tye++

      Update (hopefully temporary):
      The above technique does not work any longer, since apparently the two form fields (setfpeqnonfp, clrfpeqnonfp) are no longer settable via HTTP GET requests. Until that capability is restored, you can achieve the same with the equivalent POSTs, e.g.:

      Nodelets: <form method="post" action="?" enctype="application/x-www-form-urlenco +ded"> <input type="hidden" name="node_id" value="25185"> <input type="hidden" name="_redir" value="`id`"> <input type="hidden" name="setfpeqnonfp" value="1"> <input type="submit" name="sexisgood" value="FP"> </form> <form method="post" action="?" enctype="application/x-www-form-urlenco +ded"> <input type="hidden" name="node_id" value="25185"> <input type="hidden" name="_redir" value="`id`"> <input type="hidden" name="clrfpeqnonfp" value="1"> <input type="submit" name="sexisgood" value="Main"> </form>

Free Nodelet Hack: Collapse/expand Nodelets individually
by shmem (Chancellor) on Feb 05, 2007 at 17:19 UTC
    The following hack makes each nodelet title clickable, and you can preconfigure your nodelet's initial state (collapsed/expanded).

    Plunge into your Free nodelet and tweak the closedN array. For maximum benefit put your free nodelet last in Nodelet Settings.

    update: use the block further down. I would have deleted this first attempt, had ikegami not answered :-)

    // this function toggles a nodelet's state. function toggleVis (id) { var r = document.getElementById(id); if( == "none") { = "table-row"; } else { = "none"; } } // Array with nodelet state flags, 1 = closed, 0 = open var closedN = `[1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1]; var nc = document.getElementById('nodelet_container'); var c = 0; for(var i=0; i<nc.childNodes.length; i++) { if(nc.childNodes`[i].nodeName == "TBODY") { cn = nc.childNodes`[i]; var ary = new Array; var k = 0; for(var j=0; j<cn.childNodes.length; j++) { if(cn.childNodes`[j].nodeName=="TR") { ary`[k] = cn.childNodes`[j]; k++; } } var str= ary`[0].childNodes`[1].innerHTML; var id = ary`[1].id; id = id.replace(/\'/,"\\'"); ary`[0].childNodes`[1].innerHTML = '<div onClick="toggleVis('+"'"+id+"'"+');">'+ary`[0].childNo +des`[1].innerHTML+'</div>'; if(closedN`[c]) toggleVis(ary`[1].id); c++; } }

    That could've been more 'elegant'... but it's a hack. If JavaScript had hashes...

    This one is for firefox. IE users likely will have to replace the document.getElemetById by the appropriate IE function.


    Since some nodelets come and go, the order can change. Here's a version with hashes. The XP Nodelet has a degree sign in the upper left corner, which, when clicked, will pin/unpin the nodelet container. Use with the CSS snippet below.

    // this function toggles a nodelet's state. function toggleVis (id) { var r = document.getElementById(id); if(! || == "none") { = "table-row"; } else { = "none"; } } function togglePin () { var n = document.getElementById('nodelet_container'); var pin = document.getElementById('nodelet_pin'); if (! || == 'fixed') { = 'absolute'; pin.innerHTML = '&nbsp;|&nbsp;'; } else { = 'fixed'; pin.innerHTML = '&nbsp;&deg;&nbsp;'; } } function collapseNodelets () { // insert the nodelets you want to have expanded here var opened = { 'XP Nodelet' : 0, 'Chatterbox' : 0, 'Tick tock' : 0, 'Cabalists\' Nodelet' : 1, } var nc = document.getElementById('nodelet_container'); var c = 0; for(var i=0; i<nc.childNodes.length; i++) { if(nc.childNodes`[i].nodeName == "TBODY") { cn = nc.childNodes`[i]; var ary = new Array; var k = 0; for(var j=0; j<cn.childNodes.length; j++) { if(cn.childNodes`[j].nodeName=="TR") { ary`[k] = cn.childNodes`[j]; k++; } } var str= ary`[0].childNodes`[1].innerHTML; str = str.replace(/ *\n */g,""); str = str.replace(/ /g," "); var id = ary`[1].id; id = id.replace(/\'/,"\\'"); if(str == "Chatterbox") { // this one gets the pin div - degree(pinned) or pipe(unpinned +) ary`[0].childNodes`[1].innerHTML = '<div id="nodelet_pin" onClick="togglePin();"' + ' style="float: left; cursor: pointer">&nbsp;&deg;&nbsp;</ +div>' + '<div onClick="toggleVis('+"'"+id+"'"+');">'+str+'</div>'; } else { ary`[0].childNodes`[1].innerHTML = '<div onClick="toggleVis('+"'"+id+"'"+');">'+str+'</div>'; } if(!opened`[str]) toggleVis(ary`[1].id); c++; } } } collapseNodelets();

    And here's a stylesheet snippet to pin the nodelet container to the upper right corner of the page:

    /* pin container, make it fixed width */ #nodelet_container { position: fixed; margin-left: 5px; top: 5px; width: 200px; } /* leave a bit space on the right, so the nodelet container fits */ #monkbar, #titlebar-top, #titlebar-bottom, #footer { padding-right: 20 +5px; } /* initial state of all nodelets collapsed */ [id^="nodelet_body_row"] { display: none; }



    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      That could've been more 'elegant'... but it's a hack. If JavaScript had hashes...

      But it does! JavaScript calls them Objects. (Kinda like how objects are usually implemented as hashes in Perl).

      // Hash creation and initialization var hash = new Object; var hash = {}; var hash = { foo: "Foo!", bar: "Bar!" }; var hash = { "spaced out": "ok" }; // Setting = "Foo!"; // Static key hash["bar"] = "Bar!"; // Dynamic key // Getting alert(" " + hash["foo"]); // Dynamic key alert(" " +; // Static key // Iterating for (var key in hash) { var val = hash[key]; alert("hash." + key + ": " + val); }
Free Nodelet Hack: Add links to cbhistory, etc to CB
by ikegami (Patriarch) on Nov 09, 2006 at 21:09 UTC

    Place links to chat clients and/or chat histories at the bottom of the CB.

    // ======================================== // Replace chat clients. function replace_chat_clients() { var cb = document.getElementById('nodelet_body_row_Chatterbox') .firstChild .nextSibling; cb.removeChild(cb.lastChild); cb.removeChild(cb.lastChild); var container = document.createElement('div'); container.innerHTML = ('' + '<i>' + '<a href="">cbhi +story</a>' + ' | ' + '<a href="">cb60</a>' + ' | ' + '<a href="/?node_id=20842">Others</a>' + '</i>' ); cb.appendChild(container); } replace_chat_clients();

    Not very elegant. An array with the links would be nice.

Re: Free Nodelet freed
by ikegami (Patriarch) on Nov 09, 2006 at 23:40 UTC

    Before messing with the DOM (document.[...]), it might be smart to wait for the HTML doc to be fully parsed and the DOM tree to be fully built. This can be achieved as follows:

    <script type="text/javascript"> function my_dom_manipulator1() { ... } function my_dom_manipulator2() { ... } function my_dom_manipulator3() { ... } // Execute our snippets after the page is parsed. var old_onload = window.onload; window.onload = function() { if (old_onload != null) old_onload(); my_dom_manipulator1(); my_dom_manipulator2(); my_dom_manipulator3(); }; </script>

    For an example of where this makes a difference, refer to Free Nodelet Hack: Nodelets on the left.

Free Nodelet Hack: linkify nodelet headings (for pmdev)
by jdporter (Chancellor) on Jan 05, 2011 at 17:33 UTC

    See Free Nodelet Freed

    This will turn each of the nodelet headings (titles) into links to the corresponding nodelet code nodes. (Only pmdev members are likely to find this useful.)

    function linkify_nodelet_titles() { var nodelet_head_divs = getElementsOfTagAndClass( 'div', 'nodelet_he +ad' ); var i; for ( i = 0; i < nodelet_head_divs.length; i++ ) { var spans = nodelet_head_divs[i].getElementsByTagName('span'); var j; for ( j = 0; j < spans.length; j++ ) { if ( spans[j].className == 'title' ) { var title_span = spans[j]; var a = document.createElement('a'); a.href = '' + title_span.innerHTML; a.innerHTML = title_span.innerHTML; title_span.removeChild(title_span.firstChild); title_span.appendChild( a ); } } } }