Comment out, move autosearch after init
[mkdru-moved-to-drupal.org.git] / mkdru.client.js
1 // Set up namespace and some state.
2 var mkdru = {
3   // Settings to pass to pz2.js
4   useSessions: Drupal.settings.mkdru.use_sessions === '1',
5   //   showResponseType: 'json',
6   // Variables
7   active: false,
8   pz2: null,
9   totalRec: 0,
10   pagerRange: 6,
11   pazpar2Path: Drupal.settings.mkdru.pz2_path,
12   // Facets
13   facets: {
14     source: {
15       pz2Name: 'xtargets',
16       max: Drupal.settings.mkdru.source_max
17     },
18     subject: {
19       pz2Name: 'subject',
20       max: Drupal.settings.mkdru.subject_max
21     },
22     author: {
23       pz2Name: 'author',
24       max: Drupal.settings.mkdru.author_max
25     }
26   },
27   // State
28   defaultState: {
29     page: 1,
30     perpage: 20,
31     sort: 'relevance',
32     filter: null,
33     query:null,
34     recid:null
35   },
36   state: {},
37   realm: ''
38 };
39
40
41
42 // So we can use jQuery BBQ with Drupal 6 and its 1.2.6 jQuery
43 if (!$.isArray) $.isArray = function(obj) {
44   return Object.prototype.toString.call(obj) === "[object Array]";
45 };
46
47 // BBQ has no handy way to remove params without changing the hash.
48 // This takes an object to add and an array of keys to delete.
49 mkdru.hashAddDelMany = function (add, del) {
50   var newHash = $.deparam.fragment();
51   if (typeof(add) === 'object')
52     $.extend(newHash, add);
53   if ($.isArray(del))
54     for (var i=0; i < del.length; i++)
55       if (newHash[del[i]] !== 'undefined')
56         delete newHash[del[i]];
57   return $.param.fragment("#", newHash);
58 }
59
60 // It's sometimes cumbersome that object literals can't take variable keys.
61 mkdru.hashAddDelOne = function (key, value, del) {
62   var toAdd;
63   var toDel;
64   if (key && value) {
65     var toAdd = {};
66     toAdd[key] = value;
67   }
68   if (del) {
69     var toDel = [];
70     toDel.push(del);
71   }
72   return mkdru.hashAddDelMany(toAdd, toDel);
73 }
74
75
76
77 // pz2.js event handlers:
78 mkdru.pz2Init = function () {
79   if (mkdru.state.query) {
80     mkdru.search();
81   }
82   mkdru.pz2.stat();
83   //mkdru.pz2.bytarget();
84 };
85
86 mkdru.pz2Show = function (data) {
87   mkdru.totalRec = data.merged;
88   $('.mkdru-pager').html(mkdru.generatePager());
89   $('.mkdru-counts').html(Drupal.theme('mkdruCounts', data.start + 1,
90                                       data.num, data.merged, data.total));
91   var html = "";
92   for (var i = 0; i < data.hits.length; i++) {
93     html += Drupal.theme('mkdruResult', data.hits[i], 
94       i + 1 + mkdru.state.perpage * (mkdru.state.page - 1),
95       "#" + $.param.fragment($.param.fragment(
96         window.location.href, {recid: data.hits[i].recid})) + "\n"
97     );
98   }
99   $('.mkdru-result-list').html(html);
100   if (mkdru.state.recid) {
101     mkdru.pz2.record(mkdru.state.recid);
102   }
103   else {
104     $('.mkdru-results').show();
105   }
106 };
107
108 mkdru.pz2Status = function (data) {
109   $('.mkdru-status').html(Drupal.theme('mkdruStatus', data.activeclients, data.clients));
110 };
111
112 mkdru.pz2Term = function (data) {
113   for (var facet in mkdru.facets) {
114     // facet is limited
115     if (mkdru.state['limit_' + facet]) {
116       $('.mkdru-facet-' + facet).html(Drupal.theme('mkdruFacetLimit',
117                                  data[mkdru.facets[facet].pz2Name][0],
118                                  mkdru.hashAddDelOne(null, null, 'limit_' + facet)));
119     } else {
120       $('.mkdru-facet-' + facet).html(Drupal.theme('mkdruFacet',
121                                  data[mkdru.facets[facet].pz2Name],
122                                  facet, mkdru.facets[facet].max));
123     }
124   }
125 };
126
127 mkdru.pz2ByTarget = function (data) {
128   
129 };
130
131 mkdru.pz2Record = function (data) {
132   clearTimeout(mkdru.pz2.showTimer);
133   $('.mkdru-results').hide();
134   $('.mkdru-detail').html(Drupal.theme('mkdruDetail', data));
135   $('.mkdru-detail-back').bind('click', function () {$.bbq.removeState('recid');});
136   $('.mkdru-detail').show();
137   clearTimeout(mkdru.pz2.recordTimer);
138 };
139
140
141
142 // State and URL handling 
143
144 // populate state from an object and fill in the blanks with defaults
145 mkdru.stateFromObject = function (obj) {
146   mkdru.state = $.extend({}, mkdru.defaultState);
147   for (var key in mkdru.defaultState)
148     if (typeof(obj[key]) != "undefined")
149       mkdru.state[key] = obj[key];
150 };
151
152 // populate state from current window's hash string
153 mkdru.stateFromHash = function () {
154   mkdru.stateFromObject($.deparam.fragment());
155 };
156
157 // set current window's hash string from state
158 mkdru.hashFromState = function () {
159   // only include non-default settings in the URL
160   var alteredState = {};
161   for (var key in mkdru.defaultState) {
162     if (mkdru.state[key] != mkdru.defaultState[key]) {
163       alteredState[key] = mkdru.state[key];
164     }
165   }
166   $.bbq.pushState(alteredState, 2);
167 };
168
169 // update mkdru_form theme's ui to match state
170 mkdru.uiFromState = function () {
171   for (var key in mkdru.state) {
172     switch(key) {
173     case 'query':
174       $('.mkdru-search input:text').attr('value', mkdru.state[key]);
175       break;
176     case 'perpage':
177       $('.mkdru-perpage').attr('value', mkdru.state[key]);
178       break;
179     case 'sort':
180       $('.mkdru-sort').attr('value', mkdru.state[key]);
181       break;
182     }
183   }
184 };
185
186 mkdru.hashChange = function () {
187   mkdru.stateFromHash();
188   // Request for details
189   if (mkdru.state.recid) {
190     mkdru.pz2.record(mkdru.state.recid);
191   }
192   // Other internal link
193   else {
194     // need to run search again to limit targets
195     for (key in mkdru.state) {
196       if (key.substring(0,5) === 'limit') {
197         mkdru.search();
198         break;
199       }
200     }
201     mkdru.pz2.showPage(mkdru.state.page-1);
202     $('.mkdru-detail').hide();
203     $('.mkdru-results').show();
204   }
205 };
206
207
208
209 //form submit handler
210 mkdru.submitQuery = function () {
211   // new query, back to defaults (shallow copy)
212   mkdru.state = $.extend({}, mkdru.defaultState);
213   mkdru.state.query = $('.mkdru-search input:text').attr('value');
214   mkdru.pollDropDowns();
215   mkdru.hashFromState();
216   mkdru.search();
217   mkdru.active = true;
218   return false;
219 };
220
221 //criteria drop-down (perpage, sort) handler
222 mkdru.submitCriteria = function () {
223   mkdru.pollDropDowns();
224   //search is not ON, do nothing
225   if (!mkdru.active) return false;
226   // pages mean different things now
227   mkdru.state.page = 1;
228   mkdru.hashFromState();
229   mkdru.pz2.show(0, mkdru.state.perpage, mkdru.state.sort);
230   return false;
231 }
232
233 mkdru.search = function () {
234   var filter = null;
235   var query = mkdru.state.query;
236
237   // facet limit implementation
238   if (mkdru.state.limit_source) {
239     filter = 'pz:id=' + mkdru.state.limit_source;
240   }
241   if (mkdru.state.limit_subject) {
242     query += ' and su="' + mkdru.state.limit_subject + '"';
243   }
244   if (mkdru.state.limit_author) {
245     query += ' and au="' + mkdru.state.limit_author + '"';
246   }
247   mkdru.pz2.search(query, mkdru.state.perpage, mkdru.state.sort, filter);
248   //inform others that the search is ON
249   mkdru.active = true;
250 };
251
252 mkdru.pollDropDowns = function () {
253   mkdru.state.perpage = $('.mkdru-perpage').attr('value');
254   mkdru.state.sort = $('.mkdru-sort').attr('value');
255 };
256
257 mkdru.generatePager = function () {
258  // make sure page param is a number, otherwise pageing frwd will be broken
259   if (typeof mkdru.state.page == "string") {
260     mkdru.state.page = Number(mkdru.state.page);
261   }
262   var total = Math.ceil(mkdru.totalRec / mkdru.state.perpage);
263   var first = (mkdru.state.page - mkdru.pagerRange > 0)
264       ? mkdru.state.page - mkdru.pagerRange : 1;
265   var last = first + 2 * mkdru.pagerRange < total
266       ? first + 2 * mkdru.pagerRange : total;  
267   var prev = null;
268   var next = null;
269   var pages = [];
270
271   if ((mkdru.state.page - 1) >= first) {
272     prev = "#" + $.param.fragment($.param.fragment(
273                window.location.href, {page: mkdru.state.page - 1}))
274   }
275   if ((mkdru.state.page + 1) <= total) {
276     next = "#" + $.param.fragment($.param.fragment(
277                window.location.href, {page: mkdru.state.page + 1}))
278   }
279
280   for (var i = first; i <= last; i++) {
281     pages.push("#" + $.param.fragment($.param.fragment(
282                window.location.href, {page: i})));
283   }
284
285   return Drupal.theme('mkdruPager', pages, first, mkdru.state.page,
286                       total, prev, next);
287 };
288
289
290
291 // wait until the DOM is ready, bind events
292 // and instantiate pz2 library
293 $(document).ready(function () {
294   $(window).bind( 'hashchange', mkdru.hashChange);
295   $('.mkdru-search').bind('submit', mkdru.submitQuery);
296   $('.mkdru-search input:text').attr('value', '');
297   $('.mkdru-perpage').bind('change', mkdru.submitCriteria);
298   $('.mkdru-sort').bind('change', mkdru.submitCriteria);
299
300   // generate termlist for pz2.js and populate facet limit state
301   var termlist = [];
302   for (var key in mkdru.facets) {
303     termlist.push(mkdru.facets[key].pz2Name);
304     mkdru.defaultState['limit_' + key] = null;
305   }
306
307   mkdru.pz2 = new pz2( { "onshow": mkdru.pz2Show,
308               "showtime": 500, //each timer (show, stat, term, bytarget) can be specified this way
309               "pazpar2path": mkdru.pazpar2Path,
310               "oninit": mkdru.pz2Init,
311               "onstat": mkdru.pz2Status,
312               "onterm": mkdru.pz2Term,
313               "termlist": termlist.join(','),
314               "onbytarget": mkdru.pz2ByTarget,
315               "usesessions" : mkdru.useSessions,
316               "showResponseType": mkdru.showResponseType,
317               "onrecord": mkdru.pz2Record,
318               "autoInit": false } );
319
320   // initialise state to hash string or defaults
321   mkdru.stateFromHash();
322   // and update UI to match
323   mkdru.uiFromState();
324
325   // ting thing
326   if (typeof(Drupal.settings.mkdru.query) !== "undefined") {
327     mkdru.state.query = Drupal.settings.mkdru.query
328   }
329   //not running against SP? init, otherwise authenticate
330   if (mkdru.useSessions) {
331     mkdru.pz2.init();
332   } else {
333     //runnin against SP
334     var user = Drupal.settings.mkdru.sp_user;
335     var pass = Drupal.settings.mkdru.sp_pass;
336     var params = {};
337     params['command'] = 'auth';
338     if (user && pass) {
339       params['action'] = 'login';
340       params['username'] = user;
341       params['password'] = pass;
342     } else {
343       params['action'] = 'ipauth';
344     }
345     var authReq = new pzHttpRequest(mkdru.pazpar2Path, 
346       function (err) {
347         alert("Authentication against metasearch gateway failed: " +err);
348       }
349     );
350     authReq.get(params,
351       function (data) {
352         var s = data.getElementsByTagName('status');          
353         if (s.length && Element_getTextContent(s[0]) == "OK") {
354           mkdru.realm = data.getElementsByTagName('realm');
355           mkdru.pz2Init();
356         } else {
357           alert("Malformed response when authenticating against the metasearch"
358             + " gateway");
359         }
360       }
361     );
362   }
363  
364   //i'm not sure how this can work, does it assume the results set is active?
365   //what if no search has been executed?
366   //if (mkdru.state.recid) {
367   //  mkdru.pz2.record(mkdru.state.recid);
368   //}
369   //'mkdru.onInit/ deals with the following properly 
370   /// -- waiting for Pz2/SP to init first
371   //else if (mkdru.state.query) {
372   //  mkdru.search();
373   //}
374 });