Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Free Nodelet Hack: Add parent & root links to nodes in 'Nodes You Wrote'

by ikegami (Patriarch)
on Dec 17, 2006 at 18:46 UTC ( [id://590338]=note: print w/replies, xml ) Need Help??


in reply to Have parent 'Node ID' as link in 'Nodes You Wrote' node

It's possible to do what you want using JavaScript in the Free Nodelet. Just add the code below to your Free Nodelet and make sure your Free Nodelet is visible.

There's a delay between the time the link is clicked and when the browser loads the desired page because an extra HTTP fetch is done in the background to determine the id of the desired node.

Works in Firefox. Untested elsewhere.

<script type="text/javascript"> // ======================================== // Adds parent and root links next to nodes in // "Perl Monks User Search". Links are added even // when the node is a root node. // // When a parent or root link is clicked, the id of the // desired node is fetched using an asynchronous HTTP // request. // // When the id of the desired node is known, the browser // is directed to load the desired node. // // Should the node be a root node, the browser is directed // to load the node whose parent/root was requested. var redir_requester = null; function init_redir_asynch_request_obj() { if (redir_requester != null && redir_requester.readyState != 0 && redir_requester.readyState != 4 ) { redir_requester.abort(); } redir_requester = null; try { redir_requester = new XMLHttpRequest(); } catch (error) { try { redir_requester = new ActiveXObject("Microsoft.XMLHTTP"); } catch (error) { } } return redir_requester; } function _goto_by_field(requester, id, field) { if (requester.readyState != 4) return; if (requester.status != 200) { // XXX Need to return feedback to the user. return; } var doc = requester.responseXML; var query = "/node/data/field`[@name='" + field + "']"; var dest_id_value = doc .evaluate(query, doc, null, XPathResult.ANY_UNO +RDERED_NODE_TYPE, null) .singleNodeValue; var dest_id = (dest_id_value ? dest_id_value.textContent : id ); window.location = '/?node_id=' + dest_id; } function goto_by_field(id, field) { var requester = init_redir_asynch_request_obj(); requester.onreadystatechange = function () { _goto_by_field(requester, id, field) }; requester.open('GET', '/?displaytype=xml;node_id=' + id); requester.send(null); // XXX Need to return feedback to the user. } function goto_parent_of(id) { goto_by_field(id, 'parent_node'); } function goto_root_of(id) { goto_by_field(id, 'root_node' ); } function show_ancestors_user_search() { // if (decodeURIComponent('`title%`') != 'Perl Monks User Search') // return; if ('`title%`' != 'Perl%20Monks%20User%20Search') return; var writeups = document.getElementById('writeups'); // We need to flatten the collection returned by // getElementsByTagName into an array because we // will be adding more "a" elements. var anchs = new Array(0); for each (var anch in writeups.getElementsByTagName('a')) { if (anch.nodeType != Node.ELEMENT_NODE) continue; anchs.push(anch); } // Add parent and root links to every "a" element we found. for each (var anch in anchs) { var id = anch.href.match(/\d+$/); var container = document.createElement('span'); container.innerHTML = ('' + ' ' + '<a href="javascript:goto_parent_of(' + id + ')" class="par +ent_link">`[parent]</a>' + ' ' + '<a href="javascript:goto_root_of(' + id + ')" class="root_ +link">`[root]</a>' ); anch.parentNode.insertBefore(container, anch.nextSibling); } } // ======================================== // Execute our snippets after the page is rendered. var old_onload = window.onload; window.onload = function() { if (old_onload != null) old_onload(); show_ancestors_user_search(); // ... }; </script>

Update: Removed text that got accidently pasted in, as pointed by shmem.

  • Comment on Free Nodelet Hack: Add parent & root links to nodes in 'Nodes You Wrote'
  • Download Code

Replies are listed 'Best First'.
Re: Free Nodelet Hack: Add parent & root links to nodes in 'Nodes You Wrote' (or anywhere)
by tye (Sage) on Dec 17, 2006 at 22:14 UTC

    I think that if you avoid overgeneralizing and just hard code "redir to root" and "redir to parent", then the code can become much simpler, you don't need to depend on AJAX components (so it is easier to make work more places), and you avoid waiting for one round-trip to the server.

    Actually, the amount of hard-coding you need to do would be minimal, just a case statement on the fields that make sense, with the Free Nodelet templatung filling in values for you.

    Just check if "redir" parameter was specified, then switch on the parameter's value to redirect to the appropriate next field (not including the "redir" parameter, of course). And then add an on-load function to use the DOM to transform links of type ?node_id=... to be three links, the original plus one that includes ;redir=parent and one that includes ;redir=root. It seems like this strategy even makes it easy to provide the feedback that you note you didn't include.

    Okay, here is a working redirector that adds links to your Free Nodelet that will send you to the grandparent of a reply or to the author of the node that this node was in reply to:

    <script type="text/javascript"><!-- var params= window.location.search; if( 0 <= params.indexOf( ";_redir=root" ) ) { window.location.search= "?node_id=`root_id`"; } else if( 0 <= params.indexOf( ";_redir=parent" ) ) { window.location.search= "?node_id=`parent_id`"; } else if( 0 <= params.indexOf( ";_redir=author" ) ) { window.location.search= "?node_id=`author_id`"; } --></script> <a href="?node_id=`parent_id`;_redir=author">Who replied to</a> <a href="?node_id=`parent_id`;_redir=parent">Grandparent</a>

    The on-load code to transforms node_id= links is left as an exercise.

    It might even make sense to have PM directly support redir=parent (and perhaps redir=root and redir=author) to allow both Free Nodelet hackers and pmdev members to construct "efficient" "indirect" links... Note that I've used _redir= in my javascript code above in order to future-proof against such a redir= feature being provided by PM.

    - tye        

      Your solution (redir argument solution) occured to me, but I wanted some experience with XMLHttpRequest and XPath. I intended to implement the redir argument solution at a later point.

      There are downside to the redir argument solution (until it's handled by PM natively). It still loads two pages. Its intermediary page is slower to generate, transmit and parse. And the user sees its intermediary pages.

      I haven't tried modifying your code above, but I point out that parameter names with leading underscores are already handled for you by the Free Nodelet templating. So instead of

      if ( params.indexOf( ";_redir=root" ) > 0 )
      you should be able to write
      if ( `_redir` == "root" )
      We're building the house of the future together.
        if ( `_redir` == "root" )

        No, that'd turn into one of the following, either:

        if ( root == "root" )

        or

        if ( `_redir` == "root" )

        neither of which looks like valid javascript to me. So you'd want something more like:

        if ( "`_redir`" == "root" )

        which would induce a syntax error if somehow you got a quote (or perhaps a trailing backslash) in your parameter value.

        There needs to be an escape specifier for use in javascript strings. Perhaps:

        if ( "`_redir\`" == "root" )

        where that trailing \ tells the Free Nodelet templating to apply quotemeta to the parameter value (not implemented yet). I haven't checked exactly how escaping works in javascript strings, so quotemeta might not be appropriate. Perhaps `_redir"` would surround it in quotes and escape as appropriate.

        - tye        

      I just found a very good reason to use the redir argument solution: The ability to open the link in a different tab or window.
Re: Free Nodelet Hack: Add parent & root links to nodes in 'Nodes You Wrote'
by shmem (Chancellor) on Dec 17, 2006 at 20:34 UTC
    Nice! ikegami++

    Just one glitch in function goto_by_field():

    requester.send(null);http://www.perlmonks.org/?parent=587896;node_i +d=3333

    should be

    requester.send(null);

    <update>

    in function show_ancestors_user_search()

    container.innerHTML = ('' + '<a href="javascript:goto_root_of(' + id + ')" class="root_ +link">r</a>' + ' ' + '<a href="javascript:goto_parent_of(' + id + ')" class="par +ent_link">p</a>' + '&nbsp;&nbsp;' ); // anch.parentNode.insertBefore(container, anch.nextSibling); anch.parentNode.insertBefore(container, anch);

    adds the links up front, marked 'r' and 'p', which imho makes a nicer formatting.

    </update>

    --shmem

    _($_=" "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}

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://590338]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (2)
As of 2024-04-19 19:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found