User Tools

Site Tools


scratchpad:supercat_opac_example

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
scratchpad:supercat_opac_example [2009/04/28 15:10] mikerscratchpad:supercat_opac_example [2022/02/10 13:34] (current) – external edit 127.0.0.1
Line 1: Line 1:
 +==== Using Evergreen APIs for client-side bibliographic data rendering  ====
 +=== or Replacing result_detail.xml ===
 +
 +The following is a rough example of one mechanism available in Evergreen for displaying bibliographic data outside of the stock OPAC code.
 +
 +
 +
 +<code html>
 +<html>
 +    <head>
 +        <title>This is only a test</title>
 +        <script type="text/javascript" src='/js/dojo/dojo/dojo.js'></script>
 +    </head>
 +    <body>
 +</code>
 +First, load Dojo, which is included in Evergreen 1.4.0 and beyond.
 +
 +
 +
 +<code html>
 +    <table border=1>
 +        <tr>
 +
 +            <th>title</th>
 +            <td type="opac/slot-data+marcxml" query="datafield[tag=245] subfield">
 +                <script type='opac/slot-format'>
 +                    if (item.getAttribute('code') == 'a') {
 +                        return '<b>' + dojox.data.dom.textContent(item) + '</b>';
 +                    } else {
 +                        return dojox.data.dom.textContent(item);
 +                    }
 +                </script>
 +            </td>
 +        </tr>
 +</code>
 +Now we lay out some template slots that the bib data will be plugged into.  This requires some extra explanation, I think.
 +
 +First, we need to mark the containing element (''<td>'' here) in some way so that we can find it.  We do this by giving it a non-standard ''type'' attribute with a value of ''opac/slot-data-marcxml'' This attribute is used in two ways.  First, ''opac/slot-data'' says that this element will be used as a place to deposit data needed for constructing this "opac" Second, ''+marcxml'' tells the query processor that it should use the ''marcxml'' form of the bibliographic record.  Other formats would include ''marcxml-full'' (which includes holdings information), ''mods'', ''oai_dc'' and other formats supported by the Evergreen unAPI service.
 +
 +Next we need to tell the query processor what to extract from the XML returned by the unapi service.  We add a ''query'' attribute to the container element and set its value to the [[http://www.dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/selecting-dom-nodes-dojo-query|dojo.query()]] we need to find the relevant data in the format selected by the ''type'' attribute.
 +
 +Finally, we may need to format the data in some special way.  We do this by providing a chunk of Javascript that knows how to take the output of the ''dojo.query()'' call, one node at a time, and do something special with it.  Each node is run through this code, and the return values for all nodes passing through this code are joined with a space and used to replace the HTML content of the containing element.
 +
 +Two things to note about this ''<script>'' tag:  it's ''type'' attribute and the assumed environment of the code within the block.
 +
 +By setting the ''type'' attribute to ''opac/slot-format'' we tell the browser to ignore the content of the element (browsers will only process untyped ''<script>'' tags, or those with a type of ''language/javascript'' (more or less)) and we let the formatting processor find the code.  We place this specialized ''<script>'' inside the container element so that it is specifically associated with that bit of data.  
 +
 +The block of code within this ''<script>'' tag can assume that it will be passed a parameter called ''item'' and that this is a node coming from the nodelist produced by the relevant ''dojo.query()'' call.
 +
 +
 +
 +<code html>
 +        <tr>
 +            <th>mods title</th>
 +
 +            <td type="opac/slot-data+mods" query="titleInfo:not([type])"/>
 +        </tr>
 +</code>
 +Here we see an example of a format other than ''marcxml'', and a more complex ''dojo.query()''.
 +
 +
 +
 +<code html>
 +        <tr>
 +            <th>author</th>
 +            <td type="opac/slot-data" query="datafield[tag=100]"/>
 +        </tr>
 +</code>
 +If no format is given, ''marcxml'' is assumed.
 +
 +
 +
 +<code html>
 +        <tr>
 +            <th>abstract</th>
 +
 +            <td type="opac/slot-data+marcxml" query="datafield[tag=520]"/>
 +        </tr>
 +        <tr>
 +            <th>subjects</th>
 +            <td type="opac/slot-data+marcxml" query="datafield[tag=650]">
 +                <script type='opac/slot-format'>
 +                    return '<span>' +
 +                        dojo.query(
 +                            'subfield',
 +                            item
 +                        ).map(
 +                            function(sf){
 +                                return '<b>' + sf.getAttribute('code') + ':</b> ' + dojox.data.dom.textContent(sf);
 +                            }
 +                        ).join(' >>> ') +
 +                        '</span><br/>';
 +                </script>
 +            </td>
 +        </tr>
 +</code>
 +Here we see that by selecting nodes in the middle of the DOM tree (''<datafield>'' sits between ''<record>'' and ''<subfield>'' in ''marcxml'') we can process groups of values together, allowing richer rendering and interpretation of entire sections of information instead of simple, discrete data.
 +
 +
 +<code html>
 +        <tr>
 +            <th>items</th>
 +            <td>
 +                <ul type="opac/slot-data+marcxml-full" query="*[barcode]">
 +                    <script type='opac/slot-format'>
 +                        return '<li>' + item.getAttribute('barcode') + '</li>';
 +                    </script>
 +                </ul>
 +            </td>
 +        </tr>
 +
 +    </table>
 +</code>
 +And, finally, here's one way for dealing with the holidngs info appended to the bib by adding -full to the end of the format specifier.
 +
 +
 +<code html>
 +        <script>
 +
 +dojo.addOnLoad( function() {
 +
 +    var all_slots = dojo.query('*[type^=opac/slot-data]');
 +    var rec = location.href.split('?')[1];
 +
 +    var slots = {};
 +    all_slots.forEach(function(s){
 +        var datatype = 'marcxml';
 +
 +        if (s.getAttribute('type').indexOf('+') > -1) 
 +            datatype = s.getAttribute('type').split('+').reverse()[0];
 +
 +        if (!slots[datatype]) slots[datatype] = [];
 +        slots[datatype].push(s);
 +    });
 +
 +    for (var datatype in slots) {
 +        _flesh_by_type_and_rec(slots[datatype], datatype, rec);
 +    }
 +}); 
 +</code>
 +This bit of Javascript sets the wheels in motion.  Here's what it does at page load time:
 +  - Find all elements with a ''type'' attribute starting with ''opac/slot-data''
 +  - Get the target bib record id from the query section of the URL
 +  - Group slots by their format
 +  - For each format group, process all the slots
 +
 +
 +How does that processing happen?  Read on.
 +
 +<code html>
 +function _flesh_by_type_and_rec (slots,datatype,rec) {
 +    dojo.xhrGet({
 +        url: '/opac/extras/unapi?id=tag:acq.open-ils.org:biblio-record_entry/' + rec + '/-&format=' + datatype,
 +        handleAs: 'xml',
 +        load: function (bib) {
 +
 +            dojo.forEach(slots, function (slot) {
 +
 +                var slot_handler = dojo.query(
 +                    'script[type=opac/slot-format]',
 +                    slot
 +                ).orphan().map(
 +                    function(x){return x.textContent || x.innerText || x.innerHTML}
 +                ).join('');
 +        
 +
 +                if (slot_handler) slot_handler = new Function('item', slot_handler);
 +                else slot_handler = new Function('item','return dojox.data.dom.textContent(item);');
 +
 +                slot.innerHTML += dojo.query(
 +                    slot.getAttribute('query'),
 +                    bib
 +                ).map(slot_handler).join(' ');
 +
 +                delete(slot_handler);
 +
 +            });
 +       }
 +    });
 +}
 +        </script>
 +
 +    </body>
 +
 +</html>
 +</code>
 +This function takes the datatype and record id and makes an XHR request to the Evergreen unAPI service to retrieve the record in the required format.  When the record arrives, it loops over each data slot using this datatype and looks for one or more script elements with a ''type'' attribute of ''opac/slot-format'' If found, it takes the text content of these and concatenates these and uses that as the body of a processing function to which each node found by passing the ''query'' attribute a ''dojo.query()'' call.  If no specialized ''<script>'' element is found, a default handler is used which returns the entire text content of the supplied node.  The output of this handler is then concatenated and used to replace all existing content in the ''opac/slot-data'' container node.
 +
 +And that's it.
  

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki

© 2008-2022 GPLS and others. Evergreen is open source software, freely licensed under GNU GPLv2 or later.
The Evergreen Project is a U.S. 501(c)3 non-profit organization.