Correct an erroneous edit
[sitka/overdrive-evergreen-opac.git] / src / od_pages_myopac.coffee
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
4 define [
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>
336                         <a href="http://downloads.bclibrary.ca/ContentDetails.htm?ID=<%= id %>">Click to access online (library card required)</a>
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()
345                                 id:        hold.reserveId
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.
423                         if $rows.length > 0
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>
451                         <a href="http://downloads.bclibrary.ca/ContentDetails.htm?ID=<%= id %>">Click to access online (library card required)</a>
452                         """
453                         @empty().append tpl
454                                 expires_relatively: circ.expires.fromNow()
455                                 expires_exactly:    circ.expires.format 'YYYY MMM D, h:mm:ss a'
456                                 id:                 circ.reserveId
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