jQuery.PRIMO
jQuery.PRIMO copied to clipboard
A client side convenience library for PRIMO.
jQuery.PRIMO
The missing model for PRIMO v4.9 and better.
This is a work in progress!
If you want a feature, have a comment, found a bug you can:
- ping me. new issue
- fork -> add changes -> send pull request
See the releases for downloads and release notes
WARNING
jQuery.PRIMO.js is intended to be used with a vanilla(unchanged) view. You might not get the intended experience if you changed/removed/renamed class names, id's etc.
Contact me if you are experiencing problems. Installation
From February 2016 this will be a part of the general Primo release cycle. But if you have server access you can install it yourself.
jQuery.PRIMO exists of 2 parts:
- jQuery.PRIMO.js This is the client library that needs to be loaded inside your browser. It will expose the model.
- jQuery.PRIMO.jar (This is a seperate project) This is the server library. It exposes a Rest API used by the client library.
Install and setup
- copy jQuery.PRIMO.jar into $(fe_web)/WEB_INF/lib
- copy jQuery.PRIMO.min.js into $(fe_web)/javascript
- add javascript snippet to a tile/html(footer.html for example)
<script type='text/javascript' src='/primo_library/libweb/javascript/jQuery.PRIMO.min.js'></script>
- if you want to be able to retrieve the Original Record(MarcXML) then you need to uncomment or add
<mapping resource="com/exlibris/primo/domain/entities/OriginalSourceRecord.hbm.xml"/>
to the hibernate mapping file /exlibris/primo/p4_1/ng/primo/home/system/search/conf/hibernate.cfg.xml The hibernate mapping file will be overwritten after each update this means you need to reapply this patch after every Primo upgrade.
- restart your front end
- test it.
- Open/Reload your view
- Open a console in your browser and type:
jQuery.PRIMO.version;
That is it.
I also created 3 screencasts(no audio) as a guide.
Or if you want to isolate jQuery.PRIMO.
Just for testing
You can inject the script into your results page, for testing. This works best using Firefox. Open the JavaScript console and paste the next line. You will not be able to use the more advanced functions but it should give you an idea of what it can be used for.
$.getScript('https://cdn.rawgit.com/mehmetc/jQuery.PRIMO/4a091fc5/dist/jQuery.PRIMO.min.js')
Browsers are getting stricter with every release. If you get strange errors just copy the complete source into your console.
Compilation (TODO)
If you would want to compile jquery.PRIMO.js then follow these steps
#Exposed model

