Correct an erroneous edit
[sitka/overdrive-evergreen-opac.git] / src / od_pages_myopac.coffee
CommitLineData
8ebc3fff
SC
1# Define custom jQuery extensions to rewrite content of existing pages
2# None of the extensions directly use the API, but they depend on od_action which does.
3
4define [
5 'jquery'
6 'lodash'
7 'od_api'
8 'jquery-ui'
9 'od_action'
10 'od_pages_opac'
11], ($, _, od) ->
12
13 $.fn.extend
14
15 # Given a map between classnames and numeric values,
16 # eg, { class1: 1, class2: -1 },
17 # increment the existing values of the containers with the classnames.
18 _counters: (x) ->
19 for n, v of x
20 $x = @find ".#{n}"
21 $x.text +($x.text()) + v
22 return @
23
24 _dashboard: (x) ->
25
26 if arguments.length is 0
27
28 # Add a new dashboard for to show counts of e-items; start with
29 # zero counts
30 base = '/eg/opac/myopac'
31 @append """
32 <div id="dashboard">
33 <span class="dash-align">
34 <a class="dash-link" href="#{base}/circs?e_items"><span class="ncheckouts" id="dash_checked">0</span> E-items Checked Out</a>
35 </span>
36 <span class="dash_divider">|</span>
37 <span class="dash-align">
38 <a class="dash-link" href="#{base}/holds?e_items"><span class="nholds" id="dash_holds">0</span> E-items on Hold</a>
39 </span>
40 <span class="dash_divider">|</span>
41 <span class="dash-align">
42 <a class="dash-link" href="#{base}/holds?e_items&available=1"><span class="nholdsready" id="dash_pickup">0</span> E-items Ready for Checkout</a>
43 </span>
44 </div>
45 """
46
47 # The following sequence is necessary to align the new dashboard
48 # with the existing ones, but do not know why it needs to be done
49 @find 'div'
50 .css float: 'none'
51 .end()
52
53 else
54 @_counters x # Change the values of the counters
55 return @
56
57 # Replace account summary area with one that shows links to go to
58 # e-items lists
59 _account_summary: (x) ->
60
61 if arguments.length is 0
62 # Parse a list of totals of physical items from the account summary table
63 totals = ( +(v.textContent.match(/\d+?/)[0]) for v in @find('td').not '[align="right"]' )
64
65 tpl = """
66 <tbody>
67 <tr>
68 <td>
69 <a href="/eg/opac/myopac/circs">
70 <span><span class="ncheckouts" /> Items Currently Checked out</span>
71 </a>
72 </td>
73 <td align="right">
74 <a href="/eg/opac/myopac/circs?e_items"><span class="n_checkouts" /> E-items Currently Checked out</a>
75 </td>
76 </tr>
77 <tr>
78 <td>
79 <a href="/eg/opac/myopac/holds"><span class="nholds" /> Items Currently on Hold</a>
80 </td>
81 <td align="right">
82 <a href="/eg/opac/myopac/holds?e_items"><span class="n_holds" /> E-items Currently on Hold</a>
83 </td>
84 </tr>
85 <tr>
86 <td>
87 <a href="/eg/opac/myopac/holds?available=1"><span class="nready" /> Items ready for pickup</a>
88 </td>
89 <td align="right">
90 <a href="/eg/opac/myopac/holds?e_items&available=1"><span class="n_ready" /> E-items ready for pickup</a>
91 </td>
92 </tr>
93 </tbody>
94 """
95 @empty().append tpl
96 return totals
97
98 else
99 @_counters x # Change the values of the counters
100
101 # Relabel a history tab
102 _tab_history: ->
103 $x = $('a', @)
104 $x.text "#{ $x.text() } (Physical Items)"
105 return @
106
107 # Add a new tab for e-items and select a tab relevant for the current page name.
108 # If page name contains 'history' then select any tabs with 'history' in its ID
109 # otherwise, if search parameters has 'e_items' property then select any tabs with 'eitems' in its ID
110 #$('#acct_holds_tabs, #acct_checked_tabs')._etabs()
111 _etabs: (page_name, e_items) ->
112
113 # Tab replacement is identified by container's id
114 new_tabs =
115 acct_holds_tabs: """
116 <div id="acct_holds_tabs">
117 <div class="align" id='tab_holds'>
118 <a href="holds#">Items on Hold</a>
119 </div>
120 <div class="align" id='tab_holds_eitems'>
121 <a href="holds?e_items">E-items on Hold</a>
122 </div>
123 <div class="align" id='tab_holds_history'>
124 <a href="hold_history">Holds History</a>
125 </div>
126 </div>
127 """
128 acct_checked_tabs: """
129 <div id="acct_checked_tabs">
130 <div class="align" id='tab_circs'>
131 <a href="circs#">Current Items Checked Out</a>
132 </div>
133 <div class="align" id='tab_circs_eitems'>
134 <a href="circs?e_items">E-items Checked Out</a>
135 </div>
136 <div class="align" id='tab_circs_history'>
137 <a href="circ_history">Check Out History</a>
138 </div>
139 </div>
140 """
141 @replaceWith new_tabs[@prop 'id']
142
143 # Compute the selected tab of the current page name
144 $selected =
145 # if page name ends with '_history', select the tab with id
146 # that ends with '_history'
147 if /_history$/.test page_name
148 $('[id$=_history]')
149 # else if search parameters has 'e_items' property, select the
150 # tab with id that ends with '_eitems'
151 else if e_items
152 $('[id$=_eitems]')
153 # else select the remaining tab
154 else
155 $('[id^=tab_]').not '[id$=_history],[id$=_eitems]'
156
157 $selected.addClass 'selected'
158
159 return @
160
161
162 # Resize columns of a table, either to fixed widths, or to be equal
163 # widths, ie, 100% divided by number of columns.
164 # Also, force width of table to 100%; don't know why this is necessary.
165 _resizeCols: ->
166
167 $table = @find 'table'
168 .css 'width', '100%'
169
170 # Resize to percentage widths given in the argument list
171 if arguments.length > 0
172 $th = $table.find 'th'
173 $td = $table.find 'td'
174 for width, n in arguments
175 $th.eq(n).css 'width', width
176 $td.eq(n).css 'width', width
177
178 # Otherwise, resize to equal widths
179 else
180 ncols = @find('th').length or 1
181 width = "#{100 / ncols}%"
182
183 $table
184 .find 'th'
185 .css 'width', width
186 .end()
187 .find 'td'
188 .css 'width', width
189 .end()
190
191 return @
192
193 # Show a container having a class name from a list of candidate, and hide the rest
194 _show_from: (which, candidates...) ->
195
196 @find(x).hide() for x in candidates
197 @find candidates[which]
198 .show()
199 .end()
200
201 # Replace a title of table with new text
202 _replace_title: (x) ->
203
204 @find '.header_middle span'
205 .eq 0
206 .text x
207 .end()
208
209 # Build an empty table for showing a list of holds
210 _holds_main: ->
211
212 table = """
213 <table cellpadding="0" cellspacing="0" border="0">
214 <thead id="acct_holds_main_header"><tr>
215 <th></th>
216 <th>Title/Author</th>
217 <th>Availability</th>
218 <th>Formats</th>
219 <th>Actions</th>
220 </tr></thead>
221 <tbody id="holds_temp_parent"></tbody>
222 </table>
223 <div class="warning_box">No holds found.</div>
224 """
225 @empty().append table
226 ._resizeCols '15%', '20%', '30%', '20%', '15%'
227
228 # Build <tr> elements for showing a list of holds
229 _holds_rows: (holds) ->
230 return [] unless holds
231
232 tpl = _.template """
233 <tr id="<%= id %>" name="acct_holds_temp" class="acct_holds_temp inactive-hold">
234 <td class="thumbnail"></td>
235 <td>
236 <div class="title" /> by <div class="author" />
237 </td>
238 <td class="availability"></td>
239 <td class="formats"></td>
240 <td class="actions"></td>
241 </tr>
242 """
243
244 ids = []
245 $rows = for hold in holds
246
247 ids.push hold.reserveId
248
249 # Build an empty row element that is uniquely identified by a
250 # product ID
251 $row = $ tpl id: hold.reserveId
252
253 # Fill the row with hold values and proxy the rest of the row
254 # with progress bars
255 $row
256 ._holds_row hold # hold values
257 ._row_meta() # progress bar
258 ._holds_row_avail() # progress bar
259
260 # Add hold rows to <tbody> and remove the warning box.
261 if $rows.length > 0
262 @find 'tbody'
263 .empty().append $rows
264 .end()
265 .find '.warning_box'
266 .remove()
267 .end()
268
269 return ids
270
271 _holds_row: (hold) ->
272
273 @find 'td.availability'
274 ._holds_row_avail1 hold
275 .end()
276 .find 'td.actions'
277 ._actions hold.actions
278 .end()
279
280 # Show a title, author, or format by using the given metadata object
281 _row_meta: (meta, classnames...) ->
282
283 status = if arguments.length is 0 then value: false else 'destroy'
284 @find(".#{n}").progressbar(status) for n in ['title', 'author', 'formats']
285
286 return @ unless meta
287
288 $title = $ """
289 <a href="/eg/opac/results?query=#{meta.title};locg=10;qtype=title">#{meta.title}</a>
290 """
291 $thumbnail = $ """
292 <img src="#{od.proxy meta.images?.thumbnail?.href}" alt="#{meta.title}" />
293 """
294 $author = $ """
295 <a href="/eg/opac/results?query=#{meta.author};locg=10;qtype=author">#{meta.author}</a>
296 """
297 for n in classnames
298 $n = @find ".#{n}"
299 switch n
300 when 'thumbnail' then $n.empty().append $thumbnail
301 when 'title' then $n.empty().append $title
302 when 'author' then $n.empty().append $author
303 when 'formats' then $n._show_formats meta
304 return @
305
306 _holds_row_avail1: (hold) ->
307
308 hold_status = if hold.holdSuspension then 0 else if hold.actions.checkout then 1 else 2
309
310 x = if hold.holdSuspension?.suspensionType is 'limited' then 'show' else 'hide'
311
312 tpl = _.template """
313 <div class="suspended">
314 <div style="color: red">Suspended <span class="limited">until <%= activates %></span></div>
315 <ul style="padding-left: 20px">
316 <li name="acct_holds_status"><%= position %> / <%= nHolds %> holds <span class="copies" /></li>
317 <li>Email notification will be sent to <%= email %></li>
318 <li>Hold was placed <%= placed %></li>
319 </ul>
320 </div>
321 <div class="unavailable">
322 <div>Waiting for copy</div>
323 <ul style="padding-left: 20px">
324 <li name="acct_holds_status"><%= position %> / <%= nHolds %> holds <span class="copies" /></li>
325 <li>Email notification will be sent to <%= email %></li>
326 <li>Hold was placed <%= placed %></li>
327 </ul>
328 </div>
329 <div class="available">
330 <div style="color: green">Ready for checkout</div>
331 <ul style="padding-left: 20px">
332 <li name="acct_holds_status"><%= position %> / <%= nHolds %> holds <span class="copies" /></li>
333 <li>Hold will expire <%= expires %></li>
334 </ul>
335 </div>
6a1128e6 336 <a href="http://downloads.bclibrary.ca/ContentDetails.htm?ID=<%= id %>">Click to access online (library card required)</a>
8ebc3fff
SC
337 """
338 @empty().append tpl
339 position: hold.holdListPosition
340 nHolds: hold.numberOfHolds
341 email: hold.emailAddress
342 expires: hold.holdExpires.fromNow()
343 placed: hold.holdPlacedDate.fromNow()
344 activates: hold.holdSuspension?.numberOfDays.calendar()
6a1128e6 345 id: hold.reserveId
8ebc3fff
SC
346
347 # Illuminate areas of this row according to the hold status
348 ._show_from hold_status, '.suspended', '.available', '.unavailable'
349 # Show the hold suspension date only if suspension type is limited
350 .find('.limited')[x]()
351 .end()
352
353 # Complete building a <tr> element for showing a hold by using the
354 # given availability object
355 _holds_row_avail: (avail) ->
356
357 status = if arguments.length is 0 then value: false else 'destroy'
358 @find '.copies'
359 .progressbar status
360 .end()
361
362 return @ unless avail
363
364 text = """
365 on #{avail.copiesOwned} copies
366 """
367 @find '.copies'
368 .text text
369 .end()
370
371 # Build an empty table for showing a list of checkouts
372 _checkouts_main: ->
373
374 table = """
375 <table cellpadding="0" cellspacing="0" border="0">
376 <thead id="acct_checked_main_header"><tr>
377 <th></th>
378 <th>Title/Author</th>
379 <th>Availability</th>
380 <th>Formats</th>
381 <th>Actions</th>
382 </tr></thead>
383 <tbody id="holds_temp_parent"></tbody>
384 </table>
385 <div class="warning_box">No checkouts found.</div>
386 """
387 @empty().append table
388 ._resizeCols()
389
390 # Build <tr> elements for showing a list of checkouts
391 _checkouts_rows: (circs) ->
392 return [] unless circs
393
394 tpl = _.template """
395 <tr id="<%= id %>" name="acct_checked_temp" class="acct_checked_temp inactive-hold">
396 <td class="thumbnail"></td>
397 <td>
398 <div class="title" /> by <div class="author" />
399 </td>
400 <td class="availability"></td>
401 <td class="formats"></td>
402 <td class="actions"></td>
403 </tr>
404 """
405
406 ids = []
407 $rows = for circ in circs
408
409 ids.push circ.reserveId
410
411 # Build an empty row element that is uniquely identified by a
412 # product ID
413 $row = $ tpl id: circ.reserveId
414
415 # Fill the row with circ values and proxy the rest of the row
416 # with progress bars
417 $row
418 ._row_checkout circ # circ values
419 ._row_meta() # progress bars
420
421 # Add checkout rows to <tbody> and remove the warning box.
422 # <tbody> also has the responsibility of handling format buttons.
603dd210 423 if $rows.length > 0
8ebc3fff
SC
424 @find 'tbody'
425 .empty().append $rows
426 ._download_format()
427 .end()
428 .find '.warning_box'
429 .remove()
430 .end()
431
432 return ids
433
434 _row_checkout: (circ) ->
435
436 @find 'td.availability'
437 ._checkouts_row_avail circ
438 .end()
439 .find 'td.actions'
440 ._actions circ.actions
441 .end()
442 .find 'td.formats'
443 ._formats circ.formats
444 .end()
445
446 _checkouts_row_avail: (circ) ->
447
448 tpl = _.template """
449 <div>Expires <%= expires_relatively %></div>
450 <div><%= expires_exactly %></div>
6a1128e6 451 <a href="http://downloads.bclibrary.ca/ContentDetails.htm?ID=<%= id %>">Click to access online (library card required)</a>
8ebc3fff
SC
452 """
453 @empty().append tpl
454 expires_relatively: circ.expires.fromNow()
455 expires_exactly: circ.expires.format 'YYYY MMM D, h:mm:ss a'
6a1128e6 456 id: circ.reserveId
8ebc3fff
SC
457
458 # Build a <tr> element to show the available actions of an item.
459 # If the item is available, the check out action should be possible,
460 # and if unavailable, the place hold action should be possible.
461 _holdings_row: (id) ->
462
463 tpl = _.template """
464 <tr id="<%= id %>" name="acct_holds_temp" class="acct_holds_temp inactive-hold">
465 <td class="thumbnail"></td>
466 <td>
467 <div class="title" /> by <div class="author" />
468 </td>
469 <td class="availability"></td>
470 <td class="formats"><ul></ul></td>
471 <td class="actions"></td>
472 </tr>
473 """
474 $row = $(tpl id: id)
475 ._row_meta() # progress bar
476 ._holdings_row_avail() # progress bar
477
478 @find 'tbody'
479 .empty().append $row
480 .end()
481 .find '.warning_box'
482 .remove()
483 .end()
484
485 # Complete building a <tr> element for a holding using the given availability object
486 _holdings_row_avail: (avail) ->
487
488 # Create or destroy progress bars
489 status = if arguments.length is 0 then value: false else 'destroy'
490 @find 'td.availability'
491 .progressbar status
492 .end()
493 .find 'td.actions'
494 .progressbar status
495 .end()
496
497 return @ unless avail
498
499 tpl = _.template """
500 <div class="unavailable">No copies are available for checkout</div>
501 <div class="available" style="color: green">A copy is available for checkout</div>
502 <div><%= n_avail %> of <%= n_owned %> available, <%= n_holds %> holds</div>
503 """
504 @find 'td.availability'
505 .append tpl
506 n_owned: avail.copiesOwned
507 n_avail: avail.copiesAvailable
508 n_holds: avail.numberOfHolds
509 .end()
510
511 # Build action buttons
512 .find 'td.actions'
513 ._actions avail.actions
514 .end()
515
516 # Illuminate areas of this row according to the holdings status
517 ._show_from (if avail.available then 0 else 1), '.available', '.unavailable'
518