Pager rewrite for bookmark/history support.
[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   submitted: false,
8   pz2: null,
9   totalRec: 0,
10   pagerRange: 6,
11   sourceMax: Drupal.settings.mkdru.source_max,
12   subjectMax: Drupal.settings.mkdru.subject_max,
13   authorMax: Drupal.settings.mkdru.author_max,
14   pazpar2Path: Drupal.settings.mkdru.pz2_path,
15   // State
16   defaultState: {
17     page: 1,
18     perpage: 20,
19     sort: 'relevance',
20     filter: null,
21     query:null
22   },
23   state: {}
24 };
25
26
27
28 // So we can use jQuery BBQ with Drupal 6 and its 1.2.6 jQuery
29 if (!$.isArray) $.isArray = function(obj) {
30   return Object.prototype.toString.call(obj) === "[object Array]";
31 },
32
33
34
35 // pz2.js event handlers:
36 mkdru.pz2Init = function () {
37   if (mkdru.state.query) mkdru.triggerSearch();
38   //mkdru.pz2.stat();
39   //mkdru.pz2.bytarget();
40 };
41
42 mkdru.pz2Show = function (data) {
43   mkdru.totalRec = data.merged;
44   $('.mkdru-pager').html(mkdru.generatePager());
45   var countsHtml = Drupal.t('Displaying: ') + (data.start + 1) + 
46     Drupal.t(' to ') + (data.start + data.num) + Drupal.t(' of ')
47     + data.merged + Drupal.t(' (found: ') + data.total + ')';
48   $('.mkdru-counts').html(countsHtml);
49
50   var html = "";
51   for (var i = 0; i < data.hits.length; i++) {
52     html += Drupal.theme('mkdruResult', data.hits[i], 
53       i + 1 + mkdru.state.perpage * (mkdru.state.page - 1),
54       "#" + $.param.fragment($.param.fragment(
55         window.location.href, {recid: data.hits[i].recid})) + "\n"
56     );
57   }
58   $('.mkdru-result-list').html(html);
59   $('.mkdru-results').show();
60 };
61
62 mkdru.pz2Status = function (data) {
63 };
64
65 mkdru.pz2Term = function (data) {
66   var html = "";
67   for (var i = 0; i < data.xtargets.length && i < mkdru.sourceMax; i++ ) {
68     html += Drupal.theme('mkdruTerm', data.xtargets[i].name, data.xtargets[i].freq, 
69                           'mkdru-facet-source', data.xtargets[i].id);
70   }
71   $('.mkdru-facet-sources').html(html);
72
73   html = "";
74   for (var i = 0; i < data.subject.length && i < mkdru.subjectMax; i++ ) {
75     html += Drupal.theme('mkdruTerm', data.subject[i].name, data.subject[i].freq, 
76                           'mkdru-facet-subject', data.subject[i].id);
77   }
78   $('.mkdru-facet-subjects').html(html);
79
80   html = "";
81   for (var i = 0; i < data.author.length && i < mkdru.authorMax; i++ ) {
82     html += Drupal.theme('mkdruTerm', data.author[i].name, data.author[i].freq, 
83                           'mkdru-facet-author', data.author[i].id);
84   }
85   $('.mkdru-facet-authors').html(html);
86
87   $('.mkdru-facet-source').bind('click', function (e) {
88     mkdru.limitTarget(this.getAttribute('target_id'), this.firstChild.nodeValue);
89     return false;
90   });
91
92   $('.mkdru-facet-subject').bind('click', function (e) {
93     mkdru.limitQuery('su', this.firstChild.nodeValue);
94     return false;
95   });
96
97   $('.mkdru-facet-author').bind('click', function (e) {
98     mkdru.limitQuery('au', this.firstChild.nodeValue);
99     return false;
100   });
101 };
102
103 mkdru.pz2ByTarget = function (data) {
104   
105 };
106
107 mkdru.pz2Record = function (data) {
108   clearTimeout(mkdru.pz2.showTimer);
109   $('.mkdru-results').hide();
110   $('.mkdru-detail').html(Drupal.theme('mkdruDetail', data));
111   $('.mkdru-detail-back').bind('click', function () {$.bbq.removeState('recid');});
112   $('.mkdru-detail').show();
113   clearTimeout(mkdru.pz2.recordTimer);
114 };
115
116
117
118 // State and URL handling 
119
120 // populate state from an object and fill in the blanks with defaults
121 mkdru.stateFromObject = function (obj) {
122   for (var key in mkdru.defaultState) {
123     if (typeof(obj[key]) != "undefined") {
124       mkdru.state[key] = obj[key];
125     }
126     else {
127       mkdru.state[key] = mkdru.defaultState[key];
128     }
129   }
130 };
131
132 // populate state from current window's hash string
133 mkdru.stateFromHash = function () {
134   mkdru.stateFromObject($.deparam.fragment());
135 };
136
137 // set current window's hash string from state
138 mkdru.hashFromState = function () {
139   // only include non-default settings in the URL
140   var alteredState = {};
141   for (var key in mkdru.defaultState) {
142     if (mkdru.state[key] != mkdru.defaultState[key]) {
143       alteredState[key] = mkdru.state[key];
144     }
145   }
146   $.bbq.pushState(alteredState);
147 };
148
149 // update mkdru_form theme's ui to match state
150 mkdru.uiFromState = function () {
151   for (var key in mkdru.state) {
152     switch(key) {
153     case 'query':
154       $('.mkdru-search input:text').attr('value', mkdru.state[key]);
155       break;
156     case 'perpage':
157       $('.mkdru-perpage').attr('value', mkdru.state[key]);
158       break;
159     case 'sort':
160       $('.mkdru-sort').attr('value', mkdru.state[key]);
161       break;
162     }
163   }
164 };
165
166 mkdru.hashChange = function () {
167   var hash = $.deparam.fragment();
168   // Request for details
169   if (typeof(hash.recid) !== "undefined") {
170     mkdru.pz2.record(hash.recid);
171   }
172   // Other internal link
173   else {
174     mkdru.stateFromObject($.deparam.fragment());
175     mkdru.pz2.showPage(mkdru.state.page-1);
176     $('.mkdru-detail').hide();
177     $('.mkdru-results').show();
178   }
179 };
180
181
182
183 // UI functions:
184 mkdru.submitQuery = function () {
185   mkdru.state.query = $('.mkdru-search input:text').attr('value');
186   mkdru.resetPage();
187   mkdru.pollDropDowns();
188   mkdru.hashFromState();
189   mkdru.search();
190   mkdru.submitted = true;
191   return false;
192 };
193
194 mkdru.triggerSearch = function () {
195   mkdru.search();
196   mkdru.submitted = true;
197 };
198
199 mkdru.search = function () {
200   mkdru.pz2.search(mkdru.state.query, mkdru.state.perpage, mkdru.state.sort,
201       mkdru.state.filter);
202 };
203
204 mkdru.pollDropDowns = function () {
205   mkdru.state.perpage = $('.mkdru-perpage').attr('value');
206   mkdru.state.sort = $('.mkdru-sort').attr('value');
207   if (!mkdru.submitted) return false;
208   mkdru.resetPage();
209   mkdru.hashFromState();
210   mkdru.pz2.show(0, mkdru.state.perpage, mkdru.state.sort);
211   return false;
212 };
213
214 mkdru.limitQuery = function (field, value) {
215   $('.mkdru-search input:text').attr('value', function () {
216     return this.value += ' and ' + field + '="' + value + '"';
217   });
218   mkdru.submitQuery();
219 };
220
221 mkdru.limitTarget = function (id, name) {
222   var navi = document.getElementById('mkdru-navi');
223   navi.innerHTML = 
224         'Source: <a class="crossout" href="#" onclick="delimitTarget();return false;">'
225         + name + '</a>';
226   navi.innerHTML += '<hr/>';
227   mkdru.state.filter = 'pz:id=' + id;
228   mkdru.resetPage();
229   mkdru.pollDropDowns();
230   mkdru.search();
231   return false;
232 };
233
234 mkdru.generatePager = function () {
235   var total = Math.ceil(mkdru.totalRec / mkdru.state.perpage);
236   var first = (mkdru.state.page - mkdru.pagerRange > 0)
237       ? mkdru.state.page - mkdru.pagerRange : 1;
238   var last = first + 2 * mkdru.pagerRange < total
239       ? first + 2 * mkdru.pagerRange : total;  
240   var prev = null;
241   var next = null;
242   var pages = [];
243
244   if ((mkdru.state.page - 1) >= first) {
245     prev = "#" + $.param.fragment($.param.fragment(
246                window.location.href, {page: mkdru.state.page - 1}))
247   }
248   if ((mkdru.state.page + 1) <= total) {
249     next = "#" + $.param.fragment($.param.fragment(
250                window.location.href, {page: mkdru.state.page + 1}))
251   }
252
253   for (var i = first; i <= last; i++) {
254     pages.push("#" + $.param.fragment($.param.fragment(
255                window.location.href, {page: i})));
256   }
257
258   return Drupal.theme('mkdruPager', pages, first, mkdru.state.page,
259                       total, prev, next);
260 };
261
262 mkdru.resetPage = function () {
263   mkdru.state.page = 1;
264   mkdru.totalRec = 0;
265 };
266
267 mkdru.showPage = function (pageNum) {
268   mkdru.state.page = pageNum;
269   mkdru.pz2.showPage(pageNum-1);
270 };
271
272
273
274 // wait until the DOM is ready, bind events
275 // and instantiate pz2 library
276 $(document).ready(function () {
277   $(window).bind( 'hashchange', mkdru.hashChange);
278   $('.mkdru-search').bind('submit', mkdru.submitQuery);
279   $('.mkdru-search input:text').attr('value', '');
280   $('.mkdru-perpage').bind('change', function () { mkdru.pollDropDowns() });
281   $('.mkdru-sort').bind('change', function () { mkdru.pollDropDowns() });
282
283   mkdru.pz2 = new pz2( { "onshow": mkdru.pz2Show,
284               "showtime": 500, //each timer (show, stat, term, bytarget) can be specified this way
285               "pazpar2path": mkdru.pazpar2path,
286               "oninit": mkdru.pz2Init,
287               "onstat": mkdru.pz2Status,
288               "onterm": mkdru.pz2Term,
289               "termlist": "xtargets,subject,author",
290               "onbytarget": mkdru.pz2ByTarget,
291               "usesessions" : mkdru.usesessions,
292               "showResponseType": mkdru.showResponseType,
293               "onrecord": mkdru.pz2Record,
294               "autoInit": false } );
295
296   // initialise state to hash string or defaults
297   mkdru.stateFromHash();
298   // and update UI to match
299   mkdru.uiFromState();
300
301   // ting thing
302   if (typeof(Drupal.settings.mkdru.query) !== "undefined") {
303     mkdru.state.query = Drupal.settings.mkdru.query
304   }
305
306   if (mkdru.usesessions) {
307     mkdru.pz2.init();
308   } else if (mkdru.state.query) {
309     mkdru.triggerSearch(); 
310   }
311 });