#Examples
- Use templates and keep your sanity
- Events & Callbacks
Objects
- misc
- session
- query
- facets
- records
- search
##MISC
Version of jQuery.PRIMO library
jQuery.PRIMO.version;
Reload jQuery.PRIMO
jQuery.PRIMO.reload();
##SESSION Some functions and attributes will only be available when jQuery.PRIMO.jar is installed on the server. Otherwise it will load a minimum of session data from the default getUserInfoServlet service.
- user
- view
- ip
- pds
- performance
Get the session id
jQuery.PRIMO.session.sessionId;
Reload session data
jQuery.PRIMO.session.reload();
###USER
Read the current sessions user id
jQuery.PRIMO.session.user.id;
Read the current session user name
jQuery.PRIMO.session.user.name;
Read the current session user email
jQuery.PRIMO.session.user.email;
Check if the current user is logged in
jQuery.PRIMO.session.user.isLoggedIn();
Check if the current user is on campus
jQuery.PRIMO.session.user.isOnCampus();
Get the Personalized Ranking Categories
jQuery.PRIMO.session.user.ranking.categories;
Get the Personalized Ranking 'Prefer newer material' value
jQuery.PRIMO.session.user.ranking.prefer_new;
###VIEW
Get the current view code
jQuery.PRIMO.session.view.code;
Get the current view's institution name
jQuery.PRIMO.session.view.institution.name;
Get the current view's institution code
jQuery.PRIMO.session.view.institution.code;
Get the current view's interface language
jQuery.PRIMO.session.view.interfaceLanguage;
Is the current view in full display mode
jQuery.PRIMO.session.view.isFullDisplay();
Get the current view frontend id
This is the hashCode() of the machines hostname. It is usefull for debugging or if you want a feature to only work on for example your staging enviroment.
jQuery.PRIMO.session.view.frontEndID;
###IP
####Get IP address as seen on PRIMO
jQuery.PRIMO.session.ip.address;
####Get institution name by IP
jQuery.PRIMO.session.ip.institution.name;
####Get institution code by IP
jQuery.PRIMO.session.ip.institution.code;
##PDS When you are logged in you will get the bor-info from PDS. It serializes the xml into json.
Get the url for PDS
jQuery.PRIMO.session.pds.url;
Get PDS Handle (only available after login)
jQuery.PRIMO.session.pds.handle;
GET borrower info Object from PDS.
jQuery.PRIMO.session.pds.borInfo;
##PERFORMANCE Only available if the browser supports it. Be careful the getPageLoad and getPageRender methods are non blocking. This means they will only return sain values after the page is completely loaded and rendered.
Timing
Get timing for Network latency
jQuery.PRIMO.session.performance.timing.getNetworkLatency();
Get timing for Page Load
jQuery.PRIMO.session.performance.timing.getPageLoad();
Get timing for Page Render
jQuery.PRIMO.session.performance.timing.getPageRender();
##RECORDS Extends the DOM.
- tabs
Get number of records on screen (this is an Array)
jQuery.PRIMO.records.length;
Get the record id of the 6th field
jQuery.PRIMO.records[5].id;
Get the record index
jQuery.PRIMO.records[5].index;
Get title of 6th record
jQuery.PRIMO.records[5].title;
Get OpenUrl of 6th record
jQuery.PRIMO.records[5].openUrl;
Get type of 6th record
jQuery.PRIMO.records[5].materialType();
Get getIt1 of 6th record
jQuery.PRIMO.records[5].getIt1();
Is the 6th record a remote record
jQuery.PRIMO.records[5].isRemoteRecord();
Is the 6th record on the eShelf
jQuery.PRIMO.records[5].isOnEShelf();
Get the PNX data as text,json,xml of the 6th record
jQuery.PRIMO.records[5].getPNX('text');
jQuery.PRIMO.records[5].getPNX('json');
jQuery.PRIMO.records[5].getPNX();
Get the material type of the first record
jQuery.PRIMO.records[0].getData().display.type;
Check if 6th record was deduped
jQuery.PRIMO.records[5].isDedupedRecord();
Get all record ids for a deduped record
jQuery.PRIMO.records[2].getDedupedRecordIds();
Highlight all journals on screen
jQuery.PRIMO.records.each(
function(){
if (this.getData().display.type === 'journal') {
this.css('background-color', 'yellow')
}
}
);
Make the 'View Online' tab popout
jQuery.PRIMO.records.each(
function(index, record){
var view_online = record.tabs.getByName('ViewOnline');
try{
view_online.find('a').attr('target', '_blank').attr('href', record.getIt1);
} catch (e) {
console.log('Error setting url');
}
}
);
##FACETS Extends the DOM.
Get all facet names
jQuery.PRIMO.facets.getNames();
Get facet by name
jQuery.PRIMO.facets.getByName('facet_lang')
Get title for a facet by name
facet_lang is the technical name. Title will return the screen name. The screen name depends on the view language.
jQuery.PRIMO.facets.getByName('facet_lang').title
Get ALL value objects for facet_lang
jQuery.PRIMO.facets.getByName('facet_lang').values
Get ALL values for first facet
jQuery.map(jQuery.PRIMO.facets[0].values, function(f,i){return f.value})
Get FIRST value for facet_lang
jQuery.PRIMO.facets.getByName('facet_lang').values[0].value
Get number of hits for FIRST facet of facet_lang
jQuery.PRIMO.facets.getByName('facet_lang').values[0].count
##TABS Extends the DOM.
Add a new tab to all records
jQuery.PRIMO.records.each(
function(index, record){
record.tabs.addTab('HelloTab',{
label: 'Hello World',
state:'enabled',
click:function(event, tab, record, options){
if (tab.isOpen()){
tab.close();
} else {
tab.open('Hello from tab', {reload:true});
}
}
});
}
);
Add a new share tab and make the sendTo tab appear.
jQuery.PRIMO.records.each(
function(index, record){
record.tabs.addTab('ShareTab', {label: 'Share',tooltip:'Share', state:'enabled', click:function (event, tab, record, options) {
if (tab.isOpen()) {
tab.close();
} else {
var tab_content = "";
var details_url = $(record.tabs).filter('.EXLDetailsTab').find('a').attr('href');
tab_content += "<div style='overflow:auto;height:100%;padding:20px;'>";
tab_content += ' <div class="share_options_import"></div>';
tab_content += '</div>';
$.get(details_url,
function(data){
var html = $($.parseHTML(data)).find('.EXLTabHeaderButtonSendToList li');
var permalink = html.filter('.EXLButtonSendToPermalink').length == 0 ? false : true;
var citation = html.filter('.EXLButtonSendToCitation').length == 0 ? false : true;
if (permalink) {
html.filter('.EXLButtonSendToPermalink').find('a').attr('onclick', html.filter('.EXLButtonSendToPermalink').find('a').attr('onclick').replace(/-1/g, record.index));
}
if (citation){
html.filter('.EXLButtonSendToCitation').find('a').attr('onclick', html.filter('.EXLButtonSendToCitation').find('a').attr('onclick').replace(/-1/g, record.index));
}
$('.share_options_import').empty().append(html);
eshelfUpdate(record.children(), record.isOnEShelf());
}, 'html'
);
details_url = 'http://' + location.hostname + location.pathname.substr(0, location.pathname.lastIndexOf('/')) + '/display.do?tabs=detailsTab&ct=display&fn=search&doc=' + record.id + "&recIds=" + record.id;
tab.open(tab_content, {reload:false, url:details_url});
}
}
});
}
);
Open an URL in the tab of the first record
jQuery.PRIMO.records[0].tabs.addTab('KULeuvenTab', {label: 'KULeuven',
state:'enabled',
url:'http://www.kuleuven.be',
click:function(event, tab, record, options) {
if (tab.isOpen()) {
tab.close();
} else {
tab.open('<iframe src="'+options.url+'"/>', {reload: true});
}
}
});
Open the URL in a new window. Works as a normal link.
jQuery.PRIMO.records[1].tabs.addTab('UrlTab', {label: 'Url',
state:'enabled',
url:'http://www.kuleuven.be', url_target: '_blank',
click: null
});
Get all tab names for the 6th record
jQuery.PRIMO.records[5].tabs.getNames();
Get all active tabs
jQuery.PRIMO.records[5].tabs.getEnabled();
Get the details tab by name
jQuery.PRIMO.records[5].tabs.getByName('DetailsTab');
Programmatically click on a tab
jQuery.PRIMO.records[0].tabs.getByName('DetailsTab').find('a').click();
Get the link behind the details tab
jQuery.PRIMO.records[5].tabs.getByName('DetailsTab').find('a').attr('href');
Get the name of the first tab
jQuery.PRIMO.records[5].tabs[0].name;
Get the index of the first tab
jQuery.PRIMO.records[5].tabs[0].index;
Get the container of the second tab
jQuery.PRIMO.records[5].tabs[1].container;
Check if tab is open
jQuery.PRIMO.records[5].tabs[4].isOpen();
##SEARCH
Wraps the default XServices API this means that 'WS and XS IP' restrictions apply
Wraps the default REST API
The results returned by the different API's are not compatible(feel free to fork and change) you can not switch between them without rewriting your code that consumes the search result.
function byQuery(query, options)
query: can be a string or an array options: can be one of
- institution: your institution code defaults = view institution code
- index: index to start returning from defaults = 1
- bulkSize: amount of records to return. default = 10
extra options for use with REST api
- restAPI: true|false - use REST API default = false
- apiKey: only needed when hosted by ExLibris default = null
- regionURL: the API service URL that is enabled for your API key default = https://api-eu.hosted.exlibrisgroup.com
regionURL is one of:
* America https://api-na.hosted.exlibrisgroup.com
* EU https://api-eu.hosted.exlibrisgroup.com
* APAC https://api-ap.hosted.exlibrisgroup.com
search for water (XServices)
var result = jQuery.PRIMO.search.byQuery('any,contains,water');
search for water in title and pollution in subject return 100 records starting from position 10 on the result set. (XServices)
var result = jQuery.PRIMO.search.byQuery(['title,contains,water', 'subject,contains,pollution'], {"index":10, "bulkSize":100});
search for water and return 5 records when locally hosted (REST)
var result = jQuery.PRIMO.search.byQuery('any,contains,water', {"restAPI":true, "bulkSize":5});
search for water when hosted by ExLibris Developers Network (REST)
var result = jQuery.PRIMO.search.byQuery("any,contains,water", {"restAPI":true,"apiKey":"1234567890", "regionURL": "https://api-na.hosted.exlibrisgroup.com"})
##QUERY Parses the URL and scrapes the DOM for data.
Get result set count
jQuery.PRIMO.query.count;
Get current page number
jQuery.PRIMO.query.page;
Get number of records on page
jQuery.PRIMO.query.step;
should be equal to
jQuery.PRIMO.records.length;
Get search type basic/advanced
jQuery.PRIMO.query.type;
Get search tab (search scope)
jQuery.PRIMO.query.tab;
Get search sort
jQuery.PRIMO.query.sorted_by;
Get query
This will return an Array of Object parsed from the URL not the DOM The Object contains the index, precision and term.
jQuery.PRIMO.query.query;
contains
[
{
"index":"any",
"precision":"contains",
"term":"perceval"
}
]
Get query as text (like the xService syntax)
jQuery.PRIMO.query.query.toText();
returns
(any contains perceval)
Get search scope
jQuery.PRIMO.query.scope;
Get facets
jQuery.PRIMO.query.facets;
Is this a dlSearch.do search?
jQuery.PRIMO.query.isDeeplinkSearch();
Rendering HTML using templates
jQuery('body').append(jQuery.PRIMO.template.render('<div> Hello, {{who}}</div>', {who: 'world'}));
You can create templates using the script tag
<script type='text/template' id='helloWorld-tpl'>
<div>Hello {{who}}</div>
</script>
and use them in your javascript
<script type='text/javascript'>
jQuery('body').append(jQuery.PRIMO.template.renderById('helloWorld-tpl', {who: 'world'}));
</script>
Print all titles using a template
Loop over all records and print title
<script type='text/template' id='allTitles-tpl'>
<div id="allTitles">
<ol>
{{ for(var i=0;i<records.length;i++){ }}
<li>{{ records[i].title }}</li>
{{ } }}
</ol>
</div>
</script>
Render the allTitles template and append it to the body
<script type='text/javascript'>
jQuery('body').append(jQuery.PRIMO.template.renderById('allTitles-tpl', {records: $.PRIMO.records}));
</script>
Add a search tab to Google Scolar (for simple search)
Idea by Lukas Koster
Template to add extra Search Scope Tab
<script type='text/template' id='searchTab-tpl'>
<li class="EXLSearchTab" id="{{id}}">
<a href="{{href}}" title="{{description}}" target="{{target}}">
<span>{{label}}</span>
</a>
</li>
</script>
Render the template using some variables
<script type='text/javascript'>
var query = jQuery.PRIMO.query.query.map(function(d){return d.term}).join(" ");
var renderedTemplate = jQuery.PRIMO.template.renderById('searchTab-tpl',
{id: 'exlidTabGoogleScolar',
label: 'Google Scholar',
description: 'Perform search on Google Scholar',
href:'http://scholar.google.com/scholar?as_q=' + query,
target:'_blank'});
jQuery('#exlidSearchTabs').append(renderedTemplate);
</script>
Events & Callbacks
!!This is experimental might change in the future.
tabReady CALLBACK
When a tab is done loading a tabReady callback is fired. You can attach a callback function to a tab that gets executed when the tab content is loaded.
Add the record id to the details tab when opened.
$.each($.PRIMO.records, function(i, record){
record.tabs.getByName('DetailsTab')[0].onTabReady = function(record, container, tab){
$($(container.tabUtils.tabContent).find('.EXLDetailsContent ul')[0]).prepend("<li><strong>Record id:</strong><span class='EXLDetailsDisplayVal'>" + record.id + "</span></li>");
}
});
Contributing to jQuery.PRIMO
- Fork the project.
- Create a new branch to implement your bugfixes or features
- Commit and push until you are happy with your contribution.
- Send a pull request.
License
MIT (c) 2015 KULeuven/LIBIS written by Mehmet Celik


