Add CW MARS template overrides
authorJason Stephenson <jason@sigio.com>
Tue, 23 May 2023 17:08:20 +0000 (13:08 -0400)
committerJason Stephenson <jason@sigio.com>
Tue, 23 May 2023 17:08:20 +0000 (13:08 -0400)
Signed-off-by: Jason Stephenson <jason@sigio.com>
73 files changed:
Open-ILS/src/templates-bootstrap_cons/opac/css/style.css.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/myopac/holds_curbside.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/myopac/prefs.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/advanced/numeric.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/base.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/config.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/css/colors.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/footer.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/homesearch.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/login/form.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/login/login_modal.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/login/password_hint.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/myopac/main_refund_policy.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/qtype_selector.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/record/extras.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/record/summary.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/topnav.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/topnav_links.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/parts/topnav_logo.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap_cons/opac/register.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/kpac/getit.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/kpac/parts/footer.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/kpac/parts/header.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/advanced.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/browse.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/css/style.css.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/ecard/form.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/ecard/form_es.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/ecard/form_fr.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/ecard/form_pl.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/ecard/form_pt.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/ecard/form_ru.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/ecard/form_zh.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/ecard/lang.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/ecard/submit.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/ecard/verify.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/myopac/holds_curbside.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/acjs.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/advanced/global_row.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/advanced/numeric.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/advanced/search.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/anon_list.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/base.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/config.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/css/colors.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/filtersort.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/footer.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/hold_status.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/homesearch.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/login/help.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/login/password_hint.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/metarecord_hold_filters.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/misc_util.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/myopac/main_refund_policy.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/place_hold.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/qtype_selector.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/record/addedcontent.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/record/awards.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/record/contents.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/record/extras.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/record/marcextras.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/result/lowhits.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/topnav.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/topnav_links.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/parts/topnav_logo.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/password_reset.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/password_reset_msg.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/opac/register.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/staff/cat/item/t_circ_list_pane.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/staff/circ/patron/t_bills.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/staff/circ/patron/t_edit.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/staff/circ/patron/t_summary.tt2 [new file with mode: 0644]
Open-ILS/src/templates_cons/staff/t_splash.tt2 [new file with mode: 0644]

diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/css/style.css.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/css/style.css.tt2
new file mode 100644 (file)
index 0000000..1bad964
--- /dev/null
@@ -0,0 +1,4022 @@
+[%-
+    PROCESS "opac/parts/css/colors.tt2";
+    PROCESS "opac/parts/css/fonts.tt2";
+    rtl = ctx.get_i18n_l(ctx.eg_locale).rtl;
+%]
+
+.adv_filters{
+
+    -moz-column-count: 4;
+    -moz-column-gap: 20px;
+    -webkit-column-count: 4;
+    -webkit-column-gap: 20px;
+    column-count: 4;
+    column-gap: 20px;
+    list-style: none;
+}
+
+.top-divide{
+        border-top: 1px solid rgba(0,0,0,.1);
+}
+
+/*
+Mini Table Styling
+*/
+@media
+only screen and (max-width: 650px)  {
+    .miniTable{
+        width: 100% !important;
+    }
+
+    /* Force table to not be like tables anymore */
+    .miniTable table, .miniTable thead, .miniTable tbody, .miniTable th, .miniTable td, .miniTable tr
+    {
+        display: block;
+    }
+
+    .miniTable th{
+       display:none;
+    }
+
+    /* Hide table headers (but not display: none;, for accessibility) */
+    .miniTable thead tr{
+        position: absolute;
+        top: -9999px;
+        left: -9999px;
+    }
+
+    .miniTable tr
+     {
+         border: 1px solid #ccc;
+         margin: 10px 0px;
+     }
+
+
+    .miniTable td
+    {
+        border: none;
+        border-bottom: 1px solid #eee;
+        position: relative;
+        padding-left: 50%;
+        min-height:45px;
+        text-align: right;
+    }
+
+    .miniTable td:before
+    {
+        left: 6px;
+        width: 45%;
+        padding-right: 10px;
+        white-space: nowrap;
+        position: absolute;
+        content: attr(mobile-title);
+        font-weight: bold;
+        text-align: left;
+    }
+    
+    .copyTable tr::before { content: attr(mobile-count); display: block; text-align:center; }
+    .holdintsTable tr::before { content: attr(mobile-count); display: block; text-align:center; }
+
+
+    .chargesTable td:nth-of-type(1):before { content: "Select"; display: flex; }
+    .chargesTable td:nth-of-type(2):before { content: "Owed"; display: flex; }
+    .chargesTable td:nth-of-type(3):before { content: "Billing Type"; display: flex;}
+    .chargesTable td:nth-of-type(4):before { content: "Note"; display: flex;}
+    .chargesTable td:nth-of-type(5):before { content: "Date"; display: flex;}
+
+    .chargesMainTable td:nth-of-type(1):before { content: "Select"; display: flex; }
+    .chargesMainTable td:nth-of-type(2):before { content: "Owed"; display: flex; }
+    .chargesMainTable td:nth-of-type(3):before { content: "Billing Type"; display: flex;}
+    .chargesMainTable td:nth-of-type(4):before { content: "Title"; display: flex;}
+    .chargesMainTable td:nth-of-type(5):before { content: "Checkout"; display: flex;}
+    .chargesMainTable td:nth-of-type(6):before { content: "Due"; display: flex;}
+    .chargesMainTable td:nth-of-type(7):before { content: "Returned/Renewed"; display: flex;}
+
+    .activeHoldstable td:nth-of-type(1):before { content: "Select"; display: flex; }
+    .activeHoldstable td:nth-of-type(2):before { content: "Title"; display: flex; }
+    .activeHoldstable td:nth-of-type(3):before { content: "Author"; display: flex;}
+    .activeHoldstable td:nth-of-type(4):before { content: "Format"; display: flex;}
+    .activeHoldstable td:nth-of-type(5):before { content: "Pickup Location"; display: flex;}
+    .activeHoldstable td:nth-of-type(6):before { content: "Cancel If Not Filled By"; display: flex;}
+    .activeHoldstable td:nth-of-type(7):before { content: "Status"; display: flex;}
+    .activeHoldstable td:nth-of-type(8):before { content: "Notes"; display: flex;}
+
+    .holdHistoryTable td:nth-of-type(1):before { content: "Title"; display: flex; }
+    .holdHistoryTable td:nth-of-type(2):before { content: "Author"; display: flex; }
+    .holdHistoryTable td:nth-of-type(3):before { content: "Format"; display: flex; }
+    .holdHistoryTable td:nth-of-type(4):before { content: "Pickup Location"; display: flex; }
+    .holdHistoryTable td:nth-of-type(5):before { content: "Status"; display: flex; }
+
+    .curbsideApptTable td:nth-of-type(1):before { content: "Pickup Location"; display: flex; }
+    .curbsideApptTable td:nth-of-type(2):before { content: "Date"; display: flex; }
+    .curbsideApptTable td:nth-of-type(3):before { content: "Time"; display: flex;}
+    .curbsideApptTable td:nth-of-type(4):before { content: "Arrival Notes"; display: flex;}
+    .curbsideApptTable td:nth-of-type(5):before { content: "Action"; display: flex;}
+
+    .paymentTable td:nth-of-type(1):before { content: "Payment Date"; display: flex; }
+    .paymentTable td:nth-of-type(2):before { content: "Payment For"; display: flex; }
+    .paymentTable td:nth-of-type(3):before { content: "Amount"; display: flex; }
+    .paymentTable td:nth-of-type(4):before { content: "Receipt"; display: flex; }
+
+    .messagesTable td:nth-of-type(1):before { content: "Select"; display: flex; }
+    .messagesTable td:nth-of-type(2):before { content: "Date"; display: flex; }
+    .messagesTable td:nth-of-type(3):before { content: "Library"; display: flex; }
+    .messagesTable td:nth-of-type(4):before { content: "Subject"; display: flex; }
+    .messagesTable td:nth-of-type(5):before { content: ""; display: flex; }
+
+    .circTable td:nth-of-type(1):before { content: "Select"; display: flex; }
+    .circTable td:nth-of-type(2):before { content: "Title"; display: flex; }
+    .circTable td:nth-of-type(3):before { content: "Author"; display: flex; }
+    .circTable td:nth-of-type(4):before { content: "Renewals Left"; display: flex; }
+    .circTable td:nth-of-type(5):before { content: "Due Date"; display: flex; }
+    .circTable td:nth-of-type(6):before { content: "Barcode"; display: flex; }
+    .circTable td:nth-of-type(7):before { content: "Call Number"; display: flex; }
+
+    .circHistTable td:nth-of-type(1):before { content: "Select"; display: flex; }
+    .circHistTable td:nth-of-type(2):before { content: "Title"; display: flex; }
+    .circHistTable td:nth-of-type(3):before { content: "Author"; display: flex; }
+    .circHistTable td:nth-of-type(4):before { content: "Checkout Date"; display: flex; }
+    .circHistTable td:nth-of-type(5):before { content: "Due Date"; display: flex; }
+    .circHistTable td:nth-of-type(6):before { content: "Date Returned"; display: flex; }
+    .circHistTable td:nth-of-type(7):before { content: "Barcode"; display: flex; }
+    .circHistTable td:nth-of-type(8):before { content: "Call Number"; display: flex; }
+
+    .bookbagTable td:nth-of-type(1):before { content: ""; display: flex; }
+    .bookbagTable td:nth-of-type(2):before { content: "Title"; display: flex; }
+    .bookbagTable td:nth-of-type(3):before { content: "Author(s)"; display: flex; }
+    .bookbagTable td:nth-of-type(4):before { content: "Local Call number"; display: flex; }
+    .bookbagTable td:nth-of-type(5):before { content: "Publication Date"; display: flex; }
+    .bookbagTable td:nth-of-type(6):before { content: "Format"; display: flex; }
+    .bookbagTable td:nth-of-type(7):before { content: "Notes"; display: flex; }
+
+    .eholdsTable td:nth-of-type(1):before { content: "Title"; display: flex; }
+    .eholdsTable td:nth-of-type(2):before { content: "Author"; display: flex; }
+    .eholdsTable td:nth-of-type(3):before { content: "Expire Date"; display: flex; }
+    .eholdsTable td:nth-of-type(4):before { content: "Status"; display: flex; }
+    .eholdsTable td:nth-of-type(5):before { content: "Actions"; display: flex; }
+
+    .eholdsreadyTable td:nth-of-type(1):before { content: "Title"; display: flex; }
+    .eholdsreadyTable td:nth-of-type(2):before { content: "Author"; display: flex; }
+    .eholdsreadyTable td:nth-of-type(3):before { content: "Expire Date"; display: flex; }
+    .eholdsreadyTable td:nth-of-type(4):before { content: "Actions"; display: flex; }
+
+    .echeckoutTable td:nth-of-type(1):before { content: "Title"; display: flex; }
+    .echeckoutTable td:nth-of-type(2):before { content: "Author"; display: flex; }
+    .echeckoutTable td:nth-of-type(3):before { content: "Due Date"; display: flex; }
+    .echeckoutTable td:nth-of-type(4):before { content: "Actions"; display: flex; }
+
+    .ecircsTable td:nth-of-type(1):before { content: "Title"; display: flex; }
+    .ecircsTable td:nth-of-type(2):before { content: "Author"; display: flex; }
+    .ecircsTable td:nth-of-type(3):before { content: "Due Date"; display: flex; }
+    .ecircsTable td:nth-of-type(4):before { content: "Actions"; display: flex; }
+
+    .bucketTable td:nth-of-type(2):before { content: "Title"; display: flex; text-align:left; }
+    .bucketTable td:nth-of-type(3):before { content: "Author"; display: flex; text-align:left; }
+    .bucketTable td:nth-of-type(4):before { content: "Call Number"; display: flex; text-align:left; }
+    .reservationsTable td:nth-of-type(1):before { content: "Resource type"; display: flex; }
+    .reservationsTable td:nth-of-type(2):before { content: "Start time"; display: flex; }
+    .reservationsTable td:nth-of-type(3):before { content: "End time"; display: flex; }
+    .reservationsTable td:nth-of-type(4):before { content: "Pickup location"; display: flex; }
+    .reservationsTable td:nth-of-type(5):before { content: "Status"; display: flex; }
+
+    /*Media Style Additions*/
+    .fullRow{
+        padding: 5px !important;
+        text-align: center !important;
+        width: 100%;
+    }
+
+    .paginateText{
+        display:none;
+    }
+}/*Micro Tables End*/
+
+.sumNum {
+    font-weight:700;
+}
+
+.coverImage{position: relative;}
+.carousel .glide__arrow{background: unset;}
+
+/*
+Novelist Styling
+*/
+
+.NovGroupHeader{
+    font-size: 16pt !important;
+    text-align: center;
+    font-weight: 600 !important;
+}
+
+.NovSectionHeader{
+    font-size: 16pt !important;
+    font-weight: 600 !important;
+}
+
+.NovSelectImageHeadingToggle{
+        font-size: 20px;
+
+}
+
+/*Novelist Styling End*/
+
+/* Buttons */
+
+.btn-confirm {
+    color: [% css_colors.button_confirm_text %];
+    background-color: [% css_colors.button_confirm %];
+    border-color: [% css_colors.button_confirm_border %];
+}
+
+.btn-confirm:hover {
+    color: [% css_colors.button_confirm_text %];
+    background-color: [% css_colors.button_confirm_hover %];
+    border-color: [% css_colors.button_confirm_border_hover %];
+}
+
+.btn-deny {
+    color: [% css_colors.button_deny_text %];
+    background-color: [% css_colors.button_deny %];
+    border-color: [% css_colors.button_deny_border_hover %];
+}
+
+.btn-deny:hover {
+    color: [% css_colors.button_deny_text %];
+    background-color: [% css_colors.button_deny_hover %];
+    border-color: [% css_colors.button_deny_border_hover %];
+}
+
+.btn-remove {
+    color: [% css_colors.button_remove_text %];
+    background-color: [% css_colors.button_remove %];
+    border-color: [% css_colors.button_remove_border %];
+}
+
+.btn-remove:hover {
+    color: [% css_colors.button_remove_text %];
+    background-color: [% css_colors.button_remove_hover %];
+    border-color: [% css_colors.button_remove_border_hover %];
+}
+
+.btn-opac{
+    color: [% css_colors.opac_button_text %] !important;
+    background-color: [% css_colors.opac_button %];
+    border-color: [% css_colors.opac_button_border %];
+}
+
+.btn-opac:hover{
+    color: [% css_colors.opac_button_text %];
+    background-color: [% css_colors.opac_button_hover %] !important;
+    border-color: [% css_colors.opac_button_border_hover %];
+}
+
+.btn-action{
+    color: [% css_colors.action_button_text %] !important;
+    background-color: [% css_colors.action_button %];
+    border-color: [% css_colors.action_button_border %];
+}
+
+.btn-action:hover{
+    color: [% css_colors.action_button_text %];
+    background-color: [% css_colors.action_button_hover %] !important;
+    border-color: [% css_colors.action_button_border_hover %];
+}
+.btn-action > a{
+    color: [% css_colors.action_button_text_anchors %];
+}
+
+
+.dash-link{
+    color: #fff;
+}
+
+.dash-clear{
+    color: [% css_colors.zero_count %] !important;
+}
+
+.dash-unclear{
+    color: [% css_colors.non_zero_count %] !important;
+}
+
+.remove_filter{
+    padding: .25rem .25rem !important;
+    font-size: .875rem;
+    line-height: 0.5;
+    border-radius: 1rem !important;
+}
+
+
+.cn_browse_item .card{
+    padding: 15px;
+}
+#facets .card-header,#facets .card-header a {
+    background-color: [% css_colors.facets_back %];
+    color: [% css_colors.text_invert %]
+}
+
+.facet_template:hover{
+        background-color:#e8e8e8;
+}
+
+.danger, .validate{
+    color: [% css_colors.text_alert %] !important;
+}
+
+.danger{
+    font-weight: 600;
+    font-style: italic;
+}
+
+.success{
+    color: green !important;
+}
+.dropdown-menu{
+    border: 1px solid black;
+    box-shadow: 2px 2px #00000054;
+}
+.dropdown-item.active, .dropdown-item:active{
+    color : #000 !important;
+}
+.browse-result-list{
+    list-style:none;
+}
+.not_active_pill{
+    border: 2px solid #007bff;
+    padding: 6px;
+    margin: 0 10px;
+}
+
+.mini-control{
+    max-width: 100px !important;
+}
+
+.mod-control{
+    max-width: 150px !important;
+}
+
+.card-body:empty{
+    display:none;
+}
+.min{
+ min-height:500px;
+}
+.container{
+
+}
+html{
+    height:100%;
+    min-height: 100vh;
+}
+body {
+    min-height: 100vh;
+    margin:0;
+    font-family: [% css_fonts.font_main %] !important;
+    font-size: [% css_fonts.size_base %];
+  /*  background-color: [% css_colors.primary %]; */
+    [% IF rtl == 't' -%]
+    direction: rtl;
+    [%- END %]
+}
+
+button, input {
+    font-family: [% css_fonts.font_main %] !important;
+    font-size: [% css_fonts.size_base %];
+}
+
+img {
+    border: none;
+}
+
+#topnav_logo {
+    margin-left: 2em;
+    margin-bottom: 2em;
+}
+
+#homesearch_main_logo {
+    padding-top: 60px;
+    margin: auto;
+    width: 50%;
+}
+
+a {
+    color: [% css_colors.link %];
+}
+
+#search-wrapper h1,
+#search-wrapper h2 {
+    text-align: center;
+}
+
+#search-wrapper input[type=text] {
+    height: calc(1.8125rem + 2px);
+    margin:0;
+    padding:0;
+}
+
+#search-wrapper select, .results_header_lbl select {
+    border:1px solid [% css_colors.border_standard %];
+    height: calc(1.8125rem + 2px);
+    margin:0;
+    padding:0;
+    width: 12em;
+}
+
+.search-check {
+    text-align: center;
+}
+
+.searchbar {
+    font-weight: bold;
+    padding-top: 10px;
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    [%- ELSE %]
+    margin-left: 1em;
+    [%- END %]
+}
+
+.refine_search {
+    padding-bottom: 7px;
+    margin-left: 1em;
+}
+
+/*
+#search-wrapper select {
+    border:0px solid [% css_colors.border_dark %];
+    filter:alpha(opacity=0);
+    -khtml-opacity:0;
+    opacity:0;
+    padding:0;
+    margin:0;
+    height:18px;
+}
+*/
+
+#actions .btn-action {
+    text-align: left;
+}
+
+#adv_numeric_block{
+    max-width: 600px;
+}
+
+#adv_selector_pub_year {
+    margin-top: 5px;
+}
+
+h2.graphic880 {
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:normal;
+}
+
+.hide_me, .hidden {
+    display: none;
+    visibility: hidden;
+}
+
+div.select-box-wrapper {
+    position:absolute;
+    padding-top:2px;
+    overflow:hidden;
+    [% IF rtl == 't' -%]
+    padding-right: 3px;
+    text-align:right;
+    [%- ELSE %]
+    padding-left:3px;
+    text-align:left;
+    [%- END %]
+}
+
+#dash_wrapper {
+    [% IF rtl == 't' -%]
+    margin-right: 0.5em;
+    [%- ELSE %]
+    margin-left: 0.5em;
+    [%- END %]
+}
+
+#dash_wrapper div {
+    background-color: [% css_colors.primary %];
+    border-radius: 5px;
+    padding: 0em 1em;
+}
+
+.dash_divider {
+    margin: 0 20px;
+    color: #fff;
+    display:inline-block;
+}
+
+
+
+#dash_user {
+    font-weight: bold;
+}
+
+#logout_link {
+    [% IF rtl == 't' -%]
+    right: 1px;
+    [%- ELSE %]
+    left: 1px;
+    [%- END %]
+}
+
+
+/*
+#dash_fines { color: [% css_colors.text_badnews %]; }
+the color contrast between "text_badnews" and "primary"
+is too low for WCAG compliance.  Use "text_attention"
+for now until a better color is picked - if needed.
+*/
+
+#dash_wrapper #dash_user_message_button_container {
+    display: inline;
+    padding: 0;
+}
+#dash_wrapper #unread_message_count_floater {
+    position: absolute;
+    background-color: [% css_colors.text_alert %];
+    padding-left: 0.2em;
+    padding-right: 0.2em;
+    display: inline-block;
+    font-size: 95%;
+    border-radius: 0;
+    z-index: 2;
+    margin-top: 0.2em;
+    [% IF rtl == 't' -%]
+    margin-right: -1.5em;
+    [%- ELSE %]
+    margin-left: -1.5em;
+    [%- END %]
+}
+
+#header-wrap {
+    /* border-bottom: 5px solid [% css_colors.nav_separation %]; */
+    background-color: [% css_colors.header_primary_fade %];
+    background-image: -moz-linear-gradient([% css_colors.header_primary %], [% css_colors.header_primary_fade %]);
+    background-image: -o-linear-gradient([% css_colors.header_primary %], [% css_colors.header_primary_fade %]);
+    background-image: -webkit-linear-gradient([% css_colors.header_primary %], [% css_colors.header_primary_fade %]);
+    background-image: linear-gradient([% css_colors.header_primary %], [% css_colors.header_primary_fade %]);
+}
+#header {
+    color: [% css_colors.background %];
+    margin-left: 1em;
+    margin-right: 1em;
+    font-size: [% css_fonts.size_small %];
+}
+
+#header a {
+    color: [% css_colors.background %];
+}
+
+#header a:hover {
+    color: [% css_colors.text_invert %];
+    text-decoration: none;
+}
+
+#header-links {
+    color: [% css_colors.text_invert %];
+    font-size: [% css_fonts.size_small %];
+    font-weight: bold;
+    position: relative;
+    top:4px;
+
+}
+
+#header-links a {
+    color: [% css_colors.text_invert %];
+    display: block;
+    text-decoration: none;
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 22px;
+    [%- ELSE %]
+    float:left;
+    margin-right:22px;
+    [%- END %]
+}
+
+#header-links a:hover {
+    color: [% css_colors.text_invert %];
+    text-shadow: 0 0 0.2em [% css_colors.primary %], 0 0 0.2em [% css_colors.primary %];
+    text-decoration: none;
+}
+
+#header #header-links2 {
+    position:relative;
+    top:-8px;
+    color: [% css_colors.text_invert %];
+    padding-bottom: 15px;
+}
+
+#header #header-links2 a {
+    color: [% css_colors.text_invert %];
+}
+
+#header #header-links2 a:hover {
+    text-decoration: underline;
+}
+
+#your-acct-login {
+    padding-top:2em;
+}
+
+#gold-links {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    padding-right: 0px;
+    [%- ELSE %]
+    margin-left: 1em;
+    padding-left:0px;
+    [%- END %]
+}
+
+#gold-links-home {
+    margin:auto;
+    [% IF rtl == 't' -%]
+    padding-right: 0px;
+    [%- ELSE %]
+    padding-left:0px;
+    [%- END %]
+}
+
+#gold-links-holder {
+    height: 24px;
+    background-color: [% css_colors.background_invert %];
+}
+
+#util-bar {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    padding-right: 0px;
+    [%- ELSE %]
+    margin-left: 1em;
+    padding-left:0px;
+    [%- END %]
+    height:0px;
+}
+
+.search_box_wrapper {
+    padding-left: 1rem;
+}
+
+#search-wrapper {
+    /*border-bottom: 1px solid [% css_colors.border_standard %];*/
+    padding-bottom: 5px;
+    background-color: [% css_colors.background %];
+}
+
+#search-wrapper #breadcrumb {
+    margin-top:0px;
+    font-size: [% css_fonts.size_smaller %];
+    [% IF rtl == 't' -%]
+    float: right;
+    [%- ELSE %]
+    float:left;
+    [%- END %]
+}
+
+#search-wrapper #search-within {
+    margin-top:10px;
+    position:relative;
+    [% IF rtl == 't' -%]
+    float: left;
+    right: -173px;
+    [%- ELSE %]
+    float:right;
+    left:-173px;
+    [%- END %]
+}
+
+#search-wrapper #breadcrumb a {
+    color: [% css_colors.text %];
+}
+
+#search-wrapper #search_frm label {
+    font-size: [% css_fonts.size_smaller %];
+}
+
+#search-wrapper #search-box {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    padding-right: 0px;
+    [%- ELSE %]
+    margin-left: 1em;
+    padding-left: 0px;
+    [%- END %]
+    padding-top: 10px;
+    padding-bottom: 10px;
+}
+
+#adv_search_tabs, #acct_tabs, #acct_fines_tabs, #acct_checked_tabs, #acct_holds_tabs, #acct_prefs_tabs {
+    [% IF rtl == 't' -%]
+    margin-right:2px;
+    [%- ELSE %]
+    margin-left: 2px;
+    [%- END %]
+    overflow: auto;
+}
+
+#adv_search_tabs a, #acct_tabs a, #acct_fines_tabs a, #acct_checked_tabs a, #acct_holds_tabs a, #acct_prefs_tabs a {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin: 10px 0px 0px 7px;
+    border-radius: 10px 10px 0px 0px;
+    [%- ELSE %]
+    float: left;
+    margin: 10px 7px 0px 0px;
+    border-radius: 10px 10px 0px 0px;
+    [%- END %]
+    text-align: center;
+    vertical-align: middle;
+    display: block;
+    padding: 10px 0px 10px 0px;
+    font-weight: bold;
+    color: [% css_colors.text_invert %];
+    background-color: [% css_colors.control %];
+    font-weight: bold;
+    text-decoration: none;
+}
+
+#adv_search_tabs a, #acct_tabs a, #acct_fines_tabs a {
+    padding: 1em 1em 0.5em;
+}
+
+#adv_search_tabs a:hover, #acct_tabs a:hover, #acct_fines_tabs a:hover, #acct_checked_tabs a:hover, #acct_holds_tabs a:hover, #acct_prefs_tabs a:hover {
+    background-color: [% css_colors.primary %];
+    color: [% css_colors.text_invert %];
+    text-decoration: none;
+}
+
+#adv_search_filters {
+    position: relative;
+}
+#adv_search_rows {
+    border-bottom: none;
+}
+.adv_filter_block {
+    [% IF rtl == 't' -%]
+    float: right;
+    [%- ELSE %]
+    float: left;
+    [%- END %]
+    padding: 15px;
+    clear: both;
+}
+.adv_filter_block_item {
+    [% IF rtl == 't' -%]
+    float: right;
+    [%- ELSE %]
+    float: left;
+    [%- END %]
+    padding: 5px;
+}
+
+.adv_special_block {
+    
+    padding: 5px;
+    margin-top: 5px;
+}
+
+
+.checkbox_col {
+    width: 1%;
+    [% IF rtl == 't' -%]
+    padding-right: 10px !important;
+    [%- ELSE %]
+    padding-left: 10px !important;
+    [%- END %]
+}
+
+#adv_search.on, #num_search.on, #expert_search.on {
+    color: [% css_colors.accent_darker %];
+    background-color: [% css_colors.background %];
+    text-decoration: none;
+}
+
+#adv_search_tabs a.acct-tab-on, #acct_tabs a.acct-tab-on, #acct_fines_tabs a.acct-tab-on {
+    color: [% css_colors.accent_darker %];
+    background-color: [% css_colors.background %];
+    text-decoration: none;
+}
+
+.acct-tab-off {
+    background-color: [% css_colors.control %];
+}
+
+#acct_checked_tabs a, #acct_holds_tabs a, #acct_prefs_tabs a {
+    margin-top: 0px;
+    font-size: [% css_fonts.size_smaller %];
+    color: [% css_colors.accent_darker %];
+    padding: 10px 10px 10px 10px;
+}
+
+#acct_checked_tabs div.selected a, #acct_holds_tabs div.selected a, #acct_prefs_tabs div.selected a {
+    background-color: [% css_colors.accent_lightest %];
+    color: [% css_colors.accent_darker %];
+}
+
+#acct_checked_tabs, #acct_holds_tabs, #acct_prefs_tabs {
+    padding-bottom: 12px;
+    color: [% css_colors.accent_medium %];
+}
+
+#acct_select, #acct_prefs_select {
+     display: none;
+}
+
+#mobile_acct_search_links {
+      background-color: [% css_colors.primary_fade %];
+}
+
+.rdetail_header {
+    [% IF rtl == 't' -%]
+    padding: 5px 0px 6px 7px;
+    margin-right: 1em;
+    [%- ELSE %]
+    padding: 5px 7px 6px 0px;
+    margin-left: 1em;
+    [%- END %]
+    border-bottom: 1px dotted [% css_colors.accent_light %];
+}
+
+.rdetail_results a {
+    color:[% css_colors.primary_fade %];
+    font-weight:bold;
+    font-size: [% css_fonts.size_bigger %];
+}
+
+.rdetail_result_count {
+    color: [% css_colors.text %];
+    font-weight: normal;
+    display: inline-block;
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [%- ELSE %]
+    padding-left: 1em;
+    [%- END %]
+}
+
+.rdetail_result_nav {
+    font-weight:normal;
+    display: inline-block;
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [%- ELSE %]
+    padding-left: 1em;
+    [%- END %]
+}
+
+#rdetail_details_table {
+    margin-top: 15px;
+}
+
+#rdetail_image { border: none; }
+#rdetail_image_cell {
+    padding-top: 3px;
+    [% IF rtl == 't' -%]
+    padding-left: 10px;
+    [%- ELSE %]
+    padding-right: 10px;
+    [%- END %]
+}
+
+h2.rdetail_uris {
+    margin-top: 1em;
+}
+div.rdetail_uris {
+    padding: 0.5em 1em 0.5em 1em;
+    background-color: [% css_colors.accent_lighter2 %];
+}
+div.rdetail_uris ul li {
+    position: relative;
+    [% IF rtl == 't' -%]
+    right: 1em;
+    [%- ELSE %]
+    left: 1em;
+    [%- END %]
+}
+
+div.rdetail_show_copies {
+    margin-top: 1em;
+}
+
+div#rdetail_actions_div {
+    background-color: [% css_colors.background %];
+    [% IF rtl == 't' -%]
+    float: left;
+    [%- ELSE %]
+    float: right;
+    [%- END %]
+}
+
+div#rdetail_copy_counts {
+    margin-top; 1em;
+}
+
+/*
+span#rdetail_copy_counts {
+    display: inline-block;
+    vertical-align: top;
+    [% IF rtl == 't' -%]
+    border-left: thin;
+    margin-left: 1em;
+    padding-left: 1em;
+    [%- ELSE %]
+    border-right: thin;
+    margin-right: 1em;
+    padding-right: 1em;
+    [%- END %]
+}
+*/
+
+span#rdetail_hold_counts {
+    display: inline-block;
+    vertical-align: top;
+}
+span#rdetail_hold_counts p {
+    [% IF rtl == 't' -%]
+    padding-right: 2em;
+    [%- ELSE %]
+    padding-left: 2em;
+    [%- END %]
+}
+
+#rdetail_image_div {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 1em;
+    [%- ELSE %]
+    float: left;
+    margin-right: 1em;
+    [%- END %]
+}
+
+.rdetail_aux_utils {
+    padding-bottom: 6px;
+    [% IF rtl == 't' -%]
+    border-right: 1px dotted [% css_colors.accent_light %];
+    padding-right:17px;
+    padding-left:70px;
+    [%- ELSE %]
+    border-left:1px dotted [% css_colors.accent_light %];
+    padding-left: 17px;
+    padding-right: 70px;
+    [%- END %]
+}
+
+div.place_hold {
+    border-bottom: 1px dotted [% css_colors.accent_light %];
+    padding-top: 10px;
+}
+
+div.toggle_list { padding-top: 6px; }
+
+div.share_record {
+    padding-top: 6px;
+    border-top: 1px dotted [% css_colors.accent_light %];
+}
+
+div.format_icon {
+    [% IF rtl == 't' -%]
+    float: left;
+    margin-left: 17px;
+    [%- ELSE %]
+    float: right;
+    margin-right: 17px;
+    [%- END %]
+}
+
+#metarecord_population {
+    overflow: hidden;
+    width: 40%;
+    padding-bottom: 10px;
+}
+
+.metarecord_population_span_link {
+    line-height: 20px;
+}
+
+.metarecord_population_format {
+    border-right: thin;
+    display: inline-block;
+    margin-right: 1em;
+    padding-right: 1em;
+    vertical-align: top;
+}
+
+.metarecord_population_item_lang {
+    display: inline-block;
+    vertical-align: top;
+}
+
+.metarecord_population_all {
+    padding-top:10px;
+}
+
+.results_aux_utils {
+    display: table-cell;
+}
+
+.result_util {
+    border-bottom: 1px dotted [% css_colors.accent_light %];
+    padding-top: 6px;
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [%- ELSE %]
+    padding-left: 1em;
+    [%- END %]
+}
+
+.results_reviews {
+    top: -5px;
+}
+
+#rdetail_copies {
+    padding-top: 1.5em;
+}
+
+#rdetails_status td {
+    [% IF rtl == 't' -%]
+    padding: 7px 13px 3px 0px;
+    [%- ELSE %]
+    padding: 7px 0px 3px 13px;
+    [%- END %]
+}
+
+#rdetails_status td[headers=copy_header_library],
+#rdetails_status td[headers=copy_header_shelfloc] {
+    white-space: normal;
+}
+
+#rdetails_status thead th {
+    [% IF rtl == 't' -%]
+    padding: 13px 13px 13px 0px;
+    text-align: right;
+    [%- ELSE %]
+    padding: 13px 0px 13px 13px;
+    text-align: left;
+    [%- END %]
+    background-color: [% css_colors.accent_lighter2 %];
+    font-size: [% css_fonts.size_smaller %];
+    font-weight: bold;
+}
+
+#rdetails_status tbody td {
+    [% IF rtl == 't' -%]
+    padding-right: 13px;
+    text-align: right;
+    [%- ELSE %]
+    padding-left: 13px;
+    text-align: left;
+    [%- END %]
+}
+#rdetails_status tbody td.copy_note {
+    color: [% css_colors.primary %];
+    text-wrap:normal;
+    white-space:pre-wrap !important;
+    word-wrap:normal;
+}
+
+#rdetails_status tbody td.copy_tag {
+    border-color: [% css_colors.primary %];
+    border-style: dashed;
+    border-width: 2px;
+}
+#rdetails_status tbody .copy_tag_value {
+    font-weight: bolder;
+}
+
+.rdetail_extras {
+    background-color: [% css_colors.primary_fade %];
+    border: 1px solid [% css_colors.primary %];
+    padding-top:1px;
+    clear:both;
+}
+
+#rdetail_extras_div {
+    margin: 1em 0;
+}
+
+.rdetail_extras_hr {
+    [% IF rtl == 't' -%]
+    margin-right: 1px;
+    margin-left: 1px;
+    [%- ELSE %]
+    margin-left: 1px;
+    margin-right: 1px;
+    [%- END %]
+    height: 1px;
+    background-color: [% css_colors.accent_light %];
+}
+
+.rdetail_extras_link {
+    padding: 6px 12px;
+    font-size: [% css_fonts.size_smaller %];
+    font-weight: bold;
+}
+
+.rdetail_extras_lbl {
+    color: [% css_colors.text_invert %];
+    text-decoration: none;
+}
+
+#rdetail_extras_expand, #rdetail_extras_collapse, #rdetail_locs_collapse {
+    [% IF rtl == 't' -%]
+    margin-right: 13px;
+    [%- ELSE %]
+    margin-left: 13px;
+    [%- END %]
+}
+
+#rdetail_locs_expand, #rdetail_locs_collapse {
+    [% IF rtl == 't' -%]
+    margin-right: 13px;
+    [%- ELSE %]
+    margin-left:13px;
+    [%- END %]
+    padding-bottom:3px;
+    margin-top:15px;
+}
+
+#rdetail_anotes_div .biography {
+    margin:0;
+}
+
+span.copy_note_label {
+    font-weight: bold;
+}
+
+span.copy_tag_type_label {
+    font-weight: bold;
+}
+
+#gbp_extra, #gbp_arrow_down_link {
+    display: none;
+}
+
+.almost-content-wrapper {
+    background-color: [% css_colors.background %];
+}
+
+#cartDropdown .dropdown-menu {
+
+}
+
+#content-wrapper {
+    background-color: [% css_colors.background %];
+    height: auto;
+    display: grid;
+}
+
+.content-wrapper-record-page { top: -15px; position: relative; }
+
+#main-content-home {
+    [% IF rtl == 't' -%]
+    padding-right: 17px;
+    margin-right: 1em;
+    [%- ELSE %]
+    padding-left: 17px;
+    margin-left: 1em;
+    [%- END %]
+}
+#main-content {
+    [% IF rtl == 't' -%]
+    padding-right: 0px;
+    [%- ELSE %]
+    padding-left: 0px;
+    [%- END %]
+    margin: 0 1em;
+    clear: both;
+}
+
+#main-content-after-bar {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    padding-right: 4px;
+    [%- ELSE %]
+    margin-left: 1em;
+    padding-left: 4px;
+    [%- END %]
+}
+
+#results_header_inner {
+    padding-bottom: 1rem;
+}
+
+#results-side-bar {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 5px;
+    [%- ELSE %]
+    float: left;
+    margin-right: 5px;
+    [%- END %]
+    width: 174px;
+    background-color: [% css_colors.background %];
+}
+
+#main-content .login_boxes {
+    border: 1px solid [% css_colors.accent_lighter %];
+    background-color: [% css_colors.accent_lightest %];
+    background-image: -moz-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%);
+    background-image: -ms-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%);
+    background-image: -o-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%);
+    background-image: -webkit-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%);
+    background-image: linear-gradient(to bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%);
+    color: [% css_colors.accent_darker %];
+}
+
+#main-content .login_boxes h1 {
+    font-weight: normal;
+    font-size: [% css_fonts.size_biggest %];
+    margin:0;
+}
+
+#main-content .left_brain {
+    [% IF rtl == 't' -%]
+    padding-right: 28px;
+    [% ELSE -%]
+    padding-left:28px;
+    [% END -%]
+    padding-top:25px;
+}
+
+#main-content .left_brain input[type=text], #main-content .left_brain input[type=password] {
+    width:167px;
+    margin:0;
+    padding:0;
+    background-color: [% css_colors.background %];
+    font-size: [% css_fonts.size_bigger %];
+    color: [% css_colors.text %];
+}
+
+#main-content .left_brain .input_bg {
+    [% IF rtl == 't' -%]
+    padding: 10px 13px 0px 10px;
+    [% ELSE -%]
+    padding:10px 10px 0px 13px;
+    [% END -%]
+    width:167px;
+    height:29px;
+}
+
+.login-help-box {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-right: 2em;
+    [% ELSE -%]
+    float: left;
+    margin-left: 2em;
+    [% END -%]
+    width: 200px;
+    text-align: center;
+}
+
+.login-help-button {
+    font-size: [% css_fonts.size_biggest %];
+    padding: 1.5em;
+}
+
+#login-failed-message {
+    font-size: [% css_fonts.size_bigger %];
+    font-weight: bold;
+    color: [% css_colors.text_alert %];
+    padding-top: 1em;
+}
+
+#holds_temp_parent td {
+    border-bottom:1px solid [% css_colors.border_standard %];
+}
+
+#holds_temp_parent input, #holds_temp_parent select {
+    margin:0;
+}
+
+
+#holds_temp_parent tr td div.format_icon {
+    margin-top: 6px;
+    margin-bottom: 6px;
+    float: none;
+}
+
+#results_header_bar {
+    background-color: [% css_colors.accent_medium %];
+    border-top:1px solid [% css_colors.accent_mediumdark %];
+    border-bottom:1px solid [% css_colors.accent_mediumdark %];
+}
+
+.results_header_lbl {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float: left;
+    [% END -%]
+    font-weight: bold;
+    color: [% css_colors.text %];
+    /* this border is not visible, but it keeps these labels the same size
+    as the buttons */
+    border: 1px solid [% css_colors.accent_medium %];
+    background-color: [% css_colors.accent_medium %];
+    margin: 0.5em 0.3em;
+    padding: 0.3em;
+}
+/* we need a negative margin on the select to allow the containing <label>
+to determine the actual size of the element.  By doing this, we can increase
+the odds that the buttons and the select will be the same size, and therefore
+collapse correctly when the window width decreases */
+.results_header_lbl select {
+    margin: -0.5em 0;
+}
+
+#limit_to_available {
+    vertical-align: middle;
+}
+
+.results_header_sel {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    margin:0;
+}
+
+
+.results_header_nav1 {
+    text-align: center;
+}
+
+.results_header_nav1 .h1 {
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:bold;
+    color:[% css_colors.primary_fade %];
+}
+
+.table_no_border_space {
+  border-spacing: 0px;
+}
+.table_no_cell_pad td {
+  padding: 0px;
+}
+.table_no_border {
+  border-collapse: collapse;
+}
+
+#result_table_table {
+  margin-top:10px;
+}
+
+#result_table_div {
+    margin-top: 1em;
+}
+
+tr.result_table_row > td.results_row_count,
+tr.result_table_row > td.result_table_pic_header,
+tr.result_table_row > td.result_table_title_cell {
+    vertical-align: top;
+}
+
+.result_metadata {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding-left: 2em;
+    [% ELSE -%]
+    float: left;
+    padding-right: 2em;
+    [% END -%]
+    width: 30em;
+}
+
+tr.result_table_row:nth-child(n+2) > td {
+    border-top: 1px solid [% css_colors.accent_lighter2 %];
+}
+
+tr.result_table_row > td.result_table_pic_header {
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [% ELSE -%]
+    padding-left: 1em;
+    [% END -%]
+    white-space: nowrap;
+    width: 78px;
+}
+
+/* styles for selecting records in the results set */
+.result_table_row_selected {
+    background-color: [% css_colors.item_selected %];
+}
+#selected_records_summary, #clear_basket {
+    margin-left: 5em;
+}
+
+/* styles for the basket */
+#record_basket {
+    [% IF rtl == 't' -%]
+    float: left;
+    margin-left: 5em;
+    [% ELSE; %]
+    float: right;
+    margin-right: 5em;
+    [% END %]
+}
+#record_basket_icon {
+    [% IF rtl == 't' -%]
+    float: left;
+    margin-left: 2em;
+    [% ELSE; %]
+    float: right;
+    margin-right: 2em;
+    [% END %]
+    position: relative;
+}
+#record_basket_count_floater {
+    background-color: #ddd;
+    position: absolute;
+    top: 0px;
+    right: -10px;
+    z-index: 2;
+    text-align: center;
+    border-radius: 50%;
+    width: 20px;
+}
+#record_basket_count_floater a {
+    text-decoration: none;
+}
+#basket_actions {
+    margin: .5rem;
+}
+#basket_actions select {
+    border-color: rgb(169, 169, 169);
+}
+
+.result_number {
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [% ELSE -%]
+    padding-left: 1em;
+    [% END -%]
+    white-space: nowrap;
+}
+
+.result_count_number {
+   font-weight: bold;
+}
+
+.result_table_subtable {
+    width: 100%;
+    padding-top: 1em;
+}
+
+div.result_table_utils_cont {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    float: right;
+    [% ELSE -%]
+    text-align:left;
+    float: left;
+    [% END -%]
+}
+
+.mylist_action:hover{
+    text-decoration: none;
+}
+
+#myopac_summary_div p {
+    margin:0;
+    margin-bottom: 10px;
+}
+
+#acct_sum_checked_table td {
+    padding-bottom:5px;
+}
+
+.zero_search_hits_main {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    width:300px;
+    margin-top: 2ex;
+}
+.zero_search_hits_saved {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 2em;
+    [% ELSE -%]
+    float:left;
+    margin-right: 2em;
+    [% END -%]
+    width:200px;
+    margin-top: 2ex;
+}
+
+#zero_search_hits p {
+    margin-top:0;
+}
+
+#zero_hits_term {
+    font-weight: bold;
+}
+
+#zero_search_hits #spell_check_link {
+}
+
+#zero_search_hits #zero_hits_suggestions {
+}
+
+#lowhits_help {
+    [% IF rtl == 't' -%]
+    float: left;
+    [% ELSE -%]
+    float: right;
+    [% END-%]
+    width: 353px;
+    background-color: [% css_colors.accent_light %];
+    padding: 10px;
+    margin-top: 7px;
+}
+
+.results_info_table td {
+    [% IF rtl == 't' -%]
+    padding-left: 10px;
+    [% ELSE -%]
+    padding-right: 10px;
+    [% END-%]
+}
+
+#myopac_holds_main_table {
+    border-collapse: collapse;
+}
+
+#myopac_holds_main_table td {
+    border: 1px solid [% css_colors.border_dark %];
+
+}
+
+.myopac-hold-available {
+    color: [% css_colors.text_greatnews %];
+    font-weight: bold;
+}
+
+.myopac-hold-suspended {
+    color: [% css_colors.text_badnews %];
+    font-weight: bold;
+}
+
+#myopac_prefs_div .data_grid {
+    border-collapse:collapse;
+}
+
+#myopac_prefs_div .data_grid td {
+    [% IF rtl == 't' -%]
+    padding: 6px 17px 7px 0px;
+    [% ELSE -%]
+    padding:6px 0px 7px 17px;
+    [% END -%]
+    background-color:[% css_colors.accent_ultralight %];
+    border-bottom:3px solid [% css_colors.background %];
+}
+
+.header_middle {
+    [% IF rtl == 't' -%]
+    padding: 0px 0px 0px 7px;
+    [% ELSE -%]
+    padding: 0px 7px 0px 0px;
+    [% END -%]
+    height:22px;
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:bold;
+    color:[% css_colors.primary_header %];
+    /*border-bottom: 1px dotted [% css_colors.accent_light %];*/
+    clear: both;
+}
+
+.header_middle a {
+    font-weight: normal;
+}
+
+#acct_sum_block {
+    [% IF rtl == 't' -%]
+    float: right;
+    clear: right;
+    [% ELSE -%]
+    float: left;
+    clear: left;
+    [% END -%]
+}
+
+.acct_sum_table {
+    border-collapse: collapse;
+    background-color: [% css_colors.accent_ultralight %];
+}
+
+.acct_sum_table tr {
+    border-bottom: 2px solid white;
+}
+
+.acct_sum_table td {
+    padding: 1em;
+}
+
+.acct_sum_table a {
+    text-transform: none;
+    position:relative;
+    top:-1px;
+}
+
+.acct_sum_table .view_link {
+    font-weight: normal;
+}
+
+#myopac_sum_fines {
+    [% IF rtl == 't' -%]
+    float: left;
+    padding: 15px 23px 0px 0px;
+    [% ELSE -%]
+    float:right;
+    padding: 15px 0px 0px 23px;
+    [% END -%]
+    width: 177px;
+}
+
+.cc_logo_img
+{
+   width: 79%;
+    [% IF rtl == 't' -%]
+      padding-right: .5em;
+    [% ELSE -%]
+       padding-left: .5em;
+    [% END -%]
+}
+
+#myopac_sum_fines_placehold {
+    [% IF rtl == 't' -%]
+    float: left;
+    [% ELSE -%]
+    float: right;
+    [% END -%]
+    width: 177px;
+    height: 166px;
+}
+
+.acct_holds_temp td {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+}
+
+#acct_checked_tabs .align, #acct_holds_tabs .align, #acct_prefs_tabs .align {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+}
+
+
+
+.acct_fines_header
+{
+   width: 100%;
+   padding-bottom:1em;
+   [% IF rtl == 't' -%]
+   float: right;
+   [% ELSE -%]
+   float:left;
+   [% END -%]
+}
+
+/* tables for entering payment information */
+#acct_fines_main_header
+{
+   width: 100%;
+}
+
+/* tables for entering payment information */
+#billing_info_table
+{
+    width: auto;
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    display:inline;
+    padding-left: 1em;
+    padding-right: 1em;
+}
+
+/* tables for entering payment information */
+#credit_card_info_table
+{
+    width: auto;
+    display: block;
+}
+
+/* tables for entering payment information */
+#billing_info_table td,
+#credit_card_info_table td
+{
+   [% IF rtl == 't' -%]
+    padding-right: .5em;
+    [% ELSE -%]
+    padding-left: .5em;
+    [% END -%]
+
+}
+
+/* div for the payment buttons with the total */
+#payment_actions
+{
+   width: auto;
+   display: block;
+   padding: 1em 0 0 1em;
+   text-align:center;
+}
+
+/* Stripe's payment form */
+#payment_form
+{
+    background-color: [% css_colors.accent_ultralight %];
+    width: 75%;
+}
+#card-element
+{
+    padding: 10px;
+}
+
+/* text to state what is seen on cc statement */
+.cc_disclaimer
+{
+   font-style:italic;
+   font-size: 90%;
+   color:[% css_colors.primary_fade %];
+}
+
+.hold_notes {
+    text-transform: none;
+    font-weight: normal;
+}
+
+
+
+#acct_list_header select, #acct_list_header_anon select {
+    font-weight:normal;
+    text-transform:none;
+}
+
+.search_catalog_lbl,
+.adv_search_catalog_lbl,
+.browse_the_catalog_lbl,
+.search_courses_lbl,
+.browse_courses_lbl {
+    font-size: [% css_fonts.size_bigger %];
+}
+
+.lbl1 {
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:bold;
+}
+
+.lbl2 {
+    font-size: [% css_fonts.size_smaller %];
+    font-weight:normal;
+    position:relative;
+    top:3px;
+    max-width:300px;
+}
+
+#fines_payments_wrapper {
+    padding-left: 5px;
+    padding-right: 5px;
+}
+
+.myopac_payments_table th {
+    [% IF rtl == 't' -%]
+    text-align: right; }
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+}
+
+.myopac_payments_table thead th { border-bottom: 1px dashed [% css_colors.accent_darker %]; }
+.myopac_payments_table thead th:first-child { width: 8em; }
+.myopac_payments_table tbody tr:nth-child(odd) { background-color: [% css_colors.accent_lighter %]; }
+.myopac_payments_table form { display: inline; }
+.myopac_payments_table input[type="submit"] { padding: 1px; }
+
+.cc_header
+{
+   padding-top:1em;
+   background-color: [% css_colors.accent_lighter %];
+}
+
+.payment-error {
+    font-weight: bold; color: [% css_colors.text_alert %];
+    padding: 10px; border: 1px solid [% css_colors.accent_medium_dark %];
+}
+
+.payment-processing {
+    font-weight: bold;
+    color: [% css_colors.text_greatnews %];
+    font-size: [% css_fonts.size_bigger %];
+    padding: 10px; border: 1px solid [% css_colors.accent_medium_dark %];
+    text-align: center;
+}
+#adv_search_input { width: 100%; }
+#adv_search_parent {
+    margin-bottom:0px;
+}
+
+#search-wrapper #search-submit-go,
+#search-wrapper #search-submit-go-1,
+#search-wrapper #search-submit-go-2,
+#search-wrapper #search-submit-go-depth {
+    display: inline-block;
+    margin-top: 1.3rem;
+}
+
+#search-submit-spinner {
+    height: 16px;
+    width: 16px;
+}
+div.adv_search_available {
+    margin-top: 1em;
+}
+
+#myopac_loading {
+    width:100%;
+    text-align:center;
+    padding-top:20px;
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:bold;
+}
+
+.chili_link {
+    width:100px !important;
+    text-align: center !important;
+}
+
+.chili_review div.chili_link div {
+    margin: auto;
+}
+
+/* styling for advanced search filters that display with searchbar */
+
+.adv_filter_results_block_label {
+    font-weight:bold;
+    [% IF rtl == 't' -%]
+    padding: 0px 12px 4px 0px;
+    [% ELSE -%]
+    padding: 0px 0px 4px 12px;
+    [% END -%]
+}
+
+.adv_filter_results_group {
+    background-color:  [% css_colors.accent_lighter2 %];
+}
+
+.remove_filter {
+    font-size: 16px;
+    [% IF rtl == 't' -%]
+    margin-right: 3px;
+    [% ELSE -%]
+    margin-left: 3px;
+    [% END -%]
+}
+
+a.remove_filter {
+    text-decoration: none;
+    color: [% css_colors.accent_dark %];
+}
+
+#filter_hits {
+     display: inline-block;
+}
+
+#refine_search_link {
+    display: inline-block;
+}
+
+[%- IF we_want_to_turn_on_facet_styling.defined; %]
+/* some facet styling */
+.facetClassContainer { margin: 2px; border: 1px solid [% css_colors.accent_light %]; }
+.facetClassLabelContainer { border: 1px solid [% css_colors.accent_light %]; }
+.facetClassLabel { font-weight: bold; text-align: center; }
+.facetFieldContainer {  }
+.facetFieldLabel { padding-left: 2px; margin-top: 5px; margin-bottom: 5px; font-weight: bold; text-align: left; }
+.extraFacetFieldsWrapper { }
+.toggleExtraFacetFieldsButton { float: right; margin: 0px; padding: 0px; }
+.facetFieldLineCount {
+    display: inline-block;
+    border-right: 1px solid [% css_colors.accent_light %];
+    color: [% css_colors.accent_mediumdark %];
+    width: 3em;
+    margin-right: 3px
+}
+.facetField { border-top: 1px solid [% css_colors.accent_light %]; }
+.facetFields { padding-left: 5px; }
+.facetFieldLineValue { overflow: hidden; text-overflow: ellipsis; }
+[%- END -%]
+
+div#facet_sidebar {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 1em;
+    [% ELSE -%]
+    float: left;
+    margin-right: 1em;
+    [% END-%]
+}
+
+.facet_box_temp {
+    padding-bottom:3px;
+}
+
+.facet_box_temp .header {
+    height: 2.3em;
+    background-color:[% css_colors.primary %];
+    border-top-left-radius: 5px;
+    border-top-right-radius: 5px;
+    font-weight:bold;
+    color:[% css_colors.text_invert %];
+    padding-top:4px;
+}
+
+.facet_box_temp.filter_box_temp .header {
+    background-color: [% css_colors.background_invert %] !important;
+}
+
+.filter_box_label {
+    color: [% css_colors.background_invert %];
+    font-weight:bold;
+    padding-top:4px;
+    padding-bottom:4px;
+    padding-left:12px;
+}
+
+.facet_box_temp .header .title {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding-right: 12px;
+    [% ELSE -%]
+    float:left;
+    padding-left:12px;
+    [% END -%]
+    padding-top:6px;
+}
+
+/* in this context, where h4 is primarily for structure,
+   avoid the normal large font and margin for h4's */
+.facet_box_temp h4 {
+    font-size : 100%;
+    margin: 0px;
+}
+
+.facet_box_temp .header a.button {
+    [% IF rtl == 't' -%]
+    float: left;
+    padding-left: 6px;
+    [% ELSE -%]
+    float:right;
+    padding-right:6px;
+    [% END -%]
+    padding-top:6px;
+    color:[% css_colors.text_invert %];
+}
+
+.facet_box_wrapper .box_wrapper .box {
+    border-top:1px solid [% css_colors.border_standard %];
+    border-left:1px solid [% css_colors.border_standard %];
+    border-right:1px solid [% css_colors.border_standard %];
+    padding: 0 0.5em;
+    overflow: hidden;
+}
+
+.filter_box_wrapper {
+    margin-bottom: 3px;
+    padding: 2px;
+    border: 1px solid [% css_colors.background_invert %];
+    border-radius: 3px;
+    font-weight:bold;
+    padding-top:4px;
+}
+
+.facet_template {
+    box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    display: table;
+    margin: 0.5em 0;
+    width: 100%;
+}
+
+.facet_template div {
+    display: table-cell;
+    padding: 2px;
+}
+
+.facet_template.filter_template div {
+    padding: 0px !important;
+}
+
+.facet_template .count {
+    text-align: right;
+    color: [% css_colors.accent_dark %];
+}
+
+.page-item.active .page-link {
+    background-color: #00593d;
+    border-color: #00593d;
+}
+.page-link
+{
+    color: #00593d;
+}
+
+.filter-header{
+     background-color: [% css_colors.bg_filter %];
+     color: [% css_colors.text_filter %];
+}
+
+.filter-header:hover{
+     background-color: [% css_colors.bg_filter_hover %];
+}
+
+.extra_header{
+     background-color: [% css_colors.bg_extras %];
+}
+.facet_template_selected {
+    background-color: [% css_colors.accent_lighter2 %];
+    border: 1px solid [% css_colors.accent_medium %];
+}
+
+#footer-wrap {
+    /* border-top: 5px solid [% css_colors.nav_separation %]; */
+    background-color: [% css_colors.footer_primary %];
+    background-image: -moz-linear-gradient([% css_colors.footer_primary_fade %], [% css_colors.footer_primary %]);
+    background-image: -o-linear-gradient([% css_colors.footer_primary_fade %], [% css_colors.footer_primary %]);
+    background-image: -webkit-linear-gradient([% css_colors.footer_primary_fade %], [% css_colors.footer_primary %]);
+    background-image: linear-gradient([% css_colors.footer_primary_fade %], [% css_colors.footer_primary %]);
+    bottom: 0px;
+    width: 100%;
+}
+
+#footer {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    [% ELSE -%]
+    margin-left: 1em;
+    [% END -%]
+    padding-top:5px;
+    padding-bottom: 10px;
+    font-size: [% css_fonts.size_small %];
+}
+
+#footer .navbar-nav {
+    justify-content: center;
+}
+
+#copyright_text, #footer_logo {
+    color: [% css_colors.footer_link %];
+    font-size: [% css_fonts.size_small %];
+    margin: 5px 0;
+    text-align: center;
+}
+
+.color_4 {
+    font-weight: bold;
+}
+
+.advanced_div { padding-top: 15px; }
+#adv_global_search { width: 100%; }
+#adv_global_addrow td { padding-top: 7px; }
+[% IF rtl == 't' -%]
+#adv_global_addrow.td-search-left{text-align:right;}
+[% END -%]
+#adv_global_input_table { width: 100%; }
+#adv_global_input_table select { width: 7em; }
+.adv_adv_link {
+    font-size: [% css_fonts.size_smaller %];
+    color: [% css_colors.text_alert %];
+}
+#acct_prefs_header {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float: left;
+    [% END -%]
+}
+.search_page_nav_link {
+    cursor: pointer;
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [% ELSE -%]
+    padding-left: 1em;
+    [% END -%]
+}
+#opac.result.sort { width: 160px; }
+.renew-summary, .message-update-summary { font-size: [% css_fonts.size_bigger %]; font-style: italic; margin: 0.5ex 0; }
+.failure-text {
+    [% IF rtl == 't' -%]
+    margin-right: 4em;
+    [% ELSE -%]
+    margin-left: 4em;
+    [% END -%]
+    font-style: italic;
+    color: [% css_colors.text_alert %];
+}
+.refine-controls { font-size: [% css_fonts.size_bigger %]; padding: 0.5ex 0; }
+#adv_search_refine input[type=text] { border: 1px inset [% css_colors.accent_light %] !important; }
+#adv_search_refine select { border: 1px inset [% css_colors.accent_light %] !important; }
+#adv_search_refine {
+    [% IF rtl == 't' -%]
+    padding-right: 5em;
+    [% ELSE -%]
+    padding-left: 5em;
+    [% END -%]
+    background-color: [% css_colors.accent_lighter2 %];
+    margin: 2ex 0;
+}
+.row-remover { position: relative; top: 1px; vertical-align: middle; }
+.subtle-button {
+    background-color: [% css_colors.background %];
+    color: [% css_colors.primary %]; text-decoration: none;
+    padding: 0; border: 0; margin: 0;
+    vertical-align: middle;
+}
+.subtle-button:hover { text-decoration: underline; cursor: pointer; }
+.no-dec:hover { text-decoration: none; }
+.pending-addr td { background-color: [% css_colors.background_alert %] !important; border: 0 !important; }
+
+#account-update-email table { text-align: center; padding: 20px; margin-top: 18px; border-collapse: collapse; }
+#account-update-email table td {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+    padding: 5px 15px 5px 15px;
+    border-bottom: 1px solid [% css_colors.accent_lighter %];
+}
+#account-update-email-error { font-size: [% css_fonts.size_biggest %]; padding: 10px; border:1px solid [% css_colors.border_standard %];}
+a.dash-link:hover { text-decoration: underline !important; }
+#list_create_table td { vertical-align: middle; padding: 0 8px; }
+#list_create_table {
+    background-color: [% css_colors.accent_light %];
+    padding-bottom: 4px;
+    margin-bottom: 10px;
+    border-bottom: 1px dotted [% css_colors.accent_medium %];
+    width: 100%;
+}
+.list_create_table_label {
+    width: 30%;
+}
+#list_description, #list_create_name {
+        width: 500px;
+}
+.list-create-table-buttons input[type=image] { margin-top: 2px; }
+.result_table_format_cell { padding: 0px 10px; text-align: center; }
+.results_row_count { font-weight: bold; }
+
+.fmt-note {
+    [% IF rtl == 't' -%]
+    padding-right: 1em !important;
+    [% ELSE -%]
+    padding-left: 1em !important;
+    [% END -%]
+    vertical-align: middle;
+}
+.hold-editor-controls { text-align: center; padding-top: 1em !important; }
+.hold-editor-controls a { padding-left: 2em; }
+
+.text-right {
+    [% IF rtl == 't' -%]
+    text-align: left;
+    [% ELSE -%]
+    text-align: right;
+    [% END -%]
+}
+.text-right-top {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    vertical-align: top;
+    [% END -%]
+}
+.rdetail-author-div {
+    padding-bottom: 10px;
+    display: inline-block;
+}
+
+.invisible { visibility: hidden; }
+.rdetail-extras-summary { margin: 10px; }
+.staff-hold { background-color: [% css_colors.accent_lightest %]; }
+.expert-search tbody tr th {
+    [% IF rtl == 't' -%]
+    text-align: left;
+    padding-right: 2em;
+    [% ELSE -%]
+    text-align: right;
+    padding-left: 2em;
+    [% END -%]
+}
+#adv_expert_row label { font-weight: bold; }
+
+.cn_browse_item { padding: 2ex; }
+.results-paginator-list {
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [% ELSE -%]
+    padding-left: 1em;
+    [% END -%]
+}
+.results-paginator-selected { color: [% css_colors.text_alert %]; }
+.inactive-hold { background-color: [% css_colors.inactive_hold %]; }
+.unread-patron-message { font-weight: bold; }
+
+#hold-items-list td { padding: 5px; margin-bottom: 20px; }
+.hold-items-list-title {
+  font-size: [% css_fonts.size_bigger %];
+  margin-bottom: 20px;
+}
+.hold-items-list-problem { color: [% css_colors.text_alert %]; }
+
+.hold_success_links > span { margin: 0 2em; }
+
+.radio-parts-selection {
+   width: 75%;
+   margin-bottom: 20px;
+}
+
+.parts-radio-option {
+  display: inline-block;
+  width:15em;
+}
+
+.mr_holds_no_formats {
+  [% IF rtl == 't' -%]
+  margin-right: 25px;
+  [% ELSE -%]
+  margin-left: 25px;
+  [% END -%]
+  padding: 5px;
+  font-size: 110%;
+  font-weight: bold;
+  color: [% css_colors.text_invert %];
+  background-color: [% css_colors.primary %];
+}
+
+.holds_item_row_separator td {
+  border-top: 2px dashed [% css_colors.accent_medium %];
+}
+
+.big-strong {font-weight: bold; font-size: [% css_fonts.size_bigger %]; }
+
+.results_header_btns, .results_header_sel {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+}
+
+/*
+ * .various_containers a = shortcut to putting .opac-button on every 'a' with
+ *     the tradeoff of increased stylesheet complexity (TODO: rethink?)
+ */
+
+.opac-multiline-button > a,
+.opac-button, .results_header_btns a, #simple-detail-view-links a, .dash_account_buttons a {
+    color: [% css_colors.button_text %];
+    font-weight: bold;
+    text-decoration: none;
+    cursor: pointer !important;
+    border-radius: 5px;
+    border: 1px solid [% css_colors.primary %];
+    background-color:  [% css_colors.primary_fade %];
+    margin: 0.5em;
+    padding: 0.3em;
+    display: inline-block;
+}
+
+.opac-multiline-button > a:hover,
+.opac-button:hover, .results_header_btns a:hover, #simple-detail-view-links a:hover, #dash_wrapper a.opac-button:hover {
+    background-color: [% css_colors.primary %];
+}
+
+.opac-button:disabled {
+    color: [% css_colors.accent_medium %];
+    cursor: pointer !important;
+    border: 1px solid [% css_colors.accent_light %];
+    background-color: [% css_colors.accent_lighter %];
+}
+
+/* Firefox adds its own special space to inputs; this gets us closer */
+button.opac-button::-moz-focus-inner, input.opac-button::-moz-focus-inner {
+    padding: 0;
+    border: 0;
+}
+
+.opac-button-header, #dash_wrapper .opac-button {
+    background-color: [% css_colors.control %];
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
+    font-size: [% css_fonts.size_base %];
+}
+a.opac-button-header:hover, #dash_wrapper a.opac-button:hover {
+    border-color: [% css_colors.control %];
+}
+
+.opac-multiline-button > a {
+    display: inline-block;
+}
+
+#myopac_checked_div {
+    padding: 0px;
+}
+
+.rdetail-mfhd-head {
+    margin-top: 5px;
+    padding-top: 5px;
+    background-color: [% css_colors.table_heading %];
+}
+
+.rdetail-mfhd-type {
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [% ELSE -%]
+    padding-left: 1em;
+    [% END -%]
+}
+
+.rdetail-mfhd-bottom {
+    border-bottom: thin solid [% css_colors.border_dark %];
+    width: 100%;
+}
+
+.rdetail_record_details {
+    clear: both;
+    margin-top: 1em;
+}
+
+h2.rdetail_record_details, #rdetail_copy_counts h2, h2.rdetail_contents,
+h2.rdetail_related_subjects, h2.rdetail_related_series,
+h2.rdetail_other_formats, h2.rdetail_uris {
+    font-size: [% css_fonts.size_biggest %];
+    font-weight: bold;
+}
+
+.rdetail_content, .rdetail_subject {
+    [% IF rtl == 't' -%]
+    margin-right: 1.5em;
+    padding-right: 1.5em;
+    [% ELSE -%]
+    margin-left: 1.5em;
+    padding-left: 1.5em;
+    [% END -%]
+}
+
+.rdetail_content_type, .rdetail_subject_type {
+    vertical-align: top;
+    font-weight: bold;
+}
+
+.bookbag-item-row td { vertical-align: top; }
+
+.error { color: [% css_colors.text_alert %]; font-weight: bold; }
+.success {
+    color: [% css_colors.text_greatnews %];
+    font-weight: bold;
+}
+
+.rdetail_related_subjects {
+    margin-top: 1.5em;
+}
+
+.rdetail_related_series {
+    margin-top: 1.5em;
+}
+
+#rdetail_openurl {
+    margin-top: 1em;
+}
+
+.rdetail_openurl_entry {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    padding-right: 1em;
+    [% ELSE -%]
+    margin-left: 1em;
+    padding-left: 1em;
+    [% END -%]
+}
+.bookbag-controls-holder { width: 100%; }
+.bookbag-controls-holder:nth-child(odd) { background-color: [% css_colors.accent_lighter2 %]; }
+.bookbag-controls-holder:nth-child(even) { background-color: [% css_colors.accent_lightest %]; }
+.bookbag-controls-holder .most {
+    [% IF rtl == 't' -%]
+    padding-right: 0;
+    margin-left: 5em;
+    [% ELSE -%]
+    padding-left: 0;
+    margin-right: 5em;
+    [% END -%]
+}
+.bookbag-controls-title-block {
+    [% IF rtl == 't' -%]
+    float:right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    width:40%;
+}
+.bookbag-controls-button-block {
+    [% IF rtl == 't' -%]
+    float:right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    width:50%;
+}
+h2.bookbag-name { margin-bottom: 0em; padding-bottom: 0em; }
+.bookbag-share .fixed { min-width: 4em; }
+.bookbag-specific {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    [% ELSE -%]
+    margin-left: 1em;
+    [% END -%]
+}
+.bookbag-specific div.sort {
+    [% IF rtl == 't' -%]
+    float: right;
+    text-align: right;
+    margin-right: 15px;
+    [% ELSE -%]
+    float: left;
+    text-align: left;
+    margin-left: 15px;
+    [% END -%]
+    width: 40%;
+}
+.bookbag-specific div.meta {
+    background-color: [% css_colors.accent_light %];
+    [% IF rtl == 't' -%]
+    float: left;
+    text-align: left;
+    [% ELSE -%]
+    float: right;
+    text-align: right;
+    [% END -%]
+    width: 54%;
+    border: 1px solid [% css_colors.accent_light %];
+    padding: 5px;
+    margin-top: 5px;
+}
+#bbag-name-desc-form tr th { vertical-align: middle; }
+#bbag-name-desc-form .saver { vertical-align: middle; text-align: center; }
+.bookbag-description {
+    padding-top: 0em;
+    font-style: italic;
+    max-width: 40em;
+}
+/*
+.bbag-edit-desc-label {
+    [% IF rtl == 't' -%]
+    float:right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    width:8em;
+}
+.bbag-edit-desc-save {
+    clear:both;
+    margin-bottom:10px;
+}
+#bbag-edit-description {
+    width: 20em;
+    [% IF rtl == 't' -%]
+    float:right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+}
+#bbag-edit-name {
+    width: 20em;
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float: left;
+    [% END -%]
+}
+*/
+
+.bbag-action {
+    [% IF rtl == 't' -%]
+    margin-right: 15px;
+    [% ELSE -%]
+    margin-left: 15px;
+    [% END -%]
+}
+.bbag-navigate-list {
+    [% IF rtl == 't' -%]
+    padding-right: 32px;
+    float:right;
+    [% ELSE -%]
+    padding-left: 32px;
+    float:left;
+    [% END -%]
+}
+.bbag-navigate-list-pages {
+    [% IF rtl == 't' -%]
+    padding-right: 10px;
+    float:right;
+    [% ELSE -%]
+    padding-left: 10px;
+    float:left;
+    [% END -%]
+}
+textarea { font-family: sans-serif; }
+table.bookbag-specific {
+    border-right: 1px solid [% css_colors.accent_dark %];
+    border-bottom: 1px solid [% css_colors.accent_medium %];
+    margin-bottom: 2ex;
+    width: 100%;
+}
+.bookbag-share {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding: 0px 10px 0px 0px;
+    [% ELSE -%]
+    float: left;
+    padding: 0px 0px 0px 10px;
+    [% END -%]
+}
+.bookbag-share .fixed { min-width: 6em; }
+.bookbag-controls {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding: 0px 10px 0px 0px;
+    [% ELSE -%]
+    float: left;
+    padding: 0px 0px 0px 10px;
+    [% END -%]
+}
+.bookbag-specific td.list_checkbox {
+    [% IF rtl == 't' -%]
+    padding-right: 10px !important;
+    [% ELSE -%]
+    padding-left: 10px !important;
+    [% END -%]
+}
+.bookbag-specific td.list_entry {
+    min-width: 10em;
+    [% IF rtl == 't' -%]
+    padding-right: 5px !important;
+    [% ELSE -%]
+    padding-left: 5px !important;
+    [% END -%]
+}
+.bookbag-specific td.list_actions {
+    white-space: nowrap !important;
+}
+.bookbag-paginator-selected { color: [% css_colors.text_alert %]; }
+
+.list_is_empty {
+    padding: 8px 0px 6px 0px;
+    width: 100%;
+    border: 0;
+    font-size: [% css_fonts.size_bigger %];
+    text-align: center;
+    font-style: italic;
+}
+.save-notes { padding-bottom: 1.5ex; }
+
+.nonbreaking-wrapper {
+    display: inline-block;
+}
+
+/* Moved from semiauto.css */
+.adv_global_input_container {
+    border-bottom: none;
+    clear: both;
+}
+.opac-auto-013 {
+    border-bottom: none;
+    *height: 0px;
+}
+.adv_global_filter_sort {
+    border: none;
+    width: 100%;
+}
+.clear-both { clear: both; }
+.common-no-pad {
+    clear: both;
+    height: 0px;
+    margin: 0px;
+    padding: 0px;
+}
+.common-full-pad {
+    clear: both;
+    height: 15px;
+}
+.opac-alert { color: [% css_colors.text_alert %]; }
+
+.float-left {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float: left;
+    [% END -%]
+}
+.float-right {
+    [% IF rtl == 't' -%]
+    float: left;
+    [% ELSE -%]
+    float: right;
+    [% END -%]
+}
+
+.saved-searches-header { width: 100%; font-weight: bold; font-size: [% css_fonts.size_bigger %]; }
+.saved-searches-header .button {
+    [% IF rtl == 't' -%]
+    float: left;
+    [% ELSE -%]
+    float: right;
+    width: 28px;
+    [% END -%]
+}
+.saved-searches-header .text {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding-left: 1em;
+    [% ELSE -%]
+    float: left;
+    padding-right: 1em;
+    [% END -%]
+    margin: 0.5ex 0;
+}
+.saved-searches-header {font-weight: bold; font-size: [% css_fonts.size_bigger %]; }
+.saved-searches { border-bottom: 1px solid [% css_colors.accent_medium %]; padding-right: 1em; }
+#staff-saved-search { /* wraps .saved-searches-header and .saved-searches on the record page */
+    [% IF rtl == 't' -%]
+    border-left: 1px solid [% css_colors.accent_darker %];
+    [% ELSE -%]
+    border-right: 1px solid [% css_colors.accent_darker %];
+    [% END -%]
+}
+.result_item_circulated {
+    padding-top: 4px;
+}
+
+.result_item_circulated span {
+    position: relative;
+    top:-3px;
+    [% IF rtl == 't' -%]
+    right: 3px;
+    [% ELSE -%]
+    left:3px;
+    [% END -%]
+}
+
+#search-only-bookbag-container { margin: 2ex 0; font-weight: bold; }
+#result-bookbag-heading { text-align: center; margin: 2ex; }
+
+.result-bookbag-name { font-size: [% css_fonts.size_bigger %]; font-weight: bold; }
+.result-bookbag-description { font-size: [% css_fonts.size_bigger %]; font-style: italic; }
+.result-bookbag-item-note { font-style: italic; }
+.lowhits-bookbag-name { font-weight: bold; }
+.oils_AS { font-weight: bold; color: [% css_colors.text_match %]; }
+.oils_AS_match_term {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+    color: [% css_colors.text %];
+}
+.oils_AS_match_field {
+    font-size: [% css_fonts.size_smallest %]; padding: 0.65em 0;
+    [% IF rtl == 't' -%]
+    text-align: left;
+    [% ELSE -%]
+    text-align: right;
+    [% END -%]
+    color: [% css_colors.accent_medium %];
+}
+table.result_holdings_table {
+    margin-top: 1em;
+    margin-bottom: 1em;
+}
+table.result_holdings_table thead tr {
+    background-color: [% css_colors.table_heading %];
+}
+table.result_holdings_table thead tr th {
+    font-weight: bold;
+}
+span.preflib {
+    margin: 0 2em 0 2em;
+}
+a.preflib_change {
+  vertical-align: super;
+  font-size: [% css_fonts.size_smaller %];
+  line-height: normal;
+  text-decoration: none;
+}
+.rdetail-holding-group {
+    [% IF rtl == 't' -%]
+    margin-right: 1.5em;
+    [% ELSE -%]
+    margin-left: 1.5em;
+    [% END -%]
+}
+.rdetail-holding-group span {
+    [% IF rtl == 't' -%]
+    margin-right: 1.5em;
+    [% ELSE -%]
+    margin-left: 1.5em;
+    [% END -%]
+}
+.rdetail-holding-group .paging {
+    [% IF rtl == 't' -%]
+    margin-right: 1.5em;
+    [% ELSE -%]
+    margin-left: 1.5em;
+    [% END -%]
+}
+#rdetail_deleted_exp {
+    font-weight: bold;
+    padding: 1em;
+    margin: 1em;
+    border: thick solid [% css_colors.border_alert %];
+}
+
+#ac_tab_wrapper { width : 100%; }
+.ac_tab {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding-left: 10px;
+    [% ELSE -%]
+    float: left;
+    padding-right: 10px;
+    [% END -%]
+    font-size: [% css_fonts.size_big %];
+    padding: 5px;
+    border: 1px solid [% css_colors.primary_offset %];
+}
+.ac_tab_selected { background-color: [% css_colors.primary_offset %]; }
+.ac_tab_selected a { color: [% css_colors.text_invert %]; }
+#ac_content { clear: both; width: 100%; margin-top: 10px; }
+
+/* Popmenu styles used for making css menus. */
+.popmenu {
+    margin: 0;
+    padding: 0;
+}
+.popmenu li {
+    list-style: none;
+}
+.popmenu li a {
+    display: block;
+    padding: 3px 5px;
+}
+.popmenu li ul {
+    display: none;
+    width: 10em; /* Width to help Opera out */
+    background-color: [% css_colors.primary %];
+}
+.popmenu li:hover ul {
+    display: block;
+    position: absolute;
+    margin: 0;
+    padding: 0;
+    border-color: [% css_colors.border_dark %];
+    border-width: 1px;
+    border-style: solid;
+}
+.popmenu li:hover li {
+    float: none;
+}
+.popmenu li:hover li a {
+    background-color: [% css_colors.primary %];
+    color: [% css_colors.accent_ultralight %];
+}
+.popmenu li li a:hover {
+    background-color: [% css_colors.accent_ultralight %];
+    color: [% css_colors.primary %];
+}
+/* Styles for the basket entry. */
+.popmenu li:hover li[class~="temporary"] a {
+    background-color: [% css_colors.primary %];
+    color: [% css_colors.accent_ultralight %];
+}
+.popmenu li li[class~="temporary"] a:hover {
+    background-color: [% css_colors.accent_ultralight %];
+    color: [% css_colors.primary %];
+}
+/* Styles for the default list entry. */
+.popmenu li:hover li[class~="default"] a {
+    background-color: [% css_colors.primary %];
+    color: [% css_colors.accent_ultralight %];
+}
+.popmenu li li[class~="default"] a:hover {
+    background-color: [% css_colors.accent_ultralight %];
+    color: [% css_colors.primary %];
+}
+/* Styles for the new list entry. */
+.popmenu li:hover li[class~="new"] a {
+    background-color: [% css_colors.primary %];
+    color: [% css_colors.accent_ultralight %];
+}
+.popmenu li li[class~="new"] a:hover {
+    background-color: [% css_colors.accent_ultralight %];
+    color: [% css_colors.primary %];
+}
+/* Style to add a divider on the menu. */
+.popmenu li li[class~="divider"] {
+    border-bottom-width: 1px;
+    border-bottom-color: [% css_colors.border_dark %];
+    border-bottom-style: solid;
+}
+
+
+
+
+#patron_usr_barcode_not_found {
+    font-weight: bold; color: [% css_colors.text_alert %];
+}
+
+.record_title {
+    font-weight: bold;
+}
+
+.record_author {
+    font-style: italic;
+}
+
+.password_message {
+    padding-top: 1em;
+    padding-bottom: 0.5em;
+    font-style: italic;
+}
+
+#maintenance_message {
+    padding: 5px;
+    width: 100%;
+    background-color: [% css_colors.text_alert %];
+    color: [% css_colors.text_invert %];
+    text-align: center;
+}
+
+#search-box > span {
+    margin: 0 1em;
+}
+.browse-error {
+    font-weight: bold;
+    font-color: #c00;
+}
+.browse-result-sources, .browse-result-authority-bib-links {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    [% ELSE -%]
+    margin-left: 1em;
+    [% END -%]
+}
+.browse-result-best-match {
+    font-weight: bold;
+}
+.browse-pager {
+    margin: 2ex 0;
+}
+.browse-result-list {
+    padding-bottom: 0.5ex;
+}
+.browse-shortcuts {
+    font-size: [% css_fonts.size_bigger %];
+}
+.browse-result-authority-field-name {
+    font-style: italic;
+    [% IF rtl == 't' -%]
+    margin-left: 1em;
+    [% ELSE -%]
+    margin-right: 1em;
+    [% END -%]
+}
+.browse-leading-article-warning {
+    font-style: italic;
+    font-size: [% css_fonts.size_big %];
+}
+.browse-public-general-note {
+    font-size: [% css_fonts.size_big %];
+}
+.browse-public-general-note-label { }
+.browse-public-general-note-institution {
+    font-style: normal;
+    font-weight: bold;
+}
+.browse-public-general-note-body {
+    font-style: italic;
+}
+
+.bib_peer_type {
+    font-weight: bold;
+}
+
+#main-content-register {
+    [% IF rtl == 't' -%]
+    margin-right: 40px;
+    [% ELSE -%]
+    margin-left: 40px;
+    [% END -%]
+    font-size: [% css_fonts.size_bigger %];
+}
+
+#main-content-register table {
+    padding: 20px;
+    margin-top: 18px;
+    border-collapse: collapse;
+}
+
+#main-content-register td {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+}
+
+#main-content-register td:not(:first-child) {
+    [% IF rtl == 't' -%]
+    padding-right: 20px;
+    [% ELSE -%]
+    padding-left: 20px;
+    [% END -%]
+}
+
+.patron-reg-invalid {
+    font-weight: bold;
+    color: red;
+    [% IF rtl == 't' -%]
+    padding-left: 10px;
+    [% ELSE -%]
+    padding-right: 10px;
+    [% END -%]
+}
+
+.result_footer_nav1 {
+    clear: both;
+}
+
+.small_view_only, #filter_hits, #refine_hits, #return_to_hits {
+    display: none;
+}
+
+.rdetail_authors_div {
+    margin-bottom: 1em;
+}
+
+#search_query_label, #search_qtype_label, #search_itype_label, #search_locg_label {
+    white-space: nowrap;
+    display: inline-block;
+}
+
+.result_table_title_cell {
+    padding-top: 4px;
+    padding-bottom: 4px;
+}
+
+.record_title {
+    font-size: [% css_fonts.size_bigger %];
+}
+
+/* styling for sms text call number */
+.sms_text pre {
+    font-family: Arial, Helvetica, sans-serif;
+    font-size: [% css_fonts.size_medium %];
+    background-color: [% css_colors.accent_lightest %];
+    padding: .5%;
+    /* Allow text to wrap */
+    white-space: pre-wrap;       /* css-3 */
+    white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
+    white-space: -pre-wrap;      /* Opera 4-6 */
+    white-space: -o-pre-wrap;    /* Opera 7 */
+    word-wrap: break-word;       /* Internet Explorer 5.5+ */
+}
+
+.mobile_view {
+   display:none;
+}
+
+/* patron message center */
+#myopac_message_tbody {
+    vertical-align: top;
+}
+.myopac_message_message {
+    white-space: pre-wrap;
+}
+
+#browse-controls {
+    text-align: center;
+}
+
+.browse-pager-spinner {
+    display: inline-block;
+    height: 16px;
+    width: 16px;
+}
+
+/* override a tiny bootstrap alignment issue */
+.form-check-input {
+    margin-top: .2rem;
+}
+
+@media only screen and (min-width: 992px) {
+    .nav-fr{
+        float: right;
+    }
+    .nav-fl{
+        float: left;
+    }
+    #nav-divide{
+        display:none !important;
+    }
+}
+
+@media only screen and (max-width: 767px) {
+    .search_box_wrapper {
+        padding-left: 0;
+    }
+    
+}
+
+@media only screen and (max-width: 800px) {
+    .adv_options{
+        width: 100% !important;
+    }
+    .facet_sidebar_hidden, .result_block_hidden {
+        display: none;
+    }
+    .facet_sidebar_visible, .result_block_visible {
+        display: inline ! important;
+    }
+    #acct_select, #acct_prefs_select {
+        display: inline-block;
+    }
+    #acct_tabs, #acct_prefs_tabs {
+         display:none;
+     }
+    .radio-parts-selection { width: 90%; }
+    #list_description, #list_create_name {
+        width: 300px;
+    }
+}
+
+@media only screen and (max-width: 600px) {
+    input, select {
+        font-size: [% css_fonts.size_big %];
+    }
+    span .nav_arrow_fix {
+        display: none;
+    }
+    #header {
+        padding: 0px;
+        margin: 0px;
+    }
+    #homesearch_main_logo img {
+        width:75%;
+    }
+    #format_selector {
+        display:none;
+    }
+    #your-acct-login {
+        padding: 0px;
+        padding-top: 5px;
+    }
+    #your-acct-login a {
+        margin: 0px;
+        padding: 5px;
+    }
+    #topnav_logo {
+        margin: 0;
+    }
+    #topnav_logo img {
+        width: 200px;
+    }
+
+    #gold-links-holder {
+        display: none;
+    }
+    #simple-detail-view-links {
+        display: none;
+    }
+    #acct_tabs a, #acct_fines_tabs a {
+       [% IF rtl == 't' -%]
+       border-radius: 6px 0px 0px 6px;
+       margin: 0px 0px 0px 5px;
+       [% ELSE -%]
+       border-radius: 6px 6px 0px 0px;
+       margin: 0px 5px 0px 0px;
+       [% END -%]
+       padding: 2px 4px 3px 4px;
+       font-size: [% css_fonts.size_base %];
+    }
+    .bookbag-controls-title-block {
+        [% IF rtl == 't' -%]
+        clear:right;
+        [% ELSE -%]
+        clear:left;
+        [% END -%]
+        width:90%;
+    }
+    .bookbag-controls-button-block {
+        [% IF rtl == 't' -%]
+        clear:right;
+        [% ELSE -%]
+        clear:left;
+        [% END -%]
+        width;90%;
+    }
+    .bookbag-specific {
+        [% IF rtl == 't' -%]
+        margin-right: 0px;
+        [% ELSE -%]
+        margin-left: 0px;
+        [% END -%]
+    }
+    .bookbag-specific div.sort {
+        [% IF rtl == 't' -%]
+        float: right;
+        text-align: right;
+        [% ELSE -%]
+        float: left;
+        text-align: left;
+        [% END -%]
+        width: 95%;
+        margin: 5px 0px 5px 0px;
+        border: 1px solid [% css_colors.accent_light %];
+        padding:5px;
+    }
+    .bookbag-specific div.meta {
+        [% IF rtl == 't' -%]
+        float: right;
+        margin-right:0px;
+        text-align: right;
+        [% ELSE -%]
+        float: left;
+        margin-left:0px;
+        text-align: left;
+        [% END -%]
+        width: 95%;
+        margin-bottom:5px;
+        padding:5px;
+    }
+/*
+    #bbag-edit-name {
+        [% IF rtl == 't' -%]
+        float: right;
+        [% ELSE -%]
+        float: left;
+        [% END -%]
+        width: 220px;
+    }
+    #bbag-edit-description {
+        width: 220px;
+        margin-top:5px;
+    }
+*/
+    .bbag-content {
+        padding:5px;
+        border:1px solid [% css_colors.accent_light %];
+    }
+    .bbag-action {
+        [% IF rtl == 't' -%]
+        margin-right:0px;
+        [% ELSE -%]
+        margin-left:0px;
+        [% END -%]
+        margin-bottom:5px;
+    }
+    .bbag-action-field {
+        width:230px;
+    }
+    .bookbag-specific div.sort select {
+        width:180px;
+    }
+    .bookbag-specific tr {
+        display: block;
+        border-bottom: 1px solid [% css_colors.border_standard %];
+    }
+    .bookbag-specific td.list_checkbox {
+        [% IF rtl == 't' -%]
+        padding-right: 0px !important;
+        [% ELSE -%]
+        padding-left: 0px !important;
+        [% END -%]
+    }
+    .bookbag-specific td.list_entry {
+        display: inline-block;
+        min-width: 5em;
+        [% IF rtl == 't' -%]
+        padding-right: 40% !important;
+        [% ELSE -%]
+        padding-left: 40% !important;
+        [% END -%]
+    }
+    .bookbag-specific td.list_entry:before {
+        content: attr(data-label);
+        position: absolute;
+        [% IF rtl == 't' -%]
+        right: 10px;
+        [% ELSE -%]
+        left: 10px;
+        [% END -%]
+    }
+    .bbag-navigate-list {
+        display: none;
+    }
+    .bbag-navigate-list-pages {
+        [% IF rtl == 't' -%]
+        text-align:left;
+        float:left;
+        [% ELSE -%]
+        text-align:right;
+        float:right;
+        [% END -%]
+    }
+    #dash_wrapper div {
+        background-color: transparent;
+        padding: 0px;
+    }
+    #dash_wrapper {
+        position: static;
+        top: auto;
+    }
+    #dash_wrapper .opac-button {
+        top: 0px;
+    }
+    .small_view_only, #filter_hits {
+        display: inline !important;
+    }
+    #dash_identity a {
+        [% IF rtl == 't' -%]
+        float:right;
+        [% ELSE -%]
+        float:left;
+        [% END -%]
+    }
+
+    #holds_box form blockquote {
+        [% IF rtl == 't' -%]
+        margin-right: 10px;
+        margin-left: 2px;
+        [% ELSE -%]
+        margin-left: 10px;
+        margin-right: 2px;
+        [% END -%]
+    }
+    #holds_box form blockquote select {
+        width: 100%;
+    }
+    #myopac_sum_fines_placehold {
+        display:none;
+    }
+    #myopac_sum_fines {
+        display: none;
+    }
+    #list_description, #list_create_name {
+        width: 170px;
+    }
+    .results_header_lbl {
+        display: none;
+    }
+    .results_header_nav1 span.h1 {
+        display: none;
+    }
+    .preflib {
+        display: none;
+    }
+    .start_end_links_span {
+        display: block;
+    }
+    .invisible {
+        display: none;
+    }
+    .result_table_pic_header {
+        [% IF rtl == 't' -%]
+        padding-right: 0px !important;
+        padding-left: 5px;
+        [% ELSE -%]
+        padding-left: 0px !important;
+        padding-right: 5px;
+        [% END -%]
+        width: 0px !important;
+        margin: 0px;
+    }
+    .result_table_pic {
+        width: 55px;
+        padding: 0px;
+        margin: 0px;
+    }
+    tr[name=results_isbn_tr], tr[name=results_phys_desc_tr], tr[name=results_pub_tr] strong, .result_count {
+         display: none;
+    }
+    tr.result_table_title_cell[name=bib_cn_list] .result_holdings_table th:nth-child(4),
+    tr.result_table_title_cell[name=bib_cn_list] .result_holdings_table td:nth-child(4) {
+        display:none;
+    }
+    #results_header_bar {
+        background-color: inherit;
+    }
+    .results_header_btns a {
+        margin: 0.3em;
+    }
+    .adv_filter_results_hide {
+        display: none;
+    }
+    .adv_filter_results_show {
+        display: block;
+    }
+    .adv_filter_results_block_label {
+        display: block;
+    }
+    .adv_filter_results_group_wrapper {
+        display: block;
+    }
+    #main-content {
+        margin: 0 1px;
+    }
+    #rdetails_status thead {
+        display: none;
+    }
+    #rdetails_status tr {
+    display: block;
+    margin-top: 3px;
+    }
+    #rdetails_status td {
+    display: block;
+    padding: 1px;
+    }
+    .copy_details_row {
+    background-color: [% css_colors.accent_lightest %];
+    }
+    .copy_details_offers_row {
+    background-color: [% css_colors.accent_lightest %];
+    }
+    select#pickup_lib.search-wrapper-locg {
+        width: 100%;
+    }
+    #search-wrapper #search-box {
+        width: 85%;
+        padding-top: 5px;
+    }
+    #main-content-home {
+        padding: 0px;
+        margin: 0px;
+    }
+    /* Make use of full width in mobile mode */
+    .facet_box_wrapper .box_wrapper .box,
+    .facet_template .facet,
+    .facet_box_temp {
+        width: inherit;
+    }
+    .facet_template .count {
+        [% IF rtl == 't' -%]
+        padding-right: 1em;
+        [% ELSE -%]
+        padding-left: 1em;
+        [% END -%]
+    }
+    #facet_sidebar {
+        margin-top: 0.5em;
+    }
+    #adv_search_parent {
+        font-size: [% css_fonts.size_smaller %];
+    }
+    #adv_search_filters {
+        position: relative;
+        width: 300px;
+    }
+    #format_actions {
+        [% IF rtl == 't' -%]
+        float: right;
+        [% ELSE -%]
+        float: left;
+        [% END -%]
+    }
+    .rdetail_aux_utils {
+        padding: 0px;
+        border: none;
+    }
+    .result_metadata {
+        width: inherit;
+    }
+    div#rdetail_actions_div {
+        float: none;
+    }
+    h2.rdetail_uris {
+        clear: both;
+    }
+    #metarecord_population {
+        overflow: hidden;
+        width: 100%;
+    }
+    .metarecord_population_span_link {
+    }
+    .metarecord_population_item_lang {
+        float: none;
+    }
+    .search_catalog_lbl {
+        [% IF rtl == 't' -%]
+    margin-right: 0;
+        [% ELSE -%]
+    margin-left: 0;
+        [% END -%]
+    white-space: nowrap;
+    }
+    .adv_search_catalog_lbl {
+        margin-top: 0;
+    white-space: nowrap;
+    }
+    .browse_the_catalog_lbl {
+        white-space: nowrap;
+    }
+    .mobile_hide {
+    display: none;
+    }
+    #dash_user {
+        display: block;
+        padding: 0.5em;
+        font-size: 18px;
+        text-align: center;
+    }
+    .dash_divider {
+    display: none;
+    }
+    .dash_account_buttons {
+        display: block;
+    }
+    .searchbar { line-height: 1.5em; }
+    #browse-controls { line-height: 1.5em; }
+    #search_query_label, #search_qtype_label, #search_itype_label, #search_locg_label {
+        display: block;
+    }
+    .bookshelf td {
+    display: block;
+    width: 100%;
+    }
+    .bookshelf table thead tr {
+    display: block;
+    }
+    #lowhits_help { width: inherit; }
+    #adv_search_tabs a{
+        font-size: [% css_fonts.size_small %];
+        margin: 2px 2px 0px 2px;
+        padding: 2px 2px 5px 2px;
+        [% IF rtl == 't' -%]
+        border-radius: 7px 0px 0px 7px;
+        [% ELSE -%]
+        border-radius: 7px 7px 0px 0px;
+        [% END -%]
+    }
+    #adv_global_tbody td {
+        border-bottom: thin solid [% css_colors.accent_light %];
+    }
+    #adv_global_addrow td {
+        border-bottom: none;
+    }
+        /* Force table to not be like tables anymore */
+        table#acct_checked_main_header thead tr th, table#acct_holds_main_header thead tr th, table#acct_checked_hist_header thead tr th, table#acct_holds_hist_header thead tr th, table#ebook_circs_main_table thead tr th, table#ebook_holds_main_table thead tr th {
+                display: none;
+        }
+        table#acct_checked_main_header tbody tr td, table#acct_holds_main_header tbody tr td, table#acct_checked_hist_header tbody tr td, table#acct_holds_hist_header tbody tr td, table#ebook_circs_main_table tbody tr td, table#ebook_holds_main_table tbody tr td {
+                display: block;
+        }
+
+        /* Hide table headers (but not display: none;, for accessibility) */
+       /* thead tr {
+                position: absolute;
+                top: -9999px;
+                [% IF rtl == 't' -%]
+                right: -9999px;
+                [% ELSE -%]
+                left: -9999px;
+                [% END -%]
+        }*/
+
+        table#acct_checked_main_header, table#acct_holds_main_header, table#acct_checked_hist_header, table#acct_holds_hist_header, table#ebook_circs_main_table, table#ebook_holds_main_table {
+                width: 90%;
+        }
+
+        table#acct_checked_main_header tr, table#acct_holds_main_header tr, table#acct_checked_hist_header tr { border: 1px solid #ddd; }
+
+        /* Holds history gets large white border to mimic header cell on other
+           account screens that provide visual cue for next title. We should do
+           the same for ebook tables too since we have no actions on those
+           tables. If actions get added, we should move those tables out of
+           here. */
+
+        table#ebook_circs_main_table tr, table#ebook_holds_main_table tr { border-top: 25px solid #fff; }
+        table#acct_holds_hist_header tr{ border-top: 2px solid #bbb; }
+
+        table#acct_checked_main_header td, table#acct_holds_main_header td, table#acct_checked_hist_header td, table#acct_holds_hist_header td, table#ebook_circs_main_table td, table#ebook_holds_main_table td {
+                /* Behave  like a "row" */
+                border: none;
+                border-bottom: 1px solid #eee;
+                position: relative;
+                [% IF rtl == 't' -%]
+                padding-right: 40%;
+                [% ELSE -%]
+                padding-left: 40%;
+                [% END -%]
+        }
+
+         table#acct_checked_main_header td:before, table#acct_holds_main_header td:before, table#acct_checked_hist_header td:before, table#acct_holds_hist_header td:before, table#ebook_circs_main_table td:before, table#ebook_holds_main_table td:before {
+                /* Now like a table header */
+                position: absolute;
+                /* Top/left values mimic padding */
+                top: 2px;
+                width: 40%;
+                [% IF rtl == 't' -%]
+                right: 2px;
+                padding-left: 10px;
+                [% ELSE -%]
+                left: 2px;
+                padding-right: 10px;
+                [% END -%]
+                white-space: nowrap;
+        }
+
+        table#acct_checked_main_header td:nth-of-type(1) { border-top: 5px solid #aaa; padding-top: 15px; background-color: #fff;}
+        table#acct_checked_main_header td:nth-of-type(2):before { content: "[% l('Title') %]";}
+        table#acct_checked_main_header td:nth-of-type(3):before { content: "[% l('Author') %]"; }
+        table#acct_checked_main_header td:nth-of-type(4):before { content: "[% l('Renewals Left') %]"; }
+        table#acct_checked_main_header td:nth-of-type(5):before { content: "[% l('Due Date') %]"; }
+        table#acct_checked_main_header td:nth-of-type(6):before { content: "[% l('Barcode') %]"; }
+        table#acct_checked_main_header td:nth-of-type(7):before { content: "[% l('Call number') %]"; }
+
+     table#acct_checked_hist_header td:nth-of-type(1) { border-top: 5px solid #aaa; padding-top: 15px; background-color: #fff;}
+        table#acct_checked_hist_header td:nth-of-type(2):before { content: "[% l('Title') %]";}
+        table#acct_checked_hist_header td:nth-of-type(3):before { content: "[% l('Author') %]"; }
+        table#acct_checked_hist_header td:nth-of-type(4):before { content: "[% l('Checkout Date') %]"; }
+        table#acct_checked_hist_header td:nth-of-type(5):before { content: "[% l('Due Date') %]"; }
+        table#acct_checked_hist_header td:nth-of-type(6):before { content: "[% l('Date Returned') %]"; }
+        table#acct_checked_hist_header td:nth-of-type(7):before { content: "[% l('Barcode') %]"; }
+        table#acct_checked_hist_header td:nth-of-type(8):before { content: "[% l('Call number') %]"; }
+
+        table#acct_holds_main_header td:nth-of-type(1) { border-top: 5px solid #aaa; padding-top: 15px; background-color: #fff;}
+        table#acct_holds_main_header td:nth-of-type(2):before { content: "[% l('Title') %]";}
+        table#acct_holds_main_header td:nth-of-type(3):before { content: "[% l('Author') %]"; }
+        table#acct_holds_main_header td:nth-of-type(4):before { content: "[% l('Format') %]"; }
+        table#acct_holds_main_header td:nth-of-type(5):before { content: "[% l('Pickup Location') %]"; }
+        table#acct_holds_main_header td:nth-of-type(6):before { content: "[% l('Cancel on') %]"; }
+        table#acct_holds_main_header td:nth-of-type(7):before { content: "[% l('Status') %]"; }
+        table#acct_holds_main_header td.hold_notes:before { content: "[% l('Notes') %]"; }
+
+        table#acct_holds_hist_header td:nth-of-type(1):before { content: "[% l('Title') %]";}
+        table#acct_holds_hist_header td:nth-of-type(2):before { content: "[% l('Author') %]"; }
+        table#acct_holds_hist_header td:nth-of-type(3):before { content: "[% l('Format') %]"; }
+        table#acct_holds_hist_header td:nth-of-type(4):before { content: "[% l('Pickup Location') %]"; }
+        table#acct_holds_hist_header td:nth-of-type(8):before { content: "[% l('Status') %]"; }
+
+        table#ebook_circs_main_table td:nth-of-type(1):before { content: "[% l('Title') %]"; }
+        table#ebook_circs_main_table td:nth-of-type(2):before { content: "[% l('Author') %]"; }
+        table#ebook_circs_main_table td:nth-of-type(3):before { content: "[% l('Due Date') %]"; }
+        table#ebook_circs_main_table td:nth-of-type(4):before { content: "[% l('Actions') %]"; }
+
+        table#ebook_holds_main_table td:nth-of-type(1):before { content: "[% l('Title') %]"; }
+        table#ebook_holds_main_table td:nth-of-type(2):before { content: "[% l('Author') %]"; }
+        table#ebook_holds_main_table td:nth-of-type(3):before { content: "[% l('Due Date') %]"; }
+        table#ebook_holds_main_table td:nth-of-type(4):before { content: "[% l('Actions') %]"; }
+
+
+
+       /*Want to see these in mobile ONLY */
+       .mobile_view{
+          display:block;
+       }
+
+       .mobile_search_lbl_clr{
+          color:[% css_colors.mobile_header_text %];
+       }
+}
+
+
+/*
+For text which is visible only to screen readers.
+Borrowed from http://getbootstrap.com/css/#helper-classes-screen-readers
+See also http://webaim.org/techniques/css/invisiblecontent/
+*/
+.sr-only {
+    position: absolute;
+    width: 1px;
+    height: 1px;
+    padding: 0;
+    margin: -1px;
+    overflow: hidden;
+    clip: rect(0, 0, 0, 0);
+    border: 0;
+}
+
+/* Make added rows in Expert Search have bold labels like the initial row */
+label[for*=expert_]
+{
+    font-weight: bold;
+}
+
+.sort_deemphasize {
+    font-weight: lighter;
+    font-size: 70%;
+}
+
+#results-page-depth-hint {
+    text-align: center;
+    font-style: italic;
+}
+
+#clear-history-confirm {
+  font-weight: bold;
+  color: [% css_colors.text_badnews %];
+  padding: 10px;
+}
+
+/*Inline rules from other templates files*/
+
+.td-left{
+    [% IF rtl == 't' -%]
+    text-align:right;
+    [% ELSE -%]
+    text-align:left;
+    [% END -%]
+    width:100%;
+}
+.td-search-left{
+    [% IF rtl == 't' -%]
+    text-align:right;
+    [% ELSE -%]
+    text-align:left;
+    [% END -%]
+}
+#myopac_summary_div{padding:0px;}
+.div-left{
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float: left;
+    [% END -%]
+}
+.td-right{
+    [% IF rtl == 't' -%]
+    text-align:left;
+    [% ELSE -%]
+    text-align:right;
+    [% END -%]
+}
+.login-form-left{
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 40px;
+    [% ELSE -%]
+    float: left;
+    margin-right: 40px;
+    [% END -%]
+    padding-bottom: 10px;
+}
+.hold-div{
+    [% IF rtl == 't' -%]
+    padding-right: 10px;
+    [% ELSE -%]
+    padding-left: 10px;
+    [% END -%]
+    padding-bottom: 15px;
+}
+.hold-span{font-weight: bold;}
+.padding-left-6{
+    [% IF rtl == 't' -%]
+    padding-right: 6px;
+    [% ELSE -%]
+    padding-left: 6px;
+    [% END -%]
+}
+.padding-left-10{
+    [% IF rtl == 't' -%]
+    padding-right:10px;
+    [% ELSE -%]
+    padding-left:10px;
+    [% END -%]
+}
+.padding-left-5{
+    [% IF rtl == 't' -%]
+    padding-right: 5px;
+    [% ELSE -%]
+    padding-left: 5px;
+    [% END -%]
+}
+
+/* Rules from metarecord_hold_filters.tt2 */
+
+.metarecord_filters{
+      padding: 5px;
+      margin-top: 5px;
+      border-bottom: 1px solid #333;
+      border-top: 1px solid #333; }
+.metarecord_filter_container{
+    [% IF rtl == 't' -%]
+    float : right;
+    margin-left: 10px;
+    [% ELSE -%]
+    float : left;
+    margin-right: 10px;
+    [% END -%]
+}
+.metarecord_filter_container select{padding: 2px;width: 13em; /* consistent w/ adv search selectors */}
+.metarecord_filter_header{padding-bottom: 5px;}
+
+/* Toggled items. */
+/* A block that is initially hidden and shown by clicking an anchor. */
+[id^="toggled-block-"]{
+    display: none;
+}
+[id^="toggled-block-"]:target{
+    display: block;
+}
+/* Inline text that is initially hidden and shown by clicking an anchor. Useful on a span. */
+[id^="toggled-inline-"]{
+    display: none;
+}
+[id^="toggled-inline-"]:target{
+    display: inline;
+}
+
+.oils_SH {
+    font-weight: bolder;
+    background-color: #99ff99;
+}
+
+.oils_SH.identifier {
+    font-weight: bolder;
+    background-color: #42b0f4;
+}
+.hold_note_title { font-weight: bold; }
+
+/*
+#acct_checked_main_header td, #acct_holds_main_header td, #acct_fines_main_header td, #acct_fines_confirm_header td, #acct_fees_main_header td,#acct_checked_hist_header td, #acct_holds_hist_header td, #acct_list_header td, #acct_list_header_anon td, #temp_list_holds td, #acct_messages_main_header td, #ebook_circs_main_table td, #ebook_holds_main_table td {
+    background-color: [% css_colors.background %];
+    padding: 10px;
+     border: 1px solid #d3d3d3;
+}
+
+#acct_checked_main_header th, #acct_holds_main_header th, #acct_fines_main_header th, #acct_fines_confirm_header th, #acct_fees_main_header th, #acct_checked_hist_header th, #acct_holds_hist_header th, #acct_list_header th, #acct_list_header_anon th, #temp_list_holds th, #acct_messages_main_header th, #ebook_holds_main_table th {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+    padding: 0px 10px 0px 10px;
+}
+#acct_checked_main_header, #acct_holds_main_header, #acct_fines_main_header, #acct_checked_hist_header, #acct_holds_hist_header, #acct_list_header, #acct_list_header_anon, #temp_list_holds, #acct_messages_main_header, #ebook_circs_main_table, #ebook_holds_main_table {
+    border-collapse: collapse;
+}
+
+#hold_editor h1 { font-size: [% css_fonts.size_bigger %]; font-weight: bold; }
+#hold_editor h2 { font-size: [% css_fonts.size_big %]; font-weight: normal; text-indent: 2em; font-style: italic; }
+#hold_editor h1, #hold_editor h2 { margin: 2px 0; }
+#hold_editor_table { background-color: [% css_colors.accent_lighter %]; padding: 0.5em; }
+#hold_editor_table th {
+    [% IF rtl == 't' -%]
+    text-align: left;
+    padding-left: 1em;
+    [% ELSE -%]
+    text-align: right;
+    padding-right: 1em;
+    [% END -%]
+}
+#hold_editor_table td { padding: 0.25em 0; }
+*/
+
+
+/*
+  Carousels
+*/
+
+.carousel {
+    width: 80%;
+    margin: 0 auto;
+}
+.carousel-title {
+    font-size: 150%;
+    font-weight: bold;
+    text-align: center;
+}
+
+.fas, .far{
+    margin: 0px 3px;
+}
+.carousel-entry {
+    max-width: 150px;
+}
+
+/* Truncate titles within carousel to 4 lines */
+.carousel-entry div.titleText {
+    display: -webkit-box;
+       -webkit-line-clamp: 4;
+       -webkit-box-orient: vertical;
+       overflow: hidden;
+}
+
+.carousel-entry-image {
+    width: 100%;
+    height: auto;
+}
+.carousel .glide__arrow {
+    color: [% css_colors.button_text %];
+    font-weight: bold !important;
+    text-decoration: none !important;
+    cursor: pointer;
+    border-radius: 5px;
+    border: 1px solid [% css_colors.primary %];
+    background-color:  [% css_colors.primary_fade %];
+    margin: 0.5em;
+    padding: 0.3em;
+    display: inline-block;
+}
+.carousel .glide__arrow--right {
+    right: -6em;
+}
+.carousel .glide__arrow--left {
+    left: -6em;
+}
+
+.search-filter{
+    display: inline;
+    white-space: nowrap;
+}
+
+
+
+.search-option{
+    display: inline-block;
+    margin: 0px 10px;
+}
+
+
+#homeLogo{
+    filter: alpha(opacity=50);
+    background-color: #fff; /* Used if the image is unavailable */
+    height: 206px; /* You must set a specified height */
+    background-position: center; /* Center the image */
+    background-repeat: no-repeat; /* Do not repeat the image */
+    background-size: contain; /* Resize the background image to cover the entire container */
+    background-image: url("[% ctx.media_prefix %]/images/home-logo.png");
+
+}
+
+.navbar-dark .navbar-nav .nav-link{
+    color: #fff !important;
+}
+
+.nav-link.active {
+    color: #000;
+}
+
+.pref_table{
+    margin: 10px;
+}
+
+.checkCell{width:30px;}
+
+@media (min-width: 650px){
+.modal-dialog {
+    max-width: 600px !important;
+    }
+
+}
+
+.listTitleText{
+    width:33%;
+}
+
+.facet_box_wrapper .card-header{
+    background-color: [% css_colors.facets_back %];
+    color: [% css_colors.facets_text %];
+}
+.facet_box_wrapper .card-body {
+    padding: .5rem;
+}
+
+.vertMid {
+    position: relative;
+    top: 50%;
+    transform: translateY(-50%);
+}
+
+.sumNum{
+    margin-right:5px;
+}
+
+.my_nav .active{
+     background-color: #c8ffaf;
+}
+
+.my_nav a {
+    text-align:left !important;
+    border-radius: 0;
+}
+
+.my_nav .dropdown {
+    display: block;
+    width: 100%;
+}
+
+.my_nav .dropdown button {
+    border-radius: 0;
+}
+
+.my_nav .dropdown-toggle::after{
+    float: right;
+    margin: 5px 0 0 5px;
+}
+
+.dropdown-item:active {
+    background-color: #EDFFCC;
+}
+
+.my_nav .fas, .mynav .far{
+    min-width:20px;
+}
+
+.adv_options {
+    width: 50%;
+}
+
+.page-link {
+    color: [% css_colors.link %];
+}
+
+.page-item.active .page-link {
+    background-color: [% css_colors.link %];
+    border-color: [% css_colors.link %];
+}
+
+.btn-outline-primary {
+    border-color: [% css_colors.link %];
+    color: [% css_colors.link %];
+}
+
+.btn-outline-primary:hover {
+    color: [% css_colors.button_confirm_text %];
+    background-color: [% css_colors.button_confirm_hover %];
+    border-color: [% css_colors.button_confirm_border_hover %];
+}
+
+#rdetail_extras_div .card-header {
+    background-color: #16416F;
+}
+
+#rdetail_extras_div .card-header  a {
+    color: #FFF
+}
+
+#record_actions .btn {
+    text-align: left;
+}
+
+.alert-danger a:link,
+.alert-danger a:visited {
+    color: #424fa6;
+}
+
+.language_form button {
+    background:none;
+    border:none;
+    margin:0;
+    padding:0;
+    color:[% css_colors.footer_link %];
+}
+.language_form button:disabled {
+    color:[% css_colors.footer_link_disabled %];
+}
+.language_form ul{
+    list-style:none;
+}
+.language_form h6{
+    color:[% css_colors.footer_link %];
+        }
+.language_form{
+    float: right;
+padding: 15px;
+}
+
+.course-material-title-column {
+    width: 30%;
+}
+
+#course_material_table td, #course_material_table th {
+    padding: 4px;
+}
+
+.form-control {
+    border: 1px solid [% css_colors.border_standard %];
+}
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/myopac/holds_curbside.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/myopac/holds_curbside.tt2
new file mode 100644 (file)
index 0000000..db160cf
--- /dev/null
@@ -0,0 +1,202 @@
+[%  PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/misc_util.tt2";
+    PROCESS "opac/parts/hold_status.tt2";
+    PROCESS "opac/parts/hold_notify.tt2";
+    PROCESS "opac/parts/myopac/column_sort_support.tt2";
+    PROCESS "opac/parts/css/fonts.tt2";
+    WRAPPER "opac/parts/myopac/base.tt2";
+
+    myopac_page = "holds_curbside";
+    parent="holds";
+    limit = (ctx.holds_limit.defined) ? ctx.holds_limit : 0;
+    offset = (ctx.holds_offset.defined) ? ctx.holds_offset : 0;
+    count = (ctx.holds_ids.size.defined) ? ctx.holds_ids.size : 0;
+%]
+<p>
+Use the scheduler below to request or update your Curbside pickup appointment(s).
+<a href="https://www.cwmars.org/help/catalog-help/help-curbside-pickup#h.smw4bow2m30z" target="_blank" rel="noopener">Click here</a> or contact your Pickup Library if you need help.
+</p>
+<h3> [% l("Curbside Pickup Appointments") %]</h3>
+<div>
+    <div id='holds_main'>
+          <div class="row">
+            <div class="col-8">
+             [% IF offset != 0 %]<a href='[% mkurl('holds', {limit => limit,offset => (offset - limit)}) %]'
+              ><span class="np_nav_link classic_link btn btn-action">&#9668;[% l('Previous') %]</span></a> [% END %]
+
+             [% IF offset > 0 || count > limit; curpage = 0; WHILE curpage * limit < count; IF curpage * limit == offset; %]
+                  <span class="np_nav_link classic_link btn btn-action disabled">[% curpage + 1 %]</span>
+
+                    [%- ELSE %]
+                <a href='[% mkurl('holds', {limit => limit, offset => (curpage * limit)}) %]' class="np_nav_link classic_link btn btn-action">[% curpage + 1 %]</a>
+                    [%- END; curpage = curpage + 1; END; END %]
+                <span style="padding-left:5px;" class='error'>
+                    [%  IF ctx.hold_suspend_post_capture; l('One or more holds could not be suspended because the item is at (or en route to) the pickup library.'); END; %]
+                </span>
+
+                [% IF count > limit + offset %]<a href='[% mkurl('holds', {limit => limit, offset => (offset + limit)}) %]'
+                  ><span class="np_nav_link classic_link btn btn-action">[% l('Next') %]&#9658;</span></a>[% END %]
+            </div>
+          </div>
+
+        [% IF ctx.holds.size && ctx.holds.size < 1 %]
+        <div class="warning_box">[% l('No holds found.') %]</div>
+        [% ELSE %]
+    <div class="w-100">
+    [% FOR lib IN ctx.curbside_pickup_libs;
+
+        cs_slot = '';
+        cs_slot_id = '';
+        cs_date = '';
+        cs_time = '';
+        cs_notes = '';
+
+       cs_org = ctx.cs_org;
+        IF cs_org == lib;
+            cs_slot = ctx.cs_slot;
+            cs_slot_id = ctx.cs_slot_id;
+            cs_date = ctx.cs_date;
+            cs_time = ctx.cs_time;
+            cs_notes = ctx.cs_notes;
+        END;
+
+        appointment = ctx.curbside_appointments.$lib;
+        IF appointment;
+            cs_slot = appointment;
+            cs_slot_id = appointment.id;
+            IF appointment.slot; cs_date = date.format(ctx.parse_datetime(appointment.slot),'%F'); END;
+            IF appointment.slot; cs_time = date.format(ctx.parse_datetime(appointment.slot),'%T'); END;
+            cs_notes = appointment.notes;
+        END %]
+        <form class="egtr" method="POST">
+            <input type="hidden" name="action" value="curbside"/>
+            <input type="hidden" name="cs_slot_id" value="[% appointment.id %]"/>
+            <table class="table table-bordered miniTable curbsideApptTable w-100 my-3">
+                <thead>
+                    <th>[% l('Pickup Location') %]</th>
+                    <th>[% l('Date') %]</th>
+                    <th>[% l('Time') %]</th>
+                    <th>[% l('Arrival Notes') %]
+                        <a href="#" title="" data-toggle="tooltip" data-original-title="Vehicle Description, etc.">
+                            <i class="fas fa-question-circle" aria-hidden="true"></i>
+                        </a>
+                    </th>
+                    <th>[% l('Action') %]</th>
+                </thead>
+                <tbody><tr>
+            [% disable_me = 0 %]
+            [% no_patron_input = 0 %]
+            [% date_started_null = 0 %]
+            [% IF appointment && appointment.arrival; disable_me = 1; END %]
+            [% IF ctx.get_org_setting(lib, 'circ.curbside.disable_patron_input'); no_patron_input = 1; END %]
+            <td>
+                [% ctx.get_aou(lib).name | html %]<br/>
+                [% l('Phone:')%] [% ctx.get_aou(lib).phone | html %]
+                <input type="hidden" name="cs_org" value="[% lib %]"/>
+            </td>
+            <td>
+                [% IF !cs_date || ( date.format(cs_date _ ' 12:00:00', '%Y%m%d') < date.format(date.now, '%Y%m%d') ); cs_date = ''; tmp_cs_date = date.format(date.now, '%F'); date_started_null = 1; %]
+                [% ELSE; tmp_cs_date = cs_date; END %]
+                [% IF cs_date %]<input type="hidden" name="cs_date" value="[% cs_date | html %]"/>[% END %]
+                [% IF no_patron_input && date_started_null; %]&nbsp;
+                [% ELSE; %]<input type="date" name="cs_date" min="[% date.format(date.now, '%F') %]" value="[% tmp_cs_date | html %]" [% IF cs_date || no_patron_input %]disabled="disabled"[% END %]/>[% END %]
+            </td>
+            <td>
+                [% IF appointment || cs_date; # checking times %]
+                  [% current_date = cs_date %]
+                  [% IF date_started_null && no_patron_input %]&nbsp;
+                  [% ELSIF appointment || ctx.cs_times.$lib.$current_date.size; # show a select %]
+                    <select name="cs_time" [% IF disable_me || no_patron_input %]disabled="disabled"[% END %]>
+                      [% found_time = 0 %]
+                      [% FOR t IN ctx.cs_times.$lib.$current_date %]
+                        <option value="[% t.0 | html %]"
+                          [% IF cs_time == t.0; found_time=1 %] selected="selected"[% END %]
+                          [% IF t.1 <= 0 && cs_time != t.0 %] disabled="disabled"[% END %]>
+                            [% date.format(current_date _ ' ' _ t.0,'%l:%M %p') | html %]
+                        </option>
+                      [% END %]
+                      [% IF cs_time && !found_time %]
+                        <option value="[% cs_time | html %]" selected="selected">
+                          [% date.format(current_date _ ' ' _ cs_time,'%l:%M %p') | html %]
+                        </option>
+                      [% END %]
+                    </select>
+                  [% ELSE %] 
+                    [% l('No times available for selected date') %]
+                  [% END %]
+                [% ELSE %] 
+                  [% IF !no_patron_input; %][% l('Select a date') %][% END %]
+                [% END %]
+            </td>
+            <td>
+                [% IF cs_date; # show the notes box %]
+                <input type="text" name="cs_notes" value="[% cs_notes | html %]" [% IF no_patron_input || disable_me %]disabled="disabled"[% END %]/>
+                [% ELSE %] &nbsp;
+                [% END %]
+            </td>
+            <td>[%
+                disable_arrival_button = 1; # assume arrival is not yet allowed
+                IF appointment && appointment.slot;
+                    stime = date.format(ctx.parse_datetime(appointment.slot), '%s');
+                    now_time = date.format(date.now, '%s');
+                    IF now_time >= stime;
+                        disable_arrival_button = 0; # if 'now' is after the slot time, allow arrival
+                    END;
+                END %]
+                [% IF no_patron_input %]
+                    [% l('Please contact the library to schedule, change, or cancel your appointment.') %]
+                [% ELSIF appointment.staged && !appointment.arrival; # relevant submit action %]
+                    <button type="submit" name="cs_action" value="arrive" class="btn btn-sm btn-action" style="margin: .25em;" [% IF disable_arrival_button %]disabled="disabled"[% END %]>
+                       <i class="fas fa-bell" aria-hidden="true"></i> [% l('Alert staff of your arrival') %]
+                    </button><br/>
+                    <button type="submit" name="cs_action" value="cancel" class="btn btn-sm btn-danger" style="margin: .25em;">
+                       <i class="fas fa-ban" aria-hidden="true"></i> [% l('Cancel') %]
+                    </button>
+                [% ELSIF appointment.arrival %]
+                    [% l('Staff have been notified of your arrival.') %]<br/>
+                    <!--
+                    <button type="submit" name="cs_action" value="deliver" class="btn btn-sm btn-action" style="margin: .25em;">
+                        [% l('Confirm delivery of items') %]
+                    </button><br/>
+                    -->
+                    <button type="submit" name="cs_action" value="cancel" class="btn btn-sm btn-danger" style="margin: .25em;">
+                       <i class="fas fa-ban" aria-hidden="true"></i> [% l('Cancel') %]
+                    </button>
+                [% ELSIF appointment.slot %]
+                    <button type="submit" name="cs_action" value="arrive" class="btn btn-sm btn-action" style="margin: .25em;" [% IF disable_arrival_button %]disabled="disabled"[% END %]>
+                       <i class="fas fa-bell" aria-hidden="true"></i> [% l('Alert staff of your arrival') %]
+                    </button><br/>
+                    <button type="submit" name="cs_action" value="save" class="btn btn-sm btn-action" style="margin: .25em;">
+                       <i class="fas fa-edit" aria-hidden="true"></i> [% l('Update') %]
+                    </button><br/>
+                    <button type="submit" name="cs_action" value="cancel" class="btn btn-sm btn-danger" style="margin: .25em;">
+                       <i class="fas fa-ban" aria-hidden="true"></i> [% l('Cancel') %]
+                    </button>
+                [% ELSIF cs_date %]
+                    <button type="submit" name="cs_action" value="save" class="btn btn-sm btn-action" style="margin: .25em;">
+                       <i class="fas fa-check" aria-hidden="true"></i> [% l('Request appointment') %]
+                    </button>
+                    <button type="submit" name="cs_action" value="reset" class="btn btn-sm btn-opac" style="margin: .25em;">
+                       <i class="fas fa-calendar" aria-hidden="true"></i> [% l('Select another date') %]
+                    </button><br/>
+                [% ELSE %]
+                    <button type="submit" name="cs_action" value="next" class="btn btn-sm btn-opac" style="margin: .25em;">
+                       <i class="fas fa-clock" aria-hidden="true"></i> [% l('Check times') %]
+                    </button>
+                [% END %]
+            </td>
+        </tr></tbody></table>
+        </form>
+    [% END %]
+    </div>
+
+        [% END %]
+    </div>
+    <p>
+    Within 30 minutes of scheduling or updating an appointment, a confirmation email/text* will be sent to you with pickup details.
+    </p>
+    <p style="font-size: [% css_fonts.size_smaller %];">
+    *Delivery method will depend on <a href="/eg/opac/myopac/prefs_notify">contact options</a> stored in your account.
+    </p>
+</div>
+[% END %]
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/myopac/prefs.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/myopac/prefs.tt2
new file mode 100644 (file)
index 0000000..3211fcc
--- /dev/null
@@ -0,0 +1,296 @@
+[%  PROCESS "opac/parts/header.tt2";
+    WRAPPER "opac/parts/myopac/base.tt2";
+    myopac_page = "prefs";
+    parent="prefs";
+    prefs_page = 'prefs';
+    can_call_action_trigger = 'true' %]
+
+<h3>[% l('Account Information and Preferences') %]</h3>
+<div id="acct_info_main">
+    <table title="[% l('Account preference') %]" class='light_border table table-hover'>
+        <tbody id='myopac_summary_tbody'>
+            [% IF ctx.user.pref_first_given_name || ctx.user.pref_second_given_name || ctx.user.pref_family_name %]
+            <tr>
+                <td class='color_4 light_border'>[% l("Preferred Name") %]</td>
+
+                <td class='light_border'>[% l(
+                    HUMAN_NAME_FORMAT,
+                    ctx.user.pref_prefix,
+                    (ctx.user.pref_first_given_name || ctx.user.first_given_name),
+                    ctx.user.pref_second_given_name,
+                    (ctx.user.pref_family_name || ctx.user.family_name),
+                    ctx.user.pref_suffix
+                ) | html %]</td>
+
+                <td></td>
+            </tr>
+            [%  END %]
+            <tr>
+                <td class='color_4 light_border'>[% l("Legal Name") %]</td>
+
+                <td class='light_border'>[% l(
+                    HUMAN_NAME_FORMAT,
+                    ctx.user.prefix,
+                    ctx.user.first_given_name,
+                    ctx.user.second_given_name,
+                    ctx.user.family_name,
+                    ctx.user.suffix
+                ) | html %]</td>
+
+                <td></td>
+            </tr>
+
+            <tr>
+                <td class='color_4 light_border'>[% l("Day Phone") %]</td>
+                <td class='light_border'>[% ctx.user.day_phone | html %]</td>
+                <td></td>
+            </tr>
+
+            <tr>
+                <td class='color_4 light_border'>[% l("Evening Phone") %]</td>
+                <td class='light_border'>[% ctx.user.evening_phone | html %]</td>
+                <td></td>
+            </tr>
+
+            <tr>
+                <td class='color_4 light_border'>[% l("Other Phone") %]</td>
+                <td class='light_border'>[% ctx.user.other_phone | html %]</td>
+                <td></td>
+            </tr>
+
+            <tr>
+                <td class='color_4 light_border'>
+                    <div style="position:absolute">
+                   </div>[% l("Username") %]
+                </td>
+                <td class='light_border'>[% ctx.user.usrname | html %]</td>
+                [%- IF ctx.username_change_disallowed %]
+                <td></td>
+                [%- ELSE %]
+                <td class='light_border'><a class="btn btn-sm btn-action" href='update_username'
+                    title="[% l('Change Username') %]"><i class="fas fa-user-cog"></i> [% l("Change") %]</a></td>
+                [%- END %]
+            </tr>
+            <tr>
+                <td class='color_4 light_border'>[% l("Password") %]</td>
+                <td class='light_border'>[% l("(not shown)") %]</td>
+                <td>
+                [%- IF disable_password_change == 'true' %]
+                <span></span>
+                [%- ELSE %]
+                <span class='light_border'><a class="btn btn-sm btn-action" href='update_password'
+                    title="[% l('Change Password') %]"><i class="fas fa-user-cog"></i> [% l("Change") %]</a></span>
+                [%- END %]
+                </td>
+            </tr>
+            <tr>
+                <td class='color_4 light_border'>[% l("Email Address") %]</td>
+                <td class='light_border'>[% ctx.user.email | html %]</td>
+                <td>
+                [%- IF disable_email_change == 'true' %]
+                <span></span>
+                [%- ELSE %]
+                <span class='light_border'><a class="btn btn-sm btn-action" href='update_email'
+                    title="[% l('Update Email Address') %]"><i class="fas fa-user-cog"></i> [% l('Change') %]</a></span>
+                [%- END %]
+                [%- IF ctx.user.email %]
+                    <span class='light_border'>
+                    <a href="#" class="btn btn-sm btn-action" onclick="sendTestEmail(
+                        [% ctx.user.id %], '[% ctx.authtoken %]')"
+                        title="[% l('Send Test Email') %]">
+                        <i class="fas fa-envelope"></i> [% l('Send Test Email') %]
+                    </a>
+                    </span>
+                [%- END %]
+                </td>
+            </tr>
+            <tr id="test_notification_banner" style="display:none">
+                <td></td>
+                <td colspan='2'>
+                    [% INCLUDE "opac/myopac/test_notification.tt2" message_type = "email" %]
+                </td>
+            </tr>
+
+            [% IF ctx.user.ident_value %]<tr class="hide_me">
+                <td class='color_4 light_border'>
+                [% l("Primary Identification") %]</td>
+
+                <td class='light_border'>
+                    [%
+                    # l('[_1] ([_2])', ctx.user.ident_value, ctx.user.ident_type.name) | html
+                    # XXX uncomment the above line to show primary
+                    # identification. With a minor tweak it could
+                    # alternatively be shown but partially obscured.
+                    %]
+                </td>
+                <td></td>
+            </tr>[% END %]
+
+            <tr>
+                <td class='color_4 light_border'>[% l("Active Barcode") %]</td>
+                <td class='light_border'>[% ctx.user.card.barcode %]</td>
+                <td></td>
+            </tr>
+
+            <tr>
+                <td class='color_4 light_border'>[% l("Home Library") %]</td>
+ <td class='light_border'>
+                    [% ctx.get_aou(ctx.user.home_ou.parent_ou).name %]<br/>
+                    [% ctx.user.home_ou.name | html %]<br/>
+                    [% ctx.user.home_ou.billing_address.street1 %]<br/>
+                    [% IF ctx.user.home_ou.billing_address.street2; ctx.user.home_ou.billing_address.street2 _ "<br/>"; END %]
+                    [% ctx.user.home_ou.billing_address.city %], [% ctx.user.home_ou.billing_address.state %]
+                    [% ctx.user.home_ou.billing_address.post_code %]<br/>
+                    <br/>
+
+                    [% IF ctx.user.home_ou.phone; ctx.user.home_ou.phone _ "<br/>"; END %]
+
+                    [% IF ctx.user.home_ou.email; ctx.user.home_ou.email _ "<br/>"; END %]
+                    [% lib_url = ctx.get_org_setting(ctx.user.home_ou.id, 'lib.info_url');
+                        IF lib_url;
+                            '<a href="'; lib_url | html; '" property="url">'; lib_url; '</a>';
+                        END;
+                    %]
+                </td>                <td></td>
+            </tr>
+            <tr>
+                <td class='color_4 light_border'>[% l("Account Creation Date") %]</td>
+                <td class='light_border'>[% date.format(ctx.parse_datetime(ctx.user.create_date), DATE_FORMAT) %]</td>
+                <td></td>
+            </tr>
+            <tr>
+                <td class='color_4 light_border'>[% l("Account Expiration Date") %]</td>
+                <td class='light_border'>
+                    [%- IF date.format(ctx.parse_datetime(ctx.user.expire_date), '%s') < date.format(date.now , '%s'); -%]
+                        <span class="danger">[% date.format(ctx.parse_datetime(ctx.user.expire_date), DATE_FORMAT) %]</span>
+                    [% ELSE %]
+                        [% date.format(ctx.parse_datetime(ctx.user.expire_date), DATE_FORMAT) %]
+                    [% END %]
+                </td>
+                <td></td>
+            </tr>
+            [% IF ctx.user.stat_cat_entries.size;
+                FOR statcat IN ctx.user.stat_cat_entries;
+                    IF statcat.stat_cat.opac_visible == 't'; %]
+                        <tr>
+                            <td class='color_4 light_border'>[% statcat.stat_cat.name %]</td>
+                            <td class='light_border' colspan='2'>[% statcat.stat_cat_entry %]</td>
+                        </tr>
+                    [% END;
+                END;
+            END %]
+        </tbody>
+    </table>
+
+    <br />
+    <hr />
+    <br />
+
+       <div class="header_middle mb-3">
+        <span>[% l('Addresses') %]</span>
+    </div>
+
+<div class="row">
+            [%
+                # cycle through the non-pending address.  For each non-pending addr
+                # that has a corresponding pending addr, render the pending addr
+                # along the right inside it's own edit form
+                pending = {};
+                regular = [];
+                edit_addr_id = CGI.param('edit_address');
+                FOR addr IN ctx.user.addresses;
+                    IF addr.pending == 't';
+                        replaces = addr.replaces;
+                        pending.$replaces = addr;
+                    ELSE;
+                        regular.push(addr);
+                    END;
+                END;
+            FOR addr IN regular;
+                cur_id = addr.id;
+                pending_addr = pending.$cur_id;
+            %]
+    <div class="col-lg-6 col-12">
+        <table class='table' title="[% l('Addresses') %]">
+
+            <tbody>
+            <tr>
+                <!-- pending address form -->
+                [% IF pending_addr OR edit_addr_id == cur_id;
+                    update_addr = pending_addr || addr %]
+              <td>
+
+                    <form method='post'>
+                        [% IF pending_addr %]
+                            <input type='hidden' name='pending_addr' value='[% pending_addr.id %]'/>
+                        [% ELSE %]
+                            <input type='hidden' name='replace_addr' value='[% edit_addr_id | html %]'/>
+                        [% END %]
+                        <table class='pending-addr table' title="[% l('Pending Addresses') %]">
+                        <tr><td colspan="2"><h5 class="text-center">Pending Address Change</h5></td></tr>
+                        [% addr_fields = [
+                            {label => l("Address Type"), name => 'address_type', value => update_addr.address_type},
+                            {label => l("Street"), name => 'street1', value => update_addr.street1},
+                            {label => l("Street"), name => 'street2', value => update_addr.street2},
+                            {label => l("City"), name => 'city', value => update_addr.city},
+                            {label => l("County"), name => 'county', value => update_addr.county},
+                            {label => l("State"), name => 'state', value => update_addr.state},
+                            {label => l("Country"), name => 'country', value => update_addr.country},
+                            {label => l("ZIP"), name => 'post_code', value => update_addr.post_code},
+                        ];
+                        FOR field IN addr_fields %]
+
+                            <tr>
+
+                                <td><label for="addr-form-[% field.name %]">[% field.label %]</label></td>
+                                <td><input name="[% field.name %]"
+                                    id="addr-form-[% field.name %]"
+                                    value="[% field.value | html %]" class="form-control">
+                                </td>
+                            </tr>
+                        [% END %]
+                            <tr>
+                                <td><button type='submit' class="btn btn-confirm "><i class="fas fa-save"></i> [% l('Save Changes') %]
+
+ </button></td>
+                                <td>
+                                    [% params = (pending_addr) ? {delete_pending => pending_addr.id} : {} %]
+                                    <a href="[% mkurl('', params, 1) %]" class="btn btn-deny "><i class="fas fa-trash-alt"></i> [% l('Discard Pending Address') %]</a>
+                                </td>
+                            </tr>
+                            <tr><td colspan='2'><i>[% l('This address has a pending change.') %]</i></td></tr>
+                            <tr><td colspan='2'><i>[% l('Address changes will be verified by staff') %]</i></td></tr>
+                        </table>
+                    </form>
+                </td>
+                 [% ELSE %]
+                <td>
+
+                    <!-- read-only address display -->
+                    <table class='table table-hover light_border' title="[% l('Active Addresses') %]">
+                        <tr><td class='color_4'>[% l("Address Type") %]</td><td>[% addr.address_type | html %]</td></tr>
+                        <tr><td class='color_4'>[% l("Street") %]</td><td>[% addr.street1 | html %]</td></tr>
+                        <tr><td class='color_4'>[% l("Street") %]</td><td>[% addr.street2 | html %]</td></tr>
+                        <tr><td class='color_4'>[% l("City") %]</td><td>[% addr.city | html %]</td></tr>
+                        <tr><td class='color_4'>[% l("County") %]</td><td>[% addr.county| html  %]</td></tr>
+                        <tr><td class='color_4'>[% l("State") %]</td><td>[% addr.state | html %]</td></tr>
+                        <tr><td class='color_4'>[% l("Country") %]</td><td>[% addr.country | html %]</td></tr>
+                        <tr><td class='color_4'>[% l("Zip") %]</td><td>[% addr.post_code | html %]</td></tr>
+                        [% IF ctx.get_org_setting(ctx.user.home_ou.id, 'opac.allow_pending_address')
+                                AND !pending_addr AND edit_addr_id != cur_id %]
+                        <tr><td colspan='2'><a class="btn btn-action" href='?edit_address=[% addr.id %]'><i class="fas fa-edit"></i> [% l('Edit Address') %]</a></td></tr>
+                        [% END %]
+                    </table>
+
+                 </td>
+                [% END %]
+                </tr>
+            </tbody>
+        </table>
+     </div>
+            [% END %]
+
+</div>
+</div>
+
+[% END %]
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/advanced/numeric.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/advanced/numeric.tt2
new file mode 100644 (file)
index 0000000..eb952ad
--- /dev/null
@@ -0,0 +1,45 @@
+<form action="[% ctx.opac_root %]/results" method="get">
+    <h1 class="text-center">[% l("Numeric Search") %]</h1>
+            <h2 class="text-center">[% l("Search by a field and numeric identifier.") %]</h2>
+    <input type="hidden" name="contains" value="contains" />
+    <input type="hidden" name="_special" value="1" />
+    <input id="detail" type="hidden" name="detail_record_view"
+           value="[% show_detail_view %]"/>
+    <div id='adv_numeric_block' class='row'>
+        <div class="col-12 my-3">
+            <label for="numeric_qtype"><strong>[% l("Field:") %]</strong></label>
+                <select id="numeric_qtype" name="qtype" class="form-control">
+                    <!-- TODO: Pull labels from config.metabib_field.label -->
+                    <option value="identifier|isbn">[% l('ISBN') %]</option>
+                     <option value="identifier|upc">[% l('UPC') %]</option>
+                    <option value="identifier|issn">[% l('ISSN') %]</option>
+                    <option value="identifier|scn">[% l('OCLC') %]</option>
+                    <option value="identifier|music_number">[% l('Music Number') %]</option>
+                    <option value="cnbrowse">[% l('Call Number (Shelf Browse)') %]</option>
+                    <option value="identifier|lccn">[% l('LCCN') %]</option>
+                    <option value="identifier|tcn">[% l('TCN') %]</option>
+                    <option value="item_barcode">[% l('Item Barcode') %]</option>
+                    <option value="identifier|gov_doc_number">[% l('Government Document Number') %]</option>
+                </select>
+        </div>
+        <div class="col-12 my-3">
+                <label for="numeric_ident"><strong>[% l("Identifier:") %]</strong></label>
+                <input id="numeric_ident" class="form-control" type="text" name="query" size="16" autofocus placeholder='[% l("Identifier") %]' aria-label='[% l("Identifier") %]' />
+        </div>
+        <br/>
+        <div class="col-12 my-3">
+            [%- lib_select_id="adv_org_selector" -%]
+            <label for="[% lib_select_id %]"><strong>[% l("Search Library:") %]</strong>
+                  [% PROCESS "opac/parts/org_selector.tt2";
+                     INCLUDE build_org_selector id=lib_select_id show_loc_groups=1
+                  %]
+            </label>
+        <br/>
+
+          </div>
+          <div class="col-12 my-3">
+                      <button type="submit" class="btn btn-confirm"><i class="fas fa-search"></i> [% l('Search') %]</button>
+
+        </div>
+    </div>
+</form>
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/base.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/base.tt2
new file mode 100644 (file)
index 0000000..4ea3511
--- /dev/null
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html lang='[% ctx.eg_locale %]'>
+    <head prefix="og: http://ogp.me/ns#">
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+        [% IF ctx.refresh %]
+        <meta http-equiv="refresh" content="[% ctx.refresh %]" />
+        [% ELSIF ctx.authtime AND !ctx.is_staff %]
+        <meta http-equiv="refresh" content="[% ctx.authtime %]; url=[% ctx.home_page %]" />
+        [% END %]
+        <meta name = "viewport" content = "width=device-width, initial-scale = 1.0">
+        <!--Added bootstrap dependancies-->
+        <link rel="stylesheet" href="[% ctx.media_prefix %]/opac/deps/node_modules/bootstrap/dist/css/bootstrap.min.css[% ctx.cache_key %]">
+        <link rel="stylesheet"  href="[% ctx.media_prefix %]/opac/deps/node_modules/@fortawesome/fontawesome-free/css/all.css[% ctx.cache_key %]" />
+        <link rel="stylesheet"  href="[% ctx.media_prefix %]/opac/deps/node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker.css[% ctx.cache_key %]" />
+        <link rel="stylesheet"  href="[% ctx.media_prefix %]/css/skin/default/opac/semiauto.css[% ctx.cache_key %]" />
+        <link rel="stylesheet" href="[% ctx.opac_root %]/css/style.css[% ctx.cache_key %]&amp;dir=[%
+          IF ctx.get_i18n_l(ctx.eg_locale).rtl == 't' %]rtl[%
+          ELSE %]ltr[% END %]" />
+          <link rel="stylesheet" href="[% ctx.opac_root %]/css/mediaQuery.css[% ctx.cache_key %]" />
+        [% IF ctx.get_i18n_l(ctx.eg_locale).rtl == 't' %]
+        <link rel="stylesheet" href="[% ctx.media_prefix %]/css/skin/default/opac/semiauto-rtl.css[% ctx.cache_key %]" />
+        [% END %]
+
+           [% IF ctx.get_org_setting(ctx.search_ou, 'opac.patron.custom_css') %]
+            [% custom_css = ctx.get_org_setting(ctx.search_ou, 'opac.patron.custom_css') %]
+        [% '<style>'; custom_css ; '</style>' %]
+        [% END %]
+
+        [% matomo_id = ctx.get_org_setting(ctx.search_ou, 'opac.analytics.matomo_id'); %]
+        [% matomo_url = ctx.get_org_setting(ctx.search_ou, 'opac.analytics.matomo_url'); %]
+        [% IF matomo_id && matomo_url %]
+           [% matomo_enabled = 1; %]
+        [% END %]
+
+        [%- libname = ctx.get_aou(ctx.search_ou).name;
+            libname = libname | html;
+            libsname = ctx.get_aou(ctx.search_ou).shortname; %]
+        <title>[%- IF ctx.user_stats.messages.unread;
+                      l('([_1])', ctx.user_stats.messages.unread);
+                   END;
+               -%]
+               [% l('[_1] - [_2]', ctx.page_title, libname) %]</title>
+        <link rel="unapi-server" type="application/xml" title="unAPI" href="/opac/extras/unapi" />
+        <link type="application/opensearchdescription+xml" rel='search' title="[% l('[_1] OpenSearch', libname) %]" href="/opac/extras/opensearch/1.1/[% libsname | uri %]/-/osd.xml" />
+        [%-# Hook for page-specific metadata such as <meta name="robots" content="noindex"> %]
+        [%- ctx.metalinks.push('<meta property="og:title" content="' _ ctx.page_title _ '" />'); %]
+        [%- ctx.metalinks.push('<meta property="og:site_name" content="' _ libname _ '" />'); %]
+        [% FOREACH meta IN ctx.metalinks; meta _ "\n"; END; -%]
+        [% IF want_dojo %]
+        <style>
+            @import "[% ctx.media_prefix %]/js/dojo/dijit/themes/tundra/tundra.css[% ctx.cache_key %]";
+        </style>
+        [% END %]
+
+        [% IF !ctx.is_staff %]
+            [% INCLUDE 'opac/parts/goog_analytics.tt2' %]
+            [% INCLUDE 'opac/parts/matomo_analytics.tt2' %]
+        [% END %]
+        [% PROCESS 'opac/parts/stripe.tt2' %]
+<script  src="[% ctx.media_prefix %]/opac/deps/node_modules/jquery/dist/jquery.min.js"></script>
+
+               <script>
+                       $(document).ready(function(){
+                               $("#loginModal").on('shown.bs.modal', function(){
+                                       $(this).find('#username_field').focus();
+                               });
+                       });
+               </script>
+
+    </head>
+    <body[% IF want_dojo; ' class="tundra d-flex flex-column min-vh-100"'; ELSE; ' class="tundra d-flex flex-column min-vh-100"';  END %]>
+        <h1 class="sr-only">[% l('Catalog') %]</h1>
+        [% IF !ctx.is_staff %]
+        <p style="text-align: center; background: white; font-size:20px;">
+          <strong style="color:red;">TRAINING SERVER - DO NOT USE FOR LIVE TRANSACTIONS</strong>
+          <br />
+          Library Patrons: <a href="https://catalog.cwmars.org/">Click Here for the live catalog.</a>
+        </p>
+        [% END %]
+        [%#Each content page needs (at minimum) an <h2> describing the content%]
+       <div class="mb-3">
+        [% content %]
+        </div>
+        [% IF ctx.page != "login" ;%]
+        [% INCLUDE 'opac/parts/login/login_modal.tt2' %]
+        [% END;%]
+        <h2 class="sr-only">[% l('Additional Resources') %]</h2>
+        [% INCLUDE 'opac/parts/footer.tt2' %]
+
+        [% INCLUDE 'opac/parts/js.tt2' %]
+        <script>
+    $(document).ready(function(){
+    $('.tooltip').tooltip();
+    });
+</script>
+        [%- IF ENV.OILS_CHILIFRESH_ACCOUNT %]
+            [%- INCLUDE 'opac/parts/chilifresh.tt2' %]
+        [%- END %]
+
+
+
+    </body>
+</html>
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/config.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/config.tt2
new file mode 100644 (file)
index 0000000..63c056b
--- /dev/null
@@ -0,0 +1,279 @@
+[%
+
+##############################################################################
+# This file contains skin-level configuration settings.
+# Many of these settings will probably migrate into actor.org_unit_settings.
+##############################################################################
+
+
+##############################################################################
+# Holds blocking
+##############################################################################
+# Prevent the "Place hold" link from being displayed if a copy is available.
+# This is not perfect, given the umpteen different types of holds that are
+# possible, but addresses the major use case for libraries that don't want
+# to fetch copies from the shelves.
+ctx.holds_block.enabled = 'false';
+
+##############################################################################
+# RefWorks configuration
+##############################################################################
+# RefWorks is a Web-based citation manager
+ctx.refworks.enabled = 'false';
+
+# Base URL for RefWorks
+ctx.refworks.url = 'http://www.refworks.com';
+
+# Some sites have a hosted RefWorks instance at a different URL;
+# in addition, you might want to proxy access to RefWorks - for example:
+# ctx.refworks.url = 'http://librweb.laurentian.ca/login?url=http://refworks.scholarsportal.info';
+
+##############################################################################
+# OpenURL resolution
+##############################################################################
+# Evergreen provides the ability to point at an OpenURL resolver to find
+# electronic resources for a given ISSN or ISBN. Currently, only the SFX
+# resolver is supported.
+#
+# You must enable the open-ils.resolver instance in opensrf.xml to use
+# this feature.
+##############################################################################
+
+openurl.enabled = 'false';
+openurl.baseurl = 'http://sfx.example.com/instance';
+
+##############################################################################
+# Google Analytics support
+##############################################################################
+# You can enable Google Analytics support in Evergreen by entering a
+# valid Google Analytics code and changing 'false' to 'true'
+##############################################################################
+google_analytics.enabled = 'false';
+google_analytics.code = 'UA-9999999-99';
+
+##############################################################################
+# Ebook API integration
+##############################################################################
+ebook_api.enabled = 'false';
+ebook_api.ebook_test.enabled = 'false';
+ebook_api.ebook_test.base_uris = [ 'http://example.com/ebookapi/t/' ];
+ebook_api.oneclickdigital.enabled = 'false';
+ebook_api.oneclickdigital.base_uris = [ 'http://example.oneclickdigital.com/Products/ProductDetail.aspx' ];
+ebook_api.overdrive.enabled = 'false';
+ebook_api.overdrive.base_uris = [ 'http://elm.lib.overdrive.com/' ];
+
+##############################################################################
+# Enable "Forgot your password?" prompt at login
+##############################################################################
+reset_password = 'true';
+
+##############################################################################
+# Hide various options from user preferences that you might not want to expose
+# if you rely on centralized authentication via open-ils.auth_proxy, like LDAP
+#
+# Username changes can be disabled by the opac.lock_usernames OU setting.
+##############################################################################
+disable_password_change = 'false';
+disable_email_change = 'false';
+
+##############################################################################
+# Some libraries do not do notifications by phone; if not true, then this
+# hides the user preference for phone notifications as well as the phone
+# notification portion of the hold dialogue
+##############################################################################
+allow_phone_notifications = 'true';
+
+##############################################################################
+# Format of parts selection on Place Holds screen
+# Set to true to use radio buttons for parts selection on the Place Holds
+# screen. The default behavior is to to display them in a select menu.
+#############################################################################
+enable.radio.parts = 'false';
+
+##############################################################################
+# Misc. UI Settings
+##############################################################################
+# Option for full details as a default, esp. impt. for e-content
+# that uses resolver plumbing. Valid values are 'true', 'false' and 'hide'.
+# Setting this to 'true' shows full details by default but allows the link
+# to appear for 'Show Fewer Details'. The 'hide' option shows full details
+# and also suppresses the link from displaying at all.
+show_more_details.default = 'false';
+
+##############################################################################
+# Size of the jacket image to display on the record detail summary.
+# Sizes vary depending on added content provider.
+# Options are "small", "medium", and "large"
+record.summary.jacket_size = 'medium';
+
+##############################################################################
+# Define the order in which facets are displayed.  Only facets listed here
+# will be displayed.  To show all facets sorted by name, comment out this
+# setting.
+# facet.display = [] # show no facets
+facet.display = [
+    {facet_class => 'author',  facet_order => ['personal']},
+    {facet_class => 'subject', facet_order => ['topic']},
+    #{facet_class => 'identifier', facet_order => ['genre']},
+    {facet_class => 'series',  facet_order => ['seriestitle']},
+    {facet_class => 'subject', facet_order => ['name']}
+];
+facet.default_display_count = 4;
+
+##############################################################################
+# Define the advanced search limiters and labels.
+# Each entry is put into a table cell.
+# adv_label is the (translated) label for the limiter
+# adv_attr is an array of possible limiters, the first one that has any
+#   values will be used
+# adv_filter is the same as adv_attr, but for search filter groups
+# adv_size lets you set the height of the adv_attr or adv_filter select box.
+# if adv_size < 1, the box height is set to the number of options in it.
+# adv_break will end the current row. If specified with a label/attr it
+#   will do so *after* that limiter.
+# adv_special will drop in a special entry:
+#   lib_selector will put the search library box (with limit to available)
+#   pub_year will put the publication year box
+#   sort_selector will put the sort results selector
+# id DOM id used for linking labels to form controls.  They are pinned
+#   here instead of auto-generated (from the attr type, for example)
+#   for consistency.
+
+search.adv_config = [
+    {adv_label => l("Format"), adv_attr => [ctx.get_cgf('opac.format_selector.attr').value], id => 'adv_selector_format'},
+    {adv_label => l("Language"),  adv_attr => "item_lang", id => 'adv_selector_item_lang'},
+    {adv_label => l("Audience"),  adv_attr => ["audience_group", "audience"], id => 'adv_selector_audience', adv_break => 1},
+    {adv_label => l("Shelving Location"), adv_special => "copy_location", id => 'adv_copy_location_selector', js_only => 101, adv_break => 1},
+    {adv_label => l("Search Library"), adv_special => "lib_selector", id => 'adv_org_selector'},
+    #{adv_label => l("Where"), adv_special => "scope_selector", id => 'adv_scope_selector'},
+    {adv_label => l("Publication Year"), adv_special => "pub_year", id => 'adv_selector_pub_year'},
+    {adv_label => l("Sort Results"), adv_special => "sort_selector", id => 'adv_selector_sort_results'},
+];
+
+# Set the default height of the select boxes. Defaults to 4.
+#search.default_adv_select_height = 4;
+
+##############################################################################
+# For each search box the default "query type" value can be specified here
+# This is the actual backend value, not the label
+# Also note that including more than the row count entries won't add rows
+# The first entry should be used as a default for "basic" search as well
+
+search.default_qtypes = ['keyword','title','author'];
+
+##############################################################################
+# Basic Search Box definition
+# This allows selection of what, exactly, basic search uses for a selection
+# box. Previously it was hardcoded to use an attr box of mattype or item_type.
+#
+# type can be "attr" or "filter"
+# group is the attr or filter entries you want to check for
+# none_label is the label for the default nothing selected entry.
+
+search.basic_config = {
+    type => 'attr',
+    group => [ctx.get_cgf('opac.format_selector.attr').value, 'item_type'],
+    none_label => l("All Formats"),
+};
+
+# Make metarecord search the default.
+#search.metarecord_default = 1;
+
+# Disable search term highlighting
+#search.no_highlight = 1;
+
+##############################################################################
+# Show Google Book Previews
+# Set to 1 or 'true' to enable
+ctx.google_books_preview = 0;
+
+##############################################################################
+
+# Set a maintenance message to display in the catalogue
+#ctx.maintenance_message = "<b>This OPAC will be unavailable part of March 15, 2019 for planned upgrades.</b>";
+# Maintenance types follow Bootstrap4 alert options as follows
+# success = green; info = blue; warning = yellow; danger = red
+# Other colors would require re-coding the alert
+#ctx.maintenance_type = l('warning');
+
+##############################################################################
+# Depth Button/Checkbox
+# Recommendation: Do not enable button for basic search without enabling the
+# checkbox for the results page
+ctx.depth_sel_checkbox = 1; # Results Page Checkbox Toggle
+ctx.depth_sel_button = 1; # Basic Search Submit Button
+ctx.depth_sel_depth = 0; # Depth to set to
+ctx.depth_sel_button_label = l('All Libraries');
+ctx.depth_sel_button_class = 'btn-opac';
+ctx.depth_sel_checkbox_label = l('Show Results from All Libraries');
+ctx.depth_sel_tooltip = l('Select this option to expand your results to all libraries while retaining the priority of your selected librarys holdings.');
+ctx.depth_sel_resultshint = l('Showing results from all libraries');
+
+##############################################################################
+# Exclude Electronic Resources Checkbox
+# One setting for both the advanced search page and the results bar.
+# Off by default; set to 1 to display.
+ctx.exclude_electronic_checkbox = 1;
+
+##############################################################################
+# Metarecords configuration
+# metarecords.disabled = 1; # disable all metarecord access points
+##############################################################################
+
+##############################################################################
+# Local date format (uses POSIX strftime() formatting)
+# See http://www.template-toolkit.org/docs/modules/Template/Plugin/Date.html
+# DATE_FORMAT = '%Y-%m-%d'; # for 2014-06-31 format
+##############################################################################
+
+##############################################################################
+# Local time format (uses POSIX strftime() formatting)
+# See http://www.template-toolkit.org/docs/modules/Template/Plugin/Date.html
+# TIME_FORMAT = '%H:%M:%S'; # for 16:32:32 (24 hour) format
+# TIME_FORMAT = '%H:%M'; # for 16:32 (24 hour) format
+##############################################################################
+
+##############################################################################
+# Obalkyknih.cz support
+##############################################################################
+# Obalkyknihy.cz is free Czech service providing added content and book covers
+# Set to 'true' to enable
+##############################################################################
+# obalkyknih_cz.enabled = 'false';
+
+##############################################################################
+# JQuery support
+##############################################################################
+# Include JQuery in the TPAC?
+# Set to a true value to enable
+##############################################################################
+# ctx.want_jquery = 1;
+
+##############################################################################
+# Browser cache-busting key
+##############################################################################
+# Links to assets like stylesheets, JavaScript, and images will have this
+# key appended so that browsers will be forced to request a new version.
+# Enables you to set a cache max-date of years.
+#
+# If unset, it falls back to eg_cache_hash (which is set every time you run
+# "autogen", which may or may not be when you change styles etc)
+##############################################################################
+#ctx.cache_key = '001'
+
+##############################################################################
+# Display of badge scores
+##############################################################################
+ctx.hide_badge_scores = 'false';
+
+##############################################################################
+# Maximum number of items allowed to be stored in a basket
+##############################################################################
+ctx.max_cart_size = 500;
+
+##############################################################################
+# Display booking reservations tab in myopac
+##############################################################################
+ctx.show_reservations_tab = 'false';
+
+%]
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/css/colors.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/css/colors.tt2
new file mode 100644 (file)
index 0000000..4320cf0
--- /dev/null
@@ -0,0 +1,101 @@
+[%
+    css_colors = {
+
+
+#The counts that appear in the navigation when signed into the OPAC -EX. X Ready For Pickup where x is the modified number
+
+        zero_count = "#c1ffbf", #Logged in item/charges count at 0
+        non_zero_count = "#ffc107", #Logged in item/charges count NOT at 0
+
+        facets_back = "#16416F", #CW
+        facets_text = "#fff",
+        footer_link = "#fff",
+        footer_link_disabled = "#000",
+
+        nav_separation = "#16416F", #CW
+        header_primary = "#16416F", #CW
+        header_primary_fade = "#16416F", #CW
+        footer_primary = "#006098", #CW
+        footer_primary_fade = "#16416F", #CW
+
+        bg_extras = "#16416F", #CW
+        bg_filter = "#16416F", #CW
+        bg_filter_hover = "#63CFE3",
+
+        text_filter = "#fff",
+
+        background = "#fff", # white
+        background_alert = "#ffcccc", # pink
+        background_invert = "#252525", # charcoal
+        text = "black", # black
+        text_alert = "#c50202", # red
+        text_attention = "#ffcc33", # pumpkin orange
+        text_badnews = "#c50202", # cherry red
+        text_goodnews = "#1dd93c", # lime green
+        text_greatnews = "green", # green
+        text_invert = "#fff", # white
+        text_match = "#c00", # deep red
+        primary = "#16416F", #CW
+        primary_fade = "#002B49", #CW
+        primary_offset = "#63CFE3", #CW
+        control = "#16416F", #CW
+        accent_light = "#ccc", #  grey (light)
+        accent_lighter = "#ddd", #  grey (lighter)
+        accent_lighter2 = "#d8d8d8", #  grey (lighter again)
+        accent_lightest = "#eee", #  grey (lightest)
+        accent_ultralight = "#f0f0f0", # ivory
+        accent_medium = "#999", # gun metal grey (medium)
+        accent_mediumdark = "#888", # gun metal grey (medium dark)
+        accent_dark = "#666", # gun metal grey (dark)
+        accent_darker = "#333", # gun metal grey (darker)
+        border_standard = "#888", # gun metal grey (medium dark)
+        border_dark = "black", # black
+        border_alert = "red", # red
+        button_text = "#fbf9f9", # off-white
+        button_text_shadow = "#555555", # medium grey
+        table_heading = "#d8d8d8", # grey-blue
+        mobile_header_text = "#fff", # white
+        item_selected = "#ddd", # grey (lighter)
+        link = "#0645AD ", #CW
+
+#Buttons are using default Bootstrap styling colors by default with this scheme, changable to match your library colours
+
+#Submit buttons and confirmations likle login. Make all 4 the same color for no hover effect
+        button_confirm = "#16416F",
+        button_confirm_hover = "#00593d",
+        button_confirm_border = "#16416F",
+        button_confirm_border_hover = "#00593d",
+        button_confirm_text = "#fff",
+
+#Denial buttons like Cancel. Make all 4 the same color for no hover effect
+        button_deny = "#c82333",
+        button_deny_hover = "#b21f2d",
+        button_deny_border = "#bd2130",
+        button_deny_border_hover = "#bd2130",
+        button_deny_text = "#fff",
+
+#Removal buttons like removing a search row in the advanced search. Make all 4 the same color for no hover effect
+        button_remove = "#dc3545",
+        button_remove_hover = "#c82333",
+        button_remove_border = "#dc3545",
+        button_remove_border_hover = "#bd2130",
+        button_remove_text = "#fff",
+
+#Main search buttons and buttons that are not a confirm or deny such as the Less and More details on the record. Make all 4 the same color for no hover effect
+        opac_button = "#424fa6",
+        opac_button_hover = "#4a58b7",
+        opac_button_border = "#2e3b91;",
+        opac_button_border_hover = "#2e3b91;",
+        opac_button_text = "#fff",
+
+#Action buttons such as Place Hold and Add to List seen in record and results. Make all 4 the same color for no hover effect
+        action_button = "#f2f4f5", #CW
+        action_button_hover = "#e2e6ea",
+        action_button_border = "#f2f4f5", #CW
+        action_button_border_hover = "#e2e6ea", #CW
+        action_button_text = "#16416F", #CW
+        #Many action buttons use link coloring on the anchor tags. This setting will change the color to match your color schema if necessary
+        #action_button_text_anchors = "",
+};
+
+%]
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/footer.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/footer.tt2
new file mode 100644 (file)
index 0000000..0dcc180
--- /dev/null
@@ -0,0 +1,74 @@
+[% IF !ctx.is_staff %]
+<div id="footer-wrap" class="mt-auto">
+<div id="footer">
+<div class="row mx-0">
+<div class="col-12 col-lg-3">
+    
+</div>
+<div class="col-12 col-lg-6">
+    <nav class="navbar navbar-expand-lg navbar-dark ">
+    <div class="row w-100">
+        <div class="col-12">
+            <ul class="navbar-nav">
+            <li class="nav-item">
+            <a class="nav-link" href="http://www.cwmars.org/" target="_blank" rel="noopener">
+            <i class="fas fa-home" style="color: #fff;"></i>CW MARS
+            </a>
+            </li>
+            <li class="nav-item">
+            <a class="nav-link" href="https://www.cwmars.org/explore/new-titles" target="_blank" rel="noopener">
+            <i class="fas fa-exclamation" style="color: #fff;"></i>New Titles at Your Library
+            </a>
+            </li>
+            <li class="nav-item">
+            <a class="nav-link" href="https://www.cwmars.org/explore/most-requested-titles" target="_blank" rel="noopener">
+            <i class="fas fa-star" style="color: #fff;"></i>Popular Titles
+            </a>
+            </li>
+            <li class="nav-item">
+            <a class="nav-link" href="/eg/kpac/home">
+            <i class="fas fa-child" style="color: #fff;"></i>Kid's Catalog
+            </a>
+            </li>
+            <li class="nav-item">
+            <a class="nav-link" href="https://www.cwmars.org/search/commonwealth-catalog" target="_blank" rel="noopener">
+            <i class="fas fa-cat" style="color: #fff;"></i>Commonwealth Catalog
+            </a>
+            </li>
+            <li class="nav-item">
+            <a class="nav-link" href="https://www.cwmars.org/help" target="_blank" rel="noopener">
+            <i class="fas fa-question" style="color: #fff;"></i>Help
+            </a>
+            </li>
+            </ul>
+        </div>
+    </div>
+    </nav>
+     [% IF ctx.timing %]
+    <div id="timing">
+        [% FOR event IN ctx.timing %]
+        At <span class="timing-time">[% event.0 | format("%0.4f") %]</span>:
+        <span class="timing-event">[% event.1 %]</span><br />
+        [% END %]
+    </div>
+    [% END %]
+
+      <div id="copyright_text" class="mt-3">
+        [% l('Copyright &copy; 2006-[_1] Georgia Public Library Service, and others', date.format(date.now, '%Y')) %]
+    <div id="footer_logo">
+        [% l('Powered by') %]
+        <a href="http://evergreen-ils.org">
+            <img id="footer_logo_image" src="[% ctx.media_prefix %]/opac/images/eg_tiny_logo.png[% ctx.cache_key %]"
+                alt="[% l('Evergreen') %]"
+            />
+        </a>
+    </div>
+    </div>
+   
+</div>
+ <div class="col-12 col-lg-3">[%- INCLUDE 'opac/parts/pref_locale_picker.tt2' %]</div>
+
+    </div>
+    </div>
+</div>
+[% END %]
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/homesearch.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/homesearch.tt2
new file mode 100644 (file)
index 0000000..296216f
--- /dev/null
@@ -0,0 +1,5 @@
+[% PROCESS carousels %]
+
+<div id="homeLogo">
+    
+</div>
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/login/form.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/login/form.tt2
new file mode 100644 (file)
index 0000000..0066bef
--- /dev/null
@@ -0,0 +1,88 @@
+
+
+<div class='container'>
+<hr>
+    <h3 class="text-center">[% l('Log in to Your Account') %]</h3>
+    <form method='post'>
+   <div class="row text-center">[%# INCLUDE "opac/parts/login/help.tt2" %]</div>
+    [% IF ctx.login_failed_event %]
+<div id='login-failed-message'>
+[%
+    IF ctx.login_failed_event.textcode == 'PATRON_CARD_INACTIVE';
+        l("The barcode used to login is marked as inactive.  <br>Please contact your local library.");
+    ELSIF ctx.login_failed_event.textcode == 'PATRON_INACTIVE';
+        l("This account has been deactivated.  <br>Please contact your local library.");
+    ELSE;
+        l("Login failed. <br> The username or password provided was not valid. <br>" _
+           "Passwords are case-sensitive.  <br>Check your Caps-Lock key and try again or contact your local library.");
+    END;
+%]
+</div>
+[% END %]
+
+<div class="table table-borderless table-sm">
+       <div class="row">
+               <div class="col-sm w-50">
+                       <label for='username_field' class="lbl1" >[% l('Library Card Number or User Name') %]
+                       <a href="#" title="[% INCLUDE "opac/parts/login/username_hint.tt2" %]" data-html="true" data-toggle="tooltip">
+                       <i class="fas fa-question-circle"></i></a></label>
+               </div>
+               <div class="col-sm w-50">
+                       <label for="password_field" class="lbl1" >[% l('Password') %]
+                       <a href="#" title="[% INCLUDE "opac/parts/login/password_hint.tt2" %]" data-html="true" data-toggle="tooltip">
+            <i class="fas fa-question-circle"></i></a></label>
+               </div>
+       </div>
+       <div class="row">
+               <div class="col-sm w-50">
+                       <input class="form-control" type='text' id="username_field" name="username" autofocus />
+               </div>
+               <div class="col-sm w-50">
+                       <input class="form-control" id="password_field" name="password" type="password"/>
+               </div>
+       </div>
+       <div class="row">
+               <div class="col-sm w-50">
+            <a href="https://www.cwmars.org/card" target="_blank" rel="noopener">[% l('Need A Card?') %]</a>
+               </div>
+               <div class="col-sm w-50">
+                       [% IF reset_password == 'true' %]
+                               <a href='[% mkurl(ctx.opac_root _ '/password_reset', {}, 1) %]'>[% l('Forgot Your Password?') %]  </a>
+                       [% END %]
+               </div>
+       </div>
+       <div class="row">
+               <div class="col-sm w-50">
+                       <input type="checkbox" value="" id="rememberMe">
+            <label class="form-check-label" for="rememberMe">
+               [% l('Stay logged in?') %]
+            </label>
+               </div>
+               <div class="col-sm w-50">
+                       <button type="submit" class="btn btn-confirm my-2"><i class="fas fa-sign-in-alt" aria-hidden="true"></i> [% l('Log in') %]</button>
+               </div>
+       </div>
+</div>
+
+        <div style="clear: both; padding-top: 15px;" class="col-12 text-center">
+        [%
+            redirect = CGI.param('redirect_to');
+            # Don't use referer unless we got here from elsewhere within the TPAC
+            IF !redirect AND ctx.referer.match('^https?://' _ ctx.hostname _ ctx.opac_root);
+                redirect = ctx.referer;
+            END;
+            # If no redirect is offered or it's leading us back to the
+            # login form, redirect the user to My Account
+            IF !redirect OR redirect.match(ctx.path_info _ '$');
+                redirect = CGI.url('-full' => 1) _ '/opac/myopac/main';
+            END;
+                redirect = redirect  | replace('^http:', 'https:');
+            %]
+            <input type='hidden' name='redirect_to' value='[% redirect | html %]'/>
+
+        </div>
+        <input id="client_tz_id" name="client_tz" type="hidden" />
+    </form>
+
+</div>
+
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/login/login_modal.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/login/login_modal.tt2
new file mode 100644 (file)
index 0000000..df82321
--- /dev/null
@@ -0,0 +1,100 @@
+<div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-hidden="true">
+  <div class="modal-dialog modal-dialog-centered" role="document">
+    <div class="modal-content">
+     <form method='post' action="/eg/opac/login?redirect_to=%2Feg%2Fopac%2Fmyopac%2Fmain">
+      <div class="modal-header">
+        <h1 class="modal-title" id="exampleModalLabel">[% l('Log in to Your Account') %]</h1>
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+          <i class="fas fa-times" aria-hidden="true"></i>
+        </button>
+      </div>
+      <div class="modal-body">
+
+      [% IF ctx.login_failed_event %]
+    <div id='login-failed-message'>
+    [%
+        IF ctx.login_failed_event.textcode == 'PATRON_CARD_INACTIVE';
+            l("The barcode used to login is marked as inactive.  Please contact your local library.");
+        ELSIF ctx.login_failed_event.textcode == 'PATRON_INACTIVE';
+            l("This account has been deactivated.  Please contact your local library.");
+        ELSE;
+            l("Login failed. The username or password provided was not valid. " _
+               "Passwords are case-sensitive.  Check your Caps-Lock key and try again or contact your local library.");
+        END;
+    %]
+    </div>
+    [% END %]
+
+<div class='container'>
+       <div class="table table-borderless table-sm">
+               <div class="row">
+                       <div class="col-sm w-50">
+                               <label for='username_field' class="lbl1" >[% l('Library Card Number or User Name') %]
+                               <a href="#" title="[% INCLUDE "opac/parts/login/username_hint.tt2" %]" data-html="true" data-toggle="tooltip">
+                               <i class="fas fa-question-circle"></i></a></label>
+                       </div>
+                       <div class="col-sm w-50">
+                               <label for="password_field" class="lbl1" >[% l('Password') %]
+                               <a href="#" title="[% INCLUDE "opac/parts/login/password_hint.tt2" %]" data-html="true" data-toggle="tooltip">
+                <i class="fas fa-question-circle"></i>
+                </a></label>
+                       </div>
+               </div>
+               <div class="row">
+                       <div class="col-sm w-50">
+                               <input class="form-control" type='text' id="username_field" name="username"/>
+                       </div>
+                       <div class="col-sm w-50">
+                               <input class="form-control" id="password_field" name="password" type="password"/>
+                       </div>
+               </div>
+               <div class="row">
+                       <div class="col-sm w-50">
+                               <a href="https://www.cwmars.org/card" target="_blank" rel="noopener">[% l('Need A Card?') %]</a>
+                       </div>
+                       <div class="col-sm w-50">
+                               [% IF reset_password == 'true' %]
+                               <a href='[% mkurl(ctx.opac_root _ '/password_reset', {}, 1) %]'>[% l('Forgot Your Password?') %]  </a>
+                               [% END %]
+                       </div>
+               </div>
+       </div>
+
+    <div class="mx-auto row py-4">
+
+        <div style="clear: both; padding-top: 15px;" class="col-12">
+        [%
+            redirect = CGI.param('redirect_to');
+            # Don't use referer unless we got here from elsewhere within the TPAC
+            IF !redirect AND ctx.referer.match('^https?://' _ ctx.hostname _ ctx.opac_root);
+                redirect = ctx.referer;
+            END;
+            # If no redirect is offered or it's leading us back to the
+            # login form, redirect the user to My Account
+            IF !redirect OR redirect.match(ctx.path_info _ '$');
+                redirect = CGI.url('-full' => 1) _ '/opac/myopac/main';
+            END;
+                redirect = redirect  | replace('^http:', 'https:');
+            %]
+        </div>
+
+        <input id="client_tz_id" name="client_tz" type="hidden" />
+        </div>
+  </div>
+    [%# INCLUDE "opac/parts/login/help.tt2" %]
+
+      </div>
+      <div class="modal-footer">
+      <div class="mr-auto">
+        <input type='hidden' name='redirect_to' value='[% redirect | html %]'/>
+        <input type="checkbox" name="persist" id="login_persist" class="mr-1"/>
+        <label for="login_persist"> [% l('Stay logged in?') %]</label>
+      </div>
+
+        <button type="button" class="btn btn-secondary" data-dismiss="modal"><i class="fas fa-times" aria-hidden="true"></i> [% l('Close') %]</button>
+        <button type="submit" class="btn btn-confirm"><i class="fas fa-sign-in-alt" aria-hidden="true"></i> [% l('Log in') %]</button>
+      </div>
+      </form>
+    </div>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/login/password_hint.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/login/password_hint.tt2
new file mode 100644 (file)
index 0000000..aa0a230
--- /dev/null
@@ -0,0 +1 @@
+Passwords are case sensitive. Click 'Forgot Your Password?' if you’re having trouble.
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/myopac/main_refund_policy.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/myopac/main_refund_policy.tt2
new file mode 100644 (file)
index 0000000..1d37841
--- /dev/null
@@ -0,0 +1,9 @@
+<tr>
+    <td colspan="3">
+        <p style="font-size: 120%;">
+        <strong>
+        Online payments are non-refundable. Patrons should make every effort to find and return lost items prior to payment.
+        </strong>
+        </p>
+    </td>
+</tr>
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/qtype_selector.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/qtype_selector.tt2
new file mode 100644 (file)
index 0000000..0baf486
--- /dev/null
@@ -0,0 +1,31 @@
+[%  query_types = [
+    {value => "keyword", label => l("Keyword")},
+    {value => "title", label => l("Title"), plural_label => l("Titles"), browse => 1},
+    {value => "jtitle", label => l("Journal Title")},
+    {value => "title|uniform", label => l("Uniform Title")},
+    {value => "author", label => l("Author"), plural_label => l("Authors"), browse => 1},
+    {value => "identifier|publisher", label => l("Publisher")},
+    {value => "subject", label => l("Subject"), plural_label => l("Subjects"), browse => 1},
+    {value => "series", label => l("Series"), plural_label => l("Series"), browse => 1}
+];
+    IF  ctx.get_org_setting(ctx.search_ou, 'opac.search.enable_bookplate_search');
+        query_types.push(
+            {value => "bookplate", label => l("Digital Bookplate"), plural_label => l("Digital Bookplates")}
+        );
+    END;
+-%]
+
+<select class="form-control w-100" name="[% name || 'qtype' %]"[% IF id; ' id="'; id ; '"' ; END -%]
+    title="[% l('Select query type:') %]">
+    [%  query_type = query_type || CGI.param('qtype') || search.default_qtypes.0;
+      FOR qt IN query_types;
+        NEXT IF browse_only AND NOT qt.browse -%]
+    <option value='[% qt.value | html %]'[%
+        query_type == qt.value ? ' selected="selected"' : ''
+    %]>[% IF plural AND qt.plural_label;
+        qt.plural_label | html;
+    ELSE;
+        qt.label | html;
+    END %]</option>
+    [% END -%]
+</select>
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/record/extras.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/record/extras.tt2
new file mode 100644 (file)
index 0000000..c43973d
--- /dev/null
@@ -0,0 +1,104 @@
+[%
+    arrow_right = '&#9658;';
+    arrow_down = '&#9660;';
+%]
+<div>
+    <div id='rdetail_extras_div' class="card-columns row" style='width: 100%;'>
+        [%
+            IF ctx.google_books_preview;
+                label = l('Google Preview');
+                name = 'google_preview';
+        %]
+        <div id="gbp_extra" class="card">
+            <div id="gbp_extra_links" class="card-header">
+                <a id='gbp_arrow_link' name='[% name %]' class='rdetail_extras_lbl'>[% arrow_right %]</a>
+                <a id='gbp_arrow_down_link' name='[% name %]' class='rdetail_extras_lbl'>[% arrow_down %]</a>
+                <a name='[% name %]_lbl' class="rdetail_extras_lbl">[% label %]</a></div>
+        </div>
+        <div id="gbp_extra_container" class='card-body'></div>
+        [%  END %]
+
+        [%  # Hidden extras are not yet implemented.  Some may require JS
+
+        MACRO tab_is_active(tab) BLOCK;
+            exp_name = 'expand_' _ tab;
+            IF ctx.$exp_name OR ctx.expand_all; 1; END;
+        END;
+
+        # Let's see if we should hide the content cafe / simple summary content
+        hide_summary = 1;
+        IF attrs.summaries.0; hide_summary = 0; ELSE;
+            # Expose content cafe if it's reasonable to do so.
+            # This approach only works when using embedded content cafe.
+            IF ENV.OILS_CONTENT_CAFE_USER;
+                ident = attrs.isbn_clean || attrs.upc;
+                IF ident; hide_summary = 0; END;
+            END;
+        END;
+
+        # if no added content is available, hide the main tab.
+        # if any content is available, use the first tab as the default display tab.
+        default_ac = '';
+        IF !tab_is_active('addedcontent');
+            hide_ac = 1;
+            FOR type IN ctx.added_content.keys;
+                IF ctx.added_content.$type.status != '2'; # not available
+                    hide_ac = 0;
+                END;
+                IF ctx.added_content.$type.status == '1';
+                    SET default_ac = type UNLESS default_ac;
+                END;
+            END;
+        END;
+
+        extras = [
+            {name => 'awards',  label => l('Awards, Reviews, & Suggested Reads')},
+            {name => 'annotation', label => l('Annotation'), hide => 1},
+            {name => 'summaryplus',  label => l('Summaries & More'), hide => hide_summary},
+            {name => 'excerpt',  label => l('Excerpt'), hide => 1},
+            {name => 'issues',   label => l('Issues Held'), hide => !(ctx.have_holdings_to_show || ctx.have_mfhd_to_show)},
+            {name => 'preview',  label => l('Preview'), hide => 1},
+            {name => 'addedcontent',  label => l('Additional Content'), hide => hide_ac},  # hide if all content is known to not exist
+            {name => 'cnbrowse', label => l('Shelf Browser')},
+            {name => 'marchtml', label => l('MARC Record')}
+        ];
+
+        FOREACH extra IN extras;
+            IF extra.hide; NEXT; END;
+            name = extra.name;
+        %]
+        <div class="card border-secondary col-12 p-0">
+         [%
+                    IF tab_is_active(name) OR name == 'awards';
+                        href = mkurl('', {}, ['expand', 'ac']);
+                        arrow = arrow_down;
+                    ELSE;
+                        IF name == 'addedcontent' AND default_ac;
+                            href = mkurl('', {expand => name, ac => default_ac}) _ '#' _ name;
+                        ELSE;
+                            href = mkurl('', {expand => name}) _ '#' _ name;
+                        END;
+                        arrow = arrow_right;
+                    END;
+                %]
+            <div class="card-header extra_header">
+              <a id='[% name %]' href='[% href %]' class="text-white" rel="nofollow" vocab="" style="text-decoration:none;">
+                <span>[% IF !(name == 'awards'); arrow; END %] [% extra.label | html %]</span>
+                </a>
+            </div>
+            [%  IF tab_is_active(name) OR name == 'awards'; %]
+            <div class='card-body'>
+
+                    [% IF name == 'marchtml';
+                        ctx.marchtml;
+                    ELSE;
+                        # Load the template for the selected extra
+                        INCLUDE "opac/parts/record/${name}.tt2";
+                    END;
+                    -%]
+            </div>
+            [% END %]
+        </div>
+        [% END %]
+    </div>
+</div>
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/record/summary.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/record/summary.tt2
new file mode 100644 (file)
index 0000000..78cfe6b
--- /dev/null
@@ -0,0 +1,575 @@
+[% PROCESS "opac/parts/misc_util.tt2";
+USE ResolverResolver;
+ctx.page_title = attrs.title | html
+ctx.metalinks.push('
+<meta property="og:image" content="' _ ctx.media_prefix _ '/opac/extras/ac/jacket/large/r/' _ ctx.bre_id _ '" />');
+%]
+<!-- ****************** rdetail_summary.xml ***************************** -->
+<abbr class="unapi-id" title='tag:[% ctx.hostname %],[% date.format(date.now, ' %Y') %]:biblio-record_entry/[%
+    ctx.bre_id %]'></abbr>
+
+<hr />
+
+[%-# This holds the record summary information %]
+<div class="row">
+    <div class="col-lg-3">
+        <div id="rdetail_image_div" class="w-100 text-center">
+            [%- IF obalkyknih_cz.enabled == 'true' %]
+            [%-
+            isbnissn = '';
+            IF attrs.isbns.0;
+            isbnissn = attrs.isbns.0;
+            IF (matches = isbnissn.match('^(.+?)(\s.+)$'));
+            isbnissn = matches.0;
+            END;
+            END;
+            IF attrs.issns.0;
+            isbnissn=attrs.issns.0;
+            END;
+            %]
+            <a href='http://obalkyknih.cz/view?isbn=[% isbnissn %]'>
+                <img alt="[% attrs.title _ ' Cover Image' | html %]" class='img-thumbnail w-auto'
+                    src='[% ctx.media_prefix %]/opac/extras/ac/jacket/[% record.summary.jacket_size %]/r/[% ctx.bre_id | uri %]' />
+            </a>
+            [% ELSE %]
+            <a href='[% ctx.media_prefix %]/opac/extras/ac/jacket/large/r/[% ctx.bre_id | uri %]'><img
+                    alt="[% attrs.title _ ' Cover Image' | html %]" class='img-thumbnail w-auto'
+                    src='[% ctx.media_prefix %]/opac/extras/ac/jacket/[% record.summary.jacket_size %]/r/[% ctx.bre_id | uri %]' />
+            </a>
+            [%- END %]
+
+            [%- IF attrs.format_label %]
+            [% FOR format IN attrs.all_formats %]
+            <span style="font-size:14px;" class="mt-3 d-block">
+                <img alt="[% format.label | html %]" src="[% format.icon %]" />
+                [% format.label | html %]
+            </span>
+            [% END %]
+            [%- END %]
+
+
+
+
+        </div>
+    </div>
+
+    <div class="col-lg-9">
+        <div class="row h-100">
+            <div class="col-lg-8">
+                <div id="rdetail_title_div">
+                <h1 id="rdetail_title" style="font-size: 1.8em;" property="name">[% IF attrs.hl.title; attrs.hl.title; ELSE; attrs.title_extended | html; END %]</h1>
+                [%-
+                FOR link880 IN attrs.graphic_titles;
+                FOR alt IN link880.graphic;
+                '<h2 class="graphic880"';
+                    IF alt.dir;
+                        ' dir="' _ alt.dir _ '"';
+                    END;
+                    '>'; alt.value | html; '</h2>';
+                END;
+                END;
+                -%]
+                [%- INCLUDE "opac/parts/record/authors.tt2" %]
+                [%- INCLUDE "opac/parts/record/contents-summaryonly.tt2" %]
+                </div>
+                <div>
+                    <button id="btnMore" data-toggle="collapse" data-target="#demo"
+                        class="btn btn-action btn-sm my-3"><i class="fas fa-info-circle" aria-hidden="true"></i> [%l ("More Details") %]</button>
+                    <div id="demo" class="collapse">
+                        <h2 class='rdetail_record_details'>[% l("Record details") %]</h2>
+                        <ul class="list-unstyled">
+                            [%- IF attrs.hl.isbn.size; FOR isbn IN attrs.hl.isbn %]
+                            <li class='rdetail_isbns'>
+                                <strong class='rdetail_label'>[% l('ISBN:'); %]</strong> 
+                                <span class='rdetail_value' property='isbn'>[% isbn %]</span>
+                            </li>
+                            [%- END; ELSIF attrs.isbns.0;
+                            FOR isbn IN attrs.isbns;
+                            isbn_extra = '';
+                            IF (matches = isbn.match('^(.+?)(\s.+)$'));
+                            isbn = matches.0;
+                            isbn_extra = matches.1;
+                            END;
+                            %]
+                            <li class='rdetail_isbns'>
+                                <strong class='rdetail_label'>[% l('ISBN:'); %]</strong>
+                                <span class='rdetail_value' property='isbn'>[% isbn | html %]</span>[% isbn_extra | html
+                                %]
+                            </li>
+                            [%- END %]
+                            [%- END %]
+                            [%- IF attrs.hl.issn.size; FOR issn IN attrs.hl.issn %]
+                            <li class='rdetail_issns'>
+                                <strong class='rdetail_label'>[% l('ISSN:'); %]</strong> [% issn %]
+                            </li>
+                            [%- END; ELSIF attrs.issns.0; FOR issn IN attrs.issns %]
+                            <li class='rdetail_issns'>
+                                <strong class='rdetail_label'>[% l('ISSN:'); %]</strong>
+                                <span class='rdetail_value'>[% issn | html %]</span>
+                            </li>
+                            [%- END %]
+                            [%- END %]
+                            [%- IF attrs.hl.physical_description.size %]
+                            [%-
+                                filtered_hl_phys_desc = [];
+                                FOR hl_phys_desc IN attrs.hl.physical_description;
+                                    hl_phys_desc = hl_phys_desc;
+                                    filtered_hl_phys_desc.push(hl_phys_desc);
+                                END;
+                            -%]
+                            <li id='rdetail_phys_desc'>
+                                <strong class='rdetail_label'>[% l("Physical Description:") %]</strong>
+                                <span class='rdetail_value' highlighted='true'>[%
+                                    filtered_hl_phys_desc.join('<br/>') %]</span>
+                            </li>
+                            [%- ELSIF attrs.phys_desc %]
+                            <li id='rdetail_phys_desc'>
+                                <strong class='rdetail_label'>[% l("Physical Description:") %]</strong>
+                                <span class='rdetail_value'>[% attrs.phys_desc | html %]</span>
+                            </li>
+                            [%- END %]
+                            [%- IF attrs.hl.edition %]
+                            <li id='rdetail_edition'>
+                                <strong class='rdetail_label'>[% l("Edition:") %]</strong>
+                                <span class='rdetail_value' highlighted='true'>[% attrs.hl.edition %]</span>
+                                [%- ELSIF attrs.edition %]
+                            <li id='rdetail_edition'>
+                                <strong class='rdetail_label'>[% l("Edition:") %]</strong>
+                                <span class='rdetail_value'>[% attrs.edition | html %]</span>
+                                [%-
+                                FOR entry IN attrs.graphic_editions;
+                                FOR alt IN entry.graphic;
+                                diratt = "";
+                                IF alt.dir;
+                                diratt = ' dir="' _ alt.dir _ '"';
+                                END;
+                                -%]
+                                <div class="graphic880 rdetail_value" [% diratt %]>
+                                    [% alt.value | html %]
+                                </div>
+                                [%-
+                                END;
+                                END;
+                                -%]
+                            </li>
+                            [%- END %]
+                            [%- IF attrs.hl.publisher %]
+                            <li id='rdetail_publisher'>
+                                <strong class='rdetail_label'>[% l("Publisher:") %]</strong>
+                                <span class='rdetail_value' highlighted='true'>[% attrs.hl.publisher %]</span>
+                            </li>
+                            [%- ELSIF attrs.publisher %]
+                            <li id='rdetail_publisher'>
+                                <strong class='rdetail_label'>[% l("Publisher:") %]</strong>
+                                <span class='rdetail_value' property="publisher" typeof="Organization">
+                                    [%- IF attrs.pubplace; %]
+                                    <span property="location">[% attrs.pubplace | html; %]</span>
+                                    [%- END; %]
+                                    <span property="name">[% attrs.publisher | html; %]</span>
+                                </span>
+                                [%- IF attrs.pubdate; %]
+                                <span property="datePublished">[% attrs.pubdate | html; %]</span>
+                                [%- END; %]
+                                [%-
+                                IF attrs.graphic_pubinfos.size > 0;
+                                FOR entry IN attrs.graphic_pubinfos;
+                                FOR alt IN entry.graphic;
+                                diratt = "";
+                                IF alt.dir;
+                                diratt = ' dir="' _ alt.dir _ '"';
+                                END;
+                                -%]
+                                <div class="graphic880" [% diratt %]>
+                                    [% alt.value | html %]
+                                </div>
+                                [%-
+                                END;
+                                END;
+                                END
+                                -%]
+                            </li>
+                            [%- END %]
+                            [%- IF attrs.producer %]
+                            <li id='rdetail_producer'>
+                                <strong class='rdetail_label'>[% l("Producer:") %]</strong>
+                                <span class='rdetail_value'>
+                                    [%- IF attrs.prodplace; %]
+                                    <span>[% attrs.prodplace | html; %]</span>
+                                    [%- END; %]
+                                    <span>[% attrs.producer | html; %]</span>
+                                    [%- IF attrs.proddate; %]
+                                    <span>[% attrs.proddate | html; %]</span>
+                                    [%- END; %]
+                                </span>
+                            </li>
+                            [%- END %]
+                            [%- IF attrs.distributor %]
+                            <li id='rdetail_distributor'>
+                                <strong class='rdetail_label'>[% l("Distributor:") %]</strong>
+                                <span class='rdetail_value'>
+                                    [%- IF attrs.distplace; %]
+                                    <span>[% attrs.distplace | html; %]</span>
+                                    [%- END; %]
+                                    <span>[% attrs.distributor | html; %]</span>
+                                    [%- IF attrs.distdate; %]
+                                    <span>[% attrs.distdate | html; %]</span>
+                                    [%- END; %]
+                                </span>
+                            </li>
+                            [%- END %]
+                            [%- IF attrs.manufacturer %]
+                            <li id='rdetail_manufacturer'>
+                                <strong class='rdetail_label'>[% l("Manufacturer:") %]</strong>
+                                <span class='rdetail_value' property="manufacturer" typeof="Organization">
+                                    [%- IF attrs.manplace; %]
+                                    <span property="location">[% attrs.manplace | html; %]</span>
+                                    [%- END; %]
+                                    <span property="name">[% attrs.manufacturer | html; %]</span>
+                                    [%- IF attrs.mandate; %]
+                                    <span>[% attrs.mandate | html; %]</span>
+                                    [%- END; %]
+                                </span>
+                            </li>
+                            [%- END %]
+                            [%- IF attrs.copyright %]
+                            <li id='rdetail_copyright'>
+                                <strong class='rdetail_label'>[% l("Copyright:") %]</strong>
+                                <span class='rdetail_value'>[% attrs.copyright | html_entity; %]
+                                    [%-# Provide the 4-digit year, cleansed of '@' and other junk %]
+                                    [%- IF attrs.copyrightYear -%]
+                                    <meta property='copyrightYear' content='[% attrs.copyrightYear | html; %]'>
+                                    [%- END -%]
+                                </span>
+                            </li>
+                            [%- END %]
+                            [%- IF (ctx.badge_scores.size > 0 && ctx.hide_badge_scores != 'true') %]
+                            <li id='rdetail_badges'>
+                                <strong class='rdetail_label'>[% l("Badges:") %]</strong>
+                                <ul>
+                                    [% FOR bscore IN ctx.badge_scores; %]
+                                    <li><strong>[% bscore.badge.name | html %]</strong>: [% bscore.score %] / 5.0</li>
+                                    [%- END -%]
+                                </ul>
+                            </li>
+                            [%- END %]
+                        </ul>
+
+
+                        [%- INCLUDE "opac/parts/record/contents.tt2" %]
+                        [%- INCLUDE "opac/parts/record/subjects.tt2" %]
+                        [%- INCLUDE "opac/parts/record/series.tt2" %]
+
+                    </div>
+
+                </div>
+                <script>
+                    $(document).ready(function() {
+                        $('#demo').on('hidden.bs.collapse', function () {
+                            $('#btnMore').html("<i class='fas fa-info-circle' aria-hidden='true'></i> [%l ('More Details') %]");
+                        })
+                        $('#demo').on('shown.bs.collapse', function () {
+                            $('#btnMore').html("<i class='fas fa-info-circle' aria-hidden='true'></i> [%l ('Fewer Details') %]");
+                        })
+                    });
+                    </script>
+
+               <div id="copy_hold_counts">
+
+                [%-
+                # Hold/copy summary
+                IF ctx.copy_summary.0.count;
+                INCLUDE "opac/parts/record/copy_counts.tt2";
+                %]
+
+
+                [%- END %]
+
+                </div> <!-- metarecord_population -->
+                        <div>
+                            [%-
+                            # l( 'mmr id = ' _ ctx.mmr_id );
+                            # l( 'mmr data = ' _ ctx.mmr_data );
+                            mmr_attrs = {marc_xml => ctx.mmr_data.marc_xml};
+                            save_args = args; # need to stash the original args
+                                              # until we're done processing the
+                                              # metarecord
+                            PROCESS get_marc_attrs args=mmr_attrs;
+
+                            IF args.mmr_unique_bib.size > 1;
+                            %]
+                            <h2 class="rdetail_other_formats">[% l("Other Formats and Editions") %]</h2>
+                            <span class="metarecord_population_format">
+                                [%- IF mmr_attrs.format_label;
+
+                                FOR format IN mmr_attrs.all_formats;
+
+                                link = mkurl(ctx.opac_root _ '/record/' _ format.source_bibs.0);
+                                IF format.source_bibs.size > 1;
+                                link = mkurl( ctx.opac_root _ '/results', { modifier => 'metabib', metarecord =>
+                                ctx.mmr_id, 'fi:icon_format' => format.search_format, 'fi:from_metarecord' => ctx.mmr_id
+                                }, stop_parms.merge(expert_search_parms, general_search_parms, browse_search_parms,
+                                facet_search_parms,
+                                ['qtype','fi:search_format','fi:icon_format','fi:item_lang','fi:from_metarecord']) );
+                                END; -%]
+                                <span class="metarecord_population_span_link">
+                                    <a href="[%- l( link ) %]">
+                                        [% format.label | html %]
+                                        ([%- l( format.source_bibs.size ) %])
+                                    </a></span><br />
+
+                                [%- END %]
+                            </span>
+                            [%- IF mmr_attrs.all_lang.size > 0 %]
+                            <span class="metarecord_population_item_lang">
+                                [% FOR lang IN mmr_attrs.all_lang;
+                                link = mkurl(ctx.opac_root _ '/record/' _ lang.source_bibs.0);
+                                IF lang.source_bibs.size > 1;
+                                USE url(ctx.opac_root _ '/results');
+                                link = mkurl( ctx.opac_root _ '/results', { modifier => 'metabib', metarecord =>
+                                ctx.mmr_id, 'fi:item_lang' => lang.search_format, 'fi:from_metarecord' => ctx.mmr_id },
+                                stop_parms.merge(expert_search_parms, general_search_parms, browse_search_parms,
+                                facet_search_parms,
+                                ['qtype','fi:search_format','fi:icon_format','fi:item_lang','fi:from_metarecord']) );
+                                END; -%]
+                                <span class="metarecord_population_span_link">
+                                    <a href="[%- l( link ) %]">
+                                        [% lang.label | html %]
+                                        ([%- l( lang.source_bibs.size ) %])
+                                    </a></span><br />
+                                [%- END %]
+                            </span> <!-- metarecord_population_item_lang -->
+                            [%- END %]
+                            <div class="metarecord_population_all">
+                                [%
+                                link = mkurl( ctx.opac_root _ '/results', { modifier => 'metabib', metarecord =>
+                                ctx.mmr_id, 'fi:from_metarecord' => ctx.mmr_id }, stop_parms.merge(expert_search_parms,
+                                general_search_parms, browse_search_parms, facet_search_parms,
+                                ['qtype','fi:search_format','fi:icon_format','fi:item_lang','fi:from_metarecord'] ) );
+                                %]
+                                <span class="metarecord_population_span_link">
+                                    <a href="[%- l( link ) %]">[% l("View all formats and editions ") %] ([%-
+                                        args.mmr_unique_bib.size %])
+                                    </a></span><br />
+                            </div>
+                            [%- END;
+                            END # ending tag for IF args.mmr_unique_bib.size > 1; %]
+                            [% args = save_args; %]
+                        </div>
+
+            </div>
+            <!--rdetail_title_div-->
+
+            <div class="col-lg-4">
+             <div id="actions" class="mx-auto btn-group-vertical dropright mt-3">
+                [%- search_ou = ctx.search_ou;
+                IF ctx.place_unfillable ||
+                ( attrs.marc_xml.findnodes('//*[local-name()="holdings" and @has_holdable="true"]').size
+                && (ctx.holds_block.enabled != 'true' || !attrs.org_copy_counts.$search_ou.available)
+                )
+                %]
+                
+                    <a class="btn btn-action no-dec" role="button" href="[% mkurl(ctx.opac_root _ '/place_hold',
+                    {hold_target => ctx.bre_id, hold_type => 'T', hold_source_page => mkurl()}, stop_parms) %]">
+                        <span class="place_hold"><i class="fas fa-check" aria-hidden="true"></i> [% l('Place Hold') %]</span></a>
+              
+                [%- END -%]
+
+                [%- IF ebook_api.enabled == 'true' && args.ebook %]
+              
+                    <div id="[%- ctx.bre_id -%]_ebook_checkout" class="rdetail_aux_utils ebook_action hidden">
+                        <a class="btn btn-action no-dec" role="button" href="[% mkurl(ctx.opac_root _ '/myopac/ebook_checkout',
+                    {title => args.ebook.ebook_id, vendor => args.ebook.vendor, action => 'checkout'}, stop_parms) %]"
+                            rel="nofollow" vocab="">
+                            <span class="place_hold"><i class="fas fa-check" aria-hidden="true"></i> [% l('Check Out E-Item') %]</span></a>
+                    </div>
+               
+               
+                    <div id="[%- ctx.bre_id -%]_ebook_place_hold" class="rdetail_aux_utils ebook_action hidden">
+                        <a class="btn btn-action no-dec" role="button" href="[% mkurl(ctx.opac_root _ '/myopac/ebook_place_hold',
+                    {title => args.ebook.ebook_id, vendor => args.ebook.vendor, action => 'place_hold'}, stop_parms) %]"
+                            rel="nofollow" vocab="">
+                            <span class="place_hold"><i class="fas fa-check" aria-hidden="true"></i> [% l('Place Hold on E-Item') %]</span></a>
+                    </div>
+               
+                [%- END -%]
+
+
+               
+                    [% operation = ctx.mylist.grep('^' _ ctx.bre_id _ '$').size ? "delete" : "add";
+                    addhref = mkurl(ctx.opac_root _ '/mylist/add', {record => ctx.bre_id}, stop_parms);
+                    delhref = mkurl(ctx.opac_root _ '/mylist/delete', {record => ctx.bre_id}, stop_parms);
+                    label = (operation == "add") ? l("Add to Basket") : l("Remove from Basket");
+                    %]
+                    <a href="[% addhref %]" id="mylist_add_[% ctx.bre_id %]"
+                        data-recid="[% ctx.bre_id %]" data-action="add" role="button"
+                        class="btn btn-action mylist_action [% IF ctx.mylist.grep('^' _ ctx.bre_id _ '$').size %]hidden[% END %]"
+                        title="[% l(" Add [_1] to basket", attrs.title) | html %]" rel="nofollow" vocab="">
+                        <i class="fas fa-shopping-basket" aria-hidden="true"></i>
+                        [% l("Add to basket") %]
+                    </a>
+                    <a href="[% delhref %]" id="mylist_delete_[% ctx.bre_id %]"
+                        data-recid="[% ctx.bre_id %]" data-action="delete" role="button"
+                        class="btn btn-action mylist_action [% IF !ctx.mylist.grep('^' _ ctx.bre_id _ '$').size %]hidden[% END %]"
+                        title="[% l(" Remove [_1] from basket", attrs.title) | html %]" rel="nofollow" vocab="">
+                        <i class="fas fa-minus-circle" aria-hidden="true"></i>
+                        [% l("Remove from basket") %]
+                    </a>
+               
+                [% IF ctx.mylist.size %]
+               
+                    [%- IF ctx.user; %]
+                    <a href="[% mkurl(ctx.opac_root _ '/myopac/lists') %]" class="btn btn-action" role="button" rel="nofollow" vocab=""><i class="fas fa-glasses" aria-hidden="true"></i> [% l(' View Basket') %]</a>
+                    [%- ELSE %]
+                    <a href="[% mkurl(ctx.opac_root _ '/mylist') %]" class="btn btn-action" role="button" rel="nofollow" vocab=""><i class="fas fa-glasses" aria-hidden="true"></i> [% l(' View My Basket') %]</a>
+                    [%- END %]
+              
+                [% END %]
+
+                [% IF !ctx.is_staff %]
+                    [% IF ctx.user; %]
+                    [% INCLUDE "opac/parts/bookbag_actions.tt2"; %]
+                    [% END %]
+                [% END %]
+
+               
+                  
+                    <a href="[% mkurl(ctx.opac_root _ '/record/print_preview/' _ ctx.bre_id) %]" class="btn btn-action" role="button" rel="nofollow"
+                        vocab=""><i class="fas fa-print" aria-hidden="true"></i>[% l('Print') %]</a> 
+                    <a href="[% mkurl(ctx.opac_root _ '/record/email_preview/' _ ctx.bre_id) %]" class="btn btn-action" role="button" rel="nofollow"
+                        vocab=""> <i class="fas fa-envelope-open-text" aria-hidden="true"></i>[% l('Email') %]</a>
+                
+                [%- IF ctx.refworks.enabled == 'true' %]
+                [%- INCLUDE 'opac/parts/record/refworks.tt2' %]
+                [%- END %]
+                [% IF !ctx.is_staff %]
+                
+                    <a href="[% mkurl('', {locg =>CGI.param('locg'), copy_depth =>CGI.param('copy_depth')}, 1) %]"
+                        class="btn btn-action" role="button">
+                        <i class="fas fa-link" aria-hidden="true"></i>
+                        [% l('Permalink') %]
+                    </a>
+              
+                [% END %]
+                [% IF !search.no_highlight %]
+               
+                    [% IF CGI.param('no_highlight') %]
+                    <a class="btn btn-action no-dec" role="button" href="[% mkurl('', {}, ['no_highlight']) %]">
+                        [% ELSE %]
+                        <a href="[% mkurl('', {no_highlight => '1'}) %]" class="btn btn-action" role="button">
+                            [% END %]
+                            <i class="fas fa-highlighter" aria-hidden="true"></i>
+                            [% CGI.param('no_highlight') ? l('Enable Highlighting') : l('Disable Highlighting') %]
+                        </a>
+              
+                [% END %]
+                [%- IF ctx.is_staff %]
+                
+                    <a href="[% ctx.media_prefix %]/opac/extras/ac/clearcache/all/r/[% ctx.bre_id | uri %]"
+                        class="btn btn-action" role="button" target="_blank">
+                        <i class="fas fa-sync-alt" aria-hidden="true"></i>
+                        [% l('Clear Added Content Cache') %]
+                    </a>
+                
+                [%- END %]
+
+            </div>
+
+        </div>
+    </div>
+</div>
+</div>
+<div class="row">
+<div class="col-12">
+
+        [%-
+        IF ctx.copy_summary.0.count;
+        INCLUDE "opac/parts/record/copy_table.tt2" copies=ctx.copies;
+        END;
+        %]
+
+
+        [%- IF openurl.enabled == 'true';
+        openurls = [];
+        FOREACH issn IN args.issns;
+        NEXT IF issn == '';
+        openurls = openurls.import(ResolverResolver.resolve_issn(issn, openurl.baseurl));
+        END;
+        IF openurls.size && openurls.0 != '';
+        %]
+        <div id='rdetail_openurl'>
+            <strong class='rdetail_openurl_title'>[% l("Electronic resources") %]</strong>
+            <table>
+                <tbody>
+                    [%-
+                    FOREACH res IN openurls;
+                    %]
+                    <tr>
+                        <td class='rdetail_openurl_entry'><a href="[% res.target_url %]">[% res.public_name | html
+                                %]</a></td>
+                        <td>[% res.target_coverage | html %]
+                            [%- IF res.target_embargo != '';
+                            ' - ';
+                            res.target_embargo | html;
+                            END;
+                            -%]
+                        </td>
+                    </tr>
+                    [%- END %]
+                </tbody>
+            </table>
+        </div>
+        [%- END %]
+        [%- END %]
+        [%- merged_uris = args.uris.merge(args.online_res);
+        num_uris = merged_uris.size;
+        IF num_uris > 0;
+        -%]
+
+        <h2 class="rdetail_uris">[% l("Electronic resources") %]</h2>
+        <div class="rdetail_uris">
+            [%- IF num_uris > 1 %]<ul>[% END %]
+                [%- FOR uri IN merged_uris %]
+                [%-
+                    filtered_href = uri.href | html;
+                    filtered_link = uri.link ? uri.link : '' | html;
+                    filtered_note = uri.note ? uri.note : '' | html;
+                    filtered_materials = uri.materials ? uri.materials : '' | html;
+                    filtered_access = uri.access ? uri.access : '' | html;
+                -%]
+                [%- IF num_uris == 1 -%]
+                <p class="rdetail_uri" property="offers" vocab="http://schema.org/" typeof="Offer">
+                    [%- ELSE -%]
+                    <li class="rdetail_uri" property="offers" vocab="http://schema.org/" typeof="Offer">
+                        [%- END -%]
+                        <a href="[% filtered_href %]" class="uri_link" property="url">
+                            [%- IF filtered_href != filtered_link;
+                            '<span property="description">' _ filtered_link _ '</span>';
+                            ELSE;
+                            filtered_link;
+                            END;
+                            -%]
+                        </a>
+                        [%- '<ul><li property="description">' _ filtered_note _ '</li></ul>' IF filtered_note %]
+                        [%- '<ul><li property="description">' _ filtered_materials _ '</li></ul>' IF filtered_materials %]
+                        [%- '<ul><li property="description">' _ filtered_access _ '</li></ul>' IF filtered_access %]
+                        <link property="availability" href="http://schema.org/OnlineOnly" />
+                        [%- IF attrs.gtin13; '
+                        <meta property="gtin13" content="' _ attrs.gtin13 _ '" />'; END; %]
+                        [%- IF num_uris == 1 %]</p>[% ELSE %]</li>[% END %]
+                [%- END; %]
+                [%- IF num_uris > 1 %]</ul>[% END %]
+        </div>
+        [%- END; %]
+        [%
+        IF ebook_api.enabled == 'true';
+        INCLUDE "opac/parts/ebook_api/avail.tt2";
+        END;
+        %]
+    </div>
+</div>
+<hr>
+<div class="row">
+    <div class="col-12">
+        [%- INCLUDE "opac/parts/record/extras.tt2" %]
+    </div>
+</div>
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/topnav.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/topnav.tt2
new file mode 100644 (file)
index 0000000..5974bc6
--- /dev/null
@@ -0,0 +1,17 @@
+[%- IF ctx.maintenance_message -%]
+<div class="alert alert-[% ctx.maintenance_type %] alert-dismissible mb-0 text-center" role="alert">
+    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
+        <span aria-hidden="true">&times;</span>
+      </button>
+[% ctx.maintenance_message %]
+</div>
+[%- END -%]
+[% IF !ctx.is_staff %]
+[% INCLUDE "opac/parts/topnav_logo.tt2" %]
+<div id="header-wrap">
+[% INCLUDE "opac/parts/topnav_links.tt2" %]
+</div>
+[% END %]
+<div id="subheader-wrap">
+ [% INCLUDE "opac/parts/topnav_subnav.tt2" %]
+ </div>
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/topnav_links.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/topnav_links.tt2
new file mode 100644 (file)
index 0000000..480c7a7
--- /dev/null
@@ -0,0 +1,82 @@
+<nav class="navbar navbar-expand-lg navbar-dark ">
+<!--Home-->
+  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
+    <span class="navbar-toggler-icon"></span>
+  </button>
+  <div class="collapse navbar-collapse" id="navbarNav">
+  <!--Left Links-->
+
+
+   <ul class="navbar-nav nav-fl px-3">
+      <li class="nav-item">
+        <a class="nav-link" href="https://www.cwmars.org/#h.p_hRgZvBvYJgE9" target="_blank" rel="noopener">
+        <i class="fas fa-mobile-alt" style="color: #fff;"></i>Mobile App
+        </a>
+      </li>
+      <li class="nav-item">
+        <a class="nav-link" href="/eg/opac/ecard/form">
+        <i class="fas fa-id-card" style="color: #fff;"></i>Get an eCard
+        </a>
+      </li>
+      <li class="nav-item">
+        <a class="nav-link" href="https://www.cwmars.org/memberlibraries" target="_blank" rel="noopener">
+        <i class="fas fa-map-marker-alt" style="color: #fff;"></i>Libraries
+        </a>
+      </li>
+      <li class="nav-item">
+        <a class="nav-link" href="http://cwmars.overdrive.com/" target="_blank" rel="noopener">
+        <i class="fas fa-globe" style="color: #fff;"></i>OverDrive Catalog
+        </a>
+      </li>
+    </ul>
+    <!--Right Links-->
+    <ul class="navbar-nav ml-auto nav-fr px-3">
+      <!--If not signed in, show sign in button-->
+    [% IF !ctx.user %]
+        <li class="nav-item">
+           [% IF ctx.page != 'login' %]
+           <a href="#loginModal" data-toggle="modal" data-target="#loginModal" class="nav-link login">
+           [% ELSE %] <a href="/eg/opac/login" class="nav-link login">
+            [% END %] [% l('My Account') %] </a>
+        </li>
+      <!--User is signed in-->
+    [% ELSE %]
+    <li><div class="dropdown-divider"></div></li>
+       <!--User-->
+       <li class="nav-item">
+               <a class="nav-link disabled active mx-2" href="#">[% l('Hello, [_1] [_2]', ctx.user.pref_first_given_name || ctx.user.first_given_name, ctx.user.pref_family_name || ctx.user.family_name) | html %]</a>
+       </li>
+       <!--Messages with sup tag for # of messages-->
+       <li class="nav-item">
+          <a class="nav-link  [% IF ctx.user_stats.messages.unread %] active [% END %]" href="[% mkurl(ctx.opac_root _ '/myopac/messages', {}, ['single', 'message_id']) %]">
+                      [% IF ctx.user_stats.messages.unread %]
+                          <span class="badge badge-danger" style="font-size:unset;">
+                              [%- ctx.user_stats.messages.unread -%]
+                              <span class="sr-only">[% l('unread') %]</span>
+                          </span>
+                      [% END %]
+                      [% l('Messages') %]
+            </a>
+        </li>
+        <!--My Account-->
+        <li class="nav-item">
+         <a class="nav-link" href="[% mkurl(ctx.opac_root _ '/myopac/main', {}, ['single', 'message_id', 'sort','sort_type']) %]">[% l('My Account') %]</a>
+        </li>
+        <!--Lists Link-->
+        <li class="nav-item">
+        <a class="nav-link" href="[% mkurl(ctx.opac_root _ '/myopac/lists', {}, ['single', 'message_id']) %]">[% l('My Lists') %]</a>
+        </li>
+        <!--Logout-->
+        <li class="nav-item">
+        <a class="nav-link" href="[% mkurl(ctx.opac_root _ '/logout', {}, 1) %]" id="logout_link">[% l('Logout') %]</a>
+        </li>
+      [% END %]
+      <!--must end ul and div no matter the user state-->
+    </ul>
+       </div>
+
+
+
+         </nav>
+
+
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/parts/topnav_logo.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/parts/topnav_logo.tt2
new file mode 100644 (file)
index 0000000..0a37547
--- /dev/null
@@ -0,0 +1,5 @@
+<div id="topnav_logo">
+<a href="/eg/opac">
+<img id="topnav_logo_image" alt="[% l('Evergreen Logo') %]" src="[% ctx.media_prefix %]/opac/images/small_logo[% ENV.OILS_OPAC_LIBRARY_ID %].png[% ctx.cache_key %]" class="mr-2" />
+</a>
+</div>
diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/register.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/register.tt2
new file mode 100644 (file)
index 0000000..f787ac3
--- /dev/null
@@ -0,0 +1,296 @@
+[%- PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/org_selector.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Request Library Card");
+
+# for privacy, reload the page after (default) 5 minutes
+refresh_time = ctx.register.settings.refresh_timeout || 300;
+ctx.refresh = refresh_time _ '; ' _ ctx.opac_root _ '/home';
+
+# some useful variables and MACROs for display,
+# field validation, and added info display
+
+ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id;
+
+# list of the registration fields to (potentially)
+# display in the order they should be shown
+
+# post_code is the only field below that is required in the database and
+# post_code is only required if an address is created.
+# To prevent any of these fields from showing locally, regardless org unit
+# settings, simply remove the fields from this list.  In the case of
+# addresses, if all address fields are removed, no attempt at creating
+# an address will be made (and post_code will no longer be required).
+
+register_fields = [
+    {class => 'stgu',  name = 'first_given_name', label => l('First Name')},
+    {class => 'stgu',  name = 'second_given_name', label => l('Middle Name')},
+    {class => 'stgu',  name = 'family_name', label => l('Last Name')},
+    {class => 'stgu',  name = 'pref_first_given_name', label => l('Preferred First Name')},
+    {class => 'stgu',  name = 'pref_second_given_name', label => l('Preferred Middle Name')},
+    {class => 'stgu',  name = 'pref_family_name', label => l('Preferred Last Name')},
+    {class => 'stgma', name = 'street1', label => l('Street Address')},
+    {class => 'stgma', name = 'street2', label => l('Street Address (2)')},
+    {class => 'stgma', name = 'city', label => l('City')},
+    {class => 'stgma', name = 'county', label => l('County')},
+    {class => 'stgma', name = 'state', label => l('State')},
+    {class => 'stgma', name = 'post_code', label => l('Zip Code')},
+    {class => 'stgu',  name = 'dob', label => l('Date of Birth')},
+    {class => 'stgu',  name = 'day_phone', label => l('Phone Number')},
+    {class => 'stgu',  name = 'email', label => l('Email Address')}
+    {class => 'stgu',  name = 'usrname', label => l('Requested Username')}
+];
+
+# The dojo date widget in the patron edit UI only accepts default 
+# values in ISO8601 format.  It will not accept locale-shaped dates.
+# Force change it for this form:
+ctx.register.settings.stgu.dob.example = l('YYYY-MM-DD (1970-05-29)');
+
+
+
+%]
+
+<style type="text/css">
+#stgu\.first_given_name, #stgu\.second_given_name, #stgu\.family_name,
+ #stgu\.pref_first_given_name, #stgu\.pref_second_given_name,
+ #stgu\.pref_family_name, #stgma\.street1, #stgma\.street2, #stgma\.city,
+ #stgma\.county, #stgma\.state, #stgma\.post_code {
+ text-transform: uppercase;
+}
+</style>
+<h2 class="sr-only">[% l('Account Registration') %]</h2>
+<div class="container">
+    <div id="main-content-register">
+        <h1>[% l('Request a Library Card')%]</h1>
+        <span class="validate">&bigstar; [% l('indicates Required Field') %]</span>
+        <hr/>
+
+        [% IF ctx.register.success %]
+            <h3>Thank you for submitting your request for a library card!<h3>
+            <h4>Please allow time for a library staff member to review your application
+and reach out with next steps. If you have any questions or concerns,
+please contact your <a href="https://www.cwmars.org/memberlibraries">library.</a></h4>
+
+            [% IF ctx.register.username_taken %]
+            <p>
+                [% |l %]
+                Note: The selected username may be in use by another patron.
+                You may select another username when finalizing your
+                registration or in the online catalog.
+                [% END %]
+            </p>
+            [% END %]
+
+            <br/>
+            <p>
+                <a href="[% ctx.opac_root %]/home"
+                    class="btn btn-confirm">[% l('Return to the Catalog') %]</a>
+            </p>
+
+        [% ELSIF ctx.register.error %]
+            <h3>[% l('A registration error has occurred') %]</h3>
+            <h4>[% l('Please see library staff to complete your registration.') %]</h4>
+
+            <br/>
+            <p>
+                <a href="[% ctx.opac_root %]/home"
+                    class="btn btn-confirm">[% l('Return to the Catalog') %]</a>
+            </p>
+
+        [% ELSE %]
+
+        [% IF ctx.user %]
+            <!-- if the user is logged in, make it
+                clear we are tracking the requestor -->
+            <h4>[% l('New account requested by [_1] [_2] [_3] [_4] [_5]',
+                    ctx.user.prefix, ctx.user.first_given_name,
+                    ctx.user.second_given_name, ctx.user.family_name,
+                    ctx.user.suffix
+                ) | html %]</h4>
+        [% END %]
+
+        <form method='POST' class="needs-validation" novalidate>
+            <div class="form-group row">
+                <label class="control-label col-md-2" for='stgu.home_ou'>[% l('Home Library') %]</label>
+                <div class="col-md-6">
+                    [% INCLUDE build_org_selector
+                            name='stgu.home_ou'
+                            value=value || ctx_org
+                            can_have_users_only=1
+                            valid_org_list=ctx.register.valid_orgs
+                    %]
+                </div>    
+                <div class="col-md-4">
+                    [% IF ctx.register.invalid.bad_home_ou %]
+                    <span class='patron-reg-invalid'>
+                        [% l('Please select a valid library') %]
+                    </span>
+                    [% END %]
+                </div>
+            </div>
+
+[%
+# <=== shifting code left for readability
+
+# render a row for each of the register fields
+FOR field_def IN register_fields;
+    fclass = field_def.class;
+    fname = field_def.name;
+    orig_name = fname;
+
+    field_path = fclass _ "." _ fname;
+
+    IF fname.match('^pref_');
+        # Preferred name fields adopt most visibility, etc.
+        # settings from the primary name counterparts.
+        fname = fname.remove('^pref_');
+    END;
+
+    show = ctx.register.settings.$fclass.$fname.show;
+    require = ctx.register.settings.$fclass.$fname.require;
+    example = ctx.register.settings.$fclass.$fname.example;
+    value = ctx.register.values.$fclass.$fname;
+
+    invalid_require = ctx.register.invalid.$fclass.$fname.require;
+    invalid_regex = ctx.register.invalid.$fclass.$fname.regex;
+
+    IF orig_name.match('^pref_');
+        show = show || require;
+        require = 0; # pref name values never required
+    END;
+
+    NEXT UNLESS require OR show;
+%]
+
+<div class="form-group row">
+        <label class="control-label col-md-2" for='[% field_path %]'>[% field_def.label | html %]
+        [% IF require %]
+        <span class="validate">&bigstar;</span>
+        [% END %]
+        </label>
+        <div class="col-md-6">
+            [% IF fname == "dob"; %]
+            <div class="input-group date" data-provide="datepicker-inline">
+                <input type="text" class="form-control datepicker" id='[% field_path %]'
+                    name='[% field_path %]' value='[% value || CGI.param(field_path) | html %]' [% IF require %]required[% END %] data-date-format="yyyy-mm-dd" />
+                <div class="input-group-addon">
+                    <span class="glyphicon glyphicon-th"></span>
+                </div>
+            </div>
+           [% ELSE; %]
+        <input
+            class='form-control'
+            type='text'
+            id='[% field_path %]'
+            name='[% field_path %]'
+            value='[% value || CGI.param(field_path) | html %]' [% IF require %]required[% END %]/>
+     [% END %]
+        <div class="invalid-feedback">
+          [% l('Please enter a [_1]', field_def.label) | html %]
+        </div>
+
+        </div>
+
+    <div class="col-md-4">
+    <!-- display errors and example text -->
+
+    [% IF invalid_require %]
+        <span class='patron-reg-invalid'>
+            [% l('This field is required') %]
+        </span>
+    [% ELSIF invalid_regex %]
+        <span class='patron-reg-invalid'>
+            [% l('The value entered does not have the correct format') %]
+        </span>
+    [% END %]
+    [% IF example %]
+        <span class='patron-reg-extra'>
+            [% l('(Example: [_1])', example) %]
+        </span>
+    [% END %]
+    </div>
+</div>
+[% END %]
+
+
+<!-- ====> shifting the code back to the right for context -->
+                    [% IF ctx.register.opt_in_settings.size > 0 %]
+                        [% FOR optin IN ctx.register.opt_in_settings %]
+                        <div class="form-group row">
+                            <label class="control-label col-md-2" for="stgs.[% optin.name | uri %]'">[% optin.label | html %]</label>
+                            <div class="col-md-6">
+                                <input type='checkbox'
+                                    name='stgs.[% optin.name | uri %]'
+                                    id='stgs.[% optin.name | uri %]'
+                                    title="[% optin.label | html %]"
+                                ></input>
+                            </div>
+                            <div class="col-md-4">
+                            <!-- display errors and example text -->
+                            </div>
+                        </div>
+                        [% END %]
+                    [% END %]
+                    <div class="form-group-row">
+                    <div class="col-md-10 offset-md-2">
+                    <p style="font-size: 120%;"><strong>
+                    Submit this form to request a library card from
+                    your local library.</strong></p>
+                    <p style="font-size: 120%;"><strong> By
+                    submitting, you understand and agree to the <a target="_blank" rel="noopener"
+                    href="https://www.cwmars.org/about/borrowing-lending">CW
+                    MARS shared network policies</a><br>as well as any
+                    <a href="https://www.cwmars.org/memberlibraries" target="_blank" rel="noopener">local library</a> policies, rules, and regulations.
+                    </strong></p>
+                    <p style="font-size: 120%;"><strong>
+                    Please ensure you have entered at least one form
+                    of contact (phone number and/or email address),<br>
+                    so that staff at your local library can follow up
+                    as necessary.
+                    </strong></p>
+                    </div>
+                    </div>
+
+                    <div class="form-group row">
+                       <div class="col-md-6 offset-md-2">
+                            <a href="[% ctx.opac_root %]/home"
+                                class="btn btn-confirm">[% l('Go Back') %]</a>
+                            <input type="submit"
+                                value="[% l('Submit Registration') %]"
+                                class="btn btn-confirm" />
+                       </div>
+                    </div>
+            </form>
+            [% END %]
+        </div>
+    </div>
+[%- END %]
+<script>
+(function() {
+  'use strict';
+  window.addEventListener('load', function() {
+    // Fetch all the forms we want to apply custom Bootstrap validation styles to
+    var forms = document.getElementsByClassName('needs-validation');
+    // Loop over them and prevent submission
+    var validation = Array.prototype.filter.call(forms, function(form) {
+      form.addEventListener('submit', function(event) {
+        if (form.checkValidity() === false) {
+          event.preventDefault();
+          event.stopPropagation();
+        }
+        form.classList.add('was-validated');
+      }, false);
+    });
+  }, false);
+})();
+
+$(document).ready(function(){
+   $('.datepicker').datepicker({
+        weekStart: 1,
+        autoclose: true,
+        todayHighlight: true,
+    });
+    $('.datepicker').datepicker("setDate", "");
+});
+</script>
diff --git a/Open-ILS/src/templates_cons/kpac/getit.tt2 b/Open-ILS/src/templates_cons/kpac/getit.tt2
new file mode 100644 (file)
index 0000000..d08dd36
--- /dev/null
@@ -0,0 +1,178 @@
+[%  
+    PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/misc_util.tt2"; # MARC 
+    WRAPPER "kpac/parts/subpage.tt2";
+    attrs = {marc_xml => ctx.marc_xml};
+    INCLUDE get_marc_attrs args=attrs;
+    ctx.page_title = attrs.title | html 
+%]
+
+<div id="search_results_parent">
+    [% INCLUDE 'kpac/parts/record_row.tt2' rec_id=ctx.bre_id %]
+ <div class="sub_header">[% l('You can find this item at these locations:') %]</div>
+  <div class="item_detail_location_wrapper">
+    [% INCLUDE 'kpac/parts/copy_table.tt2' rec_id=ctx.bre_id %]
+  </div>
+ <div>[% INCLUDE 'kpac/parts/addedcontent.tt2' %]</div>
+</div>
+          
+<div class="checkout_options">
+    <table cellpadding="0" cellspacing="0" border="0">
+        <tr>
+            <td valign="top" class="left_brain_cell">
+                <div class="left_brain">
+
+                    [% WRAPPER 'kpac/parts/help_popups.tt2' popup_id='card_help' %]
+                        <img src="[% ctx.media_prefix %]/images/kpac/library_card.png[% ctx.cache_key %]" alt="[% l('library card') %]" /></div></td>
+                    [% END %]
+                    [% WRAPPER 'kpac/parts/help_popups.tt2' popup_id='password_help' %]
+                        <p>[% l('Enter your password') %]</p>
+                    [% END %]
+
+                    <div class="top_side">
+                        <h2>[% l('get it!') %]</h2>
+                        <p>[% l('If you would like to place a hold on this item, please enter the ' _
+                            'following information and click Submit below:') %]</p>
+                    </div>
+
+                    <form method='POST'><!-- login + place hold form -->
+
+                        <div class="checkout_box">
+                            <div class="box1_top">&nbsp;</div>
+                            <div class="box_inside">
+
+                                [% IF !ctx.user %]
+                                    [% seed = l(' Enter Numbers... ') %]
+                                    <p>[% l('Library Card Number without spaces:') %]</p>
+                                    <div class="input_box">
+                                        <input name="username" type="text" class="text_box" style="color:#aaa;" placeholder="[% seed %]" />
+                                    </div>
+                                    <a class="help_btn" href="javascript:;" 
+                                        onclick="helpPopup('card_help', this, event);"><img 
+                                        src="[% ctx.media_prefix %]/images/kpac/question_mark.png[% ctx.cache_key %]" alt="[% l('pin number help') %]" /></a>
+
+                                    <div class="clear">&nbsp;</div>
+                                    <div class="hr">&nbsp;</div>
+
+                                    <p>[% l('Password') %]</p>
+                                    <div class="input_box">
+                                        <input name="password" type="password" class="text_box" style="color:#aaa;" value="[% seed %]" 
+                                            onfocus="if(this.value=='[% seed %]'){this.value='';this.style.color='#424242';}" 
+                                            onblur="if(this.value==''){this.value='[% seed %]'; this.style.color='#aaa';}" />
+                                    </div>
+
+                                    <a class="help_btn" href="javascript:;" 
+                                        onclick="helpPopup('password_help', this, event);"><img 
+                                        src="[% ctx.media_prefix %]/images/kpac/question_mark.png[% ctx.cache_key %]" alt="[% l('password help') %]" /></a>
+
+                                    <input type="hidden" name='pickup_lib' value='0' id='pickup_lib'>
+                                    
+                                    <div class="clear">&nbsp;</div>
+                                    <div class="hr">&nbsp;</div>
+
+                                [% ELSE %]
+
+                                <p>[% l('Choose a Pickup Library:') %]</p>
+                                <div class="pickup_lib">
+                                    [%  def_lib = ctx.default_pickup_lib || ctx.physical_loc;
+                                        PROCESS "opac/parts/org_selector.tt2";
+                                        INCLUDE build_org_selector name='pickup_lib' 
+                                        value=def_lib id='pickup_lib' can_have_vols_only=1 hold_pickup_lib=0 %]
+
+                                 <!-- HIDDEN FIELDS FOR DEFAULT NOTIFICATION PREFERENCES -->
+                                 [%- IF ctx.notify_method -%]
+                                     [%- IF ctx.notify_method == '' OR ctx.notify_method == 'phone:email' -%]
+                                         [%- SET ctx.notify_method = 'email|phone' -%]
+                                     [%- END -%]
+                                 [%- ELSE -%]
+                                     [%- SET ctx.notify_method = 'email|phone' -%]
+                                 [%- END -%]
+                                 
+                                 [%- IF ctx.user.email -%]
+                                      [% ctx.notify_method.search('email') ? 
+                                     '<input type="hidden" id="email_notify" name="email_notify" value="t"/>' : '' %]
+                                 [%- END -%]
+
+                                 [%- IF allow_phone_notifications == 'true' -%]
+                                     [% IF ctx.default_phone %]
+                                            [% phone_value = ctx.default_phone %]
+                                     [% ELSE %]
+                                            [% phone_value= ctx.user.day_phone %]
+                                     [% END %]
+                                     
+                                     [% ctx.notify_method.search('phone') ? 
+                                         '<input type="hidden" id="phone_notify_checkbox" name="phone_notify_checkbox" value="t"/>
+                                         <input type="hidden" name="phone_notify" value="' _ phone_value _ '"/>' : '' %]
+                                 [%- END -%]
+
+                                [% IF ctx.get_org_setting(ctx.search_ou, 'sms.enable') == 1 %]
+                                       [% setting_notify = 'opac.default_sms_notify';
+                                          setting_carrier = 'opac.default_sms_carrier'; %]
+                                       [% ctx.notify_method.search('sms') ?
+                                            '<input type="hidden" id="sms_notify_checkbox" name="sms_notify_checkbox" value="t" />
+                                             <input type="hidden" id="sms_carrier" name="sms_carrier" value="' _ ctx.user_setting_map.$setting_carrier _ '" />
+                                             <input type="hidden" id="sms_notify" name="sms_notify" value="' _ ctx.user_setting_map.$setting_notify _ '" />' : '' %]
+                                 [% END %]                               
+
+                                </div>
+                                [% END %]
+                            </div>
+                        </div>
+                        <div class="submit_btn">
+                            <input type='hidden' name='action' value='hold'/>
+                            <input type='image' src="[% ctx.media_prefix %]/images/kpac/review_submit_btn.png[% ctx.cache_key %]" alt="[% l('Submit') %]"/>
+                        </div>
+                    </form>
+                </div>
+            </td>
+
+            <td valign="top">
+                <div class="right_brain">
+                    <div class="top_side">
+                        <h2>[% l('save it!') %]</h2>
+                        <p>[% l('If you would like to save this item to a list to be requested later, click Submit below.') %]</p>
+                        [% IF ctx.user AND ctx.bookbags AND ctx.bookbags.size > 0 %]
+                        <br/>
+                        <p>
+                            [% l('You may also save this item to a list you have already created by selecting one of your lists below.') %]
+                        </p>
+                        [% END %]
+                    </div>
+                    <form method='POST'>
+                        <input type='hidden' name='action' value='save'/>
+                        [% IF ctx.user AND ctx.bookbags AND ctx.bookbags.size > 0 %]
+                            <div class="checkout_box">
+                                <div class="box1_top">&nbsp;</div>
+                                <div class="box_inside">
+                                    <p>[% l('Add to one of your lists?') %]</p>
+                                    <select name='bookbag'>
+                                        <option value='' selected='selected'>[% l('-- Temporary List --') %]</option>
+                                        [% FOR bbag IN ctx.bookbags %]
+                                            <option value="[% bbag.id %]">[% bbag.name | html %]</option>
+                                        [% END %]
+                                    </select>
+                                </div>
+                            </div>
+                        [% END %]
+                        <div class="submit_btn">
+                            <input type='image' src="[% ctx.media_prefix %]/images/kpac/review_submit_btn.png[% ctx.cache_key %]" alt="[% l('Submit') %]" />
+                        </div>
+                    </div>
+                </div>
+            </td>
+        </tr>
+    </table>
+</div>
+
+<div class="sub_navigation2 checkout">
+    <table cellpadding="0" cellspacing="0" border="0" width="100%">
+        <tr>
+            [%  # in the absence of a sane referer, return to the detail page
+                url = ctx.kpac_root _ (ctx.referer.match('results') ? '/results' : '/record/' _ ctx.bre_id) %]
+            <td><a href="[% mkurl(url) %]"><img src="[% ctx.media_prefix %]/images/kpac/cancel_back_btn.png[% ctx.cache_key %]" /></a></td>
+            <td width="100%" class="nav_mid_bg">&nbsp;</td>
+        </tr>
+    </table>
+</div>
+         
+[% END %]
diff --git a/Open-ILS/src/templates_cons/kpac/parts/footer.tt2 b/Open-ILS/src/templates_cons/kpac/parts/footer.tt2
new file mode 100644 (file)
index 0000000..6dc9a07
--- /dev/null
@@ -0,0 +1,5 @@
+<div class="footer_wrapper">
+    <a href="[% mkurl(ctx.opac_root _ '/home') %]">[% l('Back to Main Catalog') %]</a>
+    <div class="clear">&nbsp;</div>
+</div>
+
diff --git a/Open-ILS/src/templates_cons/kpac/parts/header.tt2 b/Open-ILS/src/templates_cons/kpac/parts/header.tt2
new file mode 100644 (file)
index 0000000..14a1d11
--- /dev/null
@@ -0,0 +1,25 @@
+<div class="main_header_wrapper">
+    <div class="logo_wrapper">
+        <a href="http://catalog.cwmars.org">
+            <span class="logo_left">&nbsp;</span>
+            <span class="logo_middle"><img src="[% ctx.media_prefix %]/images/kpac/kpac_small_logo.png[% ctx.cache_key %]" alt="[% l('CWMARS main catalog') %]" /></span>
+            <span class="logo_right">&nbsp;</span>
+        </a>
+    </div>
+    <div class="header_utils">
+<a href="http://catalog.cwmars.org">Main Catalog</a>
+    </div>
+    <div class="header_menu">
+        <!-- menu rendered in reverse order -->
+        [% IF ctx.user %]
+            [% redir = CGI.url('-base' => 1) _ ctx.kpac_root _ '/home' %]
+            <a href="[% mkurl(ctx.logout_page, 
+                {redirect_to => redir.replace('^https:', 'http:')}, 1) %]">[% 
+                    l('Logout ([_1] [_2])', ctx.user.first_given_name, ctx.user.family_name) %]</a>
+        [% ELSE %]
+            <a href="[% mkurl(ctx.opac_root _ '/login').replace('^http:', 'https:') %]">[% l('Login') %]</a>
+        [% END %]
+    </div>
+    <div class="clear">&nbsp;</div>
+</div>
+
diff --git a/Open-ILS/src/templates_cons/opac/advanced.tt2 b/Open-ILS/src/templates_cons/opac/advanced.tt2
new file mode 100644 (file)
index 0000000..7296e1e
--- /dev/null
@@ -0,0 +1,53 @@
+[%- PROCESS "opac/parts/header.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Advanced Search");
+    pane = CGI.param("pane") || "advanced";
+    loc = ctx.search_ou;
+
+    ctx.metalinks.push('<meta name="robots" content="noindex,follow">');
+-%]
+    <h2 class="sr-only">[% l('Advanced Search') %]</h2>
+    <div id="search-wrapper">
+        <div id="search-box">
+
+            <span class="adv_search_catalog_lbl">Go to <a href="[% mkurl(ctx.opac_root _ '/home') %]"
+                    id="home_adv_search_link">[%l('Basic Search')%]</a></span>
+
+            <span class="browse_the_catalog_lbl"><a href="[% mkurl(ctx.opac_root _ '/browse') %]">[%
+                    l('Browse the Catalog')%]</a></span>
+            [% IF ctx.get_org_setting(ctx.physical_loc || ctx.aou_tree.id, 'circ.course_materials_opt_in') == 1 %]
+                <span class="search_courses_label"><a href="[% mkurl(ctx.opac_root _ '/course_search') %]">[% l('Search for Courses') %]</a></span>
+                <span class="search_courses_label"><a href="[% mkurl(ctx.opac_root _ '/course_browse') %]">[% l('Browse for Courses') %]</a></span>
+            [% END %]
+            [% INCLUDE 'opac/parts/cart.tt2' %]
+        </div>
+        <div id="adv_search_parent">
+            <div id="adv_search_tabs">
+                <a href="[% mkurl('', {pane => 'advanced'}) %]"
+                    [% IF pane == 'advanced' %]class="on" [% END %]
+                    id="adv_search">[% l('Advanced Search') %]</a>
+                <a href="[% mkurl('', {pane => 'numeric'}) %]"
+                    [% IF pane == 'numeric' %]class="on" [% END %]
+                    id="num_search">[% l('Numeric Search') %]</a>
+                <a href="[% mkurl('', {pane => 'expert'}) %]"
+                    [% IF pane == 'expert' %]class="on" [% END %]
+                    id="expert_search">[% l('Expert Search') %]</a>
+            </div>
+        </div>
+    </div>
+    <div id="content-wrapper">
+        <div id="main-content">
+            <div class="advanced_div">
+            [% IF pane == 'advanced' %]
+            [% INCLUDE "opac/parts/advanced/search.tt2" %]
+            [% ELSIF pane == 'numeric' %]
+            [% INCLUDE "opac/parts/advanced/numeric.tt2" %]
+            [% ELSIF pane == 'expert' %]
+            [% INCLUDE "opac/parts/advanced/expert.tt2" %]
+            [% END %]
+            </div>
+            <div class="common-full-pad"></div>        
+        </div>
+    </div>
+[% END %]
diff --git a/Open-ILS/src/templates_cons/opac/browse.tt2 b/Open-ILS/src/templates_cons/opac/browse.tt2
new file mode 100644 (file)
index 0000000..be24b00
--- /dev/null
@@ -0,0 +1,240 @@
+[%- # This is the bib and authority combined record browser.
+
+    PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/misc_util.tt2";
+    PROCESS "opac/parts/org_selector.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+
+    ctx.page_title = l("Browse the Catalog");
+    blimit = CGI.param('blimit') || ctx.opac_hits_per_page || 25;
+
+    depart_list = ['blimit', 'bterm', 'bpivot'];
+    ctx.metalinks.push('<meta name="robots" content="noindex,follow">');
+    MACRO heading_use_label BLOCK;
+        SWITCH use;
+            CASE 'variant';
+               l('See');
+            CASE 'broader';
+               l('Broader term');
+            CASE 'narrower';
+               l('Narrower term');
+            CASE 'other';
+               l('Related term');
+            CASE;
+               l('See');
+        END;
+    END;
+%]
+
+    <h2 class="sr-only">[% l('Catalog Browse') %]</h2>
+    <div id="search-wrapper">
+        [%# XXX TODO Give searchbar.tt2 more smarts so we can just do:
+          # INCLUDE "opac/parts/searchbar.tt2" %]
+        <div id="search-box">
+            <span class="search_catalog_lbl"><a href="[% mkurl(ctx.opac_root _ '/home', {}, depart_list) %]">[% l('Basic Search') %]</a></span>
+            <span class="adv_search_catalog_lbl"><a href="[% mkurl(ctx.opac_root _ '/advanced', {}, depart_list) %]"
+                    id="home_adv_search_link">[%l('Advanced Search')%]</a></span>
+        
+            <span class="browse_the_catalog_lbl mobile_hide">[% l('Browse the Catalog') %]</span>
+            [% IF ctx.get_org_setting(ctx.physical_loc || ctx.aou_tree.id, 'circ.course_materials_opt_in') == 1 %]
+                <span class="search_courses_label"><a href="[% mkurl(ctx.opac_root _ '/course_search') %]">[% l('Search for Courses') %]</a></span>
+                <span class="search_courses_label"><a href="[% mkurl(ctx.opac_root _ '/course_browse') %]">[% l('Browse for Courses') %]</a></span>
+
+            [% END %]
+            [% INCLUDE 'opac/parts/cart.tt2' %]
+        </div>
+    </div>
+    <div id="content-wrapper">
+        <div id="main-content">
+            <div id="browse-the-catalog">
+                <div id="browse-controls" class='searchbar'>
+                    <form method="get" onsubmit="$('browse-submit-spinner').className = ''; return true">
+                        <input type="hidden" name="blimit"
+                            value="[% blimit | html %]" />
+
+                        [% control_qtype = INCLUDE "opac/parts/qtype_selector.tt2"
+                            id="browse-search-class" browse_only=1 plural=1 %]
+
+                        [% control_bterm = BLOCK %]<input type="text" name="bterm" id="browse-term"
+                            aria-label="[% l('Browse term') %]"
+                            value="[% CGI.param('bterm') | html %]" />[% END %]
+                        [% control_locg = INCLUDE build_org_selector id='browse-context'
+                            show_loc_groups=1
+                            arialabel=l('Select holding library') %]
+                        [% l('Browse for [_1] starting with [_2] in [_3]', control_qtype, control_bterm, control_locg) %]
+
+                       <input id='search-submit-go' type="submit" value="[% l('Browse') %]" alt="[% l('Browse') %]" class="opac-button"/>
+                        <img id="browse-submit-spinner" 
+                        src="[% ctx.media_prefix %]/opac/images/progressbar_green.gif[% ctx.cache_key %]"
+                        class="hidden" style="width: 16px; height: 16px;" 
+                        alt="[% l('Search in progress icon') %]" />
+                    </form>
+                </div>
+
+                [% BLOCK browse_pager %]
+                <div class="browse-pager">
+                    [% IF ctx.back_pivot %]
+                    <a class="opac-button" href="[% mkurl('', {bpivot => ctx.back_pivot}) %]" onclick="$('browse-pager-spinner-[% id %]').className = '';">&larr; [%l ('Back') %]</a>
+                    [% END %]
+                    [% IF ctx.pager_shortcuts;
+                        current_qtype = CGI.param('qtype') || 'title' %]
+                    <span class="browse-shortcuts">
+                        [% FOR shortcut IN ctx.pager_shortcuts %]
+                            <a href="[% mkurl('', {qtype => current_qtype, bterm => shortcut.0}, ['bpivot','query']) %]">[% shortcut.1 %]</a>
+                        [% END %]
+                    </span>
+                    [% END %]
+
+                    [% IF ctx.forward_pivot %]
+                    <a class="opac-button" href="[% mkurl('', {bpivot => ctx.forward_pivot}) %]" onclick="$('browse-pager-spinner-[% id %]').className = '';">[%l ('Next') %] &rarr;</a>
+                    [% END %]
+
+                    <img id="browse-pager-spinner-[% id %]" 
+                        src="[% ctx.media_prefix %]/opac/images/progressbar_green.gif[% ctx.cache_key %]"
+                        class="hidden" style="width: 16px; height: 16px;" 
+                        alt="[% l('Search in progress icon') %]" />
+                </div>
+                [% END %]
+
+                [% PROCESS browse_pager id=0 %]
+
+                <div id="browse-results">
+                [% IF ctx.browse_error %]
+                    <span class="browse-error">
+                        [% l("An error occurred browsing records. " _
+                        "Please try again in a moment or report the issue " _
+                        "to library staff.") %]
+                    </span>
+                [% ELSE %]
+                    [% IF ctx.browse_leading_article_warning %]
+                    <div class="browse-leading-article-warning">
+                            [% l("Your browse term seems to begin with an article (a, an, the). You might get better results by omitting the article.") %]
+                            [% IF ctx.browse_leading_article_alternative %]
+                            <p>
+                            [% alternative_link = BLOCK %]
+                            <a href="[% mkurl('', {bterm => ctx.browse_leading_article_alternative}, ['bpivot']) %]">[% ctx.browse_leading_article_alternative | html %]</a>
+                            [%-  END; # alternative_link BLOCK
+                                l("Did you mean [_1]?", alternative_link);
+                            END # IF %]
+                            </p>
+                    </div>
+                    [% END %]
+                    <ul class="browse-result-list">
+                    [% FOR result IN ctx.browse_results %]
+                        <li class="browse-result">
+                            <span class="browse-result-value[% result.row_number == 0 && !CGI.param('bpivot') ? ' browse-result-best-match' : '' %]">
+                                [% IF result.sources > 0 %] <!-- bib-linked browse value -->
+                                    <a href="[% mkurl(
+                                        ctx.opac_root _ '/results', {
+                                            'fi:has_browse_entry' => (result.browse_entry _ ',' _ result.fields)
+                                        }) %]">[% result.value | html %]</a>
+                                    <span class="browse-result-sources">([%
+                                        IF result.accurate == 'f';
+                                            l("At least"); " ";
+                                        END;
+                                    result.sources %])</span>
+                                [% ELSE %] <!-- only authority links -->
+                                    [% result.value | html %]
+                                [% END %]
+                            </span>
+
+                            [% FOR a IN result.authorities;
+                                    PROCESS authority_notes authority=a IF !sees.grep(a.id);
+                               END %]
+                            [% auth_headings_ul_added = 0; %]
+                                [% seenit = {}; # for headings we've rendered
+                                   FOR a IN result.sees;
+                                    # We can go no further sans control_set.
+                                    NEXT UNLESS a.control_set;
+
+                                    # get_authority_fields is fast and cache-y.
+                                    acs = ctx.get_authority_fields(a.control_set);
+                                    FOR field_group IN a.headings;
+                                        field_id = field_group.keys.0;
+                                        field = acs.$field_id;
+                                        headings = field_group.values.0;
+                                        FOR h IN headings;
+                                            # We could display headings without
+                                            # links here when h.target is
+                                            # undef, if we wanted to, but note
+                                            # that h.target_count is only
+                                            # defined when h.target is.
+
+                                            IF h.target AND h.target_count AND result.list_authorities.grep('^' _ h.target _ '$').size == 0 AND h.main_entry;
+                                                id = h.target; NEXT IF seenit.$id; seenit.$id = 1; 
+                                                IF !auth_headings_ul_added;
+                                                    # only add a <ul> if we have at least one <li> (WCAG 2.0)
+                                                    auth_headings_ul_added = 1; %]
+                                                <ul class="browse-result-authority-headings"> 
+                                                [% END %]
+
+                                                <li><span class="browse-result-authority-field-name">[% heading_use_label(use=h.type) %]</span>
+                                                <a href="[% mkurl(ctx.opac_root _ '/browse', {bterm => h.heading}, ['bpivot']) %]">[% h.heading | html %]</a>
+                                                <span class="browse-result-authority-bib-links">([% h.target_count %])</span>
+                                                </li>
+                                            [% END %]
+                                        [% END %]
+                                    [% END %]
+                                [% END %]
+                                [% FOR a IN result.authorities;
+                                    # We can go no further sans control_set.
+                                    NEXT UNLESS a.control_set;
+
+                                    # get_authority_fields is fast and cache-y.
+                                    acs = ctx.get_authority_fields(a.control_set);
+                                    FOR field_group IN a.headings;
+                                        field_id = field_group.keys.0;
+                                        field = acs.$field_id;
+                                        headings = field_group.values.0;
+                                        FOR h IN headings;
+                                            # We could display headings without
+                                            # links here when h.target is
+                                            # undef, if we wanted to, but note
+                                            # that h.target_count is only
+                                            # defined when h.target is.
+
+                                            IF h.target AND h.target_count AND result.list_sees.grep('^' _ h.target _ '$').size == 0 AND !h.main_entry AND ctx.get_cgf('opac.show_related_headings_in_browse').enabled == 't';
+                                                id = h.target; NEXT IF seenit.$id; seenit.$id = 1; 
+                                                IF !auth_headings_ul_added;
+                                                    # only add a <ul> if we have at least one <li> (WCAG 2.0)
+                                                    auth_headings_ul_added = 1; %]
+                                                <ul class="browse-result-authority-headings"> 
+                                                [% END %]
+                                                <li><span class="browse-result-authority-field-name">[% heading_use_label(use=h.type) %]</span>
+                                                <a href="[% mkurl(ctx.opac_root _ '/results', {query => 'identifier|authority_id[' _ h.target _ ']'}) %]">[% h.heading | html %]</a>
+                                                <span class="browse-result-authority-bib-links">([% h.target_count %])</span>
+                                                </li>
+                                            [% END %]
+                                        [% END %]
+                                    [% END %]
+                                [% END %]
+                            [% IF auth_headings_ul_added %]</ul>[% END %]
+                        </li>
+                    [% END %]
+                    </ul>
+                [% END %]
+                </div>
+
+                [% PROCESS browse_pager id=1 %]
+            </div>
+
+            <div class="common-full-pad"></div>        
+        </div>
+    </div>
+
+    [% BLOCK authority_notes;
+        # Displays public general notes (sometimes called "scope notes" ?)
+        FOR note IN authority.notes %]
+            <div class="browse-public-general-note">
+                <span class="browse-public-general-note-label">
+                    [% l("Note:") %]
+                </span>
+                <span class="browse-public-general-note-body">
+                [% FOR piece IN note; piece | html; END %]
+                </span>
+            </div>
+        [% END;
+    END;    # end of BLOCK authority_notes %]
+
+[% END %]
diff --git a/Open-ILS/src/templates_cons/opac/css/style.css.tt2 b/Open-ILS/src/templates_cons/opac/css/style.css.tt2
new file mode 100644 (file)
index 0000000..c5eba40
--- /dev/null
@@ -0,0 +1,3584 @@
+[%-
+    PROCESS "opac/parts/css/colors.tt2";
+    PROCESS "opac/parts/css/fonts.tt2";
+    rtl = ctx.get_i18n_l(ctx.eg_locale).rtl;
+%]
+
+.suppress {
+   display:none;
+}
+
+body {
+    margin:0;
+    font-family: Arial, Helvetica, sans-serif;
+    font-size: [% css_fonts.size_base %];
+    background-color: [% css_colors.footer %];
+    [% IF rtl == 't' -%]
+    direction: rtl;
+    [%- END %]
+}
+
+button, input {
+    font-family: Arial, Helvetica, sans-serif;
+    font-size: [% css_fonts.size_base %];
+}
+
+img {
+    border: none;
+}
+
+#topnav_logo {
+    margin: 2em 0;
+}
+
+#homesearch_main_logo {
+    padding-top: 60px;
+    margin: auto;
+    width: 50%;
+}
+
+a {
+    color: [% css_colors.link %];
+}
+
+#search-wrapper input[type=text] {
+    margin:0;
+    padding:0;
+}
+
+#search-wrapper select, .results_header_lbl select {
+    border:1px solid [% css_colors.border_standard %];
+    margin:0;
+    padding:0;
+    width: 12em;
+}
+
+.truncated {
+    display: none;
+}
+
+.searchbar {
+    font-weight: bold;
+    padding-top: 10px;
+    text-align: center;
+}
+
+.refine_search {
+    padding-bottom: 7px;
+    margin-left: 1em;
+}
+
+/*
+#search-wrapper select {
+    border:0px solid [% css_colors.border_dark %];
+    filter:alpha(opacity=0);
+    -khtml-opacity:0;
+    opacity:0;
+    padding:0;
+    margin:0;
+    height:18px;
+}
+*/
+h1 {
+    margin:0;
+    margin-bottom: 5px;
+    font-size: [% css_fonts.size_biggest %];
+    font-weight:normal;
+}
+
+h2 {
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:bold;
+}
+
+h2.graphic880 {
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:normal;
+}
+
+.hide_me, .hidden {
+    display: none;
+    visibility: hidden;
+}
+
+div.select-box-wrapper {
+    position:absolute;
+    padding-top:2px;
+    overflow:hidden;
+    [% IF rtl == 't' -%]
+    padding-right: 3px;
+    text-align:right;
+    [%- ELSE %]
+    padding-left:3px;
+    text-align:left;
+    [%- END %]
+}
+
+#dash_wrapper {
+    [% IF rtl == 't' -%]
+    margin-right: 0.5em;
+    [%- ELSE %]
+    margin-left: 0.5em;
+    [%- END %]
+}
+
+#dash_wrapper div {
+    background-color: [% css_colors.primary %];
+    border-radius: 5px;
+    padding: 0em 1em;
+}
+
+.dash_divider {
+    margin: 1em;
+    color: [% css_colors.primary_fade %];
+    display:inline-block;
+}
+
+#dashboard, #dashboard_e {
+    margin-top: 1em;
+    height: 3em;
+}
+
+#dashboard span.dash-align a, #dashboard_e span.dash-align a {
+    font-weight: bold;
+    text-decoration: none;
+}
+
+#dash_user {
+    font-weight: bold;
+}
+
+#logout_link {
+    [% IF rtl == 't' -%]
+    right: 1px;
+    [%- ELSE %]
+    left: 1px;
+    [%- END %]
+}
+
+#dash_checked, #dash_e_checked { color: [% css_colors.text_attention %]; }
+#dash_holds, #dash_e_holds { color: [% css_colors.text_attention %]; }
+#dash_pickup, #dash_e_pickup { color: [% css_colors.text_goodnews %]; }
+
+/*  
+#dash_fines { color: [% css_colors.text_badnews %]; }
+the color contrast between "text_badnews" and "primary"
+is too low for WCAG compliance.  Use "text_attention" 
+for now until a better color is picked - if needed.
+*/
+#dash_fines { color: [% css_colors.text_attention %]; }
+
+#dash_wrapper #dash_user_message_button_container {
+    display: inline;
+    padding: 0;
+}
+#dash_wrapper #unread_message_count_floater {
+    position: absolute;
+    background-color: [% css_colors.text_alert %];
+    padding-left: 0.2em;
+    padding-right: 0.2em;
+    display: inline-block;
+    font-size: 95%;
+    border-radius: 0;
+    z-index: 2;
+    margin-top: 0.2em;
+    [% IF rtl == 't' -%]
+    margin-right: -1.5em;
+    [%- ELSE %]
+    margin-left: -1.5em;
+    [%- END %]
+}
+
+#header-wrap {
+    background-color: #fff;
+}
+#header {
+    color: #fff;
+    margin-left: 1em;
+    margin-right: 1em;
+    font-size: [% css_fonts.size_small %];
+}
+
+#header a {
+    color: [% css_colors.header_links_text %];
+}
+
+#header a:hover {
+    color: [% css_colors.opac_button_hover_text %];
+    text-decoration: none;
+}
+
+#header-links {
+    color: [% css_colors.header_text %];
+    font-size: [% css_fonts.size_small %];
+    font-weight: bold;
+    position: relative;
+    top:4px;
+    
+}
+
+#header-links a {
+    color: [% css_colors.header_links_text %];
+    display: block;
+    text-decoration: none;
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 22px;
+    [%- ELSE %]
+    float:left;
+    margin-right:22px;
+    [%- END %]
+}
+
+#header-links a:hover {
+    color: [% css_colors.header_links_text_hover %];
+    text-shadow: 0 0 0.2em [% css_colors.primary %], 0 0 0.2em [% css_colors.primary %];
+    text-decoration: none;
+}
+
+#header #header-links2 {
+    position:relative;
+    top:-8px;
+    color: [% css_colors.header_links_text %];
+    padding-bottom: 15px;
+}
+
+#header #header-links2 a {
+    color: [% css_colors.header_links_text %];
+}
+
+#header #header-links2 a:hover {
+    text-decoration: underline;
+}
+
+#your-acct-login {
+    padding-top:2em;
+}
+
+#gold-links {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    padding-right: 0px;
+    [%- ELSE %]
+    margin-left: 1em;
+    padding-left:0px;
+    [%- END %]
+}
+
+#gold-links-home {
+    margin:auto;
+    [% IF rtl == 't' -%]
+    padding-right: 0px;
+    [%- ELSE %]
+    padding-left:0px;
+    [%- END %]
+}
+
+#gold-links-holder {
+    height: 24px;
+    background-color: [% css_colors.header_links_bar %];
+}
+
+#util-bar {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    padding-right: 0px;
+    [%- ELSE %]
+    margin-left: 1em;
+    padding-left:0px;
+    [%- END %]
+    height:0px;
+}
+
+#search-wrapper {
+    border-bottom: 1px solid [% css_colors.border_standard %];
+    padding-bottom: 5px;
+    background-color: [% css_colors.background %];
+}
+
+#search-wrapper #breadcrumb {
+    margin-top:0px;
+    font-size: [% css_fonts.size_smaller %];
+    [% IF rtl == 't' -%]
+    float: right;
+    [%- ELSE %]
+    float:left;
+    [%- END %]
+}
+
+#search-wrapper #search-within {
+    margin-top:10px;
+    position:relative;
+    [% IF rtl == 't' -%]
+    float: left;
+    right: -173px;
+    [%- ELSE %]
+    float:right;
+    left:-173px;
+    [%- END %]
+}
+
+#search-wrapper #breadcrumb a {
+    color: [% css_colors.text %];
+}
+
+#search-wrapper #search_frm label {
+    font-size: [% css_fonts.size_smaller %];
+}
+
+#search-wrapper #search-box {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    padding-right: 0px;
+    [%- ELSE %]
+    margin-left: 1em;
+    padding-left: 0px;
+    [%- END %]
+    padding-top: 10px;
+    padding-bottom: 10px;
+}
+
+#adv_search_tabs, #acct_tabs, #acct_fines_tabs, #acct_checked_tabs, #acct_holds_tabs, #acct_prefs_tabs, #results_header_inner{
+    [% IF rtl == 't' -%]
+    margin-right:2px;
+    [%- ELSE %]
+    margin-left: 2px;
+    [%- END %]
+    overflow: auto;
+}
+
+#adv_search_tabs a, #acct_tabs a, #acct_fines_tabs a, #acct_checked_tabs a, #acct_holds_tabs a, #acct_prefs_tabs a {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin: 10px 0px 0px 7px;
+    border-radius: 10px 10px 0px 0px;
+    [%- ELSE %]
+    float: left;
+    margin: 10px 7px 0px 0px;
+    border-radius: 10px 10px 0px 0px;
+    [%- END %]
+    text-align: center;
+    vertical-align: middle;
+    display: block;
+    padding: 10px 0px 10px 0px;
+    font-weight: bold;
+    color: [% css_colors.text_invert %];
+    background-color: [% css_colors.control %];
+    font-weight: bold;
+    text-decoration: none;
+}
+
+#adv_search_tabs a, #acct_tabs a, #acct_fines_tabs a {
+    padding: 1em 1em 0.5em;
+}
+
+#adv_search_tabs a:hover, #acct_tabs a:hover, #acct_fines_tabs a:hover, #acct_checked_tabs a:hover, #acct_holds_tabs a:hover, #acct_prefs_tabs a:hover {
+    background-color: [% css_colors.primary %];
+    color: [% css_colors.text_invert %];
+    text-decoration: none;
+}
+
+#adv_search_filters {
+    position: relative;
+}
+#adv_search_rows {
+    border-bottom: none;
+}
+.adv_filter_block {
+    [% IF rtl == 't' -%]
+    float: right;
+    [%- ELSE %]
+    float: left;
+    [%- END %]
+    padding: 15px;
+    clear: both;
+}
+.adv_filter_block_item {
+    [% IF rtl == 't' -%]
+    float: right;
+    [%- ELSE %]
+    float: left;
+    [%- END %]
+    padding: 5px;
+}
+
+#adv_special_block {
+    [% IF rtl == 't' -%]
+    float: right;
+    [%- ELSE %]
+    float: left;
+    [%- END %]
+    padding: 5px;
+    margin-top: 5px;
+}
+
+#adv_search_submit {
+    [% IF rtl == 't' -%]
+    margin-right: 10px;
+    [%- ELSE %]
+    margin-left: 10px;
+    [%- END %]
+    position: relative;
+}
+
+.checkbox_col {
+    width: 1%;
+    [% IF rtl == 't' -%]
+    padding-right: 10px !important;
+    [%- ELSE %]
+    padding-left: 10px !important;
+    [%- END %]
+}
+
+#adv_search.on, #num_search.on, #expert_search.on {
+    color: [% css_colors.accent_darker %];
+    background-color: [% css_colors.background %];
+    text-decoration: none;
+}
+
+#adv_search_tabs a.acct-tab-on, #acct_tabs a.acct-tab-on, #acct_fines_tabs a.acct-tab-on {
+    color: [% css_colors.accent_darker %];
+    background-color: [% css_colors.background %];
+    text-decoration: none;
+}
+
+.acct-tab-off {
+    background-color: [% css_colors.control %];
+}
+
+#acct_checked_tabs a, #acct_holds_tabs a, #acct_prefs_tabs a {
+    margin-top: 0px;
+    font-size: [% css_fonts.size_smaller %];
+    padding: 10px 10px 10px 10px;
+}
+
+#acct_checked_tabs div.selected a, #acct_holds_tabs div.selected a, #acct_prefs_tabs div.selected a {
+    background-color: [% css_colors.accent_lightest %];
+    color: [% css_colors.accent_darker %];
+}
+
+#acct_checked_tabs, #acct_holds_tabs, #acct_prefs_tabs {
+    padding-bottom: 12px;
+    color: [% css_colors.accent_medium %];
+}
+
+#acct_select, #acct_prefs_select {
+     display: none;
+}
+
+#mobile_acct_search_links {
+      background-color: [% css_colors.primary_fade %];
+}
+
+.rdetail_header {
+    [% IF rtl == 't' -%]
+    padding: 5px 0px 6px 7px;
+    margin-right: 1em;
+    [%- ELSE %]
+    padding: 5px 7px 6px 0px;
+    margin-left: 1em;
+    [%- END %]
+    border-bottom: 1px dotted [% css_colors.accent_light %];
+}
+
+.rdetail_results a {
+    color:[% css_colors.primary_fade %];
+    font-weight:bold;
+    font-size: [% css_fonts.size_bigger %];
+}
+
+.rdetail_result_count {
+    color: [% css_colors.text %];
+    font-weight: normal;
+    display: inline-block;
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [%- ELSE %]
+    padding-left: 1em;
+    [%- END %]
+}
+
+.rdetail_result_nav {
+    font-weight:normal;
+    display: inline-block;
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [%- ELSE %]
+    padding-left: 1em;
+    [%- END %]
+}
+
+#rdetail_details_table {
+    margin-top: 15px;
+}
+
+#rdetail_image { border: none; }
+#rdetail_image_cell {
+    padding-top: 3px;
+    [% IF rtl == 't' -%]
+    padding-left: 10px;
+    [%- ELSE %]
+    padding-right: 10px;
+    [%- END %]
+}
+
+h2.rdetail_uris {
+    margin-top: 1em;
+}
+div.rdetail_uris {
+    padding: 0.5em 1em 0.5em 1em;
+    background-color: [% css_colors.accent_lighter2 %];
+}
+div.rdetail_uris ul li {
+    position: relative;
+    [% IF rtl == 't' -%]
+    right: 1em;
+    [%- ELSE %]
+    left: 1em;
+    [%- END %]
+}
+
+div.rdetail_show_copies {
+    margin-top: 1em;
+}
+
+div#rdetail_actions_div {
+    background-color: [% css_colors.background %];
+    [% IF rtl == 't' -%]
+    float: left;
+    [%- ELSE %]
+    float: right;
+    [%- END %]
+}
+
+span#rdetail_copy_counts {
+    display: inline-block;
+    vertical-align: top;
+    [% IF rtl == 't' -%]
+    border-left: thin;
+    margin-left: 1em;
+    padding-left: 1em;
+    [%- ELSE %]
+    border-right: thin;
+    margin-right: 1em;
+    padding-right: 1em;
+    [%- END %]
+}
+
+span#rdetail_hold_counts {
+    display: inline-block;
+    vertical-align: top;
+}
+span#rdetail_hold_counts p {
+    [% IF rtl == 't' -%]
+    padding-right: 2em;
+    [%- ELSE %]
+    padding-left: 2em;
+    [%- END %]
+}
+
+#rdetail_image_div {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 1em;
+    [%- ELSE %]
+    float: left;
+    margin-right: 1em;
+    [%- END %]
+}
+
+.rdetail_aux_utils {
+    padding-bottom: 6px;
+    [% IF rtl == 't' -%]
+    border-right: 1px dotted #ccc;
+    padding-right:17px;
+    padding-left:70px;
+    [%- ELSE %]
+    border-left:1px dotted [% css_colors.accent_light %];
+    padding-left: 17px;
+    padding-right: 70px;
+    [%- END %]
+}
+
+div.place_hold {
+    border-bottom: 1px dotted [% css_colors.accent_light %];
+    padding-top: 10px;
+}
+
+div.toggle_list { padding-top: 6px; }
+
+div.share_record {
+    padding-top: 6px;
+    border-top: 1px dotted [% css_colors.accent_light %];
+}
+
+div.format_icon {
+    [% IF rtl == 't' -%]
+    float: left;
+    margin-left: 17px;
+    [%- ELSE %]
+    float: right;
+    margin-right: 17px;
+    [%- END %]
+}
+
+#metarecord_population {
+    overflow: hidden;
+    width: 40%;
+    padding-bottom: 10px;
+}
+
+.metarecord_population_span_link {
+    line-height: 20px;
+}
+
+.metarecord_population_format {
+    border-right: thin;
+    display: inline-block;
+    margin-right: 1em;
+    padding-right: 1em;
+    vertical-align: top;
+}
+
+.metarecord_population_item_lang {
+    display: inline-block;
+    vertical-align: top;
+}
+
+.metarecord_population_all {
+    padding-top:10px;
+}
+
+.results_aux_utils {
+    display: table-cell;
+}
+
+.result_util {
+    border-bottom: 1px dotted [% css_colors.accent_light %];
+    padding-top: 6px;
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [%- ELSE %]
+    padding-left: 1em;
+    [%- END %]
+}
+
+.results_reviews {
+    top: -5px;
+}
+
+#rdetail_copies {
+    padding-top: 1.5em;
+}
+
+#rdetails_status td,
+#course_material_table td {
+    [% IF rtl == 't' -%]
+    padding: 7px 13px 3px 0px;
+    [%- ELSE %]
+    padding: 7px 0px 3px 13px;
+    [%- END %]
+    white-space: nowrap;
+}
+
+#rdetails_status td[headers=copy_header_library], 
+#rdetails_status td[headers=copy_header_shelfloc] {
+    white-space: normal;
+}
+
+#rdetails_status thead th,
+#course_material_table thead th {
+    [% IF rtl == 't' -%]
+    padding: 13px 13px 13px 0px;
+    text-align: right;
+    [%- ELSE %]
+    padding: 13px 0px 13px 13px;
+    text-align: left;
+    [%- END %]
+    background-color: [% css_colors.accent_lighter2 %];
+    font-size: [% css_fonts.size_smaller %];
+    font-weight: bold;
+}
+
+#rdetails_status tbody td,
+#course_material_table tbody td {
+    [% IF rtl == 't' -%]
+    padding-right: 13px;
+    text-align: right;
+    [%- ELSE %]
+    padding-left: 13px;
+    text-align: left;
+    [%- END %]
+}
+#rdetails_status tbody td.copy_note
+#course_material_table tbody {
+    color: [% css_colors.primary %];
+    text-wrap:normal;
+    white-space:pre-wrap !important;
+    word-wrap:normal;
+}
+
+#rdetails_status tbody td.copy_tag {
+    border-color: [% css_colors.primary %];
+    border-style: dashed;
+    border-width: 2px;
+}
+#rdetails_status tbody .copy_tag_value {
+    font-weight: bolder;
+}
+
+.rdetail_extras {
+/*    background: [% css_colors.primary_fade %]; */
+    background:#fff;
+/*    border: 1px solid [% css_colors.primary %]; */
+    padding-top:1px;
+    clear:both;
+}
+
+#rdetail_extras_div {
+    margin: 1em 0;
+}
+
+/* .rdetail_extras_hr { */
+/*    [% IF rtl == 't' -%] */
+/*    margin-right: 1px; */
+/*    margin-left: 1px; */
+/*    [%- ELSE %] */
+/*    margin-left: 1px; */
+/*    margin-right: 1px; */
+/*    [%- END %] */
+/*    height: 1px; */
+/*    background: [% css_colors.accent_light %]; */
+/* } */
+
+.rdetail_extras_link {
+    padding: 6px 12px;
+    font-size: [% css_fonts.size_smaller %];
+    font-weight: bold;
+}
+
+.rdetail_extras_lbl {
+      position:relative;
+      top:-4px;
+      left:7px;
+      color:#00593d
+/*    color: [% css_colors.text_invert %]; */
+/*    text-decoration: none; */
+}
+
+#rdetail_extras_expand, #rdetail_extras_collapse, #rdetail_locs_collapse {
+    [% IF rtl == 't' -%]
+    margin-right: 13px;
+    [%- ELSE %]
+    margin-left: 13px;
+    [%- END %]
+}
+
+#rdetail_locs_expand, #rdetail_locs_collapse {
+    [% IF rtl == 't' -%]
+    margin-right: 13px;
+    [%- ELSE %]
+    margin-left:13px;
+    [%- END %]
+    padding-bottom:3px;
+    margin-top:15px;
+}
+
+#rdetail_anotes_div .biography {
+    margin:0;
+}
+
+#gbp_extra, #gbp_arrow_down_link {
+    display: none;
+}
+
+.almost-content-wrapper {
+    background-color: [% css_colors.background %];
+}
+
+#content-wrapper {
+    background-color: [% css_colors.background %];
+    min-height: 260px;
+    border-bottom: 1px solid [% css_colors.border_dark %];
+}
+
+.content-wrapper-record-page { top: -15px; position: relative; }
+
+#main-content-home {
+    [% IF rtl == 't' -%]
+    padding-right: 17px;
+    margin-right: 1em;
+    [%- ELSE %]
+    padding-left: 17px;
+    margin-left: 1em;
+    [%- END %]
+}
+#main-content {
+    [% IF rtl == 't' -%]
+    padding-right: 0px;
+    [%- ELSE %]
+    padding-left: 0px;
+    [%- END %]
+    margin: 0 1em;
+    clear: both;
+}
+
+#main-content-after-bar {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    padding-right: 4px;
+    [%- ELSE %]
+    margin-left: 1em;
+    padding-left: 4px;
+    [%- END %]
+}
+
+#results-side-bar {
+    [% IF rtl == 't' -%]
+    float: right; 
+    margin-left: 5px;
+    [%- ELSE %]
+    float: left;
+    margin-right: 5px; 
+    [%- END %]
+    width: 174px;
+    background-color: [% css_colors.background %];
+}
+
+#main-content .login_boxes {
+    border: 1px solid [% css_colors.accent_lighter %];
+    background: linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%);
+    background: -moz-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%);
+    background: -ms-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%);
+    background: -o-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%);
+    background: -webkit-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%);
+
+    color: [% css_colors.accent_darker %];
+}
+
+#main-content .login_boxes h1 {
+    font-weight: normal;
+    font-size: [% css_fonts.size_biggest %];
+    margin:0;
+}
+
+#main-content .left_brain {
+    [% IF rtl == 't' -%]
+    padding-right: 28px;
+    [% ELSE -%]
+    padding-left:28px;
+    [% END -%]
+    padding-top:25px;
+}
+
+#main-content .left_brain input[type=text], #main-content .left_brain input[type=password] {
+    width:167px;
+    margin:0;
+    padding:0;
+    background-color: [% css_colors.background %];
+    font-size: [% css_fonts.size_bigger %];
+    color: [% css_colors.text %];
+}
+
+#main-content .left_brain .input_bg {
+    [% IF rtl == 't' -%]
+    padding: 10px 13px 0px 10px;
+    [% ELSE -%]
+    padding:10px 10px 0px 13px;
+    [% END -%]
+    width:167px;
+    height:29px;
+}
+
+.login-help-box {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-right: 2em;
+    [% ELSE -%]
+    float: left;
+    margin-left: 2em;
+    [% END -%]
+    width: 200px;
+    text-align: center;
+}
+
+.login-help-button {
+    font-size: [% css_fonts.size_biggest %];
+    padding: 1.5em;
+}
+
+#login-failed-message {
+    font-size: [% css_fonts.size_bigger %];
+    font-weight: bold;
+    color: [% css_colors.text_alert %];
+    padding-top: 1em;
+}
+
+#holds_temp_parent td {
+    border-bottom:1px solid [% css_colors.border_standard %];
+}
+
+#holds_temp_parent input, #holds_temp_parent select {
+    margin:0;
+}
+
+#holds_temp_parent tr td div {
+    margin-top: 10px;
+    margin-bottom: 10px;
+}
+
+#holds_temp_parent tr td div.format_icon {
+    margin-top: 6px;
+    margin-bottom: 6px;
+    float: none;
+}
+
+#results_header_bar {
+    background-color: [% css_colors.accent_medium %];
+    border-top:1px solid [% css_colors.accent_mediumdark %];
+    border-bottom:1px solid [% css_colors.accent_mediumdark %];
+}
+
+.results_header_lbl {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float: left;
+    [% END -%]
+    font-weight: bold;
+    color: [% css_colors.text %];
+    /* this border is not visible, but it keeps these labels the same size
+    as the buttons */
+    border: 1px solid [% css_colors.accent_medium %];
+    background-color: [% css_colors.accent_medium %];
+    margin: 0.5em 0.3em;
+    padding: 0.3em;
+}
+/* we need a negative margin on the select to allow the containing <label>
+to determine the actual size of the element.  By doing this, we can increase
+the odds that the buttons and the select will be the same size, and therefore
+collapse correctly when the window width decreases */
+.results_header_lbl select {
+    margin: -0.5em 0;
+}
+
+#limit_to_available {
+    vertical-align: middle;
+}
+
+.results_header_sel {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    margin:0;
+}
+
+.results_header_nav1 {
+    [% IF rtl == 't' -%]
+    padding: 5px 0px 6px 7px;
+    [% ELSE -%]
+    padding: 5px 7px 6px 0px;
+    [% END -%]
+    border-bottom: 1px dotted [% css_colors.accent_light %];
+}
+
+.results_header_nav1 .h1 {
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:bold;
+    color:[% css_colors.primary_fade %];
+}
+
+.table_no_border_space {
+  border-spacing: 0px;
+}
+.table_no_cell_pad td {
+  padding: 0px;
+}
+.table_no_border {
+  border-collapse: collapse;
+}
+
+#result_table_table {
+  margin-top:10px;
+}
+
+#result_table_div {
+    margin-top: 1em;
+}
+
+tr.result_table_row > td.results_row_count,
+tr.result_table_row > td.result_table_pic_header,
+tr.result_table_row > td.result_table_title_cell {
+    vertical-align: top;
+}
+
+.result_metadata {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding-left: 2em;
+    [% ELSE -%]
+    float: left;
+    padding-right: 2em;
+    [% END -%]
+    width: 30em;
+}
+
+tr.result_table_row:nth-child(n+2) > td {
+    border-top: 1px solid [% css_colors.accent_lighter2 %];
+}
+
+tr.result_table_row > td.result_table_pic_header {
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [% ELSE -%]
+    padding-left: 1em;
+    [% END -%]
+    white-space: nowrap;
+    width: 78px;
+}
+
+/* styles for selecting records in the results set */
+.result_table_row_selected {
+    background-color: [% css_colors.item_selected %];
+}
+#selected_records_summary, #clear_basket {
+    margin-left: 5em;
+}
+
+/* styles for the basket */
+#record_basket {
+    [% IF rtl == 't' -%]
+    float: left;
+    margin-left: 5em;
+    [% ELSE; %]
+    float: right;
+    margin-right: 5em;
+    [% END; %]
+}
+#record_basket_icon {
+    [% IF rtl == 't' -%]
+    float: left;
+    margin-left: 2em;
+    [% ELSE; %]
+    float: right;
+    margin-right: 2em;
+    [% END; %]
+    position: relative;
+}
+#record_basket_count_floater {
+    background-color: [% css_colors.accent_lighter %];
+    position: absolute;
+    top: -3px;
+    right: -3px; /* relative to icon, so don't want to adjust for RTL */
+    z-index: 2;
+    border-radius: 50%;
+}
+#record_basket_count_floater a {
+    text-decoration: none;
+}
+#basket_actions {
+    [% IF rtl == 't' -%]
+    float: left;
+    [% ELSE; %]
+    float: right;
+    [% END; %]
+}
+#basket_actions select {
+    border-color: rgb(169, 169, 169);
+}
+
+.result_number {
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [% ELSE -%]
+    padding-left: 1em;
+    [% END -%]
+    white-space: nowrap;
+}
+
+.result_count_number {
+   font-weight: bold;
+}
+
+.result_table_subtable {
+    width: 100%;
+    padding-top: 1em;
+}
+
+div.result_table_utils_cont {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    float: right;
+    [% ELSE -%]
+    text-align:left;
+    float: left;
+    [% END -%]
+}
+
+#myopac_summary_div p {
+    margin:0;
+    margin-bottom: 10px;
+}
+
+#acct_sum_checked_table td {
+    padding-bottom:5px;
+}
+
+.zero_search_hits_main {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    width:300px;
+    margin-top: 2ex;
+}
+.zero_search_hits_saved {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 2em;
+    [% ELSE -%]
+    float:left;
+    margin-right: 2em;
+    [% END -%]
+    width:200px;
+    margin-top: 2ex;
+}
+
+#zero_search_hits p {
+    margin-top:0;
+}
+
+#zero_hits_term {
+    font-weight: bold;
+}
+
+#zero_search_hits #spell_check_link {
+}
+
+#zero_search_hits #zero_hits_suggestions {
+}
+
+#lowhits_help {
+    [% IF rtl == 't' -%]
+    float: left;
+    [% ELSE -%]
+    float: right;
+    [% END-%]
+    width: 353px;
+    background-color: [% css_colors.accent_light %];
+    padding: 10px;
+    margin-top: 7px;
+}
+
+.results_info_table td {
+    [% IF rtl == 't' -%]
+    padding-left: 10px;
+    [% ELSE -%]
+    padding-right: 10px;
+    [% END-%]
+}
+
+#myopac_holds_main_table {
+    border-collapse: collapse;
+}
+
+#myopac_holds_main_table td {
+    border: 1px solid [% css_colors.border_dark %];
+    
+}
+
+.myopac-hold-available {
+    color: [% css_colors.text_greatnews %];
+    font-weight: bold;
+}
+
+.myopac-hold-suspended {
+    color: [% css_colors.text_badnews %];
+    font-weight: bold;
+}
+
+#myopac_prefs_div .data_grid {
+    border-collapse:collapse;
+}
+
+#myopac_prefs_div .data_grid td {
+    [% IF rtl == 't' -%]
+    padding: 6px 17px 7px 0px;
+    [% ELSE -%]
+    padding:6px 0px 7px 17px;
+    [% END -%]
+    background-color:[% css_colors.accent_ultralight %];
+    border-bottom:3px solid [% css_colors.background %];
+}
+
+.header_middle {
+    [% IF rtl == 't' -%]
+    padding: 0px 0px 0px 7px;
+    [% ELSE -%]
+    padding: 0px 7px 0px 0px;
+    [% END -%]
+    height:22px;
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:bold;
+    color:[% css_colors.primary_fade %];
+    border-bottom: 1px dotted [% css_colors.accent_light %];
+    clear: both;
+}
+
+.header_middle a {
+    font-weight: normal;
+}
+
+#acct_sum_block {
+    [% IF rtl == 't' -%]
+    float: right;
+    clear: right;
+    [% ELSE -%]
+    float: left;
+    clear: left;
+    [% END -%]
+}
+
+.acct_sum_table {
+    border-collapse: collapse;
+    background-color: [% css_colors.accent_ultralight %];
+}
+
+.acct_sum_table tr {
+    border-bottom: 2px solid white;
+}
+
+.acct_sum_table td {
+    padding: 1em;
+}
+
+.acct_sum_table a {
+    text-transform: none;
+    position:relative;
+    top:-1px;
+}
+
+.acct_sum_table .view_link {
+    font-weight: normal;
+}
+
+#myopac_sum_fines {
+    [% IF rtl == 't' -%]
+    float: left;
+    padding: 15px 23px 0px 0px;
+    [% ELSE -%]
+    float:right;
+    padding: 15px 0px 0px 23px;
+    [% END -%]
+    background: [% css_colors.accent_ultralight %];
+    width: 177px;
+    height: 166px;
+}
+.cc_logo_img
+{
+   width: 79%;
+    [% IF rtl == 't' -%]
+      padding-right: .5em;
+    [% ELSE -%]
+       padding-left: .5em;
+    [% END -%]
+}
+
+#myopac_sum_fines_placehold {
+    [% IF rtl == 't' -%]
+    float: left;
+    [% ELSE -%]
+    float: right;
+    [% END -%]
+    width: 177px;
+    height: 166px;
+}
+
+.acct_holds_temp td {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+}
+
+#acct_checked_tabs .align, #acct_holds_tabs .align, #acct_prefs_tabs .align {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+}
+
+#acct_checked_main_header, #acct_holds_main_header, #acct_fines_main_header, #acct_fees_main_header, #acct_checked_hist_header, #acct_holds_groups_header, #acct_holds_hist_header, #acct_list_header, #acct_list_header_anon, #temp_list_holds, #acct_messages_main_header, #ebook_circs_main_table, #ebook_holds_main_table {
+    border-collapse: collapse;
+}
+
+.acct_fines_header
+{
+   width: 100%;
+   padding-bottom:1em;
+   [% IF rtl == 't' -%]
+   float: right;
+   [% ELSE -%]
+   float:left;
+   [% END -%]
+}
+
+/* tables for entering payment information */
+#acct_fines_main_header, 
+#acct_fees_main_header
+{
+   width: 100%;
+}
+
+/* tables for entering payment information */
+#billing_info_table
+{
+    width: auto;
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    display:inline;
+    padding-left: 1em;
+    padding-right: 1em;
+}
+
+/* tables for entering payment information */
+#credit_card_info_table
+{
+    width: auto;
+    display: block;
+}
+
+/* tables for entering payment information */
+#billing_info_table td,
+#credit_card_info_table td
+{
+   [% IF rtl == 't' -%]
+    padding-right: .5em;
+    [% ELSE -%]
+    padding-left: .5em;
+    [% END -%]
+   
+}
+
+/* div for the payment buttons with the total */
+#payment_actions
+{
+   width: auto;
+   display: block;
+   padding: 1em 0 0 1em;
+   text-align:center;
+}
+
+/* Stripe's payment form */
+#payment-form
+{
+    background-color: [% css_colors.accent_ultralight %];
+    width: 50%;
+}
+#card-element
+{
+    padding: 10px;
+}
+
+/* Stripe's payment form */
+#payment-form
+{
+    background-color: [% css_colors.accent_ultralight %];
+    width: 50%;
+}
+#card-element
+{
+    padding: 10px;
+}
+
+/* text to state what is seen on cc statement */
+.cc_disclaimer
+{
+   font-style:italic;
+   font-size: 90%;
+   color:[% css_colors.primary_fade %];
+}
+
+.hold_notes {
+    text-transform: none;
+    font-weight: normal;
+}
+
+.hold_note_title { font-weight: bold; }
+#acct_checked_main_header td, #acct_holds_main_header td, #acct_fines_main_header td, #acct_fines_confirm_header td, #acct_fees_main_header td,#acct_checked_hist_header td, #acct_holds_groups_header td, #acct_holds_hist_header td, #acct_list_header td, #acct_list_header_anon td, #temp_list_holds td, #acct_messages_main_header td, #ebook_circs_main_table td, #ebook_holds_main_table td, #acct_reservations_main_header td {
+    background-color: [% css_colors.background %]; 
+    padding: 10px;
+        border: 1px solid #d3d3d3; 
+} 
+
+#acct_checked_main_header th, #acct_holds_main_header th, #acct_fines_main_header th, #acct_fines_confirm_header th, #acct_fees_main_header th, #acct_checked_hist_header th, #acct_holds_groups_header th, #acct_holds_hist_header th, #acct_list_header th, #acct_list_header_anon th, #temp_list_holds th, #acct_messages_main_header th, #ebook_holds_main_table th, #acct_reservations_main_header th {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+    padding: 0px 10px 0px 10px;
+}
+
+#acct_list_header select, #acct_list_header_anon select {
+    font-weight:normal;
+    text-transform:none;
+}
+
+.search_catalog_lbl {
+    font-size: [% css_fonts.size_bigger %];
+}
+.adv_search_catalog_lbl {
+    font-size: [% css_fonts.size_bigger %];
+}
+
+.browse_the_catalog_lbl {
+    font-size: [% css_fonts.size_bigger %];
+}
+
+.search_courses_label {
+    font-size: [% css_fonts.size_bigger %];
+}
+
+.lbl1 {
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:bold;
+}
+
+.lbl2 {
+    font-size: [% css_fonts.size_smaller %];
+    font-weight:normal;
+    position:relative;
+    top:3px;
+    max-width:300px;
+}
+
+#myopac_tabs, #adv_search_parent, #fines_payments_wrapper {
+    background-color: [% css_colors.primary_fade %];
+    padding-top:5px;
+    margin-bottom:20px;
+}
+
+#fines_payments_wrapper {
+    padding-left: 5px; 
+    padding-right: 5px;
+}
+
+.myopac_payments_table th {
+    [% IF rtl == 't' -%]
+    text-align: right; }
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+}
+
+.myopac_payments_table thead th { border-bottom: 1px dashed [% css_colors.accent_darker %]; }
+.myopac_payments_table thead th:first-child { width: 8em; }
+.myopac_payments_table tbody tr:nth-child(odd) { background-color: [% css_colors.accent_lighter %]; }
+.myopac_payments_table form { display: inline; }
+.myopac_payments_table input[type="submit"] { padding: 1px; }
+
+.cc_header
+{
+   padding-top:1em;
+   background-color: [% css_colors.accent_lighter %];
+}
+
+.payment-error {
+    font-weight: bold; color: [% css_colors.text_alert %];
+    padding: 10px; border: 1px solid [% css_colors.accent_medium_dark %];
+}
+
+.payment-processing {
+    font-weight: bold;
+    color: [% css_colors.text_greatnews %];
+    font-size: [% css_fonts.size_bigger %];
+    padding: 10px; border: 1px solid [% css_colors.accent_medium_dark %];
+    text-align: center;
+}
+#adv_search_input { width: 100%; }
+#adv_search_parent {
+    margin-bottom:0px;
+}
+#search-submit-spinner {
+    height: 16px;
+    width: 16px;
+}
+div.adv_search_available {
+    margin-top: 1em;
+}
+
+#myopac_loading {
+    width:100%;
+    text-align:center;
+    padding-top:20px;
+    font-size: [% css_fonts.size_bigger %];
+    font-weight:bold;
+}
+
+.chili_link {
+    width:100px !important;
+    text-align: center !important;
+}
+
+.chili_review div.chili_link div {
+    margin: auto;
+}
+
+/* styling for advanced search filters that display with searchbar */
+
+#adv_filter_results_block h4 { display: inline; }
+
+#adv_filter_results_block {
+    margin-top: 6px;
+}
+
+.adv_filter_results_block_label {
+    font-weight:bold;
+    [% IF rtl == 't' -%]
+    padding: 4px 12px 4px 0px;
+    [% ELSE -%]
+    padding: 4px 0px 4px 12px;
+    [% END -%]
+}
+
+.adv_filter_results_group {
+    font-size: 12px;
+    display: inline-block;
+    background-color:  [% css_colors.accent_lighter2 %];
+    border-style: solid;
+    border-color: [% css_colors.accent_medium %];
+    border-width: 1px;
+    border-radius: 4px;
+    padding: 2px 4px 2px 4px;
+}
+
+.adv_filter_results_group_wrapper {
+    display: inline-block;
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    [% ELSE -%]
+    margin-left: 1em;
+    [% END -%]
+    margin-bottom: 8px;
+}
+
+.adv_filter_results_group_header {
+    display: inline-block;
+}
+
+.adv_filter_results_group_values {
+    display: inline;
+}
+
+.adv_search_result_filter {
+    display: inline-block;
+}
+
+.remove_filter {
+    font-size: 16px;
+    [% IF rtl == 't' -%]
+    margin-right: 3px;
+    [% ELSE -%]
+    margin-left: 3px;
+    [% END -%]
+}
+
+a.remove_filter {
+    text-decoration: none;
+    color: [% css_colors.accent_dark %];
+}
+
+#filter_hits {
+     display: inline-block;
+}
+
+#refine_search_link {
+    display: inline-block;
+}
+
+[%- IF we_want_to_turn_on_facet_styling.defined; %]
+/* some facet styling */
+.facetClassContainer { margin: 2px; border: 1px solid [% css_colors.accent_light %]; }
+.facetClassLabelContainer { border: 1px solid [% css_colors.accent_light %]; }
+.facetClassLabel { font-weight: bold; text-align: center; }
+.facetFieldContainer {  }
+.facetFieldLabel { padding-left: 2px; margin-top: 5px; margin-bottom: 5px; font-weight: bold; text-align: left; }
+.extraFacetFieldsWrapper { }
+.toggleExtraFacetFieldsButton { float: right; margin: 0px; padding: 0px; }
+.facetFieldLineCount {
+    display: inline-block;
+    border-right: 1px solid [% css_colors.accent_light %];
+    color: [% css_colors.accent_mediumdark %];
+    width: 3em;
+    margin-right: 3px
+}
+.facetField { border-top: 1px solid [% css_colors.accent_light %]; }
+.facetFields { padding-left: 5px; }
+.facetFieldLineValue { overflow: hidden; text-overflow: ellipsis; }
+[%- END -%]
+
+div#facet_sidebar {
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 1em;
+    [% ELSE -%]
+    float: left;
+    margin-right: 1em;
+    [% END-%]
+}
+
+.facet_box_temp {
+    padding-bottom:3px;
+}
+
+.facet_box_temp .header {
+    height: 2.3em;
+    background-color:[% css_colors.primary %];
+    border-top-left-radius: 5px;
+    border-top-right-radius: 5px;
+    font-weight:bold;
+    color:[% css_colors.text_invert %];
+    padding-top:4px;
+}
+
+.facet_box_temp.filter_box_temp .header {
+    background-color: [% css_colors.background_invert %] !important;
+}
+
+.filter_box_label {
+    color: [% css_colors.background_invert %];
+    font-weight:bold;
+    padding-top:4px;
+    padding-bottom:4px;
+    padding-left:12px;
+}
+
+.facet_box_temp .header .title {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding-right: 12px;
+    [% ELSE -%]
+    float:left;
+    padding-left:12px;
+    [% END -%]
+    padding-top:6px;
+}
+
+/* in this context, where h4 is primarily for structure, 
+   avoid the normal large font and margin for h4's */
+.facet_box_temp h4 {
+    font-size : 100%; 
+    margin: 0px;
+}
+
+.facet_box_temp .header a.button {
+    [% IF rtl == 't' -%]
+    float: left;
+    padding-left: 6px;
+    [% ELSE -%]
+    float:right;
+    padding-right:6px;
+    [% END -%]
+    padding-top:6px;
+    color:[% css_colors.text_invert %];
+}
+
+.facet_box_wrapper .box_wrapper .box {
+    border-top:1px solid [% css_colors.border_standard %];
+    border-left:1px solid [% css_colors.border_standard %];
+    border-right:1px solid [% css_colors.border_standard %];
+    padding: 0 0.5em;
+    width: 14em;
+    overflow: hidden;
+}
+
+.filter_box_wrapper {
+    margin-bottom: 3px;
+    padding: 2px;
+    border: 1px solid [% css_colors.background_invert %];
+    border-radius: 3px;
+    font-weight:bold;
+    padding-top:4px;
+}
+
+.facet_template {
+    box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    display: table;
+    margin: 0.5em 0;
+    width: 100%;
+}
+
+.facet_template div {
+    display: table-cell;
+    padding: 2px;
+}
+
+.facet_template.filter_template div {
+    padding: 0px !important;
+}
+
+.facet_template .count {
+    text-align: right;
+    color: [% css_colors.accent_mediumdark %];
+}
+
+.facet_template_selected {
+    background-color: [% css_colors.accent_lighter2 %];
+    border: 1px solid [% css_colors.accent_medium %];
+}
+
+#footer-wrap {
+    background-color: [% css_colors.footer %];
+    background-image: -moz-linear-gradient([% css_colors.primary_fade %], [% css_colors.primary %]);
+    background-image: -o-linear-gradient([% css_colors.primary_fade %], [% css_colors.primary %]);
+    background-image: -webkit-linear-gradient([% css_colors.primary_fade %], [% css_colors.primary %]);
+    background-image: linear-gradient([% css_colors.primary_fade %], [% css_colors.primary %]);
+}
+
+#footer {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    [% ELSE -%]
+    margin-left: 1em;
+    [% END -%]
+    padding-top:5px;
+    padding-bottom: 10px;
+    font-size: [% css_fonts.size_small %];
+    color: [% css_colors.text_invert %];
+}
+
+#footer a {
+    color: [% css_colors.footer_text %];
+    text-decoration: none;
+    text-shadow: 0 0 0.2em [% css_colors.primary %], 0 0 0.2em [% css_colors.primary %];
+}
+
+#copyright_text, #footer_logo {
+    color: [% css_colors.footer_text %];
+}
+
+.color_4 {
+    font-weight: bold;
+}
+
+.advanced_div { padding-top: 15px; }
+#adv_global_search { width: 100%; }
+#adv_global_search select { width: 13em; }
+#adv_global_addrow td { padding-top: 7px; }
+[% IF rtl == 't' -%]
+#adv_global_addrow.td-search-left{text-align:right;}
+[% END -%]
+#adv_global_input_table { width: 100%; }
+#adv_global_input_table select { width: 7em; }
+.adv_adv_link {
+    font-size: [% css_fonts.size_smaller %];
+    color: [% css_colors.text_alert %];
+}
+#acct_prefs_header {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float: left;
+    [% END -%]
+}
+.search_page_nav_link {
+    cursor: pointer;
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [% ELSE -%]
+    padding-left: 1em;
+    [% END -%]
+}
+#opac.result.sort { width: 160px; }
+.renew-summary, .message-update-summary { font-size: [% css_fonts.size_bigger %]; font-style: italic; margin: 0.5ex 0; }
+.failure-text {
+    [% IF rtl == 't' -%]
+    margin-right: 4em;
+    [% ELSE -%]
+    margin-left: 4em;
+    [% END -%]
+    font-style: italic;
+    color: [% css_colors.text_alert %];
+}
+.refine-controls { font-size: [% css_fonts.size_bigger %]; padding: 0.5ex 0; }
+#adv_search_refine input[type=text] { border: 1px inset [% css_colors.accent_light %] !important; }
+#adv_search_refine select { border: 1px inset [% css_colors.accent_light %] !important; }
+#adv_search_refine {
+    [% IF rtl == 't' -%]
+    padding-right: 5em;
+    [% ELSE -%]
+    padding-left: 5em;
+    [% END -%]
+    background-color: [% css_colors.accent_lighter2 %];
+    margin: 2ex 0;
+}
+.row-remover { position: relative; top: 1px; vertical-align: middle; }
+.subtle-button {
+    background-color: [% css_colors.background %];
+    color: [% css_colors.primary %]; text-decoration: none;
+    padding: 0; border: 0; margin: 0;
+    vertical-align: middle;
+}
+.subtle-button:hover { text-decoration: underline; cursor: pointer; }
+.no-dec:hover { text-decoration: none; }
+.pending-addr td { background-color: [% css_colors.background_alert %] !important; border: 0 !important; }
+
+#account-update-email table { text-align: center; padding: 20px; margin-top: 18px; border-collapse: collapse; }
+#account-update-email table td {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+    padding: 5px 15px 5px 15px;
+    border-bottom: 1px solid [% css_colors.accent_lighter %];
+}
+#account-update-email-error { font-size: [% css_fonts.size_biggest %]; padding: 10px; border:1px solid [% css_colors.border_standard %];}
+a.dash-link:hover { text-decoration: underline !important; }
+#list_create_table td { vertical-align: middle; padding: 0 8px; }
+#list_create_table {
+    background-color: [% css_colors.accent_light %];
+    padding-bottom: 4px;
+    margin-bottom: 10px;
+    border-bottom: 1px dotted [% css_colors.accent_medium %];
+    width: 100%;
+}
+.list_create_table_label {
+    width: 30%;
+}
+#list_description, #list_create_name {
+        width: 500px;
+}
+.list-create-table-buttons input[type=image] { margin-top: 2px; }
+.result_table_format_cell { padding: 0px 10px; text-align: center; }
+.results_row_count { font-weight: bold; }
+#hold_editor h1 { font-size: [% css_fonts.size_bigger %]; font-weight: bold; }
+#hold_editor h2 { font-size: [% css_fonts.size_big %]; font-weight: normal; text-indent: 2em; font-style: italic; }
+#hold_editor h1, #hold_editor h2 { margin: 2px 0; }
+#hold_editor_table { background-color: [% css_colors.accent_lighter %]; padding: 0.5em; }
+#hold_editor_table th {
+    [% IF rtl == 't' -%]
+    text-align: left;
+    padding-left: 1em;
+    [% ELSE -%]
+    text-align: right;
+    padding-right: 1em;
+    [% END -%]
+}
+#hold_editor_table td { padding: 0.25em 0; }
+.fmt-note {
+    [% IF rtl == 't' -%]
+    padding-right: 1em !important;
+    [% ELSE -%]
+    padding-left: 1em !important;
+    [% END -%]
+    vertical-align: middle;
+}
+.hold-editor-controls { text-align: center; padding-top: 1em !important; }
+.hold-editor-controls a { padding-left: 2em; }
+
+.text-right {
+    [% IF rtl == 't' -%]
+    text-align: left;
+    [% ELSE -%]
+    text-align: right;
+    [% END -%]
+}
+.text-right-top {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    vertical-align: top;
+    [% END -%]
+}
+.rdetail-author-div, .course-instructor-div {
+    padding-bottom: 10px;
+    display: inline-block;
+}
+
+.invisible { visibility: hidden; }
+.rdetail-extras-summary { margin: 10px; }
+.staff-hold { background-color: [% css_colors.background %]; }
+.expert-search tbody tr th {
+    [% IF rtl == 't' -%]
+    text-align: left;
+    padding-right: 2em;
+    [% ELSE -%]
+    text-align: right;
+    padding-left: 2em;
+    [% END -%]
+}
+.expert-search-row { padding-top: 10px; }
+#adv_expert_row label { font-weight: bold; }
+
+.bookshelf tr.browse_border td {
+    border-bottom: 1px dashed [% css_colors.accent_dark %];
+    font-size: 1px;
+    height: 1px;
+    padding-bottom: 1ex;
+}
+.cn_browse_item { padding: 2ex; }
+.results-paginator-list {
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [% ELSE -%]
+    padding-left: 1em;
+    [% END -%]
+}
+.results-paginator-selected { color: [% css_colors.text_alert %]; }
+.inactive-hold { background-color: [% css_colors.accent_lightest %]; }
+.unread-patron-message { font-weight: bold; }
+
+#hold-items-list td { padding: 5px; margin-bottom: 20px; }
+.hold-items-list-title { 
+  font-size: [% css_fonts.size_bigger %];
+  margin-bottom: 20px;
+}
+.hold-items-list-problem { color: [% css_colors.text_alert %]; }
+
+.hold_success_links > span { margin: 0 2em; }
+
+.radio-parts-selection { 
+   width: 75%;
+   margin-bottom: 20px;
+}
+
+.parts-radio-option { 
+  display: inline-block;
+  width:15em;
+}
+
+.mr_holds_no_formats { 
+  [% IF rtl == 't' -%]
+  margin-right: 25px;
+  [% ELSE -%]
+  margin-left: 25px;
+  [% END -%]
+  padding: 5px;
+  font-size: 110%;
+  font-weight: bold;
+  color: [% css_colors.text_invert %]; 
+  background-color: [% css_colors.primary %];
+}
+.holds_item_row_separator td {
+  border-top: 2px dashed [% css_colors.accent_medium %];
+}
+
+.big-strong {font-weight: bold; font-size: [% css_fonts.size_bigger %]; }
+
+.results_header_btns, .results_header_sel {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+}
+
+/*
+ * .various_containers a = shortcut to putting .opac-button on every 'a' with
+ *     the tradeoff of increased stylesheet complexity (TODO: rethink?)
+ */
+
+.opac-multiline-button > a,
+.opac-button, .results_header_btns a, #simple-detail-view-links a, .dash_account_buttons a {
+    color: [% css_colors.button_text %];
+    font-weight: bold; 
+    text-decoration: none;
+    cursor: pointer !important;
+    border-radius: 5px;
+    border: 1px solid [% css_colors.primary %];
+    background-color:  [% css_colors.button %];
+    margin: 0.5em;
+    padding: 0.3em;
+    display: inline-block;
+}
+
+.opac-multiline-button > a:hover,
+.opac-button:hover, .results_header_btns a:hover, #simple-detail-view-links a:hover, #dash_wrapper a.opac-button:hover {
+    background-color: [% css_colors.opac_button_hover %];
+    color: [% css_colors.opac_button_hover_text %];
+}
+
+.opac-button:disabled {
+    color: [% css_colors.accent_medium %];
+    cursor: pointer !important;
+    border: 1px solid [% css_colors.accent_light %];
+    background-color: [% css_colors.accent_lighter %];
+}
+
+/* Firefox adds its own special space to inputs; this gets us closer */
+button.opac-button::-moz-focus-inner, input.opac-button::-moz-focus-inner {
+    padding: 0;
+    border: 0;
+}
+
+.opac-button-header, #dash_wrapper .opac-button {
+    color: [% css_colors.opac_button_text %];
+    background-color: [% css_colors.opac_button %];
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
+    font-size: [% css_fonts.size_base %];
+}
+a.opac-button-header:hover, #dash_wrapper a.opac-button:hover {
+    border-color: [% css_colors.opac_button_hover %];
+}
+
+.opac-multiline-button > a {
+    display: inline-block;
+}
+
+#myopac_checked_div {
+    padding: 0px;
+}
+
+.rdetail-mfhd-head {
+    margin-top: 5px;
+    padding-top: 5px;
+    background-color: [% css_colors.table_heading %];
+}
+
+.rdetail-mfhd-type {
+    [% IF rtl == 't' -%]
+    padding-right: 1em;
+    [% ELSE -%]
+    padding-left: 1em;
+    [% END -%]
+}
+
+.rdetail-mfhd-bottom {
+    border-bottom: thin solid [% css_colors.border_dark %];
+    width: 100%;
+}
+
+#rdetail_record_details {
+    clear: both;
+    margin-top: 1em;
+}
+
+.rdetail_content {
+    [% IF rtl == 't' -%]
+    margin-right: 1.5em;
+    padding-right: 1.5em;
+    [% ELSE -%]
+    margin-left: 1.5em;
+    padding-left: 1.5em;
+    [% END -%]
+}
+
+.rdetail_content_type, .rdetail_subject_type {
+    vertical-align: top;
+    font-weight: bold;
+}
+
+.bookbag-item-row td { vertical-align: top; }
+
+.error { color: [% css_colors.text_alert %]; font-weight: bold; }
+.success {
+    color: [% css_colors.text_greatnews %];
+    font-weight: bold;
+}
+
+.rdetail_related_subjects {
+    margin-top: 1.5em;
+}
+
+.rdetail_related_series {
+    margin-top: 1.5em;
+}
+
+#rdetail_openurl {
+    margin-top: 1em;
+}
+
+.rdetail_openurl_entry {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    padding-right: 1em;
+    [% ELSE -%]
+    margin-left: 1em;
+    padding-left: 1em;
+    [% END -%]
+}
+.bookbag-controls-holder { width: 100%; }
+.bookbag-controls-holder:nth-child(odd) { background-color: [% css_colors.accent_lighter2 %]; }
+.bookbag-controls-holder:nth-child(even) { background-color: [% css_colors.accent_lightest %]; }
+.bookbag-controls-holder .most {
+    [% IF rtl == 't' -%]
+    padding-right: 0;
+    margin-left: 5em;
+    [% ELSE -%]
+    padding-left: 0;
+    margin-right: 5em;
+    [% END -%]
+}
+.bookbag-controls-title-block {
+    [% IF rtl == 't' -%]
+    float:right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    width:40%;
+}
+.bookbag-controls-button-block {
+    [% IF rtl == 't' -%]
+    float:right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    width:50%;
+}
+h2.bookbag-name { margin-bottom: 0em; padding-bottom: 0em; }
+.bookbag-share .fixed { min-width: 4em; }
+.bookbag-specific {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    [% ELSE -%]
+    margin-left: 1em;
+    [% END -%]
+}
+.bookbag-specific div.sort {
+    [% IF rtl == 't' -%]
+    float: right;
+    text-align: right;
+    margin-right: 15px;
+    [% ELSE -%]
+    float: left;
+    text-align: left;
+    margin-left: 15px;
+    [% END -%]
+    width: 45%;
+}
+.bookbag-specific div.meta {
+    background-color: [% css_colors.accent_light %];
+    [% IF rtl == 't' -%]
+    float: left;
+    text-align: left;
+    [% ELSE -%]
+    float: right;
+    text-align: right;
+    [% END -%]
+    width: 54%;
+    border: 1px solid [% css_colors.accent_light %];
+    padding: 5px;
+    margin-top: 5px;
+}
+#bbag-name-desc-form tr th { vertical-align: middle; }
+#bbag-name-desc-form .saver { vertical-align: middle; text-align: center; }
+.bookbag-description {
+    padding-top: 0em;
+    font-style: italic;
+    max-width: 40em;
+}
+.bbag-edit-desc-label {
+    [% IF rtl == 't' -%]
+    float:right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+    width:8em;
+}
+.bbag-edit-desc-save {
+    clear:both;
+    margin-bottom:10px;
+}
+#bbag-edit-description {
+    width: 20em;
+    [% IF rtl == 't' -%]
+    float:right;
+    [% ELSE -%]
+    float:left;
+    [% END -%]
+}
+#bbag-edit-name {
+    width: 20em;
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float: left;
+    [% END -%]
+}
+.bbag-action {
+    [% IF rtl == 't' -%]
+    margin-right: 15px;
+    [% ELSE -%]
+    margin-left: 15px;
+    [% END -%]
+}
+.bbag-navigate-list {
+    [% IF rtl == 't' -%]
+    padding-right: 32px;
+    float:right;
+    [% ELSE -%]
+    padding-left: 32px;
+    float:left;
+    [% END -%]
+}
+.bbag-navigate-list-pages {
+    [% IF rtl == 't' -%]
+    padding-right: 10px;
+    float:right;
+    [% ELSE -%]
+    padding-left: 10px;
+    float:left;
+    [% END -%]
+}
+textarea { font-family: sans-serif; }
+table.bookbag-specific {
+    border-right: 1px solid [% css_colors.accent_dark %];
+    border-bottom: 1px solid [% css_colors.accent_medium %];
+    margin-bottom: 2ex;
+    width: 100%;
+}
+.bookbag-share {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding: 0px 10px 0px 0px;
+    [% ELSE -%]
+    float: left;
+    padding: 0px 0px 0px 10px;
+    [% END -%]
+}
+.bookbag-share .fixed { min-width: 6em; }
+.bookbag-controls {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding: 0px 10px 0px 0px;
+    [% ELSE -%]
+    float: left;
+    padding: 0px 0px 0px 10px;
+    [% END -%]
+}
+.bookbag-specific td.list_checkbox {
+    [% IF rtl == 't' -%]
+    padding-right: 10px !important;
+    [% ELSE -%]
+    padding-left: 10px !important;
+    [% END -%]
+}
+.bookbag-specific td.list_entry {
+    min-width: 10em;
+    [% IF rtl == 't' -%]
+    padding-right: 5px !important;
+    [% ELSE -%]
+    padding-left: 5px !important;
+    [% END -%]
+}
+.bookbag-specific td.list_actions {
+    white-space: nowrap !important;
+}
+.bookbag-paginator-selected { color: [% css_colors.text_alert %]; }
+
+.list_is_empty {
+    padding: 8px 0px 6px 0px;
+    width: 100%;
+    border: 0;
+    font-size: [% css_fonts.size_bigger %];
+    text-align: center;
+    font-style: italic;
+}
+.save-notes { padding-bottom: 1.5ex; }
+
+.nonbreaking-wrapper {
+    display: inline-block;
+}
+
+/* Moved from semiauto.css */
+.adv_global_input_container {
+    border-bottom: none;
+    clear: both;
+}
+.opac-auto-013 {
+    border-bottom: none;
+    *height: 0px;
+}
+.adv_global_filter_sort {
+    border: none;
+    width: 100%;
+}
+.clear-both { clear: both; }
+.common-no-pad {
+    clear: both;
+    height: 0px;
+    margin: 0px;
+    padding: 0px;
+}
+.common-full-pad {
+    clear: both;
+    height: 15px;
+}
+.alert { color: [% css_colors.text_alert %]; }
+.float-left {
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float: left;
+    [% END -%]
+}
+.float-right {
+    [% IF rtl == 't' -%]
+    float: left;
+    [% ELSE -%]
+    float: right;
+    [% END -%]
+}
+
+.saved-searches-header { width: 100%; font-weight: bold; font-size: [% css_fonts.size_bigger %]; }
+.saved-searches-header .button {
+    [% IF rtl == 't' -%]
+    float: left;
+    [% ELSE -%]
+    float: right;
+    width: 28px;
+    [% END -%]
+}
+.saved-searches-header .text {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding-left: 1em;
+    [% ELSE -%]
+    float: left;
+    padding-right: 1em;
+    [% END -%]
+    margin: 0.5ex 0;
+}
+.saved-searches-header {font-weight: bold; font-size: [% css_fonts.size_bigger %]; }
+.saved-searches { border-bottom: 1px solid [% css_colors.accent_medium %]; padding-right: 1em; }
+#staff-saved-search { /* wraps .saved-searches-header and .saved-searches on the record page */
+    [% IF rtl == 't' -%]
+    border-left: 1px solid [% css_colors.accent_darker %];
+    [% ELSE -%]
+    border-right: 1px solid [% css_colors.accent_darker %];
+    [% END -%]
+}
+.result_item_circulated {
+    padding-top: 4px;
+}
+
+.result_item_circulated span {
+    position: relative;
+    top:-3px;
+    [% IF rtl == 't' -%]
+    right: 3px;
+    [% ELSE -%]
+    left:3px;
+    [% END -%]
+}
+
+#search-only-bookbag-container { margin: 2ex 0; font-weight: bold; }
+#result-bookbag-heading { text-align: center; margin: 2ex; }
+
+.result-bookbag-name { font-size: [% css_fonts.size_bigger %]; font-weight: bold; }
+.result-bookbag-description { font-size: [% css_fonts.size_bigger %]; font-style: italic; }
+.result-bookbag-item-note { font-style: italic; }
+.lowhits-bookbag-name { font-weight: bold; }
+.oils_AS { font-weight: bold; color: [% css_colors.text_match %]; }
+.oils_AS_match_term {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+    color: [% css_colors.text %];
+}
+.oils_AS_match_field {
+    font-size: [% css_fonts.size_smallest %]; padding: 0.65em 0;
+    [% IF rtl == 't' -%]
+    text-align: left;
+    [% ELSE -%]
+    text-align: right;
+    [% END -%]
+    color: [% css_colors.accent_medium %];
+}
+table.result_holdings_table {
+    margin-top: 1em;
+    margin-bottom: 1em;
+}
+table.result_holdings_table thead tr {
+    background-color: [% css_colors.table_heading %];
+}
+table.result_holdings_table thead tr th {
+    font-weight: bold;
+}
+span.preflib {
+    margin: 0 2em 0 2em;
+}
+a.preflib_change {
+  vertical-align: super;
+  font-size: [% css_fonts.size_smaller %];
+  line-height: normal;
+  text-decoration: none;
+}
+.rdetail-holding-group {
+    [% IF rtl == 't' -%]
+    margin-right: 1.5em;
+    [% ELSE -%]
+    margin-left: 1.5em;
+    [% END -%]
+}
+.rdetail-holding-group span {
+    [% IF rtl == 't' -%]
+    margin-right: 1.5em;
+    [% ELSE -%]
+    margin-left: 1.5em;
+    [% END -%]
+}
+.rdetail-holding-group .paging {
+    [% IF rtl == 't' -%]
+    margin-right: 1.5em;
+    [% ELSE -%]
+    margin-left: 1.5em;
+    [% END -%]
+}
+#rdetail_deleted_exp {
+    font-weight: bold;
+    padding: 1em;
+    margin: 1em;
+    border: thick solid [% css_colors.border_alert %];
+}
+
+#ac_tab_wrapper { width : 100%; }
+.ac_tab {
+    [% IF rtl == 't' -%]
+    float: right;
+    padding-left: 10px;
+    [% ELSE -%]
+    float: left;
+    padding-right: 10px;
+    [% END -%]
+    font-size: [% css_fonts.size_big %];
+    padding: 5px;
+    border: 1px solid [% css_colors.primary_offset %];
+}
+.ac_tab_selected { background-color: [% css_colors.primary_offset %]; }
+.ac_tab_selected a { color: [% css_colors.text_invert %]; }
+#ac_content { clear: both; width: 100%; margin-top: 10px; }
+
+/* Popmenu styles used for making css menus. */
+.popmenu {
+    margin: 0;
+    padding: 0;
+}
+.popmenu li {
+    list-style: none;
+}
+.popmenu li a {
+    display: block;
+    padding: 3px 5px;
+}
+.popmenu li ul {
+    display: none; 
+    width: 10em; /* Width to help Opera out */
+    background-color: [% css_colors.primary %];
+}
+.popmenu li:hover ul {
+    display: block;
+    position: absolute;
+    margin: 0;
+    padding: 0;
+    border-color: [% css_colors.border_dark %];
+    border-width: 1px;
+    border-style: solid;
+    z-index: 1;
+}
+.popmenu li:hover li {
+    float: none;
+}
+.popmenu li:hover li a {
+    background-color: [% css_colors.primary %] !important;
+    color: [% css_colors.accent_ultralight %] !important;
+}
+.popmenu li li a:hover {
+    background-color: [% css_colors.accent_ultralight %] !important;
+    color: [% css_colors.primary %] !important;
+}
+/* Styles for the basket entry. */
+.popmenu li:hover li[class~="temporary"] a {
+    background-color: [% css_colors.primary %]; 
+    color: [% css_colors.accent_ultralight %];
+}
+.popmenu li li[class~="temporary"] a:hover {
+    background-color: [% css_colors.accent_ultralight %]; 
+    color: [% css_colors.primary %];
+}
+/* Styles for the default list entry. */
+.popmenu li:hover li[class~="default"] a {
+    background-color: [% css_colors.primary %]; 
+    color: [% css_colors.accent_ultralight %];
+}
+.popmenu li li[class~="default"] a:hover {
+    background-color: [% css_colors.accent_ultralight %]; 
+    color: [% css_colors.primary %];
+}
+/* Styles for the new list entry. */
+.popmenu li:hover li[class~="new"] a {
+    background-color: [% css_colors.primary %]; 
+    color: [% css_colors.accent_ultralight %];
+}
+.popmenu li li[class~="new"] a:hover {
+    background-color: [% css_colors.accent_ultralight %]; 
+    color: [% css_colors.primary %];
+}
+/* Style to add a divider on the menu. */
+.popmenu li li[class~="divider"] {
+    border-bottom-width: 1px;
+    border-bottom-color: [% css_colors.border_dark %];
+    border-bottom-style: solid;
+}
+    
+#locale_picker_form {
+    [% IF rtl == 't' -%]
+    float: left;
+    border-left: thin [% css_colors.control %] solid;
+    [% ELSE -%]
+    float: right;
+    border-right: thin [% css_colors.control %] solid;
+    [% END -%]
+    padding: 0.5em;
+    margin-top: 2em;
+}
+
+#locale_picker_form * {
+    margin: 0;
+    padding: 0;
+    vertical-align: middle;
+}
+
+#patron_usr_barcode_not_found {
+    font-weight: bold; color: [% css_colors.text_alert %];
+}
+
+.record_title {
+    font-weight: bold;
+}
+
+.record_author {
+    font-style: italic;
+}
+
+.password_message {
+    padding-top: 1em;
+    padding-bottom: 0.5em;
+       font-style: italic;
+}
+
+#maintenance_message {
+    padding: 5px;
+    width: 100%;
+    background-color: [% css_colors.text_alert %];
+    color: [% css_colors.text_invert %];
+    text-align: center;
+}
+
+#maintenance_message > a {
+    color: white;
+}
+
+#search-box > span {
+    margin: 0 1em;
+}
+.browse-error {
+    font-weight: bold;
+    font-color: #c00;
+}
+.browse-result-sources, .browse-result-authority-bib-links {
+    [% IF rtl == 't' -%]
+    margin-right: 1em;
+    [% ELSE -%]
+    margin-left: 1em;
+    [% END -%]
+}
+.browse-result-best-match {
+    font-weight: bold;
+}
+.browse-pager {
+    margin: 2ex 0;
+}
+.browse-result-list {
+    padding-bottom: 0.5ex;
+}
+.browse-shortcuts {
+    font-size: [% css_fonts.size_bigger %];
+}
+.browse-result-authority-field-name {
+    font-style: italic;
+    [% IF rtl == 't' -%]
+    margin-left: 1em;
+    [% ELSE -%]
+    margin-right: 1em;
+    [% END -%]
+}
+.browse-leading-article-warning {
+    font-style: italic;
+    font-size: [% css_fonts.size_big %];
+}
+.browse-public-general-note {
+    font-size: [% css_fonts.size_big %];
+}
+.browse-public-general-note-label { }
+.browse-public-general-note-institution {
+    font-style: normal;
+    font-weight: bold;
+}
+.browse-public-general-note-body {
+    font-style: italic;
+}
+
+.bib_peer_type {
+    font-weight: bold;
+}
+
+#main-content-register {
+    [% IF rtl == 't' -%]
+    margin-right: 40px;
+    [% ELSE -%]
+    margin-left: 40px;
+    [% END -%]
+    font-size: [% css_fonts.size_bigger %];
+}
+
+#main-content-register table { 
+    padding: 20px; 
+    margin-top: 18px; 
+    border-collapse: collapse;
+}
+
+#main-content-register td {
+    [% IF rtl == 't' -%]
+    text-align: right;
+    [% ELSE -%]
+    text-align: left;
+    [% END -%]
+}
+
+#main-content-register td:not(:first-child) {
+    [% IF rtl == 't' -%]
+    padding-right: 20px;
+    [% ELSE -%]
+    padding-left: 20px;
+    [% END -%]
+}
+
+.patron-reg-invalid {
+    font-weight: bold;
+    color: red;
+    [% IF rtl == 't' -%]
+    padding-left: 10px;
+    [% ELSE -%]
+    padding-right: 10px;
+    [% END -%]
+}
+
+.result_footer_nav1 {
+    clear: both;
+}
+
+.small_view_only, #filter_hits, #refine_hits, #return_to_hits {
+    display: none;
+}
+
+.rdetail_authors_div, .course_instructors_div {
+    margin-bottom: 1em;
+}
+
+#search_query_label, #search_qtype_label, #search_itype_label, #search_locg_label {
+    white-space: nowrap;
+    display: inline-block;
+}
+
+.result_table_title_cell {
+    padding-top: 4px;
+    padding-bottom: 4px;
+}
+
+.record_title {
+    font-size: [% css_fonts.size_bigger %];
+}
+
+/* styling for sms text call number */
+.sms_text pre {
+    font-family: Arial, Helvetica, sans-serif;
+    font-size: [% css_fonts.size_medium %];
+    background-color: [% css_colors.accent_lightest %];
+    padding: .5%;
+    /* Allow text to wrap */
+    white-space: pre-wrap;       /* css-3 */
+    white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
+    white-space: -pre-wrap;      /* Opera 4-6 */
+    white-space: -o-pre-wrap;    /* Opera 7 */
+    word-wrap: break-word;       /* Internet Explorer 5.5+ */
+}
+
+.mobile_view {
+   display:none;
+}
+
+/* patron message center */
+#myopac_message_tbody {
+    vertical-align: top;
+}
+.myopac_message_message {
+    white-space: pre-wrap;
+}
+
+@media only screen and (max-width: 800px) {
+    .facet_sidebar_hidden, .result_block_hidden {
+        display: none;
+    }
+    .facet_sidebar_visible, .result_block_visible {
+        display: inline ! important;
+    }
+    #acct_select, #acct_prefs_select {
+        display: inline-block;
+    }
+    #acct_tabs, #acct_prefs_tabs {
+         display:none;
+     }
+    .radio-parts-selection { width: 90%; }
+    #list_description, #list_create_name {
+        width: 300px;
+    }
+}
+
+@media only screen and (max-width: 600px) {
+    input, select {
+        font-size: [% css_fonts.size_big %];
+    }
+    span .nav_arrow_fix {
+        display: none;
+    }
+    #header {
+        padding: 0px;
+        margin: 0px;
+    }
+    #homesearch_main_logo img {
+        width:75%;
+    }
+    #format_selector {
+        display:none;
+    }
+    #your-acct-login {
+        padding: 0px;
+        padding-top: 5px;
+    }
+    #your-acct-login a {
+        margin: 0px;
+        padding: 5px;
+    }
+    #topnav_logo {
+        margin: 0;
+    }
+    #topnav_logo img {
+        width: 200px;
+    }
+    #locale_picker_form {
+        display: none;
+    }
+    #gold-links-holder {
+        display: none;
+    }
+    #simple-detail-view-links {
+        display: none;
+    }
+    #acct_tabs a, #acct_fines_tabs a {
+       [% IF rtl == 't' -%]
+       border-radius: 6px 0px 0px 6px;
+       margin: 0px 0px 0px 5px;
+       [% ELSE -%]
+       border-radius: 6px 6px 0px 0px;
+       margin: 0px 5px 0px 0px;
+       [% END -%]
+       padding: 2px 4px 3px 4px;
+       font-size: [% css_fonts.size_base %];
+    }
+    .bookbag-controls-title-block {
+        [% IF rtl == 't' -%]
+        clear:right;
+        [% ELSE -%]
+        clear:left;
+        [% END -%]
+        width:90%;
+    }
+    .bookbag-controls-button-block {
+        [% IF rtl == 't' -%]
+        clear:right;
+        [% ELSE -%]
+        clear:left;
+        [% END -%]
+        width;90%;
+    }
+    .bookbag-specific {
+        [% IF rtl == 't' -%]
+        margin-right: 0px;
+        [% ELSE -%]
+        margin-left: 0px;
+        [% END -%]
+    }
+    .bookbag-specific div.sort {
+        [% IF rtl == 't' -%]
+        float: right;
+        text-align: right;
+        [% ELSE -%]
+        float: left;
+        text-align: left;
+        [% END -%]
+        width: 95%;
+        margin: 5px 0px 5px 0px;
+        border: 1px solid [% css_colors.accent_light %];
+        padding:5px;
+    }
+    .bookbag-specific div.meta {
+        [% IF rtl == 't' -%]
+        float: right;
+        margin-right:0px;
+        text-align: right;
+        [% ELSE -%]
+        float: left;
+        margin-left:0px;
+        text-align: left;
+        [% END -%]
+        width: 95%;
+        margin-bottom:5px;
+        padding:5px;
+    }
+    #bbag-edit-name {
+        [% IF rtl == 't' -%]
+        float: right;
+        [% ELSE -%]
+        float: left;
+        [% END -%]
+        width: 220px;
+    }
+    #bbag-edit-description {
+        width: 220px;
+        margin-top:5px;
+    }
+    .bbag-content {
+        padding:5px;
+        border:1px solid [% css_colors.accent_light %];
+    }
+    .bbag-action {
+        [% IF rtl == 't' -%]
+        margin-right:0px;
+        [% ELSE -%]
+        margin-left:0px;
+        [% END -%]
+        margin-bottom:5px;
+    }
+    .bbag-action-field {
+        width:230px;
+    }
+    .bookbag-specific div.sort select {
+        width:180px;
+    }
+    .bookbag-specific tr {
+        display: block;
+        border-bottom: 1px solid [% css_colors.border_standard %];
+    }
+    .bookbag-specific td.list_checkbox {
+        [% IF rtl == 't' -%]
+        padding-right: 0px !important;
+        [% ELSE -%]
+        padding-left: 0px !important;
+        [% END -%]
+    }
+    .bookbag-specific td.list_entry {
+        display: inline-block;
+        min-width: 5em;
+        [% IF rtl == 't' -%]
+        padding-right: 40% !important;
+        [% ELSE -%]
+        padding-left: 40% !important;
+        [% END -%]
+    }
+    .bookbag-specific td.list_entry:before {
+        content: attr(data-label);
+        position: absolute;
+        [% IF rtl == 't' -%]
+        right: 10px;
+        [% ELSE -%]
+        left: 10px;
+        [% END -%]
+    }
+    .bbag-navigate-list {
+        display: none;
+    }
+    .bbag-navigate-list-pages {
+        [% IF rtl == 't' -%]
+        text-align:left;
+        float:left;
+        [% ELSE -%]
+        text-align:right;
+        float:right;
+        [% END -%]
+    }
+    #dash_wrapper div {
+        background-color: transparent;
+        padding: 0px;
+    }
+    #dash_wrapper {
+        position: static;
+        top: auto;
+    }
+    #dash_wrapper .opac-button {
+        top: 0px;
+    }
+    .small_view_only, #filter_hits {
+        display: inline !important;
+    }
+    #dash_identity a {
+        [% IF rtl == 't' -%]
+        float:right;
+        [% ELSE -%]
+        float:left;
+        [% END -%]
+    }
+    #dashboard, #dashboard_e {
+        display: none;
+    }
+    #holds_box form blockquote {
+        [% IF rtl == 't' -%]
+        margin-right: 10px;
+        margin-left: 2px;
+        [% ELSE -%]
+        margin-left: 10px;
+        margin-right: 2px;
+        [% END -%]
+    }
+    #holds_box form blockquote select {
+        width: 100%;
+    }
+    #myopac_sum_fines_placehold {
+        display:none;
+    }
+    #myopac_sum_fines {
+        display: none;
+    }
+    #list_description, #list_create_name {
+        width: 170px;
+    }
+    .results_header_lbl {
+        display: none;
+    }
+    .results_header_nav1 span.h1 {
+        display: none;
+    }
+    .preflib {
+        display: none;
+    }
+    .start_end_links_span {
+        display: block;
+    }
+    .invisible {
+        display: none;
+    }
+    .result_table_pic_header {
+        [% IF rtl == 't' -%]
+        padding-right: 0px !important;
+        padding-left: 5px;
+        [% ELSE -%]
+        padding-left: 0px !important;
+        padding-right: 5px;
+        [% END -%]
+        width: 0px !important;
+        margin: 0px;
+    }
+    .result_table_pic {
+        width: 55px;
+        padding: 0px;
+        margin: 0px;
+    }
+    tr[name=results_isbn_tr], tr[name=results_phys_desc_tr], tr[name=results_pub_tr] strong, .result_count {
+         display: none;
+    }
+    tr.result_table_title_cell[name=bib_cn_list] .result_holdings_table th:nth-child(4),
+    tr.result_table_title_cell[name=bib_cn_list] .result_holdings_table td:nth-child(4) {
+        display:none;
+    }
+    .results_info_table td {
+        padding: 0px;
+    }
+    #results_header_bar {
+        background-color: inherit;
+    }
+    .results_header_btns a {
+        margin: 0.3em;
+    }
+    .adv_filter_results_hide {
+        display: none;
+    }
+    .adv_filter_results_show {
+        display: block;
+    }
+    .adv_filter_results_block_label {
+        display: block;
+    }
+    .adv_filter_results_group_wrapper {
+        display: block;
+    }
+    #main-content {
+        margin: 0 1px;
+    }
+    #rdetails_status thead,
+    #course_material_table thead {
+        display: none;
+    }
+    #rdetails_status tr,
+    #course_material_table tr {
+       display: block;
+       margin-top: 3px;
+    }
+    #rdetails_status td,
+    #course_material_table td {
+       display: block;
+       padding: 1px;
+    }
+    .copy_details_row {
+       background-color: [% css_colors.accent_lightest %];
+    }
+    .copy_details_offers_row {
+       background-color: [% css_colors.accent_lightest %];
+    }
+    select#pickup_lib.search-wrapper-locg {
+        width: 100%;
+    }
+    #search-wrapper #search-box {
+        width: 85%;
+        padding-top: 5px;
+    }
+    #main-content-home {
+        padding: 0px;
+        margin: 0px;
+    }
+    /* Make use of full width in mobile mode */
+    .facet_box_wrapper .box_wrapper .box,
+    .facet_template .facet,
+    .facet_box_temp {
+        width: inherit;
+    }
+    .facet_template .count {
+        [% IF rtl == 't' -%]
+        padding-right: 1em;
+        [% ELSE -%]
+        padding-left: 1em;
+        [% END -%]
+    }
+    #facet_sidebar {
+        margin-top: 0.5em;
+    }
+    #adv_search_parent {
+        font-size: [% css_fonts.size_smaller %];
+    }
+    #adv_search_filters {                                                                                                                             
+        position: relative;                                                                                                                           
+        width: 300px;
+    }
+    #format_actions {
+        [% IF rtl == 't' -%]
+        float: right;
+        [% ELSE -%]
+        float: left;
+        [% END -%]
+    }
+    .rdetail_aux_utils {
+        padding: 0px;
+        border: none;
+    }
+    .result_metadata {
+        width: inherit;
+    }
+    div#rdetail_actions_div {
+        float: none;
+    }
+    h2.rdetail_uris {
+        clear: both;
+    }
+    #metarecord_population {
+        overflow: hidden;
+        width: 100%;
+    }
+    .metarecord_population_span_link {
+    }
+    .metarecord_population_item_lang {
+        float: none;
+    }
+    .search_catalog_lbl {
+        [% IF rtl == 't' -%]
+       margin-right: 0;
+        [% ELSE -%]
+       margin-left: 0;
+        [% END -%]
+       white-space: nowrap;
+    }
+    .adv_search_catalog_lbl { 
+        margin-top: 0;
+       white-space: nowrap;
+    }
+    .browse_the_catalog_lbl {
+        white-space: nowrap;
+    }
+    .mobile_hide {
+       display: none;
+    } 
+    #dash_user {
+        display: block;
+        padding: 0.5em;
+    }
+    .dash_divider {
+       display: none;
+    }
+    .dash_account_buttons {
+        display: block;
+    } 
+    .searchbar { line-height: 1.5em; }
+    #browse-controls { line-height: 1.5em; }
+    #search_query_label, #search_qtype_label, #search_itype_label, #search_locg_label {
+        display: block;
+    }
+    .bookshelf td {
+       display: block;
+       width: 100%;
+    }
+    .bookshelf table thead tr {
+       display: block;
+    }
+    #lowhits_help { width: inherit; }
+    #adv_search_tabs a{                                                                                                                           
+        font-size: [% css_fonts.size_small %];
+        margin: 2px 2px 0px 2px;
+        padding: 2px 2px 5px 2px; 
+        [% IF rtl == 't' -%]
+        border-radius: 7px 0px 0px 7px;
+        [% ELSE -%]
+        border-radius: 7px 7px 0px 0px;
+        [% END -%]
+    }
+    #adv_global_tbody td {
+        border-bottom: thin solid [% css_colors.accent_light %];
+    }
+    #adv_global_addrow td {
+        border-bottom: none;
+    }
+        /* Force table to not be like tables anymore */
+        table#acct_checked_main_header thead tr th, table#acct_holds_main_header thead tr th, table#acct_checked_hist_header thead tr th, table#acct_holds_groups_header thead tr th, table#acct_holds_hist_header thead tr th, table#ebook_circs_main_table thead tr th, table#ebook_holds_main_table thead tr th, table#acct_reservations_main_header tr th{
+                display: block;
+        }
+        table#acct_checked_main_header tbody tr td, table#acct_holds_main_header tbody tr td, table#acct_checked_hist_header tbody tr td, table#acct_holds_groups_header tbody tr td, table#acct_holds_hist_header tbody tr td, table#ebook_circs_main_table tbody tr td, table#ebook_holds_main_table tbody tr td {
+                display: block;
+        }
+
+        /* Hide table headers (but not display: none;, for accessibility) */
+        thead tr {
+                position: absolute;
+                top: -9999px;
+                [% IF rtl == 't' -%]
+                right: -9999px;
+                [% ELSE -%]
+                left: -9999px;
+                [% END -%]
+        }
+
+        table#acct_checked_main_header, table#acct_holds_main_header, table#acct_checked_hist_header, table#acct_holds_groups_header, table#acct_holds_hist_header, table#ebook_circs_main_table, table#ebook_holds_main_table, table#acct_reservations_main_header {
+                width: 90%;
+        }
+
+        table#acct_checked_main_header tr, table#acct_holds_main_header tr, table#acct_checked_hist_header tr, table#acct_reservations_main_header { border: 1px solid #ddd; }
+
+        /* Holds history gets large white border to mimic header cell on other
+           account screens that provide visual cue for next title. We should do
+           the same for ebook tables too since we have no actions on those
+           tables. If actions get added, we should move those tables out of
+           here. */
+
+        table#acct_holds_hist_header tr, table#acct_holds_groups_header tr, table#ebook_circs_main_table tr, table#ebook_holds_main_table tr { border-top: 25px solid #fff; }
+
+
+        table#acct_checked_main_header td, table#acct_holds_main_header td, table#acct_checked_hist_header td, table#acct_holds_groups_header td, table#acct_holds_hist_header td, table#ebook_circs_main_table td, table#ebook_holds_main_table td, table#acct_reservations_main_header td {
+                /* Behave  like a "row" */
+                border: none;
+                border-bottom: 1px solid #eee;
+                position: relative;
+                [% IF rtl == 't' -%]
+                padding-right: 40%;
+                [% ELSE -%]
+                padding-left: 40%;
+                [% END -%]
+        }
+
+         table#acct_checked_main_header td:before, table#acct_holds_main_header td:before, table#acct_checked_hist_header td:before, table#acct_holds_groups_header td:before, table#acct_holds_hist_header td:before, table#ebook_circs_main_table td:before, table#ebook_holds_main_table td:before, table#acct_reservations_main_header td {
+                /* Now like a table header */
+                position: absolute;
+                /* Top/left values mimic padding */
+                top: 2px;
+                width: 40%;
+                [% IF rtl == 't' -%]
+                right: 2px;
+                padding-left: 10px;
+                [% ELSE -%]
+                left: 2px;
+                padding-right: 10px;
+                [% END -%]
+                white-space: nowrap;
+        }
+
+        table#acct_checked_main_header td:nth-of-type(1) { border-top: 5px solid #aaa; padding-top: 15px; background-color: #fff;}
+        table#acct_checked_main_header td:nth-of-type(2):before { content: "[% l('Title') %]";}
+        table#acct_checked_main_header td:nth-of-type(3):before { content: "[% l('Author') %]"; }
+        table#acct_checked_main_header td:nth-of-type(4):before { content: "[% l('Renewals Left') %]"; }
+        table#acct_checked_main_header td:nth-of-type(5):before { content: "[% l('Due Date') %]"; }
+        table#acct_checked_main_header td:nth-of-type(6):before { content: "[% l('Barcode') %]"; }
+        table#acct_checked_main_header td:nth-of-type(7):before { content: "[% l('Call number') %]"; }
+
+     table#acct_checked_hist_header td:nth-of-type(1) { border-top: 5px solid #aaa; padding-top: 15px; background-color: #fff;}
+        table#acct_checked_hist_header td:nth-of-type(2):before { content: "[% l('Title') %]";}
+        table#acct_checked_hist_header td:nth-of-type(3):before { content: "[% l('Author') %]"; }
+        table#acct_checked_hist_header td:nth-of-type(4):before { content: "[% l('Checkout Date') %]"; }
+        table#acct_checked_hist_header td:nth-of-type(5):before { content: "[% l('Due Date') %]"; }
+        table#acct_checked_hist_header td:nth-of-type(6):before { content: "[% l('Date Returned') %]"; }
+        table#acct_checked_hist_header td:nth-of-type(7):before { content: "[% l('Barcode') %]"; }
+        table#acct_checked_hist_header td:nth-of-type(8):before { content: "[% l('Call number') %]"; }
+
+
+        table#acct_holds_main_header thead tr th {
+                display: block;
+        }
+        table#acct_holds_main_header tbody tr td {
+                display: block;
+        }
+
+        table#acct_holds_main_header td {
+                /* Behave  like a "row" */
+                border: none;
+                border-bottom: 1px solid #eee;
+                position: relative;
+                padding-left: 40%;
+        }
+
+
+        table#acct_holds_main_header td:before {
+                /* Now like a table header */
+                position: absolute;
+                /* Top/left values mimic padding */
+                left: 2px;
+                width: 40%;
+                padding-right: 10px;
+                white-space: nowrap;
+        }
+
+        table#acct_holds_main_header td:nth-of-type(1) { border-top: 5px solid #aaa; padding-top: 15px; background-color: #fff;}
+        table#acct_holds_main_header td:nth-of-type(2):before { content: "[% l('Title') %]";}
+        table#acct_holds_main_header td:nth-of-type(3):before { content: "[% l('Author') %]"; }
+        table#acct_holds_main_header td:nth-of-type(4):before { content: "[% l('Format') %]"; }
+        table#acct_holds_main_header td:nth-of-type(5):before { content: "[% l('Pickup Location') %]"; }
+        table#acct_holds_main_header td:nth-of-type(6):before { content: "[% l('Cancel on') %]"; }
+        table#acct_holds_main_header td:nth-of-type(7):before { content: "[% l('Status') %]"; }
+        table#acct_holds_main_header td.hold_notes:before { content: "[% l('Notes') %]"; }
+
+        table#acct_holds_groups_header td:nth-of-type(1):before { content: "[% l('Group Name') %]";}
+        table#acct_holds_groups_header td:nth-of-type(2):before { content: "[% l('Description') %]"; }
+        table#acct_holds_groups_header td:nth-of-type(3):before { content: "[% l('Actions') %]"; }
+
+        table#acct_holds_hist_header td:nth-of-type(1):before { content: "[% l('Title') %]";}
+        table#acct_holds_hist_header td:nth-of-type(2):before { content: "[% l('Author') %]"; }
+        table#acct_holds_hist_header td:nth-of-type(3):before { content: "[% l('Format') %]"; }
+        table#acct_holds_hist_header td:nth-of-type(4):before { content: "[% l('Pickup Location') %]"; }
+        table#acct_holds_hist_header td:nth-of-type(8):before { content: "[% l('Status') %]"; }
+
+        table#ebook_circs_main_table td:nth-of-type(1):before { content: "[% l('Title') %]"; }
+        table#ebook_circs_main_table td:nth-of-type(2):before { content: "[% l('Author') %]"; }
+        table#ebook_circs_main_table td:nth-of-type(3):before { content: "[% l('Due Date') %]"; }
+        table#ebook_circs_main_table td:nth-of-type(4):before { content: "[% l('Actions') %]"; }
+
+        table#ebook_holds_main_table td:nth-of-type(1):before { content: "[% l('Title') %]"; }
+        table#ebook_holds_main_table td:nth-of-type(2):before { content: "[% l('Author') %]"; }
+        table#ebook_holds_main_table td:nth-of-type(3):before { content: "[% l('Due Date') %]"; }
+        table#ebook_holds_main_table td:nth-of-type(4):before { content: "[% l('Actions') %]"; }
+
+
+
+       /*Want to see these in mobile ONLY */
+       .mobile_view{
+          display:block;
+       }
+
+       .mobile_search_lbl_clr{
+          color:[% css_colors.mobile_header_text %];
+       }
+}
+
+
+/* 
+For text which is visible only to screen readers.
+Borrowed from http://getbootstrap.com/css/#helper-classes-screen-readers 
+See also http://webaim.org/techniques/css/invisiblecontent/
+*/
+.sr-only {                                                                     
+    position: absolute;                                                          
+    width: 1px;                                                                  
+    height: 1px;                                                                 
+    padding: 0;                                                                  
+    margin: -1px;                                                                
+    overflow: hidden;                                                            
+    clip: rect(0, 0, 0, 0);                                                      
+    border: 0;                                                                   
+}
+
+/* Make added rows in Expert Search have bold labels like the initial row */
+label[for*=expert_]
+{
+    font-weight: bold;
+}  
+
+.sort_deemphasize {
+    font-weight: lighter;
+    font-size: 70%;
+}
+
+#results-page-depth-hint {
+    text-align: center;
+    font-style: italic;
+}
+
+#clear-history-confirm {
+  font-weight: bold;
+  color: [% css_colors.text_badnews %]; 
+  padding: 10px;
+}
+
+/* 
+jfk added style for inline tooltip
+*/
+
+a.tooltips {
+  position: relative;
+  display: inline;
+  outline: none;
+}
+
+a.tooltips strong {
+  line-height: 30px;
+}
+
+a.tooltips hover {
+  text-decoration: none;
+}
+
+a.tooltips span {
+  z-index:10;display:none; padding: 14px 20px;
+  margin-top: -30px; margin-left:28px;
+  width:300px; line-height:16px;
+}
+
+a.tooltips:hover span {
+  display:inline; position:absolute; color:#111;
+  border:1px solid #DCA; background:#FFFAF0;
+} 
+
+.callout {
+  z-index:20; 
+  position:absolute; 
+  top:30px;
+  border:0;
+  left:-12px;
+}
+/*Inline rules from other templates files*/
+
+.td-left{
+    [% IF rtl == 't' -%]
+    text-align:right;
+    [% ELSE -%]
+    text-align:left;
+    [% END -%]
+    width:100%;
+}
+.td-search-left{
+    [% IF rtl == 't' -%]
+    text-align:right;
+    [% ELSE -%]
+    text-align:left;
+    [% END -%]
+}
+#myopac_summary_div{padding:0px;}
+.div-left{
+    [% IF rtl == 't' -%]
+    float: right;
+    [% ELSE -%]
+    float: left;
+    [% END -%]
+}
+.td-right{
+    [% IF rtl == 't' -%]
+    text-align:left;
+    [% ELSE -%]
+    text-align:right;
+    [% END -%]
+}
+.login-form-left{
+    [% IF rtl == 't' -%]
+    float: right;
+    margin-left: 40px;
+    [% ELSE -%]
+    float: left;
+    margin-right: 40px;
+    [% END -%]
+    padding-bottom: 10px;
+}
+.hold-div{
+    [% IF rtl == 't' -%]
+    padding-right: 10px;
+    [% ELSE -%]
+    padding-left: 10px;
+    [% END -%]
+    padding-bottom: 15px;
+}
+.hold-span{font-weight: bold;}
+.padding-left-6{
+    [% IF rtl == 't' -%]
+    padding-right: 6px;
+    [% ELSE -%]
+    padding-left: 6px;
+    [% END -%]
+}
+.padding-left-10{
+    [% IF rtl == 't' -%]
+    padding-right:10px;
+    [% ELSE -%]
+    padding-left:10px;
+    [% END -%]
+}
+.padding-left-5{
+    [% IF rtl == 't' -%]
+    padding-right: 5px;
+    [% ELSE -%]
+    padding-left: 5px;
+    [% END -%]
+}
+
+/* Rules from metarecord_hold_filters.tt2 */
+
+.metarecord_filters{
+      padding: 5px;
+      margin-top: 5px;
+      border-bottom: 1px solid #333;
+      border-top: 1px solid #333; }
+.metarecord_filter_container{
+    [% IF rtl == 't' -%]
+    float : right;
+    margin-left: 10px;
+    [% ELSE -%]
+    float : left;
+    margin-right: 10px;
+    [% END -%]
+}
+.metarecord_filter_container select{padding: 2px;width: 13em; /* consistent w/ adv search selectors */}
+.metarecord_filter_header{padding-bottom: 5px;}
+
+/* Toggled items. */
+/* A block that is initially hidden and shown by clicking an anchor. */
+[id^="toggled-block-"]{
+    display: none;
+}
+[id^="toggled-block-"]:target{
+    display: block;
+}
+/* Inline text that is initially hidden and shown by clicking an anchor. Useful on a span. */
+[id^="toggled-inline-"]{
+    display: none;
+}
+[id^="toggled-inline-"]:target{
+    display: inline;
+}
+
+.oils_SH {
+    font-weight: bolder;
+    background-color: #99ff99;
+}
+
+.oils_SH.identifier {
+    font-weight: bolder;
+    background-color: #42b0f4;
+}
+
+/*
+  Carousels
+*/
+
+.carousel {
+    width: 80%;
+    margin: 0 auto;
+}
+.carousel-title {
+    font-size: 150%;
+    font-weight: bold;
+    text-align: center;
+}
+.carousel-entry {
+    max-width: 150px;
+}
+.carousel-entry-image {
+    width: 100%;
+    height: auto;
+}
+.carousel .glide__arrow {
+    color: [% css_colors.button_text %];
+    font-weight: bold !important;
+    text-decoration: none !important;
+    cursor: pointer;
+    border-radius: 5px;
+    border: 1px solid [% css_colors.primary %];
+    background-color:  [% css_colors.primary_fade %];
+    margin: 0.5em;
+    padding: 0.3em;
+    display: inline-block;
+}
+.carousel .glide__arrow--right {
+    right: -5em;
+}
+.carousel .glide__arrow--left {
+    left: -5em;
+}
+.archived_course {
+    color: [% css_colors.text_badnews %];
+    font-weight: bold;
+}
+.course_details {
+    padding-top: 1em;
+}
+.course_details_div {
+    padding-bottom: 1em;
+}
+
+/*
+  Fake tables for form-rows
+*/
+
+div.egtable { display:table; }
+form.egtr, div.egtr { display:table-row; }
+span.egth { display:table-cell; font-weight: bold; }
+span.egtd { display:table-cell; }
+
+/* Example:
+
+<div class="egtable">
+    <form class="egtr" method="post" action="blah.html">
+        <span class="egtd"><input type="text"/></span>
+        <span class="egtd"><input type="text"/></span>
+    </form>
+    <div class="egtr">
+        <span class="egtd">(cell data)</span>
+        <span class="egtd">(cell data)</span>
+    </div>
+    ...
+</div>
+
+*/
+
diff --git a/Open-ILS/src/templates_cons/opac/ecard/form.tt2 b/Open-ILS/src/templates_cons/opac/ecard/form.tt2
new file mode 100644 (file)
index 0000000..bede64a
--- /dev/null
@@ -0,0 +1,45 @@
+[%- PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/org_selector.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Get a CW MARS eCard");
+    ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id;
+%]
+<div id="content-wrapper">
+<div id="main-content-register"
+     style="margin: auto; width: 65%;">
+<h2>[% ctx.page_title %]</h2>
+[% IF ctx.ecard.enabled && ctx.ecard.quipu_id %]
+<div id="ecard-intro">
+<!-- The following script tags can be placed in the library's <head> or <body> tag -->
+<script src="https://ecard-us2.quipugroup.net/js/eCARDEmbed.js"></script>
+<script>loadQGeCARD([% ctx.ecard.quipu_id %])</script>
+
+[% INCLUDE "opac/ecard/lang.tt2" %]
+
+<p>An eCard is a CW MARS library card that you can register for online to access electronic materials, such as ebooks, audiobooks, magazines, and databases.</p>
+
+<p>The eCard is for patrons who do not already have a CW MARS library card and may be upgraded to a physical library card with borrowing privileges by visiting your local library. For more information about the eCard, <a href="https://www.cwmars.org/help/general-faq#h.tsmz4ldtjggv" target="_blank" rel="noopener">read our FAQ</a>.</p>
+
+<p>You are eligible to apply for a CW MARS eCard, if you...</p>
+<ul>
+<li>live in a Massachusetts town with a <a href="https://www.cwmars.org/memberlibraries" target="_blank" rel="noopener">CW MARS member library</a>,</li>
+<li>are age 13 or older,</li>
+<li>and do not currently have a library card from a <a href="https://www.cwmars.org/memberlibraries" target="_blank" rel="noopener">CW MARS member library</a>.</li>
+</ul>
+
+<p>Contact your local library if you are not eligible to register online or to renew an expired card.</p>
+
+<p>Funding for electronic content is provided by <a href="https://www.cwmars.org/memberlibraries" target="_blank" rel="noopener">CW MARS member libraries</a>, and the <a href="https://mblc.state.ma.us/" target="_blank" rel="noopener">Massachusetts Board of Library Commissioners</a> with funding from the <a href="https://www.imls.gov/" target="_blank" rel="noopener">Institute of Museum and Library Services</a> and the Commonwealth of Massachusetts.</p>
+
+</div>
+<!-- The following <div> tag should be placed on the web page where the library would like the registration form to display -->
+<div id="eCARD" data-language="en" data-branchid="[% ctx_org %]"></div>
+[% ELSE %]
+<p>
+[% l('Electronic card registration is not enabled for this library.') %]
+</p>
+[% END #IF %]
+</div>
+</div>
+[% END #WRAPPER %]
diff --git a/Open-ILS/src/templates_cons/opac/ecard/form_es.tt2 b/Open-ILS/src/templates_cons/opac/ecard/form_es.tt2
new file mode 100644 (file)
index 0000000..3f7980e
--- /dev/null
@@ -0,0 +1,45 @@
+[%- PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/org_selector.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Get a CW MARS eCard");
+    ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id;
+%]
+<div id="content-wrapper">
+<div id="main-content-register"
+     style="margin: auto; width: 65%;">
+<h2>Obtenga una tarjeta electrónica CW MARS</h2>
+[% IF ctx.ecard.enabled && ctx.ecard.quipu_id %]
+<div id="ecard-intro">
+<!-- The following script tags can be placed in the library's <head> or <body> tag -->
+<script src="https://ecard-us2.quipugroup.net/js/eCARDEmbed.js"></script>
+<script>loadQGeCARD([% ctx.ecard.quipu_id %])</script>
+
+[% INCLUDE "opac/ecard/lang.tt2" %]
+
+<p>Una tarjeta electrónica es una tarjeta de biblioteca de la red CW MARS en la que puede registrarse en línea para acceder a materiales electrónicos, como libros electrónicos, audiolibros, revistas y bases de datos.</p>
+
+<p>La tarjeta electrónica es para usuarios que aún no tienen una tarjeta de biblioteca de la red CW MARS y pueden actualizarse a una tarjeta de biblioteca física con privilegios de préstamo visitando su biblioteca local. Para obtener más información sobre la tarjeta electrónica, lea nuestras preguntas frecuentes.</p>
+
+<p>Usted es elegible para solicitar una tarjeta electrónica CW MARS, si ...</p>
+<ul>
+<li>vive en una ciudad de Massachusetts con una biblioteca miembro de la red CW MARS,</li>
+<li>tiene 13 años o más,</li>
+<li>y actualmente no tiene una tarjeta de biblioteca de una biblioteca miembro de la red CW MARS.</li>
+</ul>
+
+<p>Comuníquese con su biblioteca local si no es elegible para registrarse en línea o para renovar una tarjeta vencida.</p>
+
+<p>Los fondos para el contenido electrónico son proporcionados por las bibliotecas miembro de la red CW MARS y la Junta de Comisionados de Bibliotecas de Massachusetts con fondos del Instituto de Servicios de Museos y Bibliotecas y el Commonwealth of Massachusetts.</p>
+
+</div>
+<!-- The following <div> tag should be placed on the web page where the library would like the registration form to display -->
+<div id="eCARD" data-language="es" data-branchid="[% ctx_org %]"></div>
+[% ELSE %]
+<p>
+[% l('Electronic card registration is not enabled for this library.') %]
+</p>
+[% END #IF %]
+</div>
+</div>
+[% END #WRAPPER %]
diff --git a/Open-ILS/src/templates_cons/opac/ecard/form_fr.tt2 b/Open-ILS/src/templates_cons/opac/ecard/form_fr.tt2
new file mode 100644 (file)
index 0000000..9012f20
--- /dev/null
@@ -0,0 +1,45 @@
+[%- PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/org_selector.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Get a CW MARS eCard");
+    ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id;
+%]
+<div id="content-wrapper">
+<div id="main-content-register"
+     style="margin: auto; width: 65%;">
+<h2>Obtenez une eCarte de CW MARS</h2>
+[% IF ctx.ecard.enabled && ctx.ecard.quipu_id %]
+<div id="ecard-intro">
+<!-- The following script tags can be placed in the library's <head> or <body> tag -->
+<script src="https://ecard-us2.quipugroup.net/js/eCARDEmbed.js"></script>
+<script>loadQGeCARD([% ctx.ecard.quipu_id %])</script>
+
+[% INCLUDE "opac/ecard/lang.tt2" %]
+
+<p>Une carte électronique (eCarte) est une carte de bibliothèque de CW MARS à laquelle vous pouvez vous inscrire en ligne pour accéder à des documents électroniques, tels que des livres électroniques, des livres audio, des magazines et des bases de données.</p>
+
+<p>La carte électronique (ecarte) est destinée aux usagers qui n'ont pas encore de carte de bibliothèque CW MARS. Cette carte peut être convertie a une carte de bibliothèque physique avec des privilèges d'emprunt en visitant votre bibliothèque locale. Pour plus d'informations sur la carte électronique, lisez notre FAQ.</p>
+
+<p>Vous pouvez demander une carte électronique CW MARS si vous...</p>
+<ul>
+<li>vivez dans une ville de Massachusetts avec une bibliothèque membre de CW MARS,</li>
+<li>avez 13 ans ou plus,</li>
+<li>et n'avez pas actuellement de carte de bibliothèque d'une bibliothèque membre de CW MARS.</li>
+</ul>
+
+<p>Contactez votre bibliothèque locale si vous n'êtes pas éligible à vous inscrire en ligne ou à renouveler une carte expirée.</p>
+
+<p>Le financement du contenu électronique est assuré par les bibliothèques membres de CW MARS et le Conseil des commissaires des bibliothèques de Massachusetts avec un financement de l'Institut du musée et des services de bibliothèque et le Commonwealth de Massachusetts.</p>
+
+</div>
+<!-- The following <div> tag should be placed on the web page where the library would like the registration form to display -->
+<div id="eCARD" data-language="fr" data-branchid="[% ctx_org %]"></div>
+[% ELSE %]
+<p>
+[% l('Electronic card registration is not enabled for this library.') %]
+</p>
+[% END #IF %]
+</div>
+</div>
+[% END #WRAPPER %]
diff --git a/Open-ILS/src/templates_cons/opac/ecard/form_pl.tt2 b/Open-ILS/src/templates_cons/opac/ecard/form_pl.tt2
new file mode 100644 (file)
index 0000000..3dfa202
--- /dev/null
@@ -0,0 +1,45 @@
+[%- PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/org_selector.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Get a CW MARS eCard");
+    ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id;
+%]
+<div id="content-wrapper">
+<div id="main-content-register"
+     style="margin: auto; width: 65%;">
+<h2>Zdobądź CW MARS ECARD</h2>
+[% IF ctx.ecard.enabled && ctx.ecard.quipu_id %]
+<div id="ecard-intro">
+<!-- The following script tags can be placed in the library's <head> or <body> tag -->
+<script src="https://ecard-us2.quipugroup.net/js/eCARDEmbed.js"></script>
+<script>loadQGeCARD([% ctx.ecard.quipu_id %])</script>
+
+[% INCLUDE "opac/ecard/lang.tt2" %]
+
+<p>ECARD jest karta elektroniczny biblioteki CW MARS, którą możesz zarejestrować się w Internecie, aby uzyskać dostęp do materiałów elektronicznych, takich jak e-książki, audiobooki, czasopisma, gazety, i bazy danych.</p>
+
+<p>Karta jest dla klientów, którzy nie mają już fizyczną karty biblioteki CW Mars i mogą zostać zaktualizowane do fizycznej karty biblioteki z przywilejami pożyczkowania, odwiedzając lokalną bibliotekę. Aby uzyskać więcej informacji na temat ECARD, przeczytaj nasze FAQ.</p>
+
+<p>Kwalifikujesz się do ubiegania się o Karta CW MARS, jeśli ...</p>
+<ul>
+<li>mieszkasz w mieście Massachusetts z biblioteką członkowską CW MARS,</li>
+<li>masz 13 lat albo więcej,</li>
+<li>I obecnie nie masz już fizyczną karty biblioteki z biblioteki członkowskiej CW MARS.</li>
+</ul>
+
+<p>Skontaktuj się z lokalną biblioteką, jeśli nie kwalifikujesz się do rejestracji online albo odnowić wygasłą kartę.</p>
+
+<p>Finansowanie treści elektronicznych jest dostarczane przez biblioteki członkowskie CW MARS, a Rada Massachusetts komisarzy bibliotecznych z finansowaniem z Instytutu Muzeum i Biblioteki oraz Wspólnoty Massachusetts.</p>
+
+</div>
+<!-- The following <div> tag should be placed on the web page where the library would like the registration form to display -->
+<div id="eCARD" data-language="pl" data-branchid="[% ctx_org %]"></div>
+[% ELSE %]
+<p>
+[% l('Electronic card registration is not enabled for this library.') %]
+</p>
+[% END #IF %]
+</div>
+</div>
+[% END #WRAPPER %]
diff --git a/Open-ILS/src/templates_cons/opac/ecard/form_pt.tt2 b/Open-ILS/src/templates_cons/opac/ecard/form_pt.tt2
new file mode 100644 (file)
index 0000000..56a37e3
--- /dev/null
@@ -0,0 +1,45 @@
+[%- PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/org_selector.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Get a CW MARS eCard");
+    ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id;
+%]
+<div id="content-wrapper">
+<div id="main-content-register"
+     style="margin: auto; width: 65%;">
+<h2>Obtenha um eCard do CW MARS</h2>
+[% IF ctx.ecard.enabled && ctx.ecard.quipu_id %]
+<div id="ecard-intro">
+<!-- The following script tags can be placed in the library's <head> or <body> tag -->
+<script src="https://ecard-us2.quipugroup.net/js/eCARDEmbed.js"></script>
+<script>loadQGeCARD([% ctx.ecard.quipu_id %])</script>
+
+[% INCLUDE "opac/ecard/lang.tt2" %]
+
+<p>O eCard é o cartão de biblioteca do CW MARS que pode usar para se registrar online e aceder a materiais eletrônicos, como eBooks, audio livros, revistas, e bases de dados.</p>
+
+<p>O eCard é para clientes que não possuem cartão de biblioteca do CW MARS, e pode ser substituído por um cartão de biblioteca físico com privilégios de empréstimo visitando a sua biblioteca local.  Se precisar de mais informações sobre o eCard, leia o nosso FAQ.</p>
+
+<p>Você é elegível para um cartão CW MARS eCard se você…</p>
+<ul>
+<li>Reside numa cidade de Massachusetts que tem uma biblioteca conectada com o CW MARS,</li>
+<li>Tem treze anos ou mais,</li>
+<li>E atualmente não possui cartão de uma biblioteca  membro da CW MARS.</li>
+</ul>
+
+<p>Entre em contato com a sua biblioteca local se não for elegível para se registrar online, ou para renovar um cartão expirado.</p>
+
+<p>O financiamento do conteúdo eletrônico é fornecido pelas bibliotecas membros da CW MARS e pelo Conselho de Comissários das Bibliotecas de Massachusetts com fundos do Instituto de Serviços de Museus e Bibliotecas e Commonwealth of Massachusetts.</p>
+
+</div>
+<!-- The following <div> tag should be placed on the web page where the library would like the registration form to display -->
+<div id="eCARD" data-language="pt" data-branchid="[% ctx_org %]"></div>
+[% ELSE %]
+<p>
+[% l('Electronic card registration is not enabled for this library.') %]
+</p>
+[% END #IF %]
+</div>
+</div>
+[% END #WRAPPER %]
diff --git a/Open-ILS/src/templates_cons/opac/ecard/form_ru.tt2 b/Open-ILS/src/templates_cons/opac/ecard/form_ru.tt2
new file mode 100644 (file)
index 0000000..68996f0
--- /dev/null
@@ -0,0 +1,45 @@
+[%- PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/org_selector.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Get a CW MARS eCard");
+    ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id;
+%]
+<div id="content-wrapper">
+<div id="main-content-register"
+     style="margin: auto; width: 65%;">
+<h2>Получите электронный билет CW MARS</h2>
+[% IF ctx.ecard.enabled && ctx.ecard.quipu_id %]
+<div id="ecard-intro">
+<!-- The following script tags can be placed in the library's <head> or <body> tag -->
+<script src="https://ecard-us2.quipugroup.net/js/eCARDEmbed.js"></script>
+<script>loadQGeCARD([% ctx.ecard.quipu_id %])</script>
+
+[% INCLUDE "opac/ecard/lang.tt2" %]
+
+<p>Электронный билет - это библиотечный билет  CW MARS, который вы можете зарегистрировать в Интернете для доступа к электронным материалам, как например электронные книги, аудиокниги, журналы и базы данных.</p>
+
+<p>Электронный билет предназначен для посетителей, у которых еще нет библиотечного билета CW MARS, и его можно улутчить к физическому библиотечному билету с привилегиями заимствования, посетив местную библиотеку. Для получения дополнительной информации об электронном билете прочтите наш <a href="https://www.cwmars.org/help/general-faq#h.tsmz4ldtjggv" target="_blank" rel="noopener">FAQ</a>.</p>
+
+<p>Вы имеете право подать заявку на получение билета CW MARS eCard, если вы ...</p>
+<ul>
+<li>живете в городе в Массачусетс с библиотекочным членом <a href="https://www.cwmars.org/memberlibraries" target="_blank" rel="noopener">CW MARS</a>,</li>
+<li>13 лет и старше,</li>
+<li>и если в настоящее время у вас нет читательского билета из библиотеки-члена <a href="https://www.cwmars.org/memberlibraries" target="_blank" rel="noopener">CW MARS</a>.</li>
+</ul>
+
+<p>Обратитесь в местную библиотеку, если вы не имеете права зарегистрироваться онлайн или продлить библиотечный билет с истекшим сроком действия.</p>
+
+<p>Финансирование электронного контента обеспечивается библиотеками-членами CW MARS и Советом комиссаров библиотек штата Массачусетс при финансовой поддержке Института музейного и библиотечного обслуживания и Содружества Массачусетса.</p>
+
+</div>
+<!-- The following <div> tag should be placed on the web page where the library would like the registration form to display -->
+<div id="eCARD" data-language="ru" data-branchid="[% ctx_org %]"></div>
+[% ELSE %]
+<p>
+[% l('Electronic card registration is not enabled for this library.') %]
+</p>
+[% END #IF %]
+</div>
+</div>
+[% END #WRAPPER %]
diff --git a/Open-ILS/src/templates_cons/opac/ecard/form_zh.tt2 b/Open-ILS/src/templates_cons/opac/ecard/form_zh.tt2
new file mode 100644 (file)
index 0000000..78c0e00
--- /dev/null
@@ -0,0 +1,45 @@
+[%- PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/org_selector.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Get a CW MARS eCard");
+    ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id;
+%]
+<div id="content-wrapper">
+<div id="main-content-register"
+     style="margin: auto; width: 65%;">
+<h2>获取 CW MARS 电子卡</h2>
+[% IF ctx.ecard.enabled && ctx.ecard.quipu_id %]
+<div id="ecard-intro">
+<!-- The following script tags can be placed in the library's <head> or <body> tag -->
+<script src="https://ecard-us2.quipugroup.net/js/eCARDEmbed.js"></script>
+<script>loadQGeCARD([% ctx.ecard.quipu_id %])</script>
+
+[% INCLUDE "opac/ecard/lang.tt2" %]
+
+<p>电子卡是 CW MARS 借书证,您可以在线注册,用来访问各种电子资料:电子书、有声读物、杂志和数据库等。</p>
+
+<p>电子卡适用于还没有办理 CW MARS 借书证的顾客。您可通过使用电子卡访问当地图书馆,进而升级为具有借阅权限的实体借书证。 有关电子卡的更多信息,请阅读我们的常见问题解答。</p>
+
+<p>您将有资格申请 CW MARS 电子卡,如果您...</p>
+<ul>
+<li>住在有 CW MARS 会员图书馆的马萨诸塞州的镇子</li>
+<li>年龄在 13 岁或以上</li>
+<li>目前还没有 CW MARS 成员图书馆的借书证</li>
+</ul>
+
+<p>如果您没有资格在线注册或更新过期的卡片,请联系您当地的图书馆。</p>
+
+<p></p>
+
+</div>
+<!-- The following <div> tag should be placed on the web page where the library would like the registration form to display -->
+<div id="eCARD" data-language="zh" data-branchid="[% ctx_org %]"></div>
+[% ELSE %]
+<p>
+[% l('Electronic card registration is not enabled for this library.') %]
+</p>
+[% END #IF %]
+</div>
+</div>
+[% END #WRAPPER %]
diff --git a/Open-ILS/src/templates_cons/opac/ecard/lang.tt2 b/Open-ILS/src/templates_cons/opac/ecard/lang.tt2
new file mode 100644 (file)
index 0000000..df0373d
--- /dev/null
@@ -0,0 +1,23 @@
+[%-
+MACRO getformurl(lang, name)
+IF ctx.ecard.lang == lang;
+   name;
+ELSE;
+    path = '/eg/opac/ecard/form';
+    IF lang != "en";
+        path = path _ "_" _ lang;
+    END;
+    '<a href="' _ path _ '">' _ name _ '</a>';
+END;
+-%]
+<p>
+(
+[% getformurl('en', 'English') %] |
+[% getformurl('es', 'Español') %] |
+[% getformurl('pt', 'Português') %] |
+[% getformurl('zh', '中文') %] |
+[% getformurl('fr', 'Français') %] |
+[% getformurl('pl', 'Polszczyzna') %] |
+[% getformurl('ru', 'Русский') %]
+)
+</p>
diff --git a/Open-ILS/src/templates_cons/opac/ecard/submit.tt2 b/Open-ILS/src/templates_cons/opac/ecard/submit.tt2
new file mode 100644 (file)
index 0000000..ed3e58d
--- /dev/null
@@ -0,0 +1 @@
+[% ctx.response %]
diff --git a/Open-ILS/src/templates_cons/opac/ecard/verify.tt2 b/Open-ILS/src/templates_cons/opac/ecard/verify.tt2
new file mode 100644 (file)
index 0000000..08180ac
--- /dev/null
@@ -0,0 +1,153 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <title>[% l('Confirm an eCard Account') %]</title>
+    [% INCLUDE 'opac/parts/googalytics_new.tt2' %]
+
+    <link rel="stylesheet" href="/js/ui/default/staff/build/css/bootstrap.min.css" />
+
+    <!-- local CSS -->
+    <style>
+      /* BC screen reader links are not correctly hidden via their API.
+         Add some additional CSS to hide them */
+      .screen_reader_nav {
+        position: absolute;
+        top: -1000px;
+        left: -1000px;
+        z-index: 0;
+      }
+      #ecard-container-wrapper {
+        width: 98%;
+      }
+      #ecard-container {
+        margin-bottom: 20px;
+        color: #585d5e;
+        font-family: 'Open Sans', sans-serif;
+        letter-spacing: .5pt;
+        font-size: 15px;
+        width: 900px; /* to match bibliocms */
+        margin-left: auto;
+        margin-right: auto;
+      }
+    </style>
+
+    <script>
+      function handleSubmit() {
+        if (typeof ga === 'function') {
+          ga('send', 'event', 'Ecard Verify', 'submit', 'Forms');
+        }
+        return true;
+      }
+
+      function handleCancel() {
+        // unused at time of writing, keep around just in case.
+        if (typeof ga === 'function') {
+          ga('send', 'event', 'Ecard Verify', 'cancel', 'Forms');
+        }
+        return false; // avoid submit
+      }
+    </script>
+
+    <!-- BC CSS -->
+    [% ctx.bc_css %]
+    <!-- BC END CSS -->
+
+  </head>
+  <body>
+
+    <!-- BC SCREEN READER NAVIGATION -->
+    [% ctx.bc_screen_reader_navigation %]
+    <!-- BC END SCREEN READER NAVIGATION -->
+
+    <!-- BC HEADER -->
+    [% ctx.bc_header %]
+    <!-- BC END HEADER -->
+
+    <div id='ecard-container-wrapper' role="main">
+      <div id='ecard-container'>
+
+        <div id='ecard-preamble'>
+          <h1>Confirm Your KCLS eCard</h1>
+          <p>
+            Please fill out the form below to confirm your eCard account.
+          </p>
+          [% IF ctx.verify_failed %]
+          <div id='ecard-verify-failed'>
+            <div class="alert alert-warning" role="alert">
+              <p>
+                It appears that your confirmation did not go through.
+                This could happen for a variety of reasons:
+              </p>
+              <br/>
+              <ul>
+                <li>You mistyped the confirmation code</li>
+                <li>
+                  You typed in the code, but you provided it more than 30
+                  days after your application. If so, please feel free to reapply.
+                </li>
+                <li>You already confirmed, so your eCard is ready to use!</li>
+              </ul>
+              <br/>
+              <p>
+                If you have any questions about how to confirm your eCard
+                please contact <a href="https://kcls.org/ask/">Ask KCLS</a>
+                or staff at <a href="https://kcls.bibliocommons.com/locations">
+                your neighborhood library</a>.
+              </p>
+            </div>
+          </div>
+          [% END %]
+        </div>
+
+        [% IF ctx.verify_success %]
+        <div id='ecard-verify-success'>
+          <div class="alert alert-success" role="alert">
+            <p>
+            Congratulations! You have successfully confirmed your KCLS eCard!
+            </p>
+            <p>
+            <b>If you have not yet had a chance to find out what you can do with
+            your eCard, go to <a href="https://kcls.org/onlinelibrary">KCLS Online Resources</a>.
+            Read, stream, listen, find information, advance your studies, and enjoy!</b>
+            </p>
+          </div>
+        </div>
+        [% ELSE %]
+        <div id='ecard-verify-form' class='col-md-6'>
+          <form method='POST' onsubmit="return handleSubmit()">
+            <div class="form-group">
+              <label for="barcode">eCard Number</label>
+              <input type="text" class="form-control" id="barcode"
+                name="barcode" placeholder="eCard Number"
+                value="[% ctx.barcode | html %]"/>
+            </div>
+            <div class="form-group">
+              <label for="verification_code">6-Character Confirmation Code</label>
+              <input type="text" class="form-control" id="verification_code"
+                name="verification_code" placeholder="Confirmation Code"
+                value="[% ctx.verify_code | html %]"/>
+            </div>
+            <button type="submit" class="btn btn-default">Submit</button>
+          </form>
+        </div>
+        <div style="clear:both"></div>
+        [% END %]
+
+      </div>
+    </div>
+
+    <!-- BC FOOTER -->
+    [% ctx.bc_footer %]
+    <!-- BC END FOOTER -->
+
+    <!-- unlike the quipu form page, we have to manaully load jquery here -->
+    <script src="[% ctx.media_prefix %]/js/ui/default/common/build/js/jquery.min.js"></script>
+
+    <!-- BC JS -->
+    [% ctx.bc_js %]
+    <!-- BC END JS -->
+
+  </body>
+</html>
+
diff --git a/Open-ILS/src/templates_cons/opac/myopac/holds_curbside.tt2 b/Open-ILS/src/templates_cons/opac/myopac/holds_curbside.tt2
new file mode 100644 (file)
index 0000000..6623ac4
--- /dev/null
@@ -0,0 +1,210 @@
+[%  PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/misc_util.tt2";
+    PROCESS "opac/parts/hold_status.tt2";
+    PROCESS "opac/parts/hold_notify.tt2";
+    PROCESS "opac/parts/myopac/column_sort_support.tt2";
+    PROCESS "opac/parts/css/fonts.tt2";
+    WRAPPER "opac/parts/myopac/base.tt2";
+    myopac_page = "holds_curbside";
+%]
+<h3 class="sr-only">[% l('Curbside Pickup') %]</h3>
+<div id='myopac_holds_div'>
+
+    <div id="acct_holds_tabs">
+        <div class="align">
+            <a href='[% mkurl('holds',{},['limit','offset']) %]'>[% l("Items on Hold") %]</a>
+        </div>
+        [% IF ctx.curbside_pickup_libs.size > 0 %]
+        <div class="align selected">
+            <a href='#'>[% l("Curbside Pickup") %]</a>
+        </div>
+        [% END %]
+        [% IF ebook_api.enabled == 'true' %]
+        <div class="align">
+            <a href='[% mkurl('ebook_holds', {}, ['limit','offset','available','sort','sort_type']) %]'>[% l("E-Items on Hold") %]</a>
+        </div>
+        <div class="align">
+            <a href='[% mkurl('ebook_holds_ready', {}, ['limit','offset','available','sort','sort_type']) %]'>[% l("E-Items Ready for Checkout") %]</a>
+        </div>
+        [% END %]
+        <div class="align">
+            <a href='[% mkurl('hold_history', {}, ['limit','offset','available','sort','sort_type']) %]'>[% l("Holds History") %]</a>
+        </div>
+    </div>
+
+    <p>
+    Use the scheduler below to request or update your Curbside pickup appointment(s).
+    <a href="https://www.cwmars.org/help/catalog-help/help-curbside-pickup#h.smw4bow2m30z" target="_blank" rel="noopener">Click here</a> or contact your Pickup Library if you need help.
+    </p>
+
+    <div class="header_middle">
+        <span id="acct_holds_header" style="float:left;">
+            [%  l("Curbside Pickup Appointments") %]
+        </span>
+    </div>
+    <div class="clear-both"></div>
+    <div title="[% l('Curbside Pickup Appointments') %]" style="width:90%"
+        class="egtable table_no_border_space table_no_cell_pad">
+        <div class="egtr">
+            <span class="egth">[% l('Pickup Location') %]</span>
+            <span class="egth">[% l('Date') %]</span>
+            <span class="egth">[% l('Time') %]</span>
+            <span class="egth">[% l('Arrival Notes (vehicle description, etc)') %]</span>
+            <span class="egth">[% l('Action') %]</span>
+        </div>
+        <div class="egtr">
+            <span class="egtd"><hr/></span>
+            <span class="egtd"><hr/></span>
+            <span class="egtd"><hr/></span>
+            <span class="egtd"><hr/></span>
+            <span class="egtd"><hr/></span>
+        </div>
+    [% FOR lib IN ctx.curbside_pickup_libs;
+
+        cs_slot = '';
+        cs_slot_id = '';
+        cs_date = '';
+        cs_time = '';
+        cs_notes = '';
+
+       cs_org = ctx.cs_org;
+        IF cs_org == lib;
+            cs_slot = ctx.cs_slot;
+            cs_slot_id = ctx.cs_slot_id;
+            cs_date = ctx.cs_date;
+            cs_time = ctx.cs_time;
+            cs_notes = ctx.cs_notes;
+        END;
+
+        appointment = ctx.curbside_appointments.$lib;
+        IF appointment;
+            cs_slot = appointment;
+            cs_slot_id = appointment.id;
+            IF appointment.slot; cs_date = date.format(ctx.parse_datetime(appointment.slot),'%F'); END;
+            IF appointment.slot; cs_time = date.format(ctx.parse_datetime(appointment.slot),'%T'); END;
+            cs_notes = appointment.notes;
+        END %]
+        <form class="egtr" method="POST">
+            <input type="hidden" name="action" value="curbside"/>
+            <input type="hidden" name="cs_slot_id" value="[% appointment.id %]"/>
+            [% disable_me = 0 %]
+            [% no_patron_input = 0 %]
+            [% date_started_null = 0 %]
+            [% IF appointment && appointment.arrival; disable_me = 1; END %]
+            [% IF ctx.get_org_setting(lib, 'circ.curbside.disable_patron_input'); no_patron_input = 1; END %]
+            <span class="egtd">
+                [% ctx.get_aou(lib).name | html %]<br/>
+                [% l('Phone:')%] [% ctx.get_aou(lib).phone | html %]
+                <input type="hidden" name="cs_org" value="[% lib %]"/>
+            </span>
+            <span class="egtd">
+                [% IF !cs_date; tmp_cs_date = date.format(date.now, '%F'); date_started_null = 1; %]
+                [% ELSE; tmp_cs_date = cs_date; END %]
+                [% IF cs_date %]<input type="hidden" name="cs_date" value="[% cs_date | html %]"/>[% END %]
+                [% IF no_patron_input && date_started_null; %]&nbsp;
+                [% ELSE; %]<input type="date" name="cs_date" value="[% tmp_cs_date | html %]" [% IF cs_date || no_patron_input %]disabled="disabled"[% END %]/>[% END %]
+            </span>
+            <span class="egtd">
+                [% IF appointment || cs_date; # checking times %]
+                  [% current_date = cs_date %]
+                  [% IF date_started_null && no_patron_input %]&nbsp;
+                  [% ELSIF appointment || ctx.cs_times.$lib.$current_date.size; # show a select %]
+                    <select name="cs_time" [% IF disable_me || no_patron_input %]disabled="disabled"[% END %]>
+                      [% found_time = 0 %]
+                      [% FOR t IN ctx.cs_times.$lib.$current_date %]
+                        <option value="[% t.0 | html %]"
+                          [% IF cs_time == t.0; found_time=1 %] selected="selected"[% END %]
+                          [% IF t.1 <= 0 && cs_time != t.0 %] disabled="disabled"[% END %]>
+                            [% date.format(current_date _ ' ' _ t.0,'%l:%M %p') | html %]
+                        </option>
+                      [% END %]
+                      [% IF cs_time && !found_time %]
+                        <option value="[% cs_time | html %]" selected="selected">
+                          [% date.format(current_date _ ' ' _ cs_time,'%l:%M %p') | html %]
+                        </option>
+                      [% END %]
+                    </select>
+                  [% ELSE %] 
+                    [% l('No times available') %]
+                    <button type="submit" name="cs_action" value="reset" class="opac-button">
+                        [% l('Select another date') %]
+                    </button><br/>
+                  [% END %]
+                [% ELSE %] 
+                  [% IF !no_patron_input; %][% l('Select a date') %][% END %]
+                [% END %]
+            </span>
+            <span class="egtd">
+                [% IF cs_date; # show the notes box %]
+                <input type="text" name="cs_notes" value="[% cs_notes | html %]" [% IF no_patron_input || disable_me %]disabled="disabled"[% END %]/>
+                [% ELSE %] &nbsp;
+                [% END %]
+            </span>
+            <span class="egtd">[%
+                disable_arrival_button = 1; # assume arrival is not yet allowed
+                IF appointment && appointment.slot;
+                    stime = date.format(ctx.parse_datetime(appointment.slot), '%s');
+                    now_time = date.format(date.now, '%s');
+                    IF now_time >= stime;
+                        disable_arrival_button = 0; # if 'now' is after the slot time, allow arrival
+                    END;
+                END %]
+                [% IF no_patron_input %]
+                    [% l('Please contact the library to schedule, change, or cancel your appointment.') %]
+                [% ELSIF appointment.staged && !appointment.arrival; # relevant submit action %]
+                    <button type="submit" name="cs_action" value="arrive" class="opac-button" [% IF disable_arrival_button %]disabled="disabled"[% END %]>
+                        [% l('Alert staff of your arrival') %]
+                    </button><br/>
+                    <button type="submit" name="cs_action" value="cancel" class="opac-button">
+                        [% l('Cancel appointment') %]
+                    </button>
+                [% ELSIF appointment.arrival %]
+                    <!--
+                    <button type="submit" name="cs_action" value="deliver" class="opac-button">
+                        [% l('Confirm delivery of items') %]
+                    </button><br/>
+                    -->
+                    <button type="submit" name="cs_action" value="cancel" class="opac-button">
+                        [% l('Cancel appointment') %]
+                    </button>
+                [% ELSIF appointment.slot %]
+                    <button type="submit" name="cs_action" value="arrive" class="opac-button" [% IF disable_arrival_button %]disabled="disabled"[% END %]>
+                        [% l('Alert staff of your arrival') %]
+                    </button><br/>
+                    <button type="submit" name="cs_action" value="save" class="opac-button">
+                        [% l('Update appointment') %]
+                    </button><br/>
+                    <button type="submit" name="cs_action" value="cancel" class="opac-button">
+                        [% l('Cancel appointment') %]
+                    </button>
+                [% ELSIF cs_date %]
+                    <button type="submit" name="cs_action" value="save" class="opac-button">
+                        [% l('Request appointment') %]
+                    </button>
+                    <button type="submit" name="cs_action" value="reset" class="opac-button">
+                        [% l('Select another date') %]
+                    </button><br/>
+                [% ELSE %]
+                    <button type="submit" name="cs_action" value="next" class="opac-button">
+                        [% l('Check available times') %]
+                    </button>
+                [% END %]
+            </span>
+        </form>
+        <div class="egtr">
+            <span class="egtd"><hr/></span>
+            <span class="egtd"><hr/></span>
+            <span class="egtd"><hr/></span>
+            <span class="egtd"><hr/></span>
+            <span class="egtd"><hr/></span>
+        </div>
+    [% END %]
+    </div>
+    <p>
+    Within 30 minutes of scheduling or updating an appointment, a confirmation email/text* will be sent to you with pickup details.
+    </p>
+    <p style="font-size: [% css_fonts.size_smaller %];">
+    *Delivery method will depend on <a href="/eg/opac/myopac/prefs_notify">contact options</a> stored in your account.
+    </p>
+</div>
+[% END %]
diff --git a/Open-ILS/src/templates_cons/opac/parts/acjs.tt2 b/Open-ILS/src/templates_cons/opac/parts/acjs.tt2
new file mode 100644 (file)
index 0000000..7f7171a
--- /dev/null
@@ -0,0 +1,77 @@
+<script type="text/javascript">
+
+    /* Checks to see if a given type of added content has data to show.
+     * The first arg to callback() is boolean indicating the presence of data */
+    function acIsAvailable(bre_id, type, callback) {
+        var url = '/opac/extras/ac/' + type + '/html/r/' + bre_id;
+        dojo.xhr('HEAD', {
+            url : url,
+            failOk : true, // http://bugs.dojotoolkit.org/ticket/11568
+            error : function(err) { callback(false, bre_id, type); },
+            load : function(result) { callback(true, bre_id, type); }
+        });
+    }
+
+    [%-
+        FOR type IN ctx.added_content.keys;
+            IF ctx.added_content.$type.status == '3' # status unknown %]
+
+                dojo.addOnLoad(function() {
+                    var bre_id = '[% ctx.bre_id %]';
+                    var type = '[% type %]';
+
+                    acIsAvailable(bre_id, type, function(avail, bre_id, type) {
+                        if (avail) {
+
+                            [% IF CGI.param('expand') == 'addedcontent' %]
+
+                                // if the content is available, un-hide the tab
+                                dojo.removeClass(dojo.byId('ac:' + type), 'hidden');
+
+                            [% ELSE %]
+                                // if no default type is selected on the main tab link
+                                // set one here, since we have available content
+
+                                var link = dojo.query('[name=addedcontent]')[0];
+                                var href = link.getAttribute('href');
+                                if (!href.match('[\&;]ac=')) {
+                                    href = href.replace('#addedcontent', ';ac=' + type + '#addedcontent');
+                                    dojo.attr(link, 'href', href);
+                                    dojo.attr(dojo.query('[name=addedcontent_lbl]')[0], 'href', href);
+                                }
+
+                            [% END %]
+                        }
+                    });
+                });
+            [% END; # IF status unknown
+        END; # FOR type
+
+        ident = ctx.record_attrs.isbn_clean || ctx.record_attrs.upc;
+        IF ident;
+    -%]
+
+[%- IF ENV.OILS_NOVELIST_URL -%]
+            /* Load novelist content */
+            setTimeout( function() {
+            novSelect.loadContentForQuery(
+                {
+                    ClientIdentifier : '[% ident %]',
+                    ISBN : '[% ident %]',
+                    version : '2.1'
+                },
+                '[% ENV.OILS_NOVELIST_PROFILE %]',
+                '[% ENV.OILS_NOVELIST_PASSWORD %]',
+                function(d){
+                    // note if d.length == 0, there is no content to display
+                    // hide the Loading... text
+                    dojo.byId('novelist-loading').innerHTML = '';
+                }
+            );
+       /* Suggestion from Novelist */
+       }, 500);
+[%- END; # Novelist -%]
+
+        [% END; # IF ident
+    %]
+</script>
diff --git a/Open-ILS/src/templates_cons/opac/parts/advanced/global_row.tt2 b/Open-ILS/src/templates_cons/opac/parts/advanced/global_row.tt2
new file mode 100644 (file)
index 0000000..e6a1c9a
--- /dev/null
@@ -0,0 +1,56 @@
+[%
+    contains_options = [
+        {value => 'contains', label => l('Contains')},
+        {value => 'nocontains', label => l('Does not contain')},
+        {value => 'phrase', label => l('Contains phrase')}
+    ];
+    contains = CGI.param('contains');
+    queries = CGI.param('query');
+    bools = CGI.param('bool');
+    qtypes = CGI.param('qtype');
+    rowcount = 3;
+
+    # scalar.merge treats the scalar as a 1-item array
+    WHILE queries.size < rowcount; queries = queries.merge(['']); END;
+    WHILE bools.size < rowcount; bools = bools.merge(['and']); END;
+    WHILE qtypes.size < rowcount; qtypes = qtypes.merge(search.default_qtypes.${qtypes.size} ? [search.default_qtypes.${qtypes.size}] : ['keyword']); END;
+
+    FOR qtype IN qtypes;
+        c = contains.shift;
+        b = bools.shift;
+        q = queries.shift; %]
+
+<!-- tag the second row so the bool column won't be hidden -->
+<tr[% IF loop.index == 1 %] id="adv_global_row"[% END %]>
+    <td align='left' width='100%'>
+
+        <!-- bool selector.  hide for first row.  safe to ignore first bool value in form submission -->
+        <select title="[% l('Boolean search operator') %]" 
+          name='bool' style='width: auto' [% IF loop.first %] class='invisible' [% END %]>
+            <option value='and' [% b == 'and' ? 'selected="selected"' : '' %]>[% l('And') %]</option>
+            <option value='or' [% b == 'or' ? 'selected="selected"' : '' %]>[% l('Or') %]</option>
+        </select>
+
+        <!-- keyword, subject, etc. selector -->
+        <span class="qtype_selector_margin">
+            [% INCLUDE "opac/parts/qtype_selector.tt2"
+                query_type=qtype %]
+        </span>
+
+        <select title="[% l('Search phrase match strictness') %]"
+          name='contains' style='margin-right: 7px;'>
+            [% FOR o IN contains_options; -%]
+            <option value="[% o.value %]" [% c == o.value ? ' selected="selected"' : '' %]>[% o.label %]</option>
+            [% END %]
+        </select>
+        <input title="[% l('Search term') %]" aria-label="[% l('Search term') %]"
+          type='text' size='18' name='query' value="[% q | html %]" x-webkit-speech [% IF loop.index == 0 %] autofocus [% END %] />
+        <a href="javascript:;" class="row-remover"
+            title="[% l('Remove row') %]" alt="[% l('Remove row') %]"
+            onclick='return killRowIfAtLeast(2, this);'>
+                <img src="[% ctx.media_prefix %]/images/expert_row_close_btn.png[% ctx.cache_key %]"
+                    alt="[% l('Remove row') %]"/>
+            </a>
+    </td>
+</tr>
+[% END %]
diff --git a/Open-ILS/src/templates_cons/opac/parts/advanced/numeric.tt2 b/Open-ILS/src/templates_cons/opac/parts/advanced/numeric.tt2
new file mode 100644 (file)
index 0000000..01b79cb
--- /dev/null
@@ -0,0 +1,36 @@
+<form action="[% ctx.opac_root %]/results" method="get">
+    <div class="header_middle">[% l("Numeric Search") %]</div>
+    <input type="hidden" name="contains" value="contains" />
+    <input type="hidden" name="_special" value="1" />
+    <input id="detail" type="hidden" name="detail_record_view"
+           value="[% show_detail_view %]"/>
+    <div id='adv_numeric_block'>
+            <label for="numeric_qtype"><strong>[% l("Field:") %]</strong></label>
+                <select id="numeric_qtype" name="qtype">
+                    <!-- TODO: Pull labels from config.metabib_field.label -->
+                    <option value="identifier|isbn">[% l('ISBN') %]</option>
+                    <option value="identifier|upc">[% l('UPC') %]</option>
+                    <option value="identifier|issn">[% l('ISSN') %]</option>
+                    <option value="identifier|scn">[% l('OCLC') %]</option>
+                    <option value="identifier|upc">[% l('UPC') %]</option>
+                    <option value="identifier|music_number">[% l('Music Number') %]</option>
+                    <option value="cnbrowse">[% l('Call Number (Shelf Browse)') %]</option>
+                    <option value="identifier|lccn">[% l('LCCN') %]</option>
+                    <option value="identifier|tcn">[% l('TCN') %]</option>
+                    <option value="item_barcode">[% l('Item Barcode') %]</option>
+                    <option value="identifier|gov_doc_number">[% l('Government Document Number') %]</option>
+                </select>
+       
+                <input type="text" name="query" size="16" autofocus placeholder='[% l("Identifier") %]' aria-label='[% l("Identifier") %]' />
+           <br/>
+            [%- lib_select_id="numeric_search_library" -%]
+            <label for="[% lib_select_id %]"><strong>[% l("Search Library:") %]</strong>
+                  [% PROCESS "opac/parts/org_selector.tt2";
+                     INCLUDE build_org_selector id=lib_select_id show_loc_groups=1
+                  %]
+            </label>
+           <br/>
+                <input type="submit" alt="[% l('Search') %]"
+                    value="[% l('Search') %]" class="opac-button" />
+    </div>
+</form>
diff --git a/Open-ILS/src/templates_cons/opac/parts/advanced/search.tt2 b/Open-ILS/src/templates_cons/opac/parts/advanced/search.tt2
new file mode 100644 (file)
index 0000000..9c2427a
--- /dev/null
@@ -0,0 +1,181 @@
+[%
+    PROCESS "opac/parts/misc_util.tt2";
+    PROCESS get_library;
+%]
+<form action="[% ctx.opac_root %]/results" method="get">
+<div id='adv_global_search' class='data_grid data_grid_center'>
+    <div id='adv_search_rows'>
+        <!-- Contains the user-addable(?) rows to define search class, containment and text -->
+        <div class='adv_global_input_container'>
+            <table id='adv_global_input_table' role="presentation">
+                <thead>
+                    <tr>
+                        <td>
+                            <div class="header_middle" id="adv_search_input">
+                                [% l("Search Input") %]
+                            </div>
+                        </td>
+                    </tr>
+                </thead>
+                <tbody id='adv_global_tbody'>
+                    [% INCLUDE "opac/parts/advanced/global_row.tt2" %]
+                    <!-- add a new row -->
+                    <tr id='adv_global_addrow'>
+                        <td class="td-search-left">
+                            <a href="javascript:;" id="myopac_new_global_row" onclick='addSearchRow();'>[% l('Add Search Row') %]</a>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+        </div>
+    </div>
+
+    <div id='adv_search_submit'>
+        <input type="hidden" name="_adv" value="1" />
+        <input id="detail" type="hidden" name="detail_record_view"
+               value="[% show_detail_view %]"/>
+        <span>
+            <input id='search-submit-go' type="submit" value="[% l('Search') %]" title="[% l('Search') %]" class="opac-button"
+                onclick='setTimeout(function(){$("search-submit-spinner").className=""; $("search-submit-go").className="hidden"}, 2000)'/>
+            <img id='search-submit-spinner' src='/opac/images/progressbar_green.gif[% ctx.cache_key %]'
+                class='hidden' alt="[% l('Search in progress icon') %]"/>
+        </span>
+
+        <a href="[% mkurl(ctx.opac_root _ '/advanced', {$loc_name => loc_value}, 1) %]"
+            class="opac-button">[% l('Clear Form') %]</a>
+    </div>
+
+    <div id='adv_search_filters'>
+        <div class="header_middle">[% l('Search Filters') %]</div>
+
+[%
+    in_row = 0;
+    FOR adv_chunk IN search.adv_config;
+        NEXT IF adv_chunk.adv_hide;
+        IF in_row == 0;
+            in_row = 1; %]
+            <div class='adv_filter_block'>
+[%
+        END; %]
+            <div class='adv_filter_block_item'>
+            <div [% IF adv_chunk.js_only %]
+                id='adv_chunk_[% adv_chunk.adv_special %]'
+                class='hidden'[% END %]>
+                <strong><label for="[% adv_chunk.id %]">
+                  [% adv_chunk.adv_label %] </label></strong><br />
+[%
+        IF adv_chunk.adv_special;
+            SWITCH adv_chunk.adv_special;
+                CASE "scope_selector";
+                    PROCESS "opac/parts/org_selector.tt2";
+                        select_scope_label = l("Select search scope");
+                        INCLUDE build_scope_selector arialabel=select_scope_label value=ctx.search_scope
+                          id=adv_chunk.id name='search_scope' show_loc_groups=1 show_lassos=1;
+
+                CASE "lib_selector";
+                    PROCESS "opac/parts/org_selector.tt2";
+                        INCLUDE build_org_selector show_loc_groups=1 show_lassos=0 id=adv_chunk.id %]
+                            <div class="adv_search_available">
+                                <input type='checkbox' name="modifier"
+                                    value="available"[% CGI.param('modifier').grep('available').size ? ' checked="checked"' : '' %]
+                                    id='opac.result.limit2avail' />
+                                <label for='opac.result.limit2avail'>
+                                    [% l("Limit to Available") %]</label>
+                            </div>
+
+[%
+                CASE "pub_year"; %]
+                            <select name='pubdate'
+                                id="[% adv_chunk.id %]"
+                                onchange='if(this.selectedIndex == 3)
+                                    unHideMe($("adv_global_pub_date_2_span"));
+                                else
+                                    hideMe($("adv_global_pub_date_2_span"));'>
+                                    [%  FOR opt IN [
+                                            {"code" => "is", "label" => l("Is")},
+                                            {"code" => "before", "label" => l("Before")},
+                                            {"code" => "after", "label" => l("After")},
+                                            {"code" => "between", "label" => l("Between")} ] %]
+                                        <option value="[% opt.code %]"[% CGI.param('pubdate') == opt.code ? ' selected="selected"' : '' %]>[% opt.label | html %]</option>
+                                    [%  END %]
+                            </select>
+                            [% IF !ctx.exclude_electronic_checkbox %]
+                            <br/>
+                            <div id='adv_special_block'>
+                            [% END %]
+                                <input title="[% l('Search date') %]" aria-label="[% l('Search date') %]"
+                                  name='date1' type='text' size='4' maxlength='4' value="[% CGI.param('date1') | html %]" />
+                                <span id='adv_global_pub_date_2_span' class='[% CGI.param("pubdate") == "between" ? "" : "hide_me" %]'>
+                                   [% l("and") %] <input name='date2' aria-label="[% l('Secondary search date') %]"
+                                    title="[% l('Secondary search date') %]" type='text' size='4' maxlength='4' value="[% CGI.param('date2') | html %]" />
+                                </span>
+                            [% IF !ctx.exclude_electronic_checkbox %]
+                            </div>
+                            [% END %]
+                            [% IF ctx.exclude_electronic_checkbox %]
+                            <div class="adv_search_available">
+                                <input type='checkbox' name="fi:-search_format" value="electronic"
+                                [%- CGI.param('fi:-search_format').grep('electronic').size ?
+                                    ' checked="checked"' : '' %]
+                                id='opac.result.excludeelec' />
+                                <label for='opac.result.excludeelec'>
+                                    [% l("Exclude Electronic Resources") %]
+                                </label>
+                            </div>
+                            [% END %]
+[%
+                CASE "sort_selector";
+                    default_sort=ctx.default_sort;
+                    IF CGI.param('sort');
+                        default_sort=CGI.param('sort');
+                    END;
+                    INCLUDE "opac/parts/filtersort.tt2"
+                        id=adv_chunk.id
+                        value=default_sort class='results_header_sel';
+                    %]
+
+                    [% IF NOT metarecords.disabled %]
+                        <br/><!-- <br> may seem redundant, but it allows the
+                            <input> (below) to drop down inline w/ its label -->
+                        <div class="adv_search_available">
+                            <input type='checkbox' name="modifier" value="metabib"
+                              [%- CGI.param('modifier').grep('metabib').size || search.metarecord_default ?
+                                    ' checked="checked"' : '' %]
+                                id='opac.result.ismetabib' />
+                            <label for='opac.result.ismetabib'>
+                                [% l("Group Formats and Editions") %]</label>
+                        </div>
+                    [% END %]
+
+                [% CASE "copy_location" %]
+                    <select id="adv_copy_location_selector"
+                        title="[% l('Select Shelving Location') %]"
+                        name="fi:locations" size="6" multiple="multiple">
+                    </select>
+                [%
+            END;
+        ELSIF adv_chunk.adv_attr;
+            INCLUDE "opac/parts/coded_value_selector.tt2"
+                id=adv_chunk.id
+                attr=adv_chunk.adv_attr multiple="multiple"
+                size=adv_chunk.adv_size || search.default_adv_select_height || "4";
+        ELSIF adv_chunk.adv_filter;
+            INCLUDE "opac/parts/filter_group_selector.tt2"
+                id=adv_chunk.id
+                filter_group=adv_chunk.adv_filter multiple="multiple"
+                size=adv_chunk.adv_size || search.default_adv_select_height || "4";
+        END; %]
+            </div>
+        </div>
+[%
+        IF adv_chunk.adv_break;
+            in_row = 0; %]
+            </div>
+[%
+        END;
+    END; %]
+
+        </div>
+    </div>
+</div>
+</form>
diff --git a/Open-ILS/src/templates_cons/opac/parts/anon_list.tt2 b/Open-ILS/src/templates_cons/opac/parts/anon_list.tt2
new file mode 100644 (file)
index 0000000..c781e1e
--- /dev/null
@@ -0,0 +1,102 @@
+        [% IF ctx.mylist.size %]
+        <div class="bookbag-specific">
+        <p class="big-strong">[% l('Basket') %]</p>
+<p>
+Baskets are temporary. Contents will be removed automatically after your current session expires. To save the contents of your basket, you can add them to <a href="https://www.cwmars.org/help/catalog-help/help-my-lists#h.p_9OsMxIrPoA4R" target="_blank" rel="noopener">a list.</a>
+</p>
+        <div class="sort">
+            <form method="get">
+                <label for="anonsort">[% l("Sort basket items by: ") %]</label>
+                [% INCLUDE "opac/parts/filtersort.tt2" mode='bookbag'
+                    id="anonsort" name="anonsort" value=CGI.param("anonsort") %]
+                <input type="hidden" name="id"
+                    value="[% CGI.param('id') | html %]" />
+                [%- INCLUDE "opac/parts/preserve_params.tt2"; %]
+                <input class="opac-button" type="submit" value="[% l('Sort') %]" />
+            </form>
+        </div>
+        <form action="[% mkurl(ctx.opac_root _ '/mylist/move') %]" method="post">
+        <input type="hidden" name="anonsort" value="[% CGI.param('anonsort') %]" />
+        <input type="hidden" name="orig_referrer" value="[% CGI.referer | html %]" />
+        <input type="hidden" name="redirect_to" value="[% mkurl('', {}, ['list_none_selected', 'cart_none_selected']) %]" />
+        <div class="bbag-action" style="clear:both;">
+            <select name="action" aria-label="[% l('Actions for these items') %]">
+                <option>[% l('-- Actions for these items --') %]</option>
+                <option value="place_hold">[% l('Place hold') %]</option>
+                <option value="print">[% l('Print title details') %]</option>
+                <option value="email">[% l('Email title details') %]</option>
+                <option value="delete">[% l('Remove from basket') %]</option>
+                <option value="new_list">[% l('Add to new list') %]</option>
+                [% IF ctx.user AND ctx.bookbags.size %]
+                    <optgroup label="[% l('Move selected items to list:') %]">
+                    [% FOR bbag IN ctx.bookbags %]]
+                        <option value="[% bbag.id %]" class="selector_actions_for_list_inner_option">[% bbag.name | html %]</option>
+                    [% END %]
+                    </optgroup>
+                [% END %]
+            </select>
+            [%- INCLUDE "opac/parts/preserve_params.tt2"; %]
+            <input class="opac-button" type="submit" value="[% l('Go') %]" />
+            <input type="checkbox" name="clear_cart" id="clear_cart" /><label for="clear_cart">[% l('Clear entire basket when action complete') %]</label>
+            [% IF CGI.param('cart_none_selected') %]
+                <span class="error">[% l('No items were selected') %]</span>
+            [% END %]
+        </div>
+        <div class="bbag-content">
+            <table class="bookbag-specific table_no_cell_pad table_no_border_space table_no_border">
+                <thead id="acct_list_header_anon">
+                    <tr>
+                        <td class='list_checkbox'>
+                            <input type="checkbox" checked="checked"
+                                aria-label="[% l('Select all records') %]" onclick="
+                                var inputs=document.getElementsByTagName('input'); 
+                                for (i = 0; i < inputs.length; i++) { 
+                                    if (inputs[i].name == 'record' && !inputs[i].disabled) inputs[i].checked = this.checked;}"/>
+                        </td>
+                        <td><a href="[% mkurl('', {anonsort=>(CGI.param('anonsort') == 'titlesort' ? 'titlesort.descending' : 'titlesort')}) %]">[% l('Title') %]</a></td>
+                        <td><a href="[% mkurl('', {anonsort=>(CGI.param('anonsort') == 'authorsort' ? 'authorsort.descending' : 'authorsort')}) %]">[% l('Author(s)') %]</a></td>
+                        <td>[% l('Local Call Number') %]</td>
+                    </tr>
+                </thead>
+                <tbody>
+                    [% FOR item IN ctx.mylist;
+                        attrs = {marc_xml => ctx.mylist_marc_xml.$item};
+                        PROCESS get_marc_attrs args=attrs %]
+                    <tr>
+                        <td class="list_checkbox">
+                            <input type="checkbox" checked="checked" name="record" value="[% item %]" aria-label="[% l('Select record') %]" />
+                        </td>
+                        <td class="list_entry" data-label="[% l('Title') %]"><a href="[% mkurl(ctx.opac_root _ '/record/' _ item, {}, ['edit_notes', 'id']) %]">[% attrs.title | html %]</a></td>
+                        <td class="list_entry" data-label="[% l('Author(s)') %]"><a href="[%-
+                            authorquery = attrs.author | replace('[,\.:;]', '');
+                            mkurl(
+                                ctx.opac_root _ '/results',
+                                {qtype => 'author', query => authorquery},
+                                ['page', 'id', 'edit_notes']
+                            )
+                        -%]">[% attrs.author | html %]</a></td>
+                        <td class="list_entry" data-label="[% l('Local Call Number') %]">
+                        [% 
+                            copy = attrs.holdings.0;
+                            IF copy;
+                                copy_org = ctx.get_aou_by_shortname(copy.owner);
+                                FOR ctx_org IN [ctx.pref_ou, ctx.search_ou, ctx.home_ou, ctx.physical_loc];
+                                    NEXT UNLESS ctx_org;
+                                    ctx_org = ctx.get_aou(ctx_org);
+                                    IF ctx.org_within_scope(ctx_org, copy_org, ctx_org.ou_type.depth);
+                                        l('[_1] ([_2])', copy.label, copy_org.name) | html;
+                                        LAST;
+                                    END;
+                                END;
+                            END;
+                        %]
+                        </td>
+                    </tr>
+                    [% END %]
+                </tbody>
+            </table>
+            <br /><br />
+        </div>
+        </form>
+        </div>
+        [% END %]
diff --git a/Open-ILS/src/templates_cons/opac/parts/base.tt2 b/Open-ILS/src/templates_cons/opac/parts/base.tt2
new file mode 100644 (file)
index 0000000..f80cd4a
--- /dev/null
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang='[% ctx.eg_locale %]'>
+    <head prefix="og: http://ogp.me/ns#">
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+        [% IF ctx.refresh %]
+        <meta http-equiv="refresh" content="[% ctx.refresh %]" />
+        [% ELSIF ctx.authtime AND !ctx.is_staff %]
+        <meta http-equiv="refresh" content="[% ctx.authtime %]; url=[% ctx.home_page %]" />
+        [% END %]
+        <meta name = "viewport" content = "width=device-width, initial-scale = 1.0">
+        <link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/default/opac/semiauto.css[% ctx.cache_key %]" />
+        <link rel="stylesheet" type="text/css" href="[% ctx.opac_root %]/css/style.css[% ctx.cache_key %]&amp;dir=[%
+          IF ctx.get_i18n_l(ctx.eg_locale).rtl == 't' %]rtl[%
+          ELSE %]ltr[% END %]" />
+        [% IF ctx.get_i18n_l(ctx.eg_locale).rtl == 't' %]
+        <link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/default/opac/semiauto-rtl.css[% ctx.cache_key %]" />
+        [% END %]
+
+        [% IF ctx.get_org_setting(ctx.search_ou, 'opac.patron.custom_css') %]
+            [% custom_css = ctx.get_org_setting(ctx.search_ou, 'opac.patron.custom_css') %]
+        [% '<style>'; custom_css ; '</style>' %]                                          
+        [% END %]
+
+        [% matomo_id = ctx.get_org_setting(ctx.search_ou, 'opac.analytics.matomo_id'); %]
+        [% matomo_url = ctx.get_org_setting(ctx.search_ou, 'opac.analytics.matomo_url'); %]
+        [% IF matomo_id && matomo_url %]
+           [% matomo_enabled = 1; %]
+        [% END %]
+
+        [%- libname = ctx.get_aou(ctx.search_ou).name;
+            libname = libname | html;
+            libsname = ctx.get_aou(ctx.search_ou).shortname; %]
+        <title>[%- IF ctx.user_stats.messages.unread;
+                      l('([_1])', ctx.user_stats.messages.unread);
+                   END;
+               -%]
+               [% l('[_1] - [_2]', ctx.page_title, libname) %]</title>
+        <link rel="unapi-server" type="application/xml" title="unAPI" href="/opac/extras/unapi" />
+        <link type="application/opensearchdescription+xml" rel='search' title="[% l('[_1] OpenSearch', libname) %]" href="/opac/extras/opensearch/1.1/[% libsname | uri %]/-/osd.xml" />
+        [%-# Hook for page-specific metadata such as <meta name="robots" content="noindex"> %]
+        [%- ctx.metalinks.push('<meta property="og:title" content="' _ ctx.page_title _ '" />'); %]
+        [%- ctx.metalinks.push('<meta property="og:site_name" content="' _ libname _ '" />'); %]
+        [% FOREACH meta IN ctx.metalinks; meta _ "\n"; END; -%]
+        [% IF want_dojo %]
+        <style type="text/css">
+            @import "[% ctx.media_prefix %]/js/dojo/dijit/themes/tundra/tundra.css[% ctx.cache_key %]";
+        </style>
+        [% END %]
+
+        [% IF !ctx.is_staff %]
+            [% INCLUDE 'opac/parts/goog_analytics.tt2' %]
+            [% INCLUDE 'opac/parts/matomo_analytics.tt2' %]
+        [% END %]
+        [% PROCESS 'opac/parts/stripe.tt2' %]
+    </head>
+    <body[% IF want_dojo; ' class="tundra"'; END %]>
+        <h1 class="sr-only">[% l('Catalog') %]</h1>
+        [% IF !ctx.is_staff %]
+        <p style="text-align: center; background: white; font-size:20px;">
+          <strong style="color:red;">TRAINING SERVER - DO NOT USE FOR LIVE TRANSACTIONS</strong>
+          <br />
+          Library Patrons: <a href="https://catalog.cwmars.org/">Click Here for the live catalog.</a>
+        </p>
+        [% END %]
+        [%#Each content page needs (at minimum) an <h2> describing the content%]
+        [% content %] 
+        <h2 class="sr-only">[% l('Additional Resources') %]</h2>
+        [% INCLUDE 'opac/parts/footer.tt2' %]
+        [% INCLUDE 'opac/parts/js.tt2' %]
+        [%- IF ENV.OILS_CHILIFRESH_ACCOUNT %]
+            [%- INCLUDE 'opac/parts/chilifresh.tt2' %]
+        [%- END %]
+    </body>
+</html>
diff --git a/Open-ILS/src/templates_cons/opac/parts/config.tt2 b/Open-ILS/src/templates_cons/opac/parts/config.tt2
new file mode 100644 (file)
index 0000000..4727830
--- /dev/null
@@ -0,0 +1,291 @@
+[%
+
+##############################################################################
+# This file contains skin-level configuration settings.
+# Many of these settings will probably migrate into actor.org_unit_settings.
+##############################################################################
+
+##############################################################################
+# Holds blocking
+##############################################################################
+# Prevent the "Place hold" link from being displayed if a copy is available.
+# This is not perfect, given the umpteen different types of holds that are
+# possible, but addresses the major use case for libraries that don't want
+# to fetch copies from the shelves.
+ctx.holds_block.enabled = 'false';
+
+##############################################################################
+# RefWorks configuration
+##############################################################################
+# RefWorks is a Web-based citation manager
+ctx.refworks.enabled = 'false';
+
+# Base URL for RefWorks
+ctx.refworks.url = 'http://www.refworks.com';
+
+# Some sites have a hosted RefWorks instance at a different URL;
+# in addition, you might want to proxy access to RefWorks - for example:
+# ctx.refworks.url = 'http://librweb.laurentian.ca/login?url=http://refworks.scholarsportal.info';
+
+##############################################################################
+# OpenURL resolution
+##############################################################################
+# Evergreen provides the ability to point at an OpenURL resolver to find
+# electronic resources for a given ISSN or ISBN. Currently, only the SFX
+# resolver is supported.
+#
+# You must enable the open-ils.resolver instance in opensrf.xml to use
+# this feature.
+##############################################################################
+
+openurl.enabled = 'false';
+openurl.baseurl = 'http://sfx.example.com/instance';
+
+##############################################################################
+# Google Analytics support
+##############################################################################
+# You can enable Google Analytics support in Evergreen by entering a
+# valid Google Analytics code and changing 'false' to 'true'
+##############################################################################
+google_analytics.enabled = 'false';
+google_analytics.code = 'UA-9999999-99';
+
+##############################################################################
+# Ebook API integration
+##############################################################################
+ebook_api.enabled = 'false';
+ebook_api.ebook_test.enabled = 'false';
+ebook_api.ebook_test.base_uris = [ 'http://example.com/ebookapi/t/' ];
+ebook_api.oneclickdigital.enabled = 'false';
+ebook_api.oneclickdigital.base_uris = [ 'http://example.oneclickdigital.com/Products/ProductDetail.aspx' ];
+ebook_api.overdrive.enabled = 'false';
+ebook_api.overdrive.base_uris = [ 'http://digitalbooks.cwmars.org/', 'http://digitalcatalog.cwmars.org/' ];
+
+##############################################################################
+# Enable "Forgot your password?" prompt at login
+##############################################################################
+reset_password = 'true';
+
+##############################################################################
+# Hide various options from user preferences that you might not want to expose
+# if you rely on centralized authentication via open-ils.auth_proxy, like LDAP
+#
+# Username changes can be disabled by the opac.lock_usernames OU setting.
+##############################################################################
+disable_password_change = 'false';
+disable_email_change = 'false';
+
+##############################################################################
+# Some libraries do not do notifications by phone; if not true, then this
+# hides the user preference for phone notifications as well as the phone
+# notification portion of the hold dialogue
+##############################################################################
+allow_phone_notifications = 'true';
+
+##############################################################################
+# Format of parts selection on Place Holds screen
+# Set to true to use radio buttons for parts selection on the Place Holds
+# screen. The default behavior is to to display them in a select menu.
+#############################################################################
+enable.radio.parts = 'false';
+
+##############################################################################
+# Misc. UI Settings
+##############################################################################
+# Option for full details as a default, esp. impt. for e-content
+# that uses resolver plumbing. Valid values are 'true', 'false' and 'hide'.
+# Setting this to 'true' shows full details by default but allows the link
+# to appear for 'Show Fewer Details'. The 'hide' option shows full details
+# and also suppresses the link from displaying at all.
+show_more_details.default = 'false';
+
+##############################################################################
+# Size of the jacket image to display on the record detail summary.
+# Sizes vary depending on added content provider.
+# Options are "small", "medium", and "large"
+record.summary.jacket_size = 'medium';
+
+##############################################################################
+# Define the order in which facets are displayed.  Only facets listed here
+# will be displayed.  To show all facets sorted by name, comment out this
+# setting.
+# facet.display = [] # show no facets
+facet.display = [
+    {facet_class => 'author',  facet_order => ['personal', 'corporate']},
+    {facet_class => 'subject', facet_order => ['topic']},
+    {facet_class => 'identifier', facet_order => ['genre']},
+    {facet_class => 'series',  facet_order => ['seriestitle']},
+    {facet_class => 'subject', facet_order => ['name', 'geographic']}
+];
+facet.default_display_count = 5;
+
+##############################################################################
+# Define the advanced search limiters and labels.
+# Each entry is put into a table cell.
+# adv_label is the (translated) label for the limiter
+# adv_attr is an array of possible limiters, the first one that has any
+#   values will be used
+# adv_filter is the same as adv_attr, but for search filter groups
+# adv_size lets you set the height of the adv_attr or adv_filter select box.
+# if adv_size < 1, the box height is set to the number of options in it.
+# adv_break will end the current row. If specified with a label/attr it
+#   will do so *after* that limiter.
+# adv_special will drop in a special entry:
+#   lib_selector will put the search library box (with limit to available)
+#   pub_year will put the publication year box
+#   sort_selector will put the sort results selector
+# id DOM id used for linking labels to form controls.  They are pinned
+#   here instead of auto-generated (from the attr type, for example)
+#   for consistency.
+
+search.adv_config = [
+    {adv_label => l("Format"), adv_attr => [ctx.get_cgf('opac.format_selector.attr').value], id => 'adv_selector_format', adv_size => 6},
+#    {adv_label => l("Item Type"), adv_attr => ["mattype", "item_type"], id => 'adv_selector_item_type'},
+#    {adv_label => l("Item Form"), adv_attr => "item_form", id => 'adv_selector_item_form'},
+    {adv_label => l("Language"),  adv_attr => "item_lang", id => 'adv_selector_item_lang', adv_size => 6},
+    {adv_label => l("Audience"),  adv_attr => ["audience_group", "audience"], id => 'adv_selector_audience', adv_size => 6},
+#    {adv_label => l("Video Format"), adv_attr => "vr_format", id => 'adv_selector_video_format'},
+
+#    {adv_label => l("Bib Level"), adv_attr => "bib_level", id => 'adv_selector_bib_level'},
+#    {adv_label => l("Literary Form"), adv_attr => "lit_form", id => 'adv_selector_lit_form'},
+
+    {adv_label => l("Shelving Location"), adv_special => "copy_location", id => 'adv_copy_location_selector', js_only => 1, adv_break => 1},
+    {adv_label => l("Search Library"), adv_special => "lib_selector", id => 'adv_org_selector'},
+    {adv_label => l("Where"), adv_special => "scope_selector", id => 'adv_scope_selector'},
+    {adv_label => l("Publication Year"), adv_special => "pub_year", id => 'adv_selector_pub_year'},
+    {adv_label => l("Sort Results"), adv_special => "sort_selector", id => 'adv_selector_sort_results'},
+];
+
+# Set the default height of the select boxes. Defaults to 4.
+#search.default_adv_select_height = 4;
+
+##############################################################################
+# For each search box the default "query type" value can be specified here
+# This is the actual backend value, not the label
+# Also note that including more than the row count entries won't add rows
+# The first entry should be used as a default for "basic" search as well
+
+search.default_qtypes = ['keyword','title','author'];
+
+##############################################################################
+# Basic Search Box definition
+# This allows selection of what, exactly, basic search uses for a selection
+# box. Previously it was hardcoded to use an attr box of mattype or item_type.
+#
+# type can be "attr" or "filter"
+# group is the attr or filter entries you want to check for
+# none_label is the label for the default nothing selected entry.
+
+search.basic_config = {
+    type => 'attr',
+    group => [ctx.get_cgf('opac.format_selector.attr').value, 'item_type'],
+    none_label => l("All Formats"),
+};
+
+# Make metarecord search the default.
+#search.metarecord_default = 1;
+
+# Disable search term highlighting
+search.no_highlight = 1;
+
+##############################################################################
+# Show Google Book Previews
+# Set to 1 or 'true' to enable
+ctx.google_books_preview = 0;
+
+##############################################################################
+
+# Set a maintenance message to display in the catalogue
+#
+# ctx.maintenance_message = "The system will not be available February 29, 2104.";
+
+##############################################################################
+# Depth Button/Checkbox
+# Recommendation: Do not enable button for basic search without enabling the
+# checkbox for the results page
+ctx.depth_sel_checkbox = 1; # Results Page Checkbox Toggle
+ctx.depth_sel_button = 1; # Basic Search Submit Button
+ctx.depth_sel_depth = 0; # Depth to set to
+ctx.depth_sel_button_label = l('All Libraries');
+ctx.depth_sel_button_class = 'opac-button';
+ctx.depth_sel_checkbox_label = l('Show Results from All Libraries');
+ctx.depth_sel_tooltip = l('Select this option to expand your results to all libraries while retaining the priority of your selected library\'s holdings.');
+ctx.depth_sel_resultshint = l('Showing results from all libraries');
+
+##############################################################################
+# Exclude Electronic Resources Checkbox
+# One setting for both the advanced search page and the results bar.
+# Off by default; set to 1 to display.
+ctx.exclude_electronic_checkbox = 1;
+
+##############################################################################
+# Metarecords configuration
+# metarecords.disabled = 1; # disable all metarecord access points
+##############################################################################
+
+##############################################################################
+# Local date format (uses POSIX strftime() formatting)
+# See http://www.template-toolkit.org/docs/modules/Template/Plugin/Date.html
+# DATE_FORMAT = '%Y-%m-%d'; # for 2014-06-31 format
+##############################################################################
+
+##############################################################################
+# Local time format (uses POSIX strftime() formatting)
+# See http://www.template-toolkit.org/docs/modules/Template/Plugin/Date.html
+# TIME_FORMAT = '%H:%M:%S'; # for 16:32:32 (24 hour) format
+# TIME_FORMAT = '%H:%M'; # for 16:32 (24 hour) format
+##############################################################################
+
+##############################################################################
+# Obalkyknih.cz support
+##############################################################################
+# Obalkyknihy.cz is free Czech service providing added content and book covers
+# Set to 'true' to enable
+##############################################################################
+# obalkyknih_cz.enabled = 'false';
+
+##############################################################################
+# JQuery support
+##############################################################################
+# Include JQuery in the TPAC?
+# Set to a true value to enable
+##############################################################################
+# ctx.want_jquery = 1;
+
+##############################################################################
+# Browser cache-busting key
+##############################################################################
+# Links to assets like stylesheets, JavaScript, and images will have this
+# key appended so that browsers will be forced to request a new version.
+# Enables you to set a cache max-date of years.
+#
+# If unset, it falls back to eg_cache_hash (which is set every time you run
+# "autogen", which may or may not be when you change styles etc)
+##############################################################################
+# ctx.cache_key = '001'
+
+##############################################################################
+# Display of badge scores
+##############################################################################
+ctx.hide_badge_scores = 'false';
+
+##############################################################################
+# Maximum number of items allowed to be stored in a basket
+##############################################################################
+ctx.max_cart_size = 500;
+
+##############################################################################
+# Display booking reservations tab in myopac 
+##############################################################################
+ctx.show_reservations_tab = 'false';
+
+##############################################################################
+# Truncate fields in catalog
+##############################################################################
+truncate_contents = 1;
+contents_truncate_length = 50;
+
+# Edit parts/record/contents.tt2 to designate character length on a field-by-
+# field basis for notes.
+
+%]
diff --git a/Open-ILS/src/templates_cons/opac/parts/css/colors.tt2 b/Open-ILS/src/templates_cons/opac/parts/css/colors.tt2
new file mode 100644 (file)
index 0000000..a1538ff
--- /dev/null
@@ -0,0 +1,51 @@
+[%
+    css_colors = {
+
+        background = "#fff", # white
+        background_alert = "#ffcccc", # pink
+        background_invert = "#252525", # charcoal
+        text = "black", # black 
+        text_alert = "red", # red
+        text_attention = "#ffcc33", # pumpkin orange
+        text_badnews = "#f41d36", # cherry red
+        text_goodnews = "#1dd93c", # lime green
+        text_greatnews = "green", # green
+        text_invert = "#fff", # white
+        text_match = "#c00", # deep red
+        primary = "#16416F", # dark blue 
+        primary_fade = "#002B49", # dark blue
+        primary_offset = "#63CFE3", # light blue
+        control = "#16416F", # dark blue
+        accent_light = "#ccc", #  grey (light)
+        accent_lighter = "#ddd", #  grey (lighter)
+        accent_lighter2 = "#d8d8d8", #  grey (lighter again)
+        accent_lightest = "#eee", #  grey (lightest)
+        accent_ultralight = "#f0f0f0", # ivory
+        accent_medium = "#999", # gun metal grey (medium)
+        accent_mediumdark = "#888", # gun metal grey (medium dark)
+        accent_dark = "#666", # gun metal grey (dark)
+        accent_darker = "#333", # gun metal grey (darker)
+        border_standard = "#e9ebf3", # light grey-blue
+        border_dark = "black", # black
+        border_alert = "red", # red
+        button = "#16416f", #dark blue
+        button_text = "#fbf9f9", # off-white 
+        button_text_shadow = "#555555", # medium grey
+        table_heading = "#d8d8d8", # grey-blue
+        mobile_header_text = "#fff", # white
+        item_selected = "#ddd", # grey (lighter)
+        link = "#16416f", # dark blue
+        footer = "#16416f", #dark blue
+        footer_text = "#FFFFFF" #white
+        header = "#FFFFFF", #white
+        header_text = "#FFFFFF", #white
+        header_links_bar = "#000000", #black
+        header_links_text = "#FFFFFF", #white
+        header_links_text_hover = "#FFFFFF", #white
+        opac_button = "#16416f", # dark blue
+        opac_button_text = "#FFFFFF", #white
+        opac_button_hover = "#16416f", # dark blue
+        opac_button_hover_text = "#FFFFFF" #white
+    };
+    
+%]
diff --git a/Open-ILS/src/templates_cons/opac/parts/filtersort.tt2 b/Open-ILS/src/templates_cons/opac/parts/filtersort.tt2
new file mode 100644 (file)
index 0000000..720df0b
--- /dev/null
@@ -0,0 +1,20 @@
+<select title="[% l('Search sorting') %]" 
+    [% class ? ('class="' _ class _ '"') : '' %] id='[% id || "opac.result.sort" %]' 
+    name="[% name || 'sort' %]" [% IF submit_on_change %]onchange='this.form.submit()'[% END %]>
+    [% IF mode != 'bookbag' %]<option value=''>[% l("Sort by Relevance") %]</option>[% END %]
+    <optgroup label='[% l("Sort by Title") %]'>
+        <option value='titlesort'[% value == 'titlesort' ? ' selected="selected"' : '' %]>[% l("Title: A to Z") %]</option>
+        <option value='titlesort.descending'[% value == 'titlesort.descending' ? ' selected="selected"' : '' %]>[% l("Title: Z to A") %]</option>
+    </optgroup>
+    <optgroup label='[% l("Sort by Author") %]'>
+        <option value='authorsort'[% value == 'authorsort' ? ' selected="selected"' : '' %]>[% l("Author: A to Z") %]</option>
+        <option value='authorsort.descending'[% value == 'authorsort.descending' ? ' selected="selected"' : '' %]>[% l("Author: Z to A") %]</option>
+    </optgroup>
+    <optgroup label='[% l("Sort by Publication Date") %]'>
+        <option value='pubdate.descending'[% value == 'pubdate.descending' ? ' selected="selected"' : '' %]>[% l("Date: Newest to Oldest") %]</option>
+        <option value='pubdate'[% value == 'pubdate' ? ' selected="selected"' : '' %]>[% l("Date: Oldest to Newest") %]</option>
+    </optgroup>
+    <optgroup label='[% l("Sort by Popularity") %]'>
+        <option value='poprel'[% value == 'poprel' ? ' selected="selected"' : '' %]>[% l("Sort by Popularity") %]</option>
+    </optgroup>
+</select>
diff --git a/Open-ILS/src/templates_cons/opac/parts/footer.tt2 b/Open-ILS/src/templates_cons/opac/parts/footer.tt2
new file mode 100644 (file)
index 0000000..c901810
--- /dev/null
@@ -0,0 +1,39 @@
+<div id="footer-wrap">
+<div id="footer">
+    [% IF ctx.get_org_setting(
+        ctx.physical_loc || ctx.aou_tree.id, 'opac.allow_pending_user') %]
+    <a href="[% mkurl(ctx.opac_root _ '/register') %]">[% 
+        l('Request Library Card') %]</a> &nbsp;|&nbsp;
+    [% END %]
+    <a href="http://www.cwmars.org" target="_blank" rel="noopener">[% l('CW MARS Home') %]</a> &nbsp;|&nbsp;
+    <a href="https://www.cwmars.org/#h.p_hRgZvBvYJgE9" target="_blank" rel="noopener">[% l('CW MARS App') %]</a>&nbsp;|&nbsp;
+    [% IF ctx.get_org_setting(ctx.physical_loc || ctx.aou_tree.id, 'opac.ecard_registration_enabled') %]
+    <a href="[% mkurl(ctx.opac_root _ '/ecard/form') %]">[% l('CW MARS eCard') %]</a>&nbsp;|&nbsp;
+    [% END %]
+    <a href="https://www.cwmars.org/memberlibraries" target="_blank" rel="noopener">[% l('CW MARS Libraries') %]</a>&nbsp;|&nbsp;
+    <a href="http://cwmars.overdrive.com" target="_blank" rel="noopener">[% l('OverDrive Digital Catalog') %]</a> &nbsp;|&nbsp;
+    <a href="https://www.cwmars.org/search/commonwealth-catalog" target="_blank" rel="noopener">[% l('Commonwealth Catalog') %]</a> &nbsp;|&nbsp;
+    <a href="https://www.cwmars.org/help" target="_blank" rel="noopener">[% l('Help') %]</a>
+    [% IF ctx.timing %]
+    <div id="timing">
+        [% FOR event IN ctx.timing %]
+        At <span class="timing-time">[% event.0 | format("%0.4f") %]</span>:
+        <span class="timing-event">[% event.1 %]</span><br />
+        [% END %]
+    </div>
+    [% END %]
+    <div id="copyright_text" style="margin-top: 2em;">
+        [% l('Copyright &copy; 2006-[_1] Georgia Public Library Service, and others', date.format(date.now, '%Y')) %]
+    </div>
+    <div id="footer_logo">
+        [% l('Powered by') %]
+        <a href="http://evergreen-ils.org" target="_blank" rel="noopener">
+            <img id="footer_logo_image" src="[% ctx.media_prefix %]/opac/images/eg_tiny_logo.png[% ctx.cache_key %]"
+                style="border:none; width: 94px; height: 16px;"
+                alt="[% l('Evergreen') %]"
+            />
+       [% l('provided through CW MARS, Inc.') %]
+        </a>
+    </div>
+</div>
+</div>
diff --git a/Open-ILS/src/templates_cons/opac/parts/hold_status.tt2 b/Open-ILS/src/templates_cons/opac/parts/hold_status.tt2
new file mode 100644 (file)
index 0000000..9ff098d
--- /dev/null
@@ -0,0 +1,61 @@
+[% BLOCK get_hold_status %]
+    <div>
+    [% IF hold.hold.status == 4 %]
+            <span class="myopac-hold-available">[% l("Available") %] </span>
+              [% IF ahr.shelf_expire_time %]
+                <br/>
+                [% l("Expires") %]
+                 <span class="myopac-shelf-expire">
+                     [% date.format(ctx.parse_datetime(ahr.shelf_expire_time), DATE_FORMAT) %]
+                 </span>
+              [% END %]
+
+
+     [% ELSIF hold.hold.status == 6 %]
+               <span class="myopac-hold-canceled"> [% l("Canceled") %] </span>
+                  <span class="myopac-cancel-time">
+                      [% date.format(ctx.parse_datetime(ahr.cancel_time), DATE_FORMAT) %]
+                  </span>
+
+     [%  ELSIF hold.hold.status == 7 %]
+               <span class="myopac-hold-suspended"> [% l("Suspended") %] </span>
+                 [% IF ahr.thaw_date %]
+                   <br/>
+                   [% l("Activate On") %]
+                      <span class="my-account-activate-time">
+                        [% date.format(ctx.parse_datetime(ahr.thaw_date), DATE_FORMAT) %]
+                      </span>
+                 [% END %]
+
+     [% ELSIF hold.hold.status == 9 %]
+               <span class="myopac-hold-fulfilled">[% l("Fulfilled") %]</span>
+                  <span class="myopac-fulfill-time">
+                     [% date.format(ctx.parse_datetime(ahr.fulfillment_time), DATE_FORMAT) %]
+                  </span>
+
+
+     [% ELSIF hold.hold.estimated_wait AND hold.hold.estimated_wait > 0;
+            # estimated wait is delivered as seconds.
+            SET hwait = POSIX.ceil(hold.hold.estimated_wait / 86400) %]
+              <span class="myopac-hold-wait"> [% l("Estimated wait:") %] </span>
+                <span class="myopac-hold-wait-time">
+                  [% l("[quant,_1,day,days]", hwait) | html %]
+                </span>
+
+     [% ELSIF hold.hold.status == 3 OR hold.hold.status == 8 %]
+            <span class="myopac-transit"> [% l("In Transit") %] </span>
+
+     [% ELSIF hold.hold.status < 3 OR hold.hold.status == 5 %]
+            <span class="myopac-uncaptured-hold"> [% l("Waiting for copy") %] </span>
+     [% END %]
+    </div>
+    <div>
+        [% # Only show the count for holds that have not been captured
+           IF hold.hold.status < 3 OR hold.hold.status == 5 OR hold.hold.status == 7 %]
+             <span class="myopac-hold-count">
+                [% l('Hold #[_1] on [quant,_2, circulating copy, circulating copies]',
+                   hold.hold.queue_position, hold.hold.potential_copies) | html %]
+             </span>
+         [% END %]
+    </div>
+[% END %]
diff --git a/Open-ILS/src/templates_cons/opac/parts/homesearch.tt2 b/Open-ILS/src/templates_cons/opac/parts/homesearch.tt2
new file mode 100644 (file)
index 0000000..3083312
--- /dev/null
@@ -0,0 +1,4 @@
+[% PROCESS carousels %]
+<div id="homesearch_main_logo">
+<img id="homesearch_main_logo_image" src="[% ctx.media_prefix %]/opac/images/home-logo.png[% ctx.cache_key %]" alt="[% l('CW MARS') %]" style="display:block; margin-left: auto; margin-right: auto;"/>
+</div>
diff --git a/Open-ILS/src/templates_cons/opac/parts/login/help.tt2 b/Open-ILS/src/templates_cons/opac/parts/login/help.tt2
new file mode 100644 (file)
index 0000000..5e528c5
--- /dev/null
@@ -0,0 +1,10 @@
+<p>
+    <a href="https://www.cwmars.org/help"><img
+        src="[% ctx.media_prefix %]/opac/images/questions.png[% ctx.cache_key %]" alt="[% l('Questions?') %]" style="margin-top:29px;" /></a>
+
+    <div style="width:182px;color:black;padding:5px 25px;">
+        [% l('Visit our FAQs section for answers to common questions about how to use your account.') %]
+    </div>
+    <a href="https://www.cwmars.org/help/catalog-help/help-my-account"><img
+        alt="[% l('FAQs') %]" src="[% ctx.media_prefix %]/opac/images/faqs-btn.png[% ctx.cache_key %]" style="margin-top:13px;" /></a>
+
diff --git a/Open-ILS/src/templates_cons/opac/parts/login/password_hint.tt2 b/Open-ILS/src/templates_cons/opac/parts/login/password_hint.tt2
new file mode 100644 (file)
index 0000000..6b8b7da
--- /dev/null
@@ -0,0 +1,4 @@
+<div class="lbl2">
+[%- l('If you do not remember your password, please click the Forgot your password link or contact your library.'); %]
+<p><b> Note:</b> Your username and password are both case-sensitive.</p>
+</div>
diff --git a/Open-ILS/src/templates_cons/opac/parts/metarecord_hold_filters.tt2 b/Open-ILS/src/templates_cons/opac/parts/metarecord_hold_filters.tt2
new file mode 100644 (file)
index 0000000..046085d
--- /dev/null
@@ -0,0 +1,78 @@
+[%#
+Draws the format multi-select and the language multi-select for
+limiting the set of desired records for a given metarecord.
+%]
+
+<style>
+  /* The rules has been moved to style.css  */
+</style>
+
+[% BLOCK metarecord_hold_filters_selector;
+    # in edit mode, pull the target from the existing hold
+    target_id = hold_data.hold.hold.target || hold_data.target.id;
+
+    selected_formats = {};
+    selected_langs = {};
+    FOR fmt IN hold_data.metarecord_selected_filters.formats;
+        code = fmt.code;
+        selected_formats.$code = fmt;
+    END;
+    FOR lang IN hold_data.metarecord_selected_filters.langs;
+        code = lang.code;
+        selected_langs.$code = lang;
+    END;
+%]
+
+<div class="metarecord_filters">
+<div><p><strong>This hold will be filled by the first item available in any of the formats or languages you have chosen.</strong><br /><a class="tooltips" href="#"><strong>More Information<img alt="More Information" src="/images/question-mark.png"></strong><span>The selections below DO NOT place holds on more than one item. If you select more than one format, your hold will be filled by the first available copy in any selected format.<br /><br /> For example, you might see a regular print, large print or audiobook option. If you just want a paper copy, you might select regular print and large print, but not the audiobook.</span></a></p></div>
+  <div class="metarecord_filter_container">
+    <div class="metarecord_filter_header">
+      <div>[% l('Select your desired format(s).') %]</div>
+      <div>[% l('If none are selected, any available formats may be used.') %]</div>
+    </div>
+    <select multiple='multiple' 
+      name="metarecord_formats_[% target_id %]">
+      [% FOR ccvm IN
+          hold_data.metarecord_filters.formats.sort('search_label');
+          NEXT IF ccvm.opac_visible == 'f' %]
+        <option value="[% ccvm.code %]"[%- code = ccvm.code; 
+            IF selected_formats.$code %] selected='selected'[% END -%]>
+          [% ccvm.search_label | html %]
+        </option>
+      [% END %]
+    </select>
+  </div>
+  [% IF hold_data.metarecord_filters.langs.size;
+        my_lang = ctx.get_i18n_l(ctx.eg_locale).marc_code;
+  %]
+  <div class="metarecord_filter_container">
+    <div class="metarecord_filter_header">
+      <div>[% l('Select your desired language(s).') %]</div>
+      <div>[% l('If none are selected, any available languages may be used.') %]</div>
+    </div>
+    <select multiple='multiple' 
+      name="metarecord_langs_[% target_id %]">
+      [% FOR lang_ccvm IN hold_data.metarecord_filters.langs.sort('value');
+            NEXT IF lang_ccvm.opac_visible == 'f';
+            selected = 0; 
+            code = lang_ccvm.code;
+            IF selected_langs.size;
+                # user has already selected their preferred language(s)
+                SET selected = 1 IF selected_langs.$code;
+
+            ELSIF !hold_data.hold.hold.target; # new hold
+                # no prefered language selected; use current locale
+                SET selected = 1 IF code == my_lang;
+            END;
+        %]
+        <option value="[% lang_ccvm.code %]"[%- 
+            IF selected %] selected='selected'[%- END %]>
+          [% lang_ccvm.value | html %]
+        </option>
+      [% END %]
+    </select>
+  </div>
+  [% END %]
+  <div class="clear-both">&nbsp;</div>
+</div>
+[% END # metarecord_hold_filters_selector %]
diff --git a/Open-ILS/src/templates_cons/opac/parts/misc_util.tt2 b/Open-ILS/src/templates_cons/opac/parts/misc_util.tt2
new file mode 100644 (file)
index 0000000..2d083ad
--- /dev/null
@@ -0,0 +1,909 @@
+[%- 
+    # Support multiscript records via alternate graphic 880 fields
+    # get_graphic_880s(target_field='100')
+    # See "Model A" in http://www.loc.gov/marc/bibliographic/ecbdmulti.html
+    # and $6 description in http://www.loc.gov/marc/bibliographic/ecbdcntf.html
+    MACRO get_graphic_880s BLOCK;
+        FOR node IN xml.findnodes('//*[@tag="' _ target_field _ '"]');
+            raw_vals = [];
+            core_val = '';
+            FOR subnode IN node.findnodes('./*[not(contains("e w 0 4 5 6 7 8 9", @code))]');
+                raw_vals.push(subnode.textContent());
+            END;
+            core_val = raw_vals.join(" ");
+            raw_vals = [];
+
+            linked_fields = [];
+            FOR sub IN node.findnodes('./*[@code="6"]');
+                linked_fields.push(sub.textContent);
+            END;
+            graphics = [];
+            get_linked_880s;
+            graphic_880s.push({
+                primary => {"occur" => occurrence, "value" => core_val},
+                graphic => graphics
+            });
+        END;
+    END;
+
+    MACRO get_linked_880s BLOCK;
+        FOR link_field IN linked_fields;
+            target = target_field _ link_field.substr(3);
+            # Get the linked 880 value
+            raw_val = '';
+            dir = '';
+            occurrence = '';
+            script = '';
+            FOR node IN xml.findnodes('//*[@tag="880"]');
+                # Operate only on the target linked fields
+                FOR linknode IN node.findnodes('./*[@code="6"]');
+                    lf = linknode.textContent();
+                    IF lf.substr(0, target.length) == target;
+                        occurrence = lf.substr(4, 2);
+                        rawscript = lf.substr(7, 2);
+                        SWITCH rawscript;
+                        CASE '(3';
+                            script = 'Arabic';
+                        CASE '(B';
+                            script = 'Latin';
+                        CASE '$1';
+                            script = 'CJK';
+                        CASE '(N';
+                            script = 'Cyrillic';
+                        CASE '(S';
+                            script = 'Greek';
+                        CASE '(2';
+                            script = 'Hebrew';
+                        END;
+
+                        rawdir = lf.substr(9, 1);
+                        SWITCH rawdir;
+                        CASE 'r';
+                            dir = 'rtl';
+                        END;
+
+                        raw_vals = [];
+                        FOR subnode IN node.findnodes('./*[not(contains("w 0 5 6 8 9", @code))]');
+                            raw_vals.push(subnode.textContent());
+                        END;
+                        raw_val = raw_vals.join(" ");
+                    END;
+                END;
+            END;
+            graphics.push({
+                occur => occurrence,
+                value => raw_val,
+                script => script,
+                dir => dir
+            });
+        END;
+    END;
+
+    BLOCK get_ccvm_icon;
+        ctx.media_prefix _ '/images/format_icons/' _ ccvm.ctype _ '/' _ ccvm.code _ '.png' _ ctx.cache_key;
+    END;
+
+    # Extract MARC fields from XML
+    #   get_marc_attrs( { marc_xml => doc } )
+    BLOCK get_marc_attrs;
+        USE Dumper;
+        xml = args.marc_xml;
+
+        args.bibid = [];
+        FOR bibid IN xml.findnodes('//*[@tag="901"]/*[@code="c"]');
+            args.bibid.push(bibid.textContent);
+        END;
+
+        args.df_bib_list = args.bibid;
+        args.bibid = args.bibid.0; 
+
+        IF args.mr_constituent_ids.size && !args.df_bib_list.size;
+            args.df_bib_list = args.mr_constituent_ids;
+        END;
+
+
+        # Gather display field data for this record and map it
+        # to a display field map.  Hopefully, one day, this can
+        # replace the XPath below entirely.
+
+        args.display_fields = {};
+        args.hl = {};
+
+        args.hl_field = 'highlight';
+        IF CGI.param('no_highlight') || search.no_highlight;
+            args.hl_field = 'value';
+        END;
+        hl_field = args.hl_field;
+
+        junk = ctx.timelog('Fetching display fields and Using data from "' _ hl_field _ '" for rendering'); 
+        args.display_field_list = ctx.fetch_display_fields(args.df_bib_list.list);
+
+        junk = ctx.timelog('Mapping display fields for bib(s) ' _ args.df_bib_list.list.join(', ')); 
+        FOR df IN args.display_field_list;
+            df_map = ctx.search_cdfm('field', df.field).0;
+            df_name = df_map.name();
+            IF df_map.multi() == 't';
+                IF NOT args.hl_display_fields.$df_name;
+                    args.hl_display_fields.$df_name = [];
+                    args.hl.$df_name = [];
+                END;
+                args.hl_display_fields.$df_name.push(df);
+                args.hl.$df_name.push(df.$hl_field || df.value);
+            ELSIF !args.hl_display_fields.$df_name.defined;
+                args.hl_display_fields.$df_name = df;
+                args.hl.$df_name = df.$hl_field || df.value;
+            END;
+        END;
+        junk = ctx.timelog('Finished mapping display fields for bib(s) ' _ args.df_bib_list.list.join(', ')); 
+
+        # Map item types to schema.org types; impedance mismatch :(
+        args.schema.itemtype = {};
+        schema_typemap = {};
+
+        schema_typemap.bluray = 'Movie'; # Movie could also be TVSeries
+        schema_typemap.book = 'Book';
+        schema_typemap.braille = 'Book';
+        schema_typemap.casaudiobook = 'Book AudioObject';
+        schema_typemap.casmusic = 'MusicAlbum';
+        schema_typemap.cdaudiobook = 'Book AudioObject';
+        schema_typemap.cdmusic = 'MusicAlbum';
+        schema_typemap.dvd = 'Movie';
+        schema_typemap.eaudio = 'AudioObject';
+        schema_typemap.ebook = 'Book';
+        # schema_typemap.equip = '';
+        schema_typemap.evideo = 'Movie';
+        # schema_typemap.kit = '';
+        schema_typemap.lpbook = 'Book';
+        schema_typemap.map = 'Map';
+        # schema_typemap.microform = '';
+        schema_typemap.music = 'MusicAlbum';
+        schema_typemap.phonomusic = 'MusicAlbum';
+        # schema_typemap.phonospoken = '';
+        # schema_typemap.picture = ''; Painting or Photograph?
+        schema_typemap.score = 'Book'; # schema.org has no generic Music type
+        schema_typemap.serial = 'Periodical';
+        schema_typemap.software = 'SoftwareApplication';
+        schema_typemap.vhs = 'Movie';
+
+        schema_typemap.a = 'Book';
+        schema_typemap.e = 'Map';
+        schema_typemap.j = 'MusicAlbum';
+
+        # Hard-coded to match defaults in config.copy_status for all OPAC-visible statuses
+        schema_copy_status = {};
+        schema_copy_status.0 = '<link property="availability" href="http://schema.org/InStock" />'; # Available
+        schema_copy_status.1 = '<link property="availability" href="http://schema.org/OutOfStock" />'; # Checked out
+        schema_copy_status.5 = '<link property="availability" href="http://schema.org/PreOrder" />'; # In process
+        schema_copy_status.6 = '<link property="availability" href="http://schema.org/PreOrder" />'; # In transit
+        schema_copy_status.7 = '<link property="availability" href="http://schema.org/InStock" />'; # Reshelving
+        schema_copy_status.8 = '<link property="availability" href="http://schema.org/OutOfStock" />'; # On holds shelf
+        schema_copy_status.9 = '<link property="availability" href="http://schema.org/PreOrder" />'; # On order
+        schema_copy_status.12 = '<link property="availability" href="http://schema.org/InStoreOnly" />'; # Reserves
+
+        args.isbns = [];
+        FOR isbn IN xml.findnodes('//*[@tag="020"]/*[@code="a"]');
+            text = isbn.textContent;
+            FOR q IN isbn.findnodes('../*[@code="q"]');
+                text = text _ ' ' _ q.textContent;
+                LAST; # Should only be 1, but just makin' sure.
+            END;
+            args.isbns.push(text);
+        END;
+
+        # UPCs can be identified either by ind1="1" or subfield 2 of "upc"
+        args.upcs = [];
+        FOR upc IN xml.findnodes('//*[@tag="024" and @ind="1"]/*[@code="a"]');
+            args.upcs.push(upc.textContent);
+        END;
+        FOR upcfield IN xml.findnodes('//*[@tag="024"]/*[@code="2" and text()="upc"]');
+            my_parent = upcfield.parentNode();
+            FOR upc IN my_parent.findnodes('./*[@code="a"]');
+                args.upcs.push(upc.textContent);
+            END;
+        END;
+        args.upc = args.upcs.0; # use first UPC as the default
+
+        # These are URIs that link out to related works for linked data purposes,
+        # such as OCLC Work Entities like http://worldcat.org/entity/work/id/415491
+
+        # We differentiate between http://schema.org/sameAs relations, which
+        # are roughly the same as the work we're describing here, and
+        # http://schema.org/exampleOfWork which point to a broader work, of which
+        # this is a more specific edition or manifestation.
+        args.links.sameAs = [];
+        args.links.exampleOfWork = [];
+        FOR link_node IN xml.findnodes('//*[@tag="024"]/*[@code="2" and text()="uri"]');
+            my_parent = link_node.parentNode();
+            FOR link IN my_parent.findnodes('./*[@code="a"]');
+                link_uri = link.textContent | trim;
+                IF link_uri.search('worldcat.org/entity/work');
+                    args.links.exampleOfWork.push(link_uri);
+                ELSE;
+                    args.links.sameAs.push(link_uri);
+                END;
+            END;
+        END;
+        FOR lccn IN xml.findnodes('//*[@tag="010"]/*[@code="a"]');
+            lccn_num = lccn.textContent | trim;
+            args.links.sameAs.push('http://lccn.loc.gov/' _ lccn_num);
+        END;
+        FOR oclcnum IN xml.findnodes('//*[@tag="035"]/*[@code="a"]');
+            oclcnum = oclcnum.textContent | trim;
+            NEXT UNLESS oclcnum.search('^\(OCoLC\)');
+            oclcnum = oclcnum | remove('\(OCoLC\)');
+            # These prefixes are often included in the 035, even though they should not be
+            oclcnum = oclcnum | remove('ocm');
+            oclcnum = oclcnum | remove('ocn');
+            oclcnum = oclcnum | remove('on') | trim;
+            args.links.sameAs.push('http://www.worldcat.org/oclc/' _ oclcnum);
+        END;
+        args.links.sameAs = args.links.sameAs.unique;
+
+        args.issns = [];
+        FOR sub IN xml.findnodes('//*[@tag="022"]/*[@code="a"]');
+            args.issns.push(sub.textContent);
+        END;
+        args.issn = (args.issns.size) ? args.issn.0 : '';
+
+        graphic_880s = [];
+        get_graphic_880s(target_field='100');
+        get_graphic_880s(target_field='110');
+        get_graphic_880s(target_field='111');
+        args.graphic_authors = graphic_880s;
+        args.authors = [];
+        FOR author IN args.graphic_authors;
+            args.authors.push(author.primary.value);
+        END;
+        args.author = (args.authors.size) ? args.authors.0 : '';
+
+        # Include subfields 'abnp' to generate a more comprehensive title display in search results
+        titresults = xml.findnodes('//*[@tag="245"]/*[@code="a" or @code="b" or @code="n" or @code="p"]');
+        titresults_content = [];
+            FOR sub IN titresults; titresults_content.push(sub.textContent); END;
+
+        args.title = titresults_content.join(" ");
+        # Avoid ugly trailing syntax on brief titles
+        args.title = args.title | replace('[:;/]$', '');
+
+        graphic_880s = [];
+        get_graphic_880s(target_field='245');
+        args.graphic_titles = graphic_880s;
+        args.titles = [];
+        FOR title IN args.graphic_titles;
+            args.titles.push(title.primary.value);
+        END;
+        args.title_extended = (args.titles.size) ? args.titles.0 : '';
+
+        # Create a version of the title designed for sorted displays.
+        args.sort_title = args.title | upper;
+
+        # If the title has a "non-filing chaaracters" 
+        # (to logically remove leading "The " for example)
+        # chop the title. Otherwise, chop until the first alphanumeric.
+        # BTW: Template Toolkit folds 1-element arrays to scalars!
+        title_node = xml.findnodes('//*[@tag="245"]');
+
+        args.nonfiling_characters = title_node.findvalue('@ind2');
+      
+        IF (args.nonfiling_characters > 0);
+             args.sort_title = args.sort_title.substr(args.nonfiling_characters); 
+        ELSE;
+             args.sort_title = args.sort_title.replace('^[^A-Z0-9]*','');
+        END;
+      
+        args.pubplaces = [];
+        pubplace_hunt = xml.findnodes('//*[@tag="260"]/*[@code="a"]') ||
+            xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="a"]');
+        FOR sub IN pubplace_hunt;
+            args.pubplaces.push(sub.textContent);
+        END;
+        args.pubplace = (args.pubplaces.size) ? args.pubplaces.0 : '';
+
+        args.publishers = [];
+        publishers_hunt = xml.findnodes('//*[@tag="260"]/*[@code="b"]') ||
+            xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="b"]');
+        FOR sub IN publishers_hunt;
+            args.publishers.push(sub.textContent);
+        END;
+        args.publisher = (args.publishers.size) ? args.publishers.0 : '';
+
+        args.pubdates = [];
+        pubdates_hunt = xml.findnodes('//*[@tag="260"]/*[@code="c"]') || 
+            xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="c"]');
+        FOR sub IN pubdates_hunt;
+            args.pubdates.push(sub.textContent);
+        END;
+        args.pubdate = (args.pubdates.size) ? args.pubdates.0 : '';
+
+        # Get RDA Copyright Info.
+        args.copyrights = [];
+        FOR sub IN xml.findnodes('//*[@tag="264" and @ind2="4"]/*[@code="c"]');
+            args.copyrights.push(sub.textContent);
+        END;
+        args.copyright = (args.copyrights.size) ? args.copyrights.0 : '';
+
+        IF args.copyright.length >= 4;
+            args.copyrightYear = args.copyright.match('(\d{4})');
+            IF args.copyrightYear;
+                args.copyrightYear = args.copyrightYear.0;
+            END;
+        END;
+
+        # Get the RDA Production info.
+        args.producers = [];
+        FOR sub IN xml.findnodes('//*[@tag="264" and @ind2="0"]/*[@code="b"]');
+            args.producers.push(sub.textContent);
+        END;
+        args.producer = (args.producers.size) ? args.producers.0 : '';
+
+        args.prodplaces = [];
+        FOR sub IN xml.findnodes('//*[@tag="264" and @ind2="0"]/*[@code="a"]');
+            args.prodplaces.push(sub.textContent);
+        END;
+        args.prodplace = (args.prodplaces.size) ? args.prodplaces.0 : '';
+
+        args.proddates = [];
+        FOR sub IN xml.findnodes('//*[@tag="264" and @ind2="0"]/*[@code="c"]');
+            args.proddates.push(sub.textContent);
+        END;
+        args.proddate = (args.proddates.size) ? args.proddates.0 : '';
+
+        # Get the RDA Distribution args.
+        args.distributors = [];
+        FOR sub IN xml.findnodes('//*[@tag="264" and @ind2="2"]/*[@code="b"]');
+            args.distributors.push(sub.textContent);
+        END;
+        args.distributor = (args.distributors.size) ? args.distributors.0 : '';
+
+        args.distplaces = [];
+        FOR sub IN xml.findnodes('//*[@tag="264" and @ind2="2"]/*[@code="a"]');
+            args.distplaces.push(sub.textContent);
+        END;
+        args.distplace = (args.distplaces.size) ? args.distplaces.0 : '';
+
+        args.distdates = [];
+        FOR sub IN xml.findnodes('//*[@tag="264" and @ind2="2"]/*[@code="c"]');
+            args.distdates.push(sub.textContent);
+        END;
+        args.distdate = (args.distdates.size) ? args.distdates.0 : '';
+
+        # Get the RDA Manufacture args.
+        args.manufacturers = [];
+        FOR sub IN xml.findnodes('//*[@tag="264" and @ind2="3"]/*[@code="b"]');
+            args.manufacturers.push(sub.textContent);
+        END;
+        args.manufacturer = (args.manufacturers.size) ? args.manufacturers.0 : '';
+
+        args.manplaces = [];
+        FOR sub IN xml.findnodes('//*[@tag="264" and @ind2="3"]/*[@code="a"]');
+            args.manplaces.push(sub.textContent);
+        END;
+        args.manplace = (args.manplaces.size) ? args.manplaces.0 : '';
+
+        args.mandates = [];
+        FOR sub IN xml.findnodes('//*[@tag="264" and @ind2="3"]/*[@code="c"]');
+            args.mandates.push(sub.textContent);
+        END;
+        args.mandate = (args.mandates.size) ? args.mandates.0 : '';
+
+        # RDA adds 264 to the pubinfo 880 consideration mix
+        graphic_880s = [];
+        get_graphic_880s(target_field='260');
+        get_graphic_880s(target_field='264');
+        args.graphic_pubinfos = graphic_880s;
+        args.pubinfos = [];
+        FOR pubinfo IN args.graphic_pubinfos;
+            args.pubinfos.push(pubinfo.primary.value);
+        END;
+        args.pubinfo = (args.pubinfos.size) ? args.pubinfos.0 : '';
+
+        args.summaries = [];
+        FOR sub IN xml.findnodes('//*[@tag="520"]/*[@code="a"]');
+            args.summaries.push(sub.textContent);
+        END;
+        args.summary = (args.summaries.size) ? args.summaries.0 : '';
+
+        args.targetauds = [];
+        FOR sub IN xml.findnodes('//*[@tag="521"]/*[@code="a"]');
+            args.targetauds.push(sub.textContent);
+        END;
+        args.targetaud = (args.targetauds.size) ? args.targetauds.0 : '';
+
+        # 250 gets pride of place for edition statement, and is the
+        # only logical choice for 880 graphic fields
+        graphic_880s = [];
+        get_graphic_880s(target_field='250');
+        args.graphic_editions = graphic_880s;
+        args.editions = [];
+        FOR edition IN args.graphic_editions;
+            args.editions.push(edition.primary.value);
+        END;
+
+        ed_hunt = xml.findnodes('//*[@tag="250"]/*[@code="a"]');
+        FOR sub IN ed_hunt;
+            args.editions.push(sub.textContent);
+        END;
+        args.edition = (args.editions.size) ? args.editions.0 : '';
+
+        phys_content = [];
+        FOR sub IN xml.findnodes(
+            '//*[@tag="300"]/*[@code="a" or @code="b" or @code="c" or @code="e"]'
+        );
+            phys_content.push(sub.textContent);
+        END;
+        args.phys_desc = phys_content.join(" ");
+
+        graphic_880s = [];
+        get_graphic_880s(target_field='505');
+        args.graphic_contents = graphic_880s;
+        FOR content IN args.graphic_contents;
+            args.contents.push(content.primary.value);
+        END;
+        args.content = (args.contents.size) ? args.contents.0 : '';
+
+        # Maintain contents_list in case any custom use was made of it
+        args.contents_list = [];
+        FOR sub IN xml.findnodes('//*[@tag="505"]');
+            args.contents_list.push(sub.textContent);
+        END;
+
+        # MARC Callnumber
+        args.marc_cns = [];
+        FOR sub IN xml.findnodes('//*[@tag="092" or @tag="099"]/*');
+            args.marc_cns.push(sub.textContent);
+        END;
+        args.marc_cn = (args.marc_cns.size ) ? args.marc_cns.0 : '';
+            
+
+        # clean up the ISBN
+        args.isbn_clean = args.isbns.0.replace('\ .*', '');
+        FOR isbn IN args.isbns;
+            clean_isbn = isbn.replace('\ .*', '');
+            clean_isbn = clean_isbn.replace('-', '');
+            IF clean_isbn.length == 13;
+                args.gtin13 = clean_isbn;
+                LAST;
+            END;
+        END;
+
+        IF ebook_api.overdrive.enabled == 'true';
+            FOR marc037 IN xml.findnodes('//*[@tag="037"]');
+                marc037_id = marc037.findnodes('./*[@code="a"]').textContent;
+                marc037_source = marc037.findnodes('./*[@code="b"]').textContent;
+                IF marc037_source.match('OverDrive') AND marc037_id;
+                    args.overdrive_id = marc037_id;
+                    LAST;
+                END;
+            END;
+        END;
+
+        # Extract the 856 URLs that are not otherwise represented by asset.uri's
+        args.online_res = [];
+        FOR node IN xml.findnodes('//*[@tag="856" and @ind1="4" and (@ind2="0" or @ind2="1")]');
+            IF node.findnodes('./*[@code="9" or @code="w" or @code="n"]'); NEXT; END; # asset.uri's
+            label = node.findnodes('./*[@code="y" or @code="z"][1]');
+            notes = node.findnodes('./*[@code="3"]');
+            FOR href IN node.findnodes('./*[@code="u"]');
+                NEXT UNLESS href;
+                # it's possible for multiple $u's to exist within 1 856 tag.
+                # in that case, honor the label/notes data for the first $u, but
+                # leave any subsequent $u's as unadorned href's. 
+                # use href/link/note keys to be consistent with args.uri's
+                args.online_res.push({
+                    href => href.textContent, 
+                    link => (loop.first AND label) ? label.textContent : href.textContent,
+                    note => (loop.first) ? notes.textContent : ''
+                });
+            END;
+        END;
+        args.holdings = [];
+        args.uris = [];
+        args.issns = [];
+        args.resolver_isbns = [];
+        args.resolver_issns = [];
+
+        # we use $9 of ISBN and ISSN as a flag for e-version
+        FOR resolver_isbn IN xml.findnodes('//*[@tag="020"]/*[@code="9"]');
+            IF resolver_isbn.textContent == "SFX" || resolver_isbn.textContent == "CUFTS";
+                my_parent = resolver_isbn.parentNode();
+                FOR resolver_isbn_val IN my_parent.findnodes('./*[@code="a"]');
+                    args.resolver_isbns.push(
+                        resolver_isbn_val.textContent.replace('-', '').replace('\ .*', '')
+                    );
+                END;
+            END;
+        END;
+
+        FOR resolver_issn IN xml.findnodes('//*[@tag="022"]/*[@code="9"]');
+            IF resolver_issn.textContent == "SFX" || resolver_issn.textContent == "CUFTS";
+                my_parent = resolver_issn.parentNode();
+                FOR resolver_issn_val IN my_parent.findnodes('./*[@code="a"]');
+                    args.resolver_issns.push(
+                        resolver_issn_val.textContent.replace('[^\d\-X]', '')
+                    );
+                END;
+            END;
+        END;
+
+        # now snag all issns 
+        FOR rawissn IN xml.findnodes('//*[@tag="022"]/*[@code="a"]');
+            args.issns.push(
+                rawissn.textContent.replace('[^\d\-X]', '')
+            );
+        END;
+
+        ou_hiding_disabled = ctx.org_hiding_disabled();
+
+        # explicitly grabbing the first bib_source node, though there should be only one anyway
+        bib_source = xml.findnodes('//*[local-name()="bib_source"][1]');
+        args.bib_source.id = bib_source.getAttribute('ident');
+        args.bib_source.source = bib_source.textContent;
+
+        FOR volume IN xml.findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]');
+
+            # Check volume visibility - could push this into XPath
+            vol.label = volume.getAttribute('label');
+
+            # Prepend prefix, if any
+            prefix = volume.findnodes('./*[local-name()="call_number_prefix"][@ident!="-1"]');
+            IF prefix.getAttribute('label') != '';
+                vol.label = prefix.getAttribute('label') _ " " _ vol.label;
+            END;
+
+            # Append prefix, if any
+            suffix = volume.findnodes('./*[local-name()="call_number_suffix"][@ident!="-1"]');
+            IF suffix.getAttribute('label') != '';
+                vol.label = vol.label _ " " _ suffix.getAttribute('label');
+            END;
+
+            vol.id = volume.getAttribute('id');
+            NEXT IF volume.getAttribute('opac_visible') == 'false';
+            NEXT IF volume.getAttribute('deleted') == 'true';
+
+            IF vol.label == '##URI##';
+                FOR uri IN volume.findnodes('./*[local-name()="uris"]/*[local-name()="uri"]');
+                    res = {};
+                    res.href = uri.getAttribute('href');
+                    res.link = uri.getAttribute('label');
+                    res.note = uri.getAttribute('use_restriction');
+                    # Avoid displaying the href as the link text if we can display the note instead
+                    IF res.link == res.href AND res.note;
+                        res.link = res.note;
+                        res.note = '';
+                    END;
+                    args.uris.push(res);
+
+                    IF ebook_api.ebook_test.enabled == 'true';
+                        IF !args.ebook_test_id;
+                            FOR base_uri IN ebook_api.ebook_test.base_uris;
+                                IF res.href.match(base_uri);
+                                    args.ebook_test_id = res.href.remove(base_uri);
+                                    LAST;
+                                END;
+                            END;
+                        END;
+                    END;
+
+                    IF ebook_api.oneclickdigital.enabled == 'true';
+                        # A record might conceivably have multiple OneClickdigital URIs,
+                        # but we use (the same) ISBN as the ebook ID in each case.
+                        IF !args.oneclickdigital_id;
+                            FOR base_uri IN ebook_api.oneclickdigital.base_uris;
+                                IF res.href.match(base_uri);
+                                    # found a OneClickdigital URI, let's grab our ID and move on
+                                    args.oneclickdigital_id = clean_isbn;
+                                    LAST;
+                                END;
+                            END;
+                        END;
+                    END;
+
+                    IF ebook_api.overdrive.enabled == 'true';
+                        # Ideally we already have an OverDrive record ID from MARC 037 (see above).
+                        # But for older records, it will be embedded in the URI in MARC 856.
+                        IF !args.overdrive_id;
+                            FOR base_uri IN ebook_api.overdrive.base_uris;
+                                IF res.href.match(base_uri);
+                                    args.overdrive_id = res.href.remove('^.*/ContentDetails.htm\?ID=');
+                                    LAST;
+                                END;
+                            END;
+                        END;
+                    END;
+                END;
+
+                NEXT;
+            ELSE;
+                copies = volume.findnodes('./*[local-name()="copies"]/*[local-name()="copy"]');
+                FOR copy IN copies;
+                    parts = copy.findnodes('./*[local-name()="monograph_parts"]/*[local-name()="monograph_part"]');
+                    part_label = '';
+                    FOREACH part IN parts;
+                        part_label = part.getAttribute('label');
+                        LAST IF part_label != '';
+                    END;
+                    # Check copy visibility
+                    cp.deleted = copy.getAttribute('deleted');    
+                    cp.visible = copy.getAttribute('opac_visible');
+                    NEXT IF (cp.deleted == 'true' OR cp.visible == 'false');
+
+                    # Iterate through all of the children to determine visibility
+                    FOR node IN cp.childNodes;
+                        NEXT IF cp.visible == 'false';
+                        vis = node.getAttribute('opac_visible');
+                        del = node.getAttribute('deleted');
+                        IF vis == 'false' or del == 'true';
+                            cp.visible = 'false';
+                        END;
+                    END;
+
+                    NEXT IF cp.visible == 'false';
+                    
+                    loc = copy.findnodes('./*[local-name()="location"]');
+                    NEXT IF loc.getAttribute('opac_visible') == 'false';
+
+                    circlib = copy.findnodes('./*[local-name()="circlib"]');
+                    NEXT IF circlib.getAttribute('opac_visible') == 'false';
+
+                    status = copy.findnodes('./*[local-name()="status"]');
+                    NEXT IF status.getAttribute('opac_visible') == 'false';
+
+                    # extract the circ_lib id from the circ_lib node
+                    circ_lib = copy.findnodes('./*[local-name()="circ_lib"]');
+                    circ_lib_id = circ_lib.getAttribute('id').replace('.*/', '');
+
+                    UNLESS ou_hiding_disabled;
+                        NEXT UNLESS ctx.org_within_hiding_scope(circ_lib_id);
+                    END;
+
+                    holding = {
+                        circ_lib => circ_lib_id,
+                        label => vol.label,
+                        part_label => part_label,
+                        location => loc.textContent,
+                        library => circlib.textContent,
+                        status => status.textContent,
+                        status_code => status.getAttribute('ident'),
+                        barcode => copy.getAttribute('barcode'),
+                        owner => volume.getAttribute('lib')
+                    };
+                    args.holdings.push(holding);
+                    part_label = '';
+                END;
+            END;
+        END;
+
+        # Extract the copy count summary
+        count_type = (ctx.is_staff) ? 'staff' : 'public';
+
+        # Consortial copy count summary first
+        xpath = '//*[local-name()="counts"]/*[local-name()="count"][@type="' _ count_type _ '"]';
+        args.copy_counts = {};
+        FOR node IN xml.findnodes(xpath);
+            FOR attr IN ['count', 'available', 'unshadow', 'transcendant', 'org_unit']; 
+                depth = node.getAttribute('depth');
+                count_org_unit = node.getAttribute('org_unit');
+                args.copy_counts.$depth.$attr = node.getAttribute(attr);
+                args.org_copy_counts.$count_org_unit.$attr = node.getAttribute(attr);
+            END;
+        END;
+
+        # Get preferred library copy count
+        args.plib_copy_counts = {};
+        count_type = 'pref_lib';
+        xpath = '//*[local-name()="counts"]/*[local-name()="count"][@type="' _ count_type _ '"]';
+        FOR node IN xml.findnodes(xpath);
+            FOR attr IN ['count', 'available', 'unshadow', 'transcendant', 'org_unit']; 
+                depth = node.getAttribute('depth');
+                args.plib_copy_counts.$depth.$attr = node.getAttribute(attr);
+            END;
+        END;
+
+        mmr_unique_bib = [];
+        # "mattype" == "custom marc format specifier"
+        icon_style = ctx.get_cgf('opac.icon_attr').value || 'item_type';
+        formats_xpath = '//*[local-name()="attributes"]/*[local-name()="field"][@name="' _ icon_style _ '"]';
+
+        args.all_formats = [];
+        FOR node IN xml.findnodes(formats_xpath);
+            IF node AND node.textContent;
+                ccvm = ctx.get_ccvm(node.getAttribute('cvmid'));
+                NEXT IF ccvm.opac_visible == 'f';
+
+                format = {};
+                this_icon_source = node.getAttribute('source_list');
+                including = 'F';
+                # Just display everything if we don't have the data
+                IF NOT args.mr_constituent_ids OR NOT this_icon_source;
+                    including = 'T';
+                # We have an array of search-included bib IDs and we have the bib ID that this icon belongs to
+                ELSE;
+                    FOR mr_constituent_id IN args.mr_constituent_ids;
+                        IF this_icon_source.split(',').grep('^' _ mr_constituent_id _ '$' ).size;
+                            # This bib appears to be in the array of filtered bibs
+                            including = 'T';
+                        END;
+                    END;
+                END;
+                IF including == 'T';
+                    type = ccvm.code.remove('-'); # blu-ray to bluray
+                    format.label = ccvm.search_label || ccvm.value;
+                    format.icon = PROCESS get_ccvm_icon ccvm=ccvm;
+                    format.itemtype = schema_typemap.$type || 'CreativeWork';
+                    format.search_format = ccvm.code;
+                    format.source_bibs = this_icon_source.split(',');
+                    FOR bib_source IN format.source_bibs;
+                        IF NOT mmr_unique_bib.grep(bib_source).size; mmr_unique_bib.push(bib_source); END;
+                    END;
+                    args.all_formats.push(format); # metarecords want all formats
+
+                    IF !args.format_label;
+                        # use the first format as the default
+                        args.format_label = format.label;
+                        args.schema.itemtype = format.itemtype;
+                        args.format_icon = format.icon;
+                    END;
+                END;
+            END;
+        END;
+
+        formats_xpath = '//*[local-name()="attributes"]/*[local-name()="field"][@name="item_lang"]';
+        args.all_lang = [];
+        FOR node IN xml.findnodes(formats_xpath);
+            IF node AND node.textContent;
+                ccvm = ctx.get_ccvm(node.getAttribute('cvmid'));
+                NEXT IF ccvm.opac_visible == 'f';
+
+                lang = {};
+                this_source = node.getAttribute('source_list');
+                including = 'F';
+                # Just display everything if we don't have the data
+                IF NOT args.mr_constituent_ids OR NOT this_source;
+                    including = 'T';
+                # We have an array of search-included bib IDs and we have the bib ID that this lang belongs to
+                ELSE;
+                    FOR mr_constituent_id IN args.mr_constituent_ids;
+                        IF this_source.split(',').grep('^' _ mr_constituent_id _ '$' ).size;
+                            # This bib appears to be in the array of filtered bibs
+                            including = 'T';
+                        END;
+                    END;
+                END;
+                IF including == 'T';
+                    lang.label = ccvm.search_label || ccvm.value;
+                    lang.itemtype = schema_typemap.$type || 'CreativeWork';
+                    lang.search_format = node.textContent;
+                    lang.source_bibs = this_source.split(',');
+                    FOR bib_source IN lang.source_bibs;
+                        IF NOT mmr_unique_bib.grep(bib_source).size; mmr_unique_bib.push(bib_source); END;
+                    END;
+
+                    args.all_lang.push(lang); # metarecords want all
+                END;
+            END;
+        END;
+        args.mmr_unique_bib = mmr_unique_bib;
+
+        IF args.ebook_test_id;
+            args.ebook.ebook_id = args.ebook_test_id;
+            args.ebook.vendor = 'ebook_test';
+        ELSIF args.oneclickdigital_id;
+            args.ebook.ebook_id = args.oneclickdigital_id;
+            args.ebook.vendor = 'oneclickdigital';
+        ELSIF args.overdrive_id;
+            args.ebook.ebook_id = args.overdrive_id;
+            args.ebook.vendor = 'overdrive';
+        END;
+
+    END;
+
+    # Get the library or location group
+    # get_library()
+    # magically upgrades any use of 'loc' to 'locg', 
+    # which is a superset of 'loc'.
+    BLOCK get_library;
+        loc_name = 'locg';
+
+        # Location groups don't have shortnames, so they'll take priority
+        # (_org doesn't contain the group and breaks the selector).
+        loc_value = ctx.copy_location_group ? CGI.param(loc_name)
+                  : ctx.copy_location_group_org # resolved locg
+                    || CGI.param(loc_name) || CGI.param('loc') || ctx.search_ou;
+    END;
+
+-%]
+
+
+[%- BLOCK carousels;
+    config = {
+        animated => 0,
+        animation_interval => 5,
+        width => 5,
+        sm_width => 3,
+        xs_width => 2,
+    };
+    config.import(args);
+    carousels = [];
+    IF config.carousel_id;
+        carousels.push(ctx.get_carousel(config.carousel_id));
+    ELSE;
+        visible_carousels = ctx.get_visible_carousels();
+        FOREACH car IN visible_carousels;
+            carousel = ctx.get_carousel(car.carousel);
+            IF car.override_name.defined;
+                carousel.name = car.override_name;
+            END;
+            carousels.push(carousel);
+        END; 
+    END;
+    IF carousels.size > 0;
+%]
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/common/build/js/glide/glide.min.js[% ctx.cache_key %]"></script>
+<div class="carousels">
+[% FOREACH carousel IN carousels;
+   IF carousel.bibs.size > 0;
+%]
+<div class="carousel">
+<div class="carousel-title">[% carousel.name %]</div>
+<div class="carousel-body glide" id="carousel-[% carousel.id %]">
+  <div class="glide__track" data-glide-el="track">
+    <ul class="glide__slides">
+[% FOREACH bib IN carousel.bibs; %]
+      <li class="glide__slide"><div class="carousel-entry">
+        <a href="[% mkurl(ctx.opac_root  _ '/record/' _ bib.id) %]">
+          <img alt="[% l('Book cover') %]" class="carousel-entry-image" src="[% ctx.media_prefix %]/opac/extras/ac/jacket/medium/r/[% bib.id | uri %]"></img>
+        </a><br>
+        <span class="carousel-entry-title"><a href="[% mkurl(ctx.opac_root  _ '/record/' _ bib.id) %]">[% bib.title | html %]</a></span>
+      </div></li>
+[% END; %]
+    </ul>
+  </div>
+  <div class="glide__arrows" data-glide-el="controls">
+    <button class="glide__arrow glide__arrow--left" data-glide-dir="<">prev</button>
+    <button class="glide__arrow glide__arrow--right" data-glide-dir=">">next</button>
+  </div>
+</div>
+</div>
+<script>
+    var glide = new Glide('#carousel-[% carousel.id %]', {
+        type: 'carousel',
+        rewind: false,
+        perView: [% config.width %],
+        breakpoints: {
+            992: {
+                perView: [% config.sm_width %]
+            },
+            768: {
+                perView: [% config.xs_width %]
+            }
+        },
+        startAt: 0,
+        [% IF config.animated %] autoplay: [% config.animation_interval * 1000 %],[% END %]
+    });
+    glide.mount();
+</script>
+[% END; %]
+[% END; %]
+</div>
+[% END -%]
+[% END -%]
+[% MACRO accordion(str, trunc_length, element) BLOCK;
+    IF truncate_contents != 1;
+        ctx.defang_string(str);
+    ELSE;
+        UNLESS trunc_length;
+            trunc_length = contents_truncate_length || 100;
+        END;
+        IF str.length > trunc_length;
+            accordion_res = ctx.split_for_accordion(str, trunc_length);
+            str = accordion_res.0;
+            IF accordion_res.1;
+                str = str _ " <a onclick='toggleAccordion(this, " _ element _ ")'>" _ l('Read More') _ "</a>";
+            END;
+            str;
+        ELSE;
+            ctx.defang_string(str);
+        END;
+    END;
+END; %]
diff --git a/Open-ILS/src/templates_cons/opac/parts/myopac/main_refund_policy.tt2 b/Open-ILS/src/templates_cons/opac/parts/myopac/main_refund_policy.tt2
new file mode 100644 (file)
index 0000000..1d37841
--- /dev/null
@@ -0,0 +1,9 @@
+<tr>
+    <td colspan="3">
+        <p style="font-size: 120%;">
+        <strong>
+        Online payments are non-refundable. Patrons should make every effort to find and return lost items prior to payment.
+        </strong>
+        </p>
+    </td>
+</tr>
diff --git a/Open-ILS/src/templates_cons/opac/parts/place_hold.tt2 b/Open-ILS/src/templates_cons/opac/parts/place_hold.tt2
new file mode 100644 (file)
index 0000000..c36ba89
--- /dev/null
@@ -0,0 +1,317 @@
+[%  PROCESS "opac/parts/misc_util.tt2";
+    PROCESS "opac/parts/hold_error_messages.tt2";
+    PROCESS "opac/parts/metarecord_hold_filters.tt2";
+%]
+<script>
+// Toggle the activation date input and check the suspend checkbox.
+// If JavaScript is disabled, the CSS will handle the former, but
+// the latter will not happen.
+function toggleActivationDate() {
+    var cb = document.getElementById("hold_suspend");
+    var block = document.getElementById("toggled-block-suspend");
+    var anchor = document.getElementById("actDateToggle");
+    var actText = "[%- l('Hide activation date') -%]";
+    var inActText = "[%- l('Set activation date') -%]";
+    // Check for not equal to block so it works on first click.
+    if (block.style.display != "block") {
+        block.style.display = "block";
+        anchor.innerHTML = actText;
+        if (cb.checked != true) cb.checked = true;
+    } else {
+        block.style.display = "none";
+        anchor.innerHTML = inActText;
+    }
+    // Prevent the href from being followed, thus overriding the CSS.
+    return false;
+}
+
+// Maybe enable or disable the num_copies select when the user selects
+// or deselects a part.
+function maybeToggleNumCopies(obj) {
+    var numCopies = document.getElementById("num_copies");
+    // Only if numCopies exists.
+    if (numCopies) {
+        var objValue;
+        if (obj.type == 'radio') {
+            if (obj.checked) objValue = obj.value;
+            else return;
+        } else {
+            objValue = obj.value;
+        }
+        if (objValue && objValue != '') {
+            if (numCopies.value != '1') numCopies.value = '1';
+            if (!numCopies.disabled) numCopies.disabled = true;
+        } else {
+            if (numCopies.disabled) numCopies.disabled = false;
+        }
+    }
+}
+</script>
+<div id='holds_box' class='canvas' style='margin-top: 6px;'>
+    <h1>[% l('Place Hold') %]</h1>
+
+    [% some_holds_allowed = -1 %]
+
+    <!-- loop through the holds and display status of request where appropriate -->
+        [% FOR hdata IN ctx.hold_data;
+            attrs = {marc_xml => hdata.marc_xml};
+            PROCESS get_marc_attrs args=attrs;
+            this_hold_disallowed = 0;
+
+            IF CGI.param('hold_type') == 'M';
+              IF hdata.metarecord_filters.formats.size == 0;
+                this_hold_disallowed = 1;
+                # if this is the first hold and it's disallowed,
+                # assume all holds are, until we proven otherwise
+                SET some_holds_allowed = 0 IF some_holds_allowed == -1;
+              ELSE; some_holds_allowed = 1; END;
+            END %]
+     
+      [% IF loop.first %] 
+    <form method="post" name="PlaceHold" onsubmit="return validateHoldForm()" >
+        <input type="hidden" name="hold_type" value="[% CGI.param('hold_type') | html %]" />
+        [%  
+            redirect = CGI.param('hold_source_page') || CGI.param('redirect_to') || CGI.referer;
+            # since we have to be logged in to get this far, return to a secure page
+            redirect = redirect.replace('^http:', 'https:') 
+        %]
+        <input type="hidden" name="redirect_to" value="[% redirect | html %]" />
+        <input type="hidden" name="hold_source_page" value="[% CGI.param('hold_source_page') | html %]" />
+
+        <!-- Adding hidden fields so that parameters are maintained in
+        searchbar throughout the place hold process. -->
+        <input type="hidden" name="locg" value="[% CGI.param('locg') | html %]" />
+        <input type="hidden" name="qtype" value="[% CGI.param('qtype') | html %]" />
+        <input type="hidden" name="query" value="[% CGI.param('query') | html %]" />
+        [%
+            usr_barcode = CGI.param('usr_barcode') | html;
+            is_requestor = CGI.param('is_requestor');
+
+           IF is_requestor == '';
+               is_requestor = '0';
+           END;
+
+           IF is_requestor == '0' && usr_barcode == ctx.staff_recipient.card.barcode;
+               usr_barcode = '';
+           END;
+        %]
+
+        [% IF ctx.is_staff %]
+        <!-- request for a patron -->
+        <p class="staff-hold">
+            <input type="radio" id="hold_usr_is_requestor_not"
+                onchange="staff_hold_usr_input_disabler(this);"
+                name="hold_usr_is_requestor" value="0"
+                />
+            <label for="hold_usr_is_requestor_not">
+                [% l("Place hold for patron by barcode:") %]
+            </label>
+            <input type="text" name="hold_usr" id="hold_usr_input"
+              aria-label="[% l('Barcode') %]"
+              value="[% usr_barcode | html %]" 
+              onpaste="return debounce_barcode_change(event)"
+              onkeydown="return debounce_barcode_change(event)" autofocus /> 
+            <span id="patron_name"></span>
+            <span id="patron_usr_barcode_not_found" style="display: none">
+              [% l('Patron barcode was not found') %]
+            </span>
+            [% IF ctx.is_browser_staff %]
+            <button id="hold_usr_search" type="button" class="opac-button" style="display: none;">[% l('Patron Search') %]</button>
+            [% END %]
+            <br />
+            <input type="hidden" id="staff_barcode" 
+              value="[% ctx.staff_recipient.card.barcode | html %]"/>
+            <span>
+                <input type="radio" id="hold_usr_is_requestor"
+                    onchange="staff_hold_usr_input_disabler(this);"
+                    name="hold_usr_is_requestor" value="1" />
+                <label for="hold_usr_is_requestor">
+                    [% l("Place this hold for me ([_1] [_2])", ctx.user.first_given_name, ctx.user.family_name) | html %]
+                </label>
+            </span>
+            [% IF CGI.param('hold_type') == 'T' AND ctx.hold_subscriptions.size > 0 AND NOT CGI.param('from_basket') %]
+              <br />
+              <!-- request for a reading group / subscription -->
+              <input type="radio" id="hold_usr_is_subscription"
+                  onchange="staff_hold_usr_input_disabler(this);"
+                  name="hold_usr_is_requestor" value="2"
+                  />
+              <label for="hold_usr_is_subscription">
+                  [% l("Place hold for patron Hold Group:") %]
+              </label>
+              <select id='select_hold_subscription' name='hold_subscription'>
+                  <option selected='selected' value=''>[% l('- Hold Groups -') %]</option>
+                  [% FOR sub IN ctx.hold_subscriptions %]
+                  <option value='[% sub.id %]'>[% sub.name | html %]</option>
+                  [% END %]
+              </select>
+            [% END %]
+            <br/>
+            <label>
+              <input id="override_blocks_subscription" name="override" type="checkbox" checked="checked"/>
+              [% l("Override all hold-blocking conditions possible?") %]
+            </label>
+        </p>
+        [% END %]
+
+      [% END %]
+
+        <table id='hold-items-list'>
+            <tr>
+                <td>
+                    [% IF !this_hold_disallowed %]
+                    <input type="hidden" name="hold_target" value="[% hdata.target.id | html %]" />
+                    [% END %]
+                    <div class='hold-items-list-title'>
+                                           <!-- If hold is for grouped formats/editions (metarecord), show short title - else, show complete title --> 
+                                           [% IF CGI.param('hold_type') == 'M' %]
+                                                   [% attrs.title | html %]
+                                               [% ELSE %]
+                                                   [% attrs.title_extended | html %]
+                                               [% END %]
+                    </div>
+                    [% IF hdata.parts AND !this_hold_disallowed %]
+                        [% IF hdata.parts.size > 0 %]
+                        <div class='hold-div'>
+                            [% IF enable.radio.parts == 'true' %]
+                                <span class='hold-span'><label for='select_hold_part'>[%
+                               l('Select a Part:')
+                               %]</label></span>
+                             <div class='radio-parts-selection'>
+                             [% IF !hdata.part_required %]
+                                <span class='parts-radio-option'>
+                                 <input type='radio' name='part' value='' onchange='maybeToggleNumCopies(this);' required>[% l('All Parts') %]</span>
+                              [% END %]
+                               [% FOR part IN hdata.parts %]
+                                 <span class='parts-radio-option'><input type='radio' name='part' id=[% part.id %] value=[% part.id %] onchange='maybeToggleNumCopies(this);' required>
+                                  <label for=[% part.id %]>[% part.label | html %]</label></span>
+                              [% END %]
+                              </div>
+                          [% ELSE %]
+                            <span style='font-weight: bold; font-size: 120%; color: red;'><label for='select_hold_part'>[%
+                                hdata.part_required ? l('Select a Part:') : l('Select a Part (optional):')
+                            %]</label></span>
+                            <select id='select_hold_part' name='part' onchange='maybeToggleNumCopies(this);'>
+                                [% IF !hdata.part_required %]
+                                <option selected='selected' value=''>[% l('- All Parts -') %]</option>
+                                [% END %]
+                                [% FOR part IN hdata.parts %]
+                                <option value='[% part.id %]'>[% part.label | html %]</option>
+                                [% END %]
+                            </select>
+                          [% END %]
+                        </div>
+                        [% ELSE %]
+                        <input type='hidden' name='part' value=''/>
+                        [% END %]
+                    [% END %]
+                   [% INCLUDE "opac/parts/multi_hold_select.tt2" IF NOT (this_hold_disallowed AND hdata.part_required); %]
+                    [% IF NOT metarecords.disabled AND ctx.hold_data.size == 1 %]
+                        [% IF CGI.param('hold_type') == 'T' AND hdata.record.metarecord AND !hdata.part_required %]
+                        <!-- Grab the bre_id so that we can restore it if user accidentally clicks advanced options -->
+                           [% bre_id = hdata.target.id %]
+                            <a  id='advanced_hold_link'
+                                href="[% mkurl('', {hold_type => 'M', hold_target => hdata.record.metarecord.id, bre_id => bre_id}) %]">
+                                [% l('Advanced Hold Options') %]</a>
+                        [% END %]
+                        [% IF CGI.param('hold_type') == 'M' AND CGI.param('bre_id') %]
+                            <input type="hidden" name="bre_id" value="[% CGI.param('bre_id') | html %]" />
+                            <a id='basic_hold_link'
+                               href="[% mkurl('', {hold_target => CGI.param('bre_id'), hold_type => 'T'}) %]">
+                                [% l('Basic Hold Options') %]</a>
+                        [% END %]
+                        [% IF hdata.metarecord_filters.formats.size OR # should this be size > 1
+                            (hdata.metarecord_filters.langs.size && hdata.metarecord_filters.langs.size > 1);
+                            PROCESS metarecord_hold_filters_selector hold_data=hdata;
+                        END;
+                    END %]
+                </td>
+            </tr>
+
+            [% IF this_hold_disallowed %]
+              <tr><td>
+                <div class="mr_holds_no_formats">
+                [% l('This item does not have any formats available for holds placement') %]
+                </div>
+              </td></tr>
+            [% END %]
+
+            [%  IF !loop.last AND ctx.hold_data.size > 1 %]
+            <tr class="holds_item_row_separator"><td> </td></tr>
+            [% END %]
+
+        [% END %]
+        </table>
+
+        [% IF some_holds_allowed %]
+
+        <p>
+            [%- org_select_id = 'pickup_lib'; -%]
+            <label for="[% org_select_id %]">[%l('Pickup location:') %]</label>
+            [% PROCESS "opac/parts/org_selector.tt2";
+                INCLUDE build_org_selector name='pickup_lib' 
+                    value=ctx.default_pickup_lib id=org_select_id 
+                    can_have_vols_only=1 hold_pickup_lib=1 %]
+        </p>
+        <p>
+            [% l('Notify when hold is ready for pickup?') %]
+            <blockquote>
+                <input class="hold-alert-method" type="checkbox" id="email_notify" name="email_notify" value="t"
+                    [% IF !ctx.user.email %]disabled="true"[% ELSIF ctx.default_email_notify %]checked="checked"[% END %]/>
+                    <label for="email_notify">[% l('Yes, by Email') %]</label><br/>
+                <blockquote>
+                    [% IF !ctx.user.email and !ctx.is_staff; l('No configured Email address. See "My Account" for setting your Email address.');
+                     ELSE; l('Email Address:') %] <span name="email_address">[% ctx.user.email %]</span>[% END %]
+                </blockquote>
+                [%- IF allow_phone_notifications == 'true' %]
+                <input class="hold-alert-method" type="checkbox" id="phone_notify_checkbox" name="phone_notify_checkbox"
+                    [% IF ctx.default_phone_notify %]checked="checked"[% END %]/>
+                    <label for="phone_notify_checkbox">[% l('Yes, by Phone') %]</label><br/>
+                <blockquote>
+                    <label>[% l('Phone Number:') %]<input type="text" id="phone_notify" name="phone_notify" [% setting = 'opac.default_phone';
+                    IF ctx.user_setting_map.$setting; %] value='[% ctx.user_setting_map.$setting | html %]'
+                    [%- ELSIF ctx.user.day_phone; %] value='[% ctx.user.day_phone | html %]' [% END %]/></label>
+                </blockquote>
+                [%- END -%]
+                [% IF ctx.get_org_setting(ctx.search_ou, 'sms.enable') == 1 %]
+                <input class="hold-alert-method" type="checkbox" id="sms_notify_checkbox" name="sms_notify_checkbox"
+                    [% IF ctx.default_sms_notify %]checked="checked"[% END %]/>
+                    <label for="sms_notify_checkbox">[% l('Yes, by Text Messaging') %]</label><br/>
+                <blockquote>
+                    [% INCLUDE "opac/parts/sms_carrier_selector.tt2" %]<br/>
+                    [% INCLUDE "opac/parts/sms_number_textbox.tt2" %]<br/>
+                </blockquote>
+                [% END %]
+            </blockquote>
+            <blockquote>
+                <label for="hold_suspend">
+                [% IF ctx.hold_data.size == 1;
+                      l('Suspend this hold?');
+                  ELSE;
+                      l('Suspend these holds?');
+                  END %]
+                </label>
+                <img src="[% ctx.media_prefix %]/images/question-mark.png[% ctx.cache_key %]"
+                     alt="[% l('Suspend Hold Help') %]"
+                     title="[% l('A suspended hold will retain its place in the queue, but will not be fulfilled until it has been activated.') %]" />
+                <br/>
+                <input type="checkbox" name="hold_suspend" id="hold_suspend" value="t"/> [% l('Yes') %]
+                <a id="actDateToggle" href="#toggled-block-suspend" onclick="return toggleActivationDate();">[% l('Set activation date') %]</a>
+            </blockquote>
+            <blockquote id="toggled-block-suspend">
+                <label for="thaw_date">[% l('Activate on') %]</label>
+                <input type="text" id="thaw_date" name="thaw_date" />
+                <em>[% l('Enter date in MM/DD/YYYY format') %]</em>
+            </blockquote>
+        </p>
+        [% IF CGI.param('from_basket') %]
+          <blockquote><input type="checkbox" name="clear_cart" id="clear_cart" /><label for="clear_cart">[% l('Clear basket after holds are requested?') %]</label></blockquote>
+        [% END %]
+        <input id="place_hold_submit" type="submit" name="submit" 
+            value="[% l('Submit') %]" title="[% l('Submit') %]"
+            alt="[% l('Submit') %]" class="opac-button" />
+        [% END # some_holds_allowed %]
+        <input type="reset" name="cancel" onclick="window.location='[% redirect | html %]'" value="[% l('Cancel') %]" id="holds_cancel" class="opac-button" />
+    </form>
+</div>
+
diff --git a/Open-ILS/src/templates_cons/opac/parts/qtype_selector.tt2 b/Open-ILS/src/templates_cons/opac/parts/qtype_selector.tt2
new file mode 100644 (file)
index 0000000..008eb21
--- /dev/null
@@ -0,0 +1,24 @@
+[%  query_types = [
+    {value => "keyword", label => l("Keyword")},
+    {value => "title", label => l("Title"), plural_label => l("Titles"), browse => 1},
+    {value => "jtitle", label => l("Journal Title")},
+    {value => "title|uniform", label => l("Uniform Title")},
+    {value => "author", label => l("Author"), plural_label => l("Authors"), browse => 1},
+    {value => "identifier|publisher", label => l("Publisher")},
+    {value => "subject", label => l("Subject"), plural_label => l("Subjects"), browse => 1},
+    {value => "series", label => l("Series"), plural_label => l("Series"), browse => 1}
+] %]
+<select name="[% name || 'qtype' %]"[% IF id; ' id="'; id ; '"' ; END -%]
+    title="[% l('Select query type:') %]">
+    [%  query_type = query_type || CGI.param('qtype') || search.default_qtypes.0;
+      FOR qt IN query_types;
+        NEXT IF browse_only AND NOT qt.browse -%]
+    <option value='[% qt.value | html %]'[%
+        query_type == qt.value ? ' selected="selected"' : ''
+    %]>[% IF plural AND qt.plural_label;
+        qt.plural_label | html;
+    ELSE;
+        qt.label | html;
+    END %]</option>
+    [% END -%]
+</select>
diff --git a/Open-ILS/src/templates_cons/opac/parts/record/addedcontent.tt2 b/Open-ILS/src/templates_cons/opac/parts/record/addedcontent.tt2
new file mode 100644 (file)
index 0000000..4a4b859
--- /dev/null
@@ -0,0 +1,57 @@
+<div class='rdetail_extras_div'> 
+
+[% 
+    ac_types = {
+        reviews => l('Reviews'),
+        anotes  => l('Author Notes'),
+        toc     => l('Table of Contents'),
+        excerpt => l('Excerpt'),
+        summary => l('Summary')
+    };
+
+    selected_type = CGI.param('ac');
+    
+    # For each type of added content, render the link if it's known to have
+    # content, do not render the link if it's known to not have content.  If 
+    # the content status is unknown, render the link, but hide the link via CSS
+    # if dojo is enabled.  If dojo is not enabled, render and display the link.
+%]
+
+    <div id='ac_tab_wrapper'>
+        <a name="addedcontent"></a><!-- Anchor is here! -->
+    [% 
+        all_hidden = 1;
+        FOR type IN ac_types.keys;
+            tab_class = 'ac_tab';
+            SET tab_class = tab_class _ ' ac_tab_selected' IF type == selected_type; 
+            IF ctx.added_content.$type.status != '2'; # no content
+                all_hidden = 0;
+                IF ctx.added_content.$type.status == '3' AND want_dojo; # status unknown
+                    tab_class = tab_class _ ' hidden';
+                END %]
+            <div class="[% tab_class %]" id="ac:[% type %]">
+                <a href="[% mkurl('', {ac => type}) _ '#addedcontent' %]" rel="nofollow" vocab="">[% ac_types.$type %]</a>
+            </div>
+            [% END;
+        END;
+    %]
+    </div>
+
+    <div id='ac_content'>
+        [% 
+            IF selected_type; 
+                content = ctx.added_content.$selected_type.content;
+                IF content;
+                    content;
+                ELSE;
+                    l(''); #Removed "No Content Available" text
+                END;
+            ELSIF all_hidden;
+                l(''); #Removed "No Content Available" text
+            END;
+        %]
+    </div>
+</div>
+
+
diff --git a/Open-ILS/src/templates_cons/opac/parts/record/awards.tt2 b/Open-ILS/src/templates_cons/opac/parts/record/awards.tt2
new file mode 100644 (file)
index 0000000..fd0168b
--- /dev/null
@@ -0,0 +1,11 @@
+<div class='rdetail_extras_div'> 
+    <div style="margin-bottom:20px;"></div>
+
+    <!-- Novelist suggestions-->
+    [% IF ENV.OILS_NOVELIST_URL %] 
+        <div id='novelist-loading'>[% l('No NoveList content is available for this item.') %]</div>
+        <div data-novelist-novelistselect="[% attrs.isbn_clean || attrs.upc %]"></div>
+    [% END %]
+
+</div>
+
diff --git a/Open-ILS/src/templates_cons/opac/parts/record/contents.tt2 b/Open-ILS/src/templates_cons/opac/parts/record/contents.tt2
new file mode 100644 (file)
index 0000000..0fffc9c
--- /dev/null
@@ -0,0 +1,231 @@
+[% USE  Dumper %][%-
+# You can supply a trunc_length parameter to override the default contents_truncate_length value
+contents =  [
+    {
+        label => l('General Note: '),
+        trunc_length => 100,
+        xpath => '//*[@tag="500"]'
+    }, {
+        label => l('With Note: '),
+        xpath => '//*[@tag="501"]'
+    }, {
+        display_field => 'thesis',
+        label => l('Dissertation Note: '),
+        xpath => '//*[@tag="502"]'
+    }, {
+        display_field => 'bibliography',
+        label => l('Bibliography, etc. Note: '),
+        xpath => '//*[@tag="504"]'
+    }, {
+        display_field => 'toc',
+        label => l('Formatted Contents Note: '),
+        xpath => '//*[@tag="505"]'
+    }, {
+        label => l('Restrictions on Access Note: '),
+        xpath => '//*[@tag="506"]'
+    }, {
+        label => l('Scale Note for Graphic Material: '),
+        xpath => '//*[@tag="507"]'
+    }, {
+        display_field => 'production_credits',
+        label => l('Creation/Production Credits Note: '),
+        xpath => '//*[@tag="508"]'
+    }, {
+        label => l('Citation/References Note: '),
+        xpath => '//*[@tag="510"]'
+    }, {
+        display_field => 'performers',
+        label => l('Participant or Performer Note: '),
+        xpath => '//*[@tag="511"]'
+    }, {
+        label => l('Type of Report and Period Covered Note: '),
+        xpath => '//*[@tag="513"]'
+    }, {
+        label => l('Data Quality Note: '),
+        xpath => '//*[@tag="514"]'
+    }, {
+        label => l('Numbering Peculiarities Note: '),
+        xpath => '//*[@tag="515"]'
+    }, {
+        label => l('Type of Computer File or Data Note: '),
+        xpath => '//*[@tag="516"]'
+    }, {
+        label => l('Date/Time and Place of an Event Note: '),
+        xpath => '//*[@tag="518"]'
+    }, {
+        display_field => 'abstract',
+        label => l('Summary, etc.: '),
+        xpath => '//*[@tag="520"]'
+    }, {
+        label => l('Target Audience Note: '),
+        xpath => '//*[@tag="521"]'
+    }, {
+        label => l('Geographic Coverage Note: '),
+        xpath => '//*[@tag="522"]'
+    }, {
+        label => l('Preferred Citation of Described Materials Note: '),
+        xpath => '//*[@tag="524"]'
+    }, {
+        label => l('Supplement Note: '),
+        xpath => '//*[@tag="525"]'
+    }, {
+        label => l('Study Program Information Note: '),
+        xpath => '//*[@tag="526"]'
+    }, {
+        label => l('Additional Physical Form available Note: '),
+        xpath => '//*[@tag="530"]'
+    }, {
+        label => l('Reproduction Note: '),
+        xpath => '//*[@tag="533"]'
+    }, {
+        label => l('Original Version Note: '),
+        xpath => '//*[@tag="534"]'
+    }, {
+        label => l('Location of Originals/Duplicates Note: '),
+        xpath => '//*[@tag="535"]'
+    }, {
+        label => l('Funding Information Note: '),
+        xpath => '//*[@tag="536"]'
+    }, {
+        label => l('System Details Note: '),
+        xpath => '//*[@tag="538"]'
+    }, {
+        label => l('Terms Governing Use and Reproduction Note: '),
+        xpath => '//*[@tag="540"]'
+    }, {
+        label => l('Immediate Source of Acquisition Note: '),
+        xpath => '//*[@tag="541"]'
+    }, {
+        label => l('Information Relating to Copyright Status: '),
+        xpath => '//*[@tag="542"]'
+    }, {
+        label => l('Location of Other Archival Materials Note: '),
+        xpath => '//*[@tag="544"]'
+    }, {
+        label => l('Biographical or Historical Data: '),
+        xpath => '//*[@tag="545"]'
+    }, {
+        label => l('Language Note: '),
+        xpath => '//*[@tag="546"]'
+    }, {
+        label => l('Former Title Complexity Note: '),
+        xpath => '//*[@tag="547"]'
+    }, {
+        label => l('Issuing Body Note: '),
+        xpath => '//*[@tag="550"]'
+    }, {
+        label => l('Entity and Attribute Information Note: '),
+        xpath => '//*[@tag="552"]'
+    }, {
+        label => l('Cumulative Index/Finding Aids Note: '),
+        xpath => '//*[@tag="555"]'
+    }, {
+        label => l('Information About Documentation Note: '),
+        xpath => '//*[@tag="556"]'
+    }, {
+        label => l('Ownership and Custodial History: '),
+        xpath => '//*[@tag="561"]'
+    }, {
+        label => l('Copy and Version Identification Note: '),
+        xpath => '//*[@tag="562"]'
+    }, {
+        label => l('Binding Information: '),
+        xpath => '//*[@tag="563"]'
+    }, {
+        label => l('Case File Characteristics Note: '),
+        xpath => '//*[@tag="565"]'
+    }, {
+        label => l('Methodology Note: '),
+        xpath => '//*[@tag="567"]'
+    }, {
+        label => l('Linking Entry Complexity Note: '),
+        xpath => '//*[@tag="580"]'
+    }, {
+        label => l('Publications About Described Materials Note: '),
+        xpath => '//*[@tag="581"]'
+    }, {
+        label => l('Action Note: '),
+        xpath => '//*[@tag="583"]'
+    }, {
+        label => l('Accumulation and Frequency of Use Note: '),
+        xpath => '//*[@tag="584"]'
+    }, {
+        label => l('Exhibitions Note: '),
+        xpath => '//*[@tag="585"]'
+    }, {
+        label => l('Awards Note: '),
+        xpath => '//*[@tag="586"]'
+    }, {
+        label => l('Source of Description Note: '),
+        xpath => '//*[@tag="588"]'
+    } 
+];
+
+BLOCK render_contents;
+    xpath = xpath || '//*[starts-with(@tag,"5")]';
+    FOR node IN ctx.marc_xml.findnodes(xpath);
+        all_content = [];
+        graphics = [];
+        FOR subfield IN node.childNodes;
+            NEXT UNLESS subfield.nodeName == "subfield";
+            code = subfield.getAttribute('code');
+            IF code == '6';
+               linked_fields = [subfield.textContent()];
+               target_field = node.getAttribute('tag');
+               get_linked_880s;
+            END;
+            NEXT UNLESS code.match('[a-z]');
+            all_content.push(subfield.textContent);
+        END;
+        total_contents = all_content.join(" ").replace('\s+$', '');
+        %] [% IF total_contents.size;
+            trunc_length = cont.trunc_length || contents_truncate_length || 100;
+            
+            "<div class='content_field'>"; accordion(total_contents, trunc_length); "</div>";
+        ELSE;
+            "<div class='content_field'>"; accordion(total_contents); "</div>";
+        END;
+        FOREACH link880 IN graphics;
+            '<div class="graphic880"' _ link880.dir _ '>';
+            accordion(link880.value);
+            '</div>';
+        END;
+    END;
+END;
+
+BLOCK render_all_contents;
+    FOREACH cont IN contents;
+        note_arr = [];
+        content = '';
+        df = cont.display_field;
+        trunc_length = cont.trunc_length || contents_truncate_length || 100;
+        IF df AND attrs.hl.$df.size; -%]
+            <tr>
+                <td class='rdetail_content_type'>[% cont.label %]</td>
+                <td class='rdetail_content_value' property='keywords'>
+            [%- FOREACH note IN attrs.hl.$df;
+                "<div class='content_field'>"; accordion(note, trunc_length); "</div>";
+            END -%]
+            </td></tr>
+        [%- ELSE;
+            content = PROCESS render_contents(xpath=cont.xpath);
+            IF content.match('\S'); -%]                
+                <tr>
+                    <td class='rdetail_content_type'>[% cont.label %]</td>
+                    <td class='rdetail_content_value' property='keywords'>[% content %]</td>
+                </tr>
+            [%- END;
+        END;
+    END; %]
+[%- END %]
+
+[%-  content_html = PROCESS render_all_contents;
+    IF content_html.length > 0;
+%]
+<h2 class='rdetail_contents'>[% l('Notes') %]</h2>
+<table class='rdetail_content'>
+    <tbody>
+[%- content_html %]
+    </tbody>
+</table>
+[%- END %]
diff --git a/Open-ILS/src/templates_cons/opac/parts/record/extras.tt2 b/Open-ILS/src/templates_cons/opac/parts/record/extras.tt2
new file mode 100644 (file)
index 0000000..3e8c6c5
--- /dev/null
@@ -0,0 +1,103 @@
+[%
+    arrow_right = '&#9658;';
+    arrow_down = '&#9660;';
+%]
+<div>
+    <div id='rdetail_extras_div' style='width: 100%;'> 
+        [%
+            IF ctx.google_books_preview;
+                label = l('Google Preview');
+                name = 'google_preview';
+        %]
+        <div id="gbp_extra" class="rdetail_extras hide_me">
+            <div class="rdetail_extras_hr"></div>
+            <div id="gbp_extra_links" class="rdetail_extras_link">
+                <a id='gbp_arrow_link' name='[% name %]' class='rdetail_extras_lbl'>[% arrow_right %]</a>
+                <a id='gbp_arrow_down_link' name='[% name %]' class='rdetail_extras_lbl'>[% arrow_down %]</a>
+                <a name='[% name %]_lbl' class="rdetail_extras_lbl">[% label %]</a></div>
+        </div>
+        <div id="gbp_extra_container" class='rdetail_extras_div'></div>
+        [%  END %]
+
+        [%  # Hidden extras are not yet implemented.  Some may require JS
+
+        MACRO tab_is_active(tab) BLOCK;
+            exp_name = 'expand_' _ tab;
+            IF ctx.$exp_name OR ctx.expand_all; 1; END;
+        END;
+
+        # Let's see if we should hide the content cafe / simple summary content
+        hide_summary = 1;
+        IF attrs.summaries.0; hide_summary = 0; ELSE;
+            # Expose content cafe if it's reasonable to do so.
+            # This approach only works when using embedded content cafe.
+            IF ENV.OILS_CONTENT_CAFE_USER; 
+                ident = attrs.isbn_clean || attrs.upc; 
+                IF ident; hide_summary = 0; END;
+            END;
+        END;
+
+        # if no added content is available, hide the main tab.
+        # if any content is available, use the first tab as the default display tab.
+        default_ac = '';
+        IF !tab_is_active('addedcontent');
+            hide_ac = 1;
+            FOR type IN ctx.added_content.keys;
+                IF ctx.added_content.$type.status != '2'; # not available
+                    hide_ac = 0;
+                END;
+                IF ctx.added_content.$type.status == '1';
+                    SET default_ac = type UNLESS default_ac;
+                END;
+            END;
+        END;
+
+        extras = [
+        #    {name => 'summaryplus',  label => l('Summaries & More'), hide => hide_summary},
+        #    {name => 'annotation', label => l('Annotation'), hide => 1}, 
+        #    {name => 'awards',  label => l('Awards, Reviews, & Suggested Reads')}, 
+        #    {name => 'excerpt',  label => l('Excerpt'), hide => 1},
+            {name => 'issues',   label => l('Issues Held'), hide => !(ctx.have_holdings_to_show || ctx.have_mfhd_to_show)},
+        #    {name => 'preview',  label => l('Preview'), hide => 1}, 
+        #    {name => 'addedcontent',  label => l('Additional Content'), hide => hide_ac},  # hide if all content is known to not exist
+        #    {name => 'cnbrowse', label => l('Shelf Browser')},
+            {name => 'marchtml', label => l('Bibliographic Record')}
+        ];
+
+        FOREACH extra IN extras;
+            IF extra.hide; NEXT; END; 
+            name = extra.name;
+        %]
+        <div class="rdetail_extras">
+            <div class="rdetail_extras_hr"></div>
+            <div class="rdetail_extras_link">
+                [%  
+                    IF tab_is_active(name);
+                        href = mkurl('', {}, ['expand', 'ac']);
+                        arrow = arrow_down;
+                    ELSE;
+                        IF name == 'addedcontent' AND default_ac;
+                            href = mkurl('', {expand => name, ac => default_ac}) _ '#' _ name; 
+                        ELSE;
+                            href = mkurl('', {expand => name}) _ '#' _ name; 
+                        END;
+                        arrow = arrow_right;
+                    END;
+                %]
+                <a name='[% name %]' href='[% href %]' class="rdetail_extras_lbl" rel="nofollow" vocab="">[% arrow %] [% extra.label | html %]</a>
+            </div>
+        </div>
+        <div class='rdetail_extras_div'>
+            [%  IF tab_is_active(name);
+                    IF name == 'marchtml';
+                        ctx.marchtml;
+                    ELSE;
+                        # Load the template for the selected extra
+                        INCLUDE "opac/parts/record/${name}.tt2";
+                    END;
+                END; 
+            %]
+        </div>
+        [% END %]
+    </div>
+</div>
diff --git a/Open-ILS/src/templates_cons/opac/parts/record/marcextras.tt2 b/Open-ILS/src/templates_cons/opac/parts/record/marcextras.tt2
new file mode 100644 (file)
index 0000000..f3af3a9
--- /dev/null
@@ -0,0 +1,104 @@
+[%
+    arrow_right = '&#9658;';
+    arrow_down = '&#9660;';
+%]
+<div>
+    <div id='rdetail_extras_div'> 
+        [%
+            IF ctx.google_books_preview;
+                label = l('Google Preview');
+                name = 'google_preview';
+                href = 'javascript:GBDisplayPreview();';
+        %]
+        <div id="gbp_extra" class="rdetail_extras hide_me">
+            <div class="rdetail_extras_hr"></div>
+            <div id="gbp_extra_links" class="rdetail_extras_link">
+                <a id='gbp_arrow_link' name='[% name %]' href='[% href %]' class='rdetail_extras_lbl'>[% arrow_right %]</a>
+                <a id='gbp_arrow_down_link' name='[% name %]' href='[% href %]' class='rdetail_extras_lbl hide_me'>[% arrow_down %]</a>
+                <a name='[% name %]_lbl' href='[% href %]' class="rdetail_extras_lbl">[% label %]</a></div>
+        </div>
+        <div id="gbp_extra_container" class='rdetail_extras_div'></div>
+        [%  END %]
+
+        [%  # Hidden extras are not yet implemented.  Some may require JS
+
+        MACRO tab_is_active(tab) BLOCK;
+            exp_name = 'expand_' _ tab;
+            IF ctx.$exp_name OR ctx.expand_all; 1; END;
+        END;
+
+        # Let's see if we should hide the content cafe / simple summary content
+        hide_summary = 1;
+        IF attrs.summaries.0; hide_summary = 0; ELSE;
+            # Expose content cafe if it's reasonable to do so.
+            # This approach only works when using embedded content cafe.
+            IF ENV.OILS_CONTENT_CAFE_USER; 
+                ident = attrs.isbn_clean || attrs.upc; 
+                IF ident; hide_summary = 0; END;
+            END;
+        END;
+
+        # if no added content is available, hide the main tab.
+        # if any content is available, use the first tab as the default display tab.
+        default_ac = '';
+        IF !tab_is_active('addedcontent');
+            hide_ac = 1;
+            FOR type IN ctx.added_content.keys;
+                IF ctx.added_content.$type.status != '2'; # not available
+                    hide_ac = 0;
+                END;
+                IF ctx.added_content.$type.status == '1';
+                    SET default_ac = type UNLESS default_ac;
+                END;
+            END;
+        END;
+
+        extras = [
+        #    {name => 'summaryplus',  label => l('Summaries & More'), hide => hide_summary},
+        #    {name => 'annotation', label => l('Annotation'), hide => 1}, 
+        #    {name => 'awards',  label => l('Awards, Reviews, & Suggested Reads')}, 
+        #    {name => 'excerpt',  label => l('Excerpt'), hide => 1},
+        #    {name => 'issues',   label => l('Issues Held'), hide => !(ctx.have_holdings_to_show || ctx.have_mfhd_to_show)},
+        #    {name => 'preview',  label => l('Preview'), hide => 1}, 
+        #    {name => 'addedcontent',  label => l('Additional Content'), hide => hide_ac},  # hide if all content is known to not exist
+        #    {name => 'cnbrowse', label => l('Shelf Browser')},
+            {name => 'marchtml', label => l('Bibliographic Record')}
+        ];
+
+        FOREACH extra IN extras;
+            IF extra.hide; NEXT; END; 
+            name = extra.name;
+        %]
+        <div class="rdetail_extras">
+            <div class="rdetail_extras_hr"></div>
+            <div class="rdetail_extras_link">
+                [%  
+                    IF tab_is_active(name);
+                        href = mkurl('', {}, ['expand', 'ac']);
+                        arrow = arrow_down;
+                    ELSE;
+                        IF name == 'addedcontent' AND default_ac;
+                            href = mkurl('', {expand => name, ac => default_ac}) _ '#' _ name; 
+                        ELSE;
+                            href = mkurl('', {expand => name}) _ '#' _ name; 
+                        END;
+                        arrow = arrow_right;
+                    END;
+                %]
+                <a name='[% name %]' href='[% href %]' class="rdetail_extras_lbl">[% arrow %] [% extra.label | html %]</a>
+            </div>
+        </div>
+        <div class='rdetail_extras_div'>
+            [%  IF tab_is_active(name);
+                    IF name == 'marchtml';
+                        ctx.marchtml;
+                    ELSE;
+                        # Load the template for the selected extra
+                        INCLUDE "opac/parts/record/${name}.tt2";
+                    END;
+                END; 
+            %]
+        </div>
+        [% END %]
+    </div>
+</div>
diff --git a/Open-ILS/src/templates_cons/opac/parts/result/lowhits.tt2 b/Open-ILS/src/templates_cons/opac/parts/result/lowhits.tt2
new file mode 100644 (file)
index 0000000..9e26c01
--- /dev/null
@@ -0,0 +1,80 @@
+<div>
+    <div id="zero_search_hits">
+        <div class="facet_sidebar_hidden" id="facet_sidebar">
+          <h3 class="sr-only">[% l('Search Results filters') %]</h3>
+        </div>
+        <div class="zero_search_hits_saved">
+            [% INCLUDE "opac/parts/staff_saved_searches.tt2" %]
+        </div>
+        <div class="zero_search_hits_main">
+            <p>[% qhtml = CGI.param('query') | html;
+                  IF ctx.bookbag;
+                      wbbag = ctx.bookbag.name | html;
+                      fmt_bookbag = '<span class="lowhits-bookbag-name">' _ wbbag _ '</span>';
+                       IF is_advanced OR is_special;
+                         l('Sorry, no entries were found for your search within [_1].', fmt_bookbag);
+                       ELSE;
+                          l('Sorry, no entries were found for [_1] within [_2].', '<q>' _ qhtml _ '</q>', fmt_bookbag);
+                       END;
+                   ELSE;
+                     IF is_advanced OR is_special;
+                          l('Sorry, no entries were found for your search.');
+                       ELSE;
+                          IF !qhtml;
+                             l('Please enter a search term in the Search box.');
+                          ELSE;
+                             l('Sorry, no entries were found for [_1].', '<q>' _ qhtml _ '</q>');
+                          END;
+                       END;
+                   END %]
+            </p>
+            [% IF ctx.search_summary.suggestions.one_class_one_term %]
+            <div class="result_block_visible refine_search" id="did_you_mean">
+                <em><strong>[% s_list = ctx.search_summary.suggestions.one_class_one_term; l('Did you mean: ') %]</strong></em>
+                [% FOREACH s IN s_list.suggestions %]
+                    [% IF !loop.first(); l('or'); END %]
+                    <a href="[% mkurl(ctx.opac_root _ '/results', {qtype=>s_list.class, query=>s.suggestion}) %]">[% s.suggestion | html %]</a>
+                [% END %]
+            </div>
+            <br/>
+            [% END %]
+        </div>
+        <div style="float:right;width:353px;background:#ccc;padding:10px;margin-top:7px;">
+
+
+            [% INCLUDE "opac/parts/result/lowhits_purchase.tt2" %]
+            <p>
+                <strong>[% l('Keyword Search Tips') %]</strong><br />
+               [% i18n_advsearch = l('Advanced Search');
+                   l('Try changing to [_1].', '<strong>' _ i18n_advsearch _ '</strong>') %]
+            </p>
+            <p>
+                <strong>[% l('Adjacency') %]</strong><br />
+                [% l('Multiple words are not searched together as a phrase. They will ' _
+                    'be found in various parts of the record. To search for a phrase, enclose your ' _
+                    'search terms in quotation marks.') %]<br />
+               [% i18n_searchphrase = l('garcia marquez');
+                   l('(example: [_1])', '<strong>&quot;' _ i18n_searchphrase _ '&quot;</strong>') %]
+            </p>
+            <p>
+                <strong>[% l('Truncation') %]</strong><br />
+                [% l('Words may be right-hand truncated using an asterisk. Use a single asterisk * ' _
+                    'to truncate any number of characters.') %]<br />
+               [% i18n_searchtrunc = l('environment* agency');
+                   l('(example: [_1])', '<strong>' _ i18n_searchtrunc _ '</strong>') %]
+            </p>
+            <p>
+                <strong>[% l('Anchored Searching') %]</strong><br />
+                [% l('You may use ^ and $ to indicate "phrase begins with" and ' _
+                    '"phrase ends with," respectively, within a search phrase ' _
+                    'enclosed in quotation marks.') %]<br />
+               [% i18n_searchbegins = l('harry');
+                  i18n_searchends = l('stone');
+                   l('(examples: [_1] for phrases that begin with the term [_2]. ' _
+                     '[_3] for phrases that end in [_4].)',
+                    '<strong>&quot;^' _ i18n_searchbegins _ '&quot;</strong>', '<em>' _ i18n_searchbegins _ '</em>',
+                    '<strong>&quot;' _ i18n_searchends _ '$&quot;</strong>', '<em>' _ i18n_searchends _ '</em>') %]
+            </p>
+        </div>
+    </div>
+</div>
diff --git a/Open-ILS/src/templates_cons/opac/parts/topnav.tt2 b/Open-ILS/src/templates_cons/opac/parts/topnav.tt2
new file mode 100644 (file)
index 0000000..23a9787
--- /dev/null
@@ -0,0 +1,99 @@
+[%- IF ctx.maintenance_message -%]
+<div id="maintenance_message">[% ctx.maintenance_message %]</div>
+[%- END -%]
+[% IF !ctx.is_staff && !ctx.readonly %]
+<div id="header-wrap">
+<div id="header">
+    <div class="float-left">
+        [% INCLUDE "opac/parts/topnav_logo.tt2" %]
+    </div>
+    <div class="float-right">
+        [% IF !ctx.user %]
+        <div id="your-acct-login">
+            <a href="[% mkurl(ctx.opac_root _ '/myopac/main') %]" 
+                class="opac-button opac-button-header" id="home_myopac_link">
+                [% l('Log into My Account') %]
+            </a>
+        </div>
+        [% ELSE %]
+        <div id="dash_wrapper">
+            <div id="dash_identity">
+                <span id="dash_user">
+                    [%  l('[_1] [_2]', 
+                      (ctx.user.pref_first_given_name || ctx.user.first_given_name), 
+                      (ctx.user.pref_family_name || ctx.user.family_name)
+                    ) | html %]
+                </span>
+                <span class="dash_divider">|</span>
+                <span class="dash_account_buttons">
+                <div id="dash_user_message_button_container">
+                    <a href="[% mkurl(ctx.opac_root _ '/myopac/messages', {}, ['single', 'message_id', 'hid']) %]" class="opac-button">
+                        [% l('Messages') %]
+                    </a>
+                    [% IF ctx.user_stats.messages.unread %]
+                        <div id="unread_message_count_floater">
+                            [%- ctx.user_stats.messages.unread -%]
+                            <span class="sr-only">[% l('unread') %]</a>
+                        </div>
+                    [% END %]
+                </div>
+                <a href="[% mkurl(ctx.opac_root _ '/myopac/main', {}, ['single', 'message_id', 'sort','sort_type', 'hid']) %]"
+                    class="opac-button">[% l('My Account') %]</a>
+                <a href="[% mkurl(ctx.opac_root _ '/myopac/lists', {}, ['single', 'message_id', 'hid', 'from_basket']) %]"
+                    class="opac-button">[% l('My Lists') %]</a>
+                <a href="[% mkurl(ctx.opac_root _ '/logout', {active_logout => 1}, 1) %]"
+                    class="opac-button" id="logout_link">[% l('Logout') %]</a>
+                </span>
+            </div>
+            <div id="dashboard">
+                <span class="dash-align">
+                    <a class="dash-link" href="[% mkurl(ctx.opac_root _ '/myopac/circs', {}, 
+                        ['limit','offset', 'single', 'message_id', 'sort','sort_type', 'hid'])
+                        %]"><span id="dash_checked">[% ctx.user_stats.checkouts.total_out
+                        %]</span> [% l("Checked Out") %]</a>
+                </span>
+                <span class="dash_divider">|</span>
+                <span class="dash-align">
+                    <a class="dash-link" href="[% mkurl(ctx.opac_root _ '/myopac/holds', {}, 
+                        ['available', 'single', 'message_id', 'sort','sort_type', 'hid'])
+                        %]"><span id="dash_holds">[% ctx.user_stats.holds.total
+                        %]</span> [% l("On Hold") %]</a>
+                </span>
+                <span class="dash_divider">|</span>
+                <span class="dash-align">
+                    <a class="dash-link" href="[% mkurl(ctx.opac_root _ '/myopac/holds',
+                        {available => 1}, ['single', 'message_id', 'sort','sort_type', 'hid']) %]"><span id="dash_pickup">[%
+                        ctx.user_stats.holds.ready %]</span> [% l("Ready for Pickup") %]</a>
+                </span>
+                <span class="dash_divider">|</span>
+                <span class="dash-align">
+                    <a class="dash-link" href="[% mkurl(ctx.opac_root _ '/myopac/main', {}, ['single', 'message_id', 'sort','sort_type', 'hid'])
+                        %]"><span id="dash_fines">[% money(ctx.user_stats.fines.balance_owed)
+                        %]</span> [% l("Fines") %]</a>
+                </span>
+            </div>
+            <div id="dashboard_e" class="hidden">
+                <span class="dash-align">
+                    <a class="dash-link" href="[% mkurl(ctx.opac_root _ '/myopac/ebook_circs')
+                        %]"><span id="dash_e_checked">-</span> [% l("E-Items Checked Out") %]</a>
+                </span>
+                <span class="dash_divider">|</span>
+                <span class="dash-align">
+                    <a class="dash-link" href="[% mkurl(ctx.opac_root _ '/myopac/ebook_holds')
+                        %]"><span id="dash_e_holds">-</span> [% l("E-Items on Hold") %]</a>
+                </span>
+                <span class="dash_divider">|</span>
+                <span class="dash-align">
+                    <a class="dash-link" href="[% mkurl(ctx.opac_root _ '/myopac/ebook_holds_ready')
+                        %]"><span id="dash_e_pickup">-</span> [% l("E-Items Ready for Checkout") %]</a>
+                </span>
+            </div>
+        </div>
+        [% END %]
+    </div>
+    [%- INCLUDE "opac/parts/locale_picker.tt2" %]
+    <div class="common-no-pad"></div>
+</div>
+</div>
+[% INCLUDE "opac/parts/topnav_links.tt2" %]
+[% END %]
diff --git a/Open-ILS/src/templates_cons/opac/parts/topnav_links.tt2 b/Open-ILS/src/templates_cons/opac/parts/topnav_links.tt2
new file mode 100644 (file)
index 0000000..e862d5e
--- /dev/null
@@ -0,0 +1,16 @@
+<div id="gold-links-holder">
+    <div id="gold-links">
+    <div id="header-links">
+    <a href="https://www.cwmars.org/explore/new-titles" target="_blank" rel="noopener">
+       New Titles at Your Library
+    </a>
+    &nbsp;|&nbsp;
+    <a href="https://www.cwmars.org/explore/most-requested-titles" target="_blank" rel="noopener">
+       Popular Titles
+    </a>
+    &nbsp;|&nbsp;
+    <a href="http://catalog.cwmars.org/eg/kpac/home">Kids Catalog</a>
+    </div>
+    </div>
+</div>
+
diff --git a/Open-ILS/src/templates_cons/opac/parts/topnav_logo.tt2 b/Open-ILS/src/templates_cons/opac/parts/topnav_logo.tt2
new file mode 100644 (file)
index 0000000..40d87ec
--- /dev/null
@@ -0,0 +1,2 @@
+       <div id="topnav_logo"> <a href="/"><img id="topnav_logo_image" alt="[% l('Evergreen Logo') %]" 
+            src="[% ctx.media_prefix %]/opac/images/small_logo[% ENV.OILS_OPAC_LIBRARY_ID %].png[% ctx.cache_key %]" /></a></div>
diff --git a/Open-ILS/src/templates_cons/opac/password_reset.tt2 b/Open-ILS/src/templates_cons/opac/password_reset.tt2
new file mode 100644 (file)
index 0000000..ef39b73
--- /dev/null
@@ -0,0 +1,78 @@
+[%- PROCESS "opac/parts/header.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l('Library system password reset request form');
+-%]
+<h2 class="sr-only">[% l('Reset Password') %]</h2>
+<div class="mobile_hide">
+[% INCLUDE "opac/parts/searchbar.tt2" %]
+</div>
+
+[%  
+    uuid = ctx.page_args.0;
+    msg_map = {
+        SUCCESS => l('Password has been reset'),
+        NO_MATCH => l('Passwords did not match. Please try again'),
+        NOT_ACTIVE => l('This was not an active password reset request. Your password has not been reset.'),
+        NOT_STRONG => l('The password you chose was not considered complex enough to protect your account. Your password has not been reset.'),
+        TWO_PASSWORDS => l('Please enter and repeat your new password.'),
+        REQUEST_SUCCESS => l('Your barcode or user name has been submitted for a password reset. ' _ 
+            'An email will be sent to the email address in your library account with instructions on resetting your password. If you do not receive an email within 30 minutes, please contact your library for assistance.')
+    }
+%]
+<div id="content-wrapper">
+    <div id="main-content">
+        <br/>
+        <p class='[% ctx.pwreset.style %]'>[% stat = ctx.pwreset.status; msg_map.$stat %]</p>
+        [% IF uuid %]
+            [% IF stat == 'SUCCESS' %]
+                <p><a href='[% mkurl(ctx.opac_root _ '/myopac/main', {}, 1) %]'>[% l('Log in to My Account') %]</a>
+            [% ELSE %]
+            <form method="post">
+                <input type='hidden' name='uuid' value='[% uuid | html %]'/>
+                <table>
+                    <tr>
+                        <td><label for="pwd1">[% l('New password:') %]</label></td>
+                        <td><input type="password" name="pwd1"/></td>
+                    </tr>
+                    <tr>
+                        <td><label for="pwd2">[% l('Re-enter new password:') %]</label></td>
+                        <td><input type="password" name="pwd2"/></td>
+                    </tr>
+                    <tr>
+                        <td>
+                            <button name="submit" class="opac-button" id="submitButton" type="submit">[% l('Submit') %]</button>
+                        </td>
+                    </tr>
+                </table>
+            </form>
+            [% END %]
+        [% ELSIF !ctx.pwreset.status %]
+        <h2>[% l('Please enter your library card number <strong> OR</strong> user name to identify your library account and request a password reset') %]</h2>
+
+        <form method="post">
+            <table>
+                <tr>
+                    <td><label for="barcode">[% l('Library Card Number:') %] </label></td>
+                    <td><input type="text" id="barcode" name="barcode"/></td>
+                </tr>
+                <tr>
+                    <td colspan="2"><strong>OR</strong></td>
+                <tr>
+                    <td><label for="username">[% l('User name:') %] </label></td>
+                    <td><input type="text" id="username" name="username"/></td>
+                </tr>
+                <tr>
+                    <td colspan="2">Enter one <strong>or</strong> the other. You do not need both.</td>
+                </tr>
+            </table>
+            [% IF ctx.get_org_setting(ctx.physical_loc || ctx.aou_tree.id, 'circ.password_reset_request_requires_matching_email') %]
+            <label for="email">[% l('Email address associated with the account:') %] </label><input type="text" name="email"/><br/>
+            [% END %]
+            <button name="submit" id="submitButton" class="opac-button" type="submit">[% l('Submit') %]</button>
+        </form>
+        [% INCLUDE "opac/password_reset_msg.tt2" %]
+        [% END %]
+    </div>
+</div>
+[%- END %]
diff --git a/Open-ILS/src/templates_cons/opac/password_reset_msg.tt2 b/Open-ILS/src/templates_cons/opac/password_reset_msg.tt2
new file mode 100644 (file)
index 0000000..b939fee
--- /dev/null
@@ -0,0 +1,3 @@
+<div class="password_message">
+[% l('Note: An email will be sent with instructions on resetting your password. You must have a valid email address associated with your library account. The reset email may take up to 30 minutes to arrive.<br />If you have any additional questions, please contact your local library for further assistance.'); %]
+</div>
diff --git a/Open-ILS/src/templates_cons/opac/register.tt2 b/Open-ILS/src/templates_cons/opac/register.tt2
new file mode 100644 (file)
index 0000000..fb82fd5
--- /dev/null
@@ -0,0 +1,257 @@
+[%- PROCESS "opac/parts/header.tt2";
+    PROCESS "opac/parts/org_selector.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Request Library Card");
+
+# for privacy, reload the page after (default) 5 minutes
+refresh_time = ctx.register.settings.refresh_timeout || 300; 
+ctx.refresh = refresh_time _ '; ' _ ctx.opac_root _ '/home';
+
+# some useful variables and MACROs for display, 
+# field validation, and added info display
+
+ctx_org = ctx.physical_loc || ctx.search_ou || ctx.aou_tree.id;
+
+# list of the registration fields to (potentially) 
+# display in the order they should be shown
+
+# post_code is the only field below that is required in the database and
+# post_code is only required if an address is created.
+# To prevent any of these fields from showing locally, regardless org unit
+# settings, simply remove the fields from this list.  In the case of 
+# addresses, if all address fields are removed, no attempt at creating
+# an address will be made (and post_code will no longer be required).
+
+register_fields = [
+    {class => 'stgu',  name = 'first_given_name', label => l('First Name')},
+    {class => 'stgu',  name = 'second_given_name', label => l('Middle Name')},
+    {class => 'stgu',  name = 'family_name', label => l('Last Name')},
+    {class => 'stgu',  name = 'pref_first_given_name', label => l('Preferred First Name')},
+    {class => 'stgu',  name = 'pref_second_given_name', label => l('Preferred Middle Name')},
+    {class => 'stgu',  name = 'pref_family_name', label => l('Preferred Last Name')},
+    {class => 'stgma', name = 'street1', label => l('Street Address')},
+    {class => 'stgma', name = 'street2', label => l('Street Address (2)')},
+    {class => 'stgma', name = 'city', label => l('City')},
+    {class => 'stgma', name = 'county', label => l('County')},
+    {class => 'stgma', name = 'state', label => l('State')},
+    {class => 'stgma', name = 'post_code', label => l('Zip Code')},
+    {class => 'stgu',  name = 'dob', label => l('Date of Birth')},
+    {class => 'stgu',  name = 'day_phone', label => l('Phone Number')},
+    {class => 'stgu',  name = 'email', label => l('Email Address')}
+    {class => 'stgu',  name = 'usrname', label => l('Requested Username')}
+];
+
+# The dojo date widget in the patron edit UI only accepts default 
+# values in ISO8601 format.  It will not accept locale-shaped dates.
+# Force change it for this form:
+ctx.register.settings.stgu.dob.example = l('YYYY-MM-DD (1970-05-29)');
+
+%]
+
+<style type="text/css">
+#stgu\.first_given_name, #stgu\.second_given_name, #stgu\.family_name,
+ #stgu\.pref_first_given_name, #stgu\.pref_second_given_name,
+ #stgu\.pref_family_name, #stgma\.street1, #stgma\.street2, #stgma\.city,
+ #stgma\.county, #stgma\.state, #stgma\.post_code {
+ text-transform: uppercase;
+}
+</style>
+<h2 class="sr-only">[% l('Account Registration') %]</h2>
+<div id="content-wrapper">
+    <div id="main-content-register">
+        <div class="common-full-pad"></div>
+        <h1>[% l('Request a Library Card')%]</h1>
+        <hr/>
+
+        [% IF ctx.register.success %]
+            <h3>Thank you for submitting your request for a library card!<h3>
+            <h4>Please allow time for a library staff member to review your application
+and reach out with next steps. If you have any questions or concerns,
+please contact your <a href="https://www.cwmars.org/memberlibraries">library.</a></h4>
+
+            [% IF ctx.register.username_taken %]
+            <p>
+                [% |l %]
+                Note: The selected username may be in use by another patron.  
+                You may select another username when finalizing your 
+                registration or in the online catalog.
+                [% END %]
+            </p>
+            [% END %]
+
+            <br/>
+            <p>
+                <a href="[% ctx.opac_root %]/home" 
+                    class="opac-button">[% l('Return to the Catalog') %]</a>
+            </p>
+
+        [% ELSIF ctx.register.error %]
+            <h3>[% l('A registration error has occurred') %]</h3>
+            <h4>[% l('Please see library staff to complete your registration.') %]</h4>
+
+            <br/>
+            <p>
+                <a href="[% ctx.opac_root %]/home" 
+                    class="opac-button">[% l('Return to the Catalog') %]</a>
+            </p>
+
+        [% ELSE %]
+
+        [% IF ctx.user %]
+            <!-- if the user is logged in, make it 
+                clear we are tracking the requestor -->
+            <h4>[% l('New account requested by [_1] [_2] [_3] [_4] [_5]',
+                    ctx.user.prefix, ctx.user.first_given_name,
+                    ctx.user.second_given_name, ctx.user.family_name,
+                    ctx.user.suffix
+                ) | html %]</h4>
+        [% END %]
+
+        [%
+            #prepopulate org selector on refresh or error
+            cgi_org = CGI.param('stgu.home_ou') | html;
+            IF cgi_org && ctx.register.valid_orgs.grep("^$cgi_org$").size;
+                prepopulate_org = cgi_org;
+            END
+        %]
+
+        <form method='POST' onSubmit="return dobValidate(document.getElementById('stgu.dob'))">
+            <table>
+                <tr>
+                    <td>
+                        <label for='stgu.home_ou'>[% l('Home Library') %]</label>
+                    </td>
+                    <td>[% INCLUDE build_org_selector 
+                            name='stgu.home_ou' 
+                            value=value || prepopulate_org || ctx_org
+                            can_have_users_only=1
+                            valid_org_list=ctx.register.valid_orgs
+                        %]
+                    </td>
+                    <td>
+                        [% IF ctx.register.invalid.bad_home_ou %]
+                        <span class='patron-reg-invalid'>
+                            [% l('Please select a valid library') %]
+                        </span>
+                        [% END %]
+                </tr>
+[%
+# <=== shifting code left for readability
+
+# render the table row for each of the register fields
+FOR field_def IN register_fields;
+    fclass = field_def.class;
+    fname = field_def.name;
+    orig_name = fname;
+
+    field_path = fclass _ "." _ fname;
+
+    IF fname.match('^pref_');
+        # Preferred name fields adopt most visibility, etc.
+        # settings from the primary name counterparts.
+        fname = fname.remove('^pref_');
+    END;
+
+    show = ctx.register.settings.$fclass.$fname.show;
+    require = ctx.register.settings.$fclass.$fname.require;
+    example = ctx.register.settings.$fclass.$fname.example;
+    value = ctx.register.values.$fclass.$fname;
+
+    invalid_require = ctx.register.invalid.$fclass.$fname.require;
+    invalid_regex = ctx.register.invalid.$fclass.$fname.regex;
+
+    IF orig_name.match('^pref_');
+        show = show || require;
+        require = 0; # pref name values never required
+    END;
+
+    NEXT UNLESS require OR show;
+%]
+<tr>
+    <td>
+        <label for='[% field_path %]'>[% field_def.label | html %]</label>
+    </td>
+    <td>
+        <input 
+            type='text'
+            id='[% field_path %]'
+            name='[% field_path %]'
+            value='[% value || CGI.param(field_path) | html %]'/>
+        [% IF require %]
+        <span class='patron-reg-invalid'>*</span>
+        [% END %]
+    </td>
+    <td>
+
+    <!-- display errors and example text -->
+
+    [% IF invalid_require %]
+        <span class='patron-reg-invalid'>
+            [% l('This field is required') %]
+        </span>
+    [% ELSIF invalid_regex %]
+        <span class='patron-reg-invalid'>
+            [% l('The value entered does not have the correct format') %]
+        </span>
+    [% END %]
+    [% IF example %]
+        <span class='patron-reg-extra'>
+            [% l('(Example: [_1])', example) %]
+        </span>
+    [% END %]
+
+    </td>
+</tr>
+[% END %]
+<!-- ====> shifting the code back to the right for context -->
+                    [% IF ctx.register.opt_in_settings.size > 0 %]
+                        [% FOR optin IN ctx.register.opt_in_settings %]
+                        <tr>
+                            <td><label for="stgs.[% optin.name | uri %]'">[% optin.label | html %]</label></td>
+                            <td>
+                                <input type='checkbox'
+                                    name='stgs.[% optin.name | uri %]'
+                                    id='stgs.[% optin.name | uri %]'
+                                    title="[% optin.label | html %]"
+                                ></input>
+                            </td>
+                            <td><!-- display errors and example text --></td>
+                        </tr>
+                        [% END %]
+                    [% END %]
+                    <tr>
+                    <td colspan='3'>
+                    <p style="font-size: 120%;"><strong>
+                    Submit this form to request a library card from
+                    your local library.</strong></p>
+                    <p style="font-size: 120%;"><strong> By
+                    submitting, you understand and agree to the <a target="_blank" rel="noopener"
+                    href="https://www.cwmars.org/about/borrowing-lending">CW
+                    MARS shared network policies</a><br>as well as any
+                    <a href="https://www.cwmars.org/memberlibraries" target="_blank" rel="noopener">local library</a> policies, rules, and regulations.
+                    </strong></p>
+                    <p style="font-size: 120%;"><strong>
+                    Please ensure you have entered at least one form
+                    of contact (phone number and/or email address),<br>
+                    so that staff at your local library can follow up
+                    as necessary.
+                    </strong></p>
+                    </td>
+                    </tr>
+                    <tr>
+                        <td colspan='3'>
+                            <a href="[% ctx.opac_root %]/home" 
+                                class="opac-button">[% l('Go Back') %]</a>
+                            <input type="submit" 
+                                value="[% l('Submit Registration') %]" 
+                                class="opac-button" />
+                        </td>
+                    </tr>
+                </table>
+            </form>
+            [% END %]
+            <div class="common-full-pad"></div>        
+        </div>
+    </div>
+[%- END %]
diff --git a/Open-ILS/src/templates_cons/staff/cat/item/t_circ_list_pane.tt2 b/Open-ILS/src/templates_cons/staff/cat/item/t_circ_list_pane.tt2
new file mode 100644 (file)
index 0000000..5165571
--- /dev/null
@@ -0,0 +1,70 @@
+<div class="col-md-12" ng-show="!isMaxCircHistoryZero && circ_list.length == 0">
+  <div class="alert alert-info">
+    [% l('Item has not circulated.') %]
+  </div>
+</div>
+<div class="col-md-12" ng-show="isMaxCircHistoryZero">
+  <div class="alert alert-info">
+    [% l('Circulation History not available for display.') %]
+  </div>
+</div>
+<div class="row" ng-show="!isMaxCircHistoryZero && circ_list.length">
+  <div class="flex-row">
+      <div class="flex-cell well">
+          <button class="btn btn-default" ng-click="retrieveAllPatrons()">
+            [% l('Retrieve All These Patrons') %]
+          </button>
+      </div>
+  </div>
+</div>
+
+
+<div class="row" ng-show="!isMaxCircHistoryZero" ng-repeat="circ in circ_list">
+  <div class="flex-row">
+    <div class="flex-cell well">
+      <a ng-if="circ.usr()" target="_self"
+        href="./circ/patron/{{circ.usr().id()}}/checkout">
+        [% l('[_1], [_2] [_3] : [_4]', 
+          '{{circ.usr().family_name()}}'
+          '{{circ.usr().first_given_name()}}'
+          '{{circ.usr().second_given_name()}}'
+          '{{circ.usr().card().barcode()}}') %]
+      </a>
+      <span ng-if="!circ.usr()">[% l('<Aged Circulation>') | html %]</span>
+      <span class="pad-horiz">[% l('Circulation ID: [_1]', '{{circ.id()}}') %]</span>
+    </div>
+    <div>
+      <button class="btn btn-default" ng-click="addBilling(circ)" 
+        ng-disabled="!circ.usr()">
+        [% l('Add Billing') %]
+      </button>
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Check Out Date') %]</div>
+    <div class="flex-cell well">{{circ.xact_start() | date:egDateAndTimeFormat}}</div>
+    <div class="flex-cell">[% l('Due Date') %]</div>
+    <div class="flex-cell well">{{circ.due_date() | egDueDate:egDateAndTimeFormat:circ.circ_lib():circ.duration()}}</div>
+    <div class="flex-cell">[% l('Stop Fines Time') %]</div>
+    <div class="flex-cell well">{{circ.stop_fines_time() | date:egDateAndTimeFormat}}</div>
+    <div class="flex-cell">[% l('Checkin Time') %]</div>
+    <div class="flex-cell well">{{circ.checkin_time() | date:egDateAndTimeFormat}}</div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Check Out Library') %]</div>
+    <div class="flex-cell well">{{circ.circ_lib().shortname()}}</div>
+    <div class="flex-cell">[% l('Renewal?') %]</div>
+    <div class="flex-cell well">{{
+      circ.phone_renewal() == 't' ||
+      circ.desk_renewal() == 't' ||
+      circ.opac_renewal() == 't' ||
+      circ.auto_renewal() == 't'
+    }}</div>
+    <div class="flex-cell">[% l('Stop Fines Reason') %]</div>
+    <div class="flex-cell well">{{circ.stop_fines()}}</div>
+    <div class="flex-cell">[% l('Check In Library') %]</div>
+    <div class="flex-cell well">{{circ.checkin_lib().shortname()}}</div>
+  </div>
+  <hr/>
+</div>
+
diff --git a/Open-ILS/src/templates_cons/staff/circ/patron/t_bills.tt2 b/Open-ILS/src/templates_cons/staff/circ/patron/t_bills.tt2
new file mode 100644 (file)
index 0000000..5cf2166
--- /dev/null
@@ -0,0 +1,130 @@
+
+<div class="row">
+  <div class="col-md-7">
+
+    <div class="row">
+      <div class="col-md-4">[% l('Total Owed:') %]</div>
+      <div class="col-md-2 strong-text">{{(summary.balance_owed() || 0) | currency}}</div>
+      <div class="col-md-4">[% l('Refunds Available:') %]</div>
+      <div class="col-md-2">{{refunds_available() | currency}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-4">[% l('Total Billed:') %]</div>
+      <div class="col-md-2">{{(summary.total_owed() || 0) | currency}}</div>
+      <div class="col-md-4">[% l('Credit Available:') %]</div>
+      <div class="col-md-2">{{patron().credit_forward_balance() | currency}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-4">[% l('Total Paid/Credited:') %]</div>
+      <div class="col-md-2">{{(summary.total_paid() || 0) | currency}}</div>
+      <div class="col-md-4">[% l('Session Voided:') %]</div>
+      <div class="col-md-2">{{session_voided | currency}}</div>
+    </div>
+    <div class="row"><hr/></div>
+    <div class="row">
+      <div class="col-md-4">[% l('Owed for Selected:') %]</div>
+      <div class="col-md-2">{{owed_selected() | currency}}</div>
+      <div class="col-md-4">[% l('Pending Payment:') %]</div>
+      <div class="col-md-2 strong-text">{{pending_payment() | currency}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-4">[% l('Billed for Selected:') %]</div>
+      <div class="col-md-2">{{billed_selected() | currency}}</div>
+      <div class="col-md-4">[% l('Pending Change:') %]</div>
+      <div class="col-md-2 strong-text">{{pending_change() | currency}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-4">[% l('Paid/Credited for Selected:') %]</div>
+      <div class="col-md-2">{{paid_selected() | currency}}</div>
+    </div>
+  </div><!-- col -->
+
+  <div class="col-md-5">
+    <form role="form" class="form-horizontal" ng-submit="applyPayment()">
+      <fieldset>
+        <legend>[% l('Pay Bill') %]</legend>
+
+        <div class="form-group">
+          <label for="type-input" class="col-md-6 control-label">[% l('Payment Type') %]</label>
+          <div class="col-md-6">
+            <select ng-model="payment_type" class="form-control">
+              <option value="cash_payment" selected="selected">[% l('Cash') %]</option>
+              <option value="check_payment">[% l('Check') %]</option>
+              <option value="credit_payment">[% l('Patron Credit') %]</option>
+              <option value="work_payment">[% l('Work') %]</option>
+              <option value="forgive_payment">[% l('Forgive') %]</option>
+              <option value="goods_payment">[% l('Goods') %]</option>
+            </select>
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="check-input" class="col-md-6 control-label">
+            [% l('Check Number') %]
+          </label>
+          <div class="col-md-6">
+            <input type="number" min="1" step="any" id="check-input" 
+              ng-model="check_number" focus-me="focus_check"
+              ng-disabled="payment_type!='check_payment'"
+              value="" class="form-control col-md-6 "/>
+          </div>
+        <div class="form-group">
+          <label for="amount-input" class="col-md-6 control-label">
+            [% l('Payment Received') %]
+          </label>
+          <div class="col-md-6">
+            <input type="number" min="0" step="any" id="amount-input" 
+              ng-model="payment_amount" focus-me="focus_payment" 
+              value="" class="form-control col-md-6 "/>
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="annotate-payment" class="control-label col-md-5">[% l('Annotate') %]</label>
+          <div class="col-md-1">
+            <input id="annotate-payment" type="checkbox" ng-model="annotate_payment" ng-change="onAnnotatePaymentChanged()"/>
+          </div>
+          <div class="col-md-6">
+            <button
+                type="submit"
+                class="btn btn-default"
+                ng-disabled="!payment_amount || invalid_check_number() || !gridControls.selectedItems().length || applyingPayment"
+            >[% l('Apply Payment') %]</button>
+          </div>
+        </div>
+      </fieldset>
+    </form>
+  </div>
+</div>
+
+<div class="pad-vert">
+[% INCLUDE 'staff/circ/patron/t_bills_list.tt2' %]
+</div>
+
+<!-- pull-right is causing the content to flow several pixels 
+off to the right.  flex-row is honoring the boundaries better. 
+not sure what's up, there. -->
+<div class="flex-row" ng-show="!disable_auto_print">
+  <div class="flex-cell"></div>
+  <div ng-hide="disablePatronCredit" class="pad-right">
+    <div class="checkbox">
+      <label>
+        <input type="checkbox" ng-model="convert_to_credit.isChecked">
+        [% l('Convert Change to Patron Credit') %]
+      </label>
+    </div>
+  </div>
+  <form class="form-inline" role="form">
+   <div class="checkbox">
+      <label>
+        <input id="receipt_on_pay" type="checkbox" ng-model="receipt_on_pay.isChecked" ng-change="onReceiptOnPayChanged()"/>
+        [% l('Receipt On Payment') %]
+      </label>
+    </div>
+    <div class="form-group" style="margin-left:10px">
+      <label for="bill-receipt-copies">[% l('# Copies') %]</label>
+      <input type="number" min="1" style="width:5em"
+        ng-model="receipt_count"
+        class="form-control" id="bill-receipt-copies"/>
+    </div>
+  </form>
+</div>
+
diff --git a/Open-ILS/src/templates_cons/staff/circ/patron/t_edit.tt2 b/Open-ILS/src/templates_cons/staff/circ/patron/t_edit.tt2
new file mode 100644 (file)
index 0000000..ba72496
--- /dev/null
@@ -0,0 +1,1221 @@
+[% DOC_IMG = '/images/question-mark.png' %]
+
+<!-- register banner -->
+<div ng-if="!patron_id" ng-class='{"patron-reg-fixed-bar":!offline}'>
+
+  <div class="container-fluid" style="text-align:center">
+    <div class="alert alert-info alert-less-pad strong-text-2">
+      <span >[% l('Register Patron') %]</span>
+    </div>
+  </div>
+
+  <div class="flex-row" class='patron-reg-actions-bar'>
+    [% INCLUDE 'staff/circ/patron/reg_actions.tt2' %]
+  </div>
+</div>
+
+
+<!-- edit banner -->
+<div ng-if="patron_id"
+    class="strong-text-2">[% l('Patron Edit') %]</div>
+
+<div id="reg-alert-pane">
+
+  <div id="reg-dupe-links">
+    [%# dupe_search_encoded is uri escaped in the JS %]
+    <div class="alert alert-danger" ng-show="dupe_counts.name">
+      <a target="_blank"
+        href="/eg/staff/circ/patron/search?search={{dupe_search_encoded.name}}&inactive=1">
+      [% l('[_1] patron(s) with same name', '{{dupe_counts.name}}') %]
+      </a>
+    </div>
+    <div class="alert alert-danger" ng-show="dupe_counts.email">
+      <a target="_blank"
+        href="/eg/staff/circ/patron/search?search={{dupe_search_encoded.email}}">
+        [% l('[_1] patron(s) with same email', 
+        '{{dupe_counts.email}}') %]</a>
+    </div>
+    <div class="alert alert-danger" ng-show="dupe_counts.ident">
+      <a target="_blank" 
+        href="/eg/staff/circ/patron/search?search={{dupe_search_encoded.ident}}">
+        [% l('[_1] patron(s) with same identification', 
+        '{{dupe_counts.ident}}') %]</a>
+    </div>
+    <div class="alert alert-danger" ng-show="dupe_counts.day_phone">
+      <a target="_blank" 
+        href="/eg/staff/circ/patron/search?search={{dupe_search_encoded.day_phone}}">
+        [% l('[_1] patron(s) with same phone', 
+        '{{dupe_counts.day_phone}}') %]</a>
+    </div>
+    <div class="alert alert-danger" ng-show="dupe_counts.evening_phone">
+      <a target="_blank" 
+        href="/eg/staff/circ/patron/search?search={{dupe_search_encoded.evening_phone}}">
+        [% l('[_1] patron(s) with same phone', 
+        '{{dupe_counts.evening_phone}}') %]</a>
+    </div>
+    <div class="alert alert-danger" ng-show="dupe_counts.other_phone">
+      <a target="_blank" 
+        href="/eg/staff/circ/patron/search?search={{dupe_search_encoded.other_phone}}">
+        [% l('[_1] patron(s) with same phone', 
+        '{{dupe_counts.other_phone}}') %]</a>
+    </div>
+    <div class="alert alert-danger" ng-show="dupe_counts.address">
+      <a target="_blank" 
+        href="/eg/staff/circ/patron/search?search={{dupe_search_encoded.address}}" >
+        [% l('[_1] patron(s) with same address', 
+        '{{dupe_counts.address}}') %]</a>
+    </div>
+  </div>
+
+  <div class="alert alert-danger" ng-show="address_alerts.length > 0">
+      <div class="strong-text-3">[% l('Address Alert') %]</div>
+      <div ng-repeat="address_alert in address_alerts">
+        {{address_alert.alert_message()}}
+      </div>
+  </div>
+
+  <!-- IDL field documentation window -->
+  <div class="alert alert-info" ng-show="selected_field_doc">
+    <fieldset id="reg-field-doc">
+      <legend>
+      {{idl_fields[selected_field_doc.fm_class()][selected_field_doc.field()].label}}
+      </legend>
+      <div>{{selected_field_doc.string()}}</div>
+    </fieldset>
+  </div>
+
+  <div class="alert alert-info" ng-show="stage_user_requestor">
+    <a target="_blank" 
+      href="/eg/staff/circ/patron/{{stage_user.reqesting_usr()}}/edit">
+      [% l('Requested by [_1]', '{{stage_user_requestor}}') %]
+    </a>
+  </div>
+</div>
+
+[%
+# draws a label for inputs based on the idl class's field's
+# label OR a supplied string
+MACRO draw_field_label (cls, field, label_override) BLOCK %]
+  <div class="col-md-3 reg-field-label"> <!-- field label -->
+    [% IF label_override %]<label>[% label_override %]</label>
+    [% ELSE %]<label id="{{idl_fields.[% cls %].[% field %].name}}">{{idl_fields.[% cls %].[% field %].label}}</label>[% END %]
+    <!-- field documentation img/link -->
+    <img ng-show="field_doc.[% cls %].[% field %]" 
+      ng-click="set_selected_field_doc('[% cls %]','[% field %]')"
+      src='[% DOC_IMG %]'></img>
+  </div>
+[% END %]
+
+
+[% 
+# draws a vanilla form input field for inputs that require no 
+# special additions.
+MACRO draw_form_input(cls, field, path, type, disable) BLOCK;
+  IF !type; type = 'text'; END;
+  base_obj = path ? 'patron.' _ path : 'patron';
+  model = base_obj _ '.' _ field;
+%]
+  <div class="col-md-3 reg-field-input">
+    <input 
+      [% IF type == "email" %]type="text" ng-required="hold_notify_type.email"
+      [% ELSE %]type="[% type %]"
+      [% END %]
+      class="form-control" 
+      name="[% model %]"
+      aria-labelledby="{{idl_fields.[% cls %].[% field %].name}}"
+      ng-change="field_modified()" 
+      ng-required="field_required('[% cls %]', '[% field %]')"
+      ng-blur="handle_field_changed([% base_obj %], '[% field %]')"
+      ng-pattern="field_pattern('[% cls %]', '[% field %]')"
+      [% IF disable %]ng-disabled="[% disable %]"[% END %]
+      ng-model="[% model %]"/>
+  </div>
+[% END %]
+
+[% MACRO draw_example_text(cls, field) BLOCK;
+  set_str = "org_settings['ui.patron.edit." _ cls _ "." _ field _ ".example']";
+%]
+  <span ng-if="[% set_str %]">
+    [% l('Example: [_1]', '{{' _ set_str _ '}}') %]
+  </span>
+[% END %]
+
+<!-- progress dialog displayed as we await all data to finish loading -->
+<div class="row" ng-show="!page_data_loaded">
+  <div class="col-md-6 pad-vert">
+    <div class="progress progress-striped active">
+        <div class="progress-bar"  role="progressbar" aria-valuenow="100" 
+              aria-valuemin="0" aria-valuemax="100" style="width: 100%">
+            <span class="sr-only">[% l('Loading...') %]</span>
+        </div>
+    </div>
+  </div>
+</div>
+
+<!--  
+MAIN FORM
+This div wraps the entire form so we can hide it until all needed data
+has been loaded.  Setting ng-form and a name lets us refer to fields
+within the "form" by name for validation.
+-->
+<div ng-form id="patron-reg-container" 
+  name="reg_form" ng-show="page_data_loaded">
+
+<!-- BARCODE -->
+
+<div class="row reg-field-row" ng-show="show_field('ac.barcode')">
+  [% draw_field_label('ac', 'barcode') %]
+  <div class="col-md-3 reg-field-input"> <!-- field form input -->
+      <input type="text" 
+        name="barcode"
+        aria-labelledby="{{idl_fields.ac.barcode.name}}"
+        ng-model="patron.card.barcode"
+        ng-pattern="field_pattern('ac', 'barcode')"
+        ng-required="field_required('ac', 'barcode')"
+        focus-me="focus_bc"
+        ng-change="field_modified()" 
+        ng-disabled="disable_bc"
+        class="form-control"
+        ng-blur="handle_field_changed(patron.card, 'barcode')"/>
+  </div>
+  <div class="col-md-6 patron-reg-example">
+      <button class="btn btn-default" ng-show="!patron.isnew"
+        ng-click="replace_card()">[% l('Replace Barcode') %]</button>
+      <button class="btn btn-default" ng-if="!patron.isnew" 
+        ng-click="cards_dialog()">[% l('See All') %]</button>
+      <div ng-show="dupe_barcode" class="patron-reg-validation-alert">
+        <span>[% l('Barcode is already in use') %]</span>
+      </div>
+  </div>
+</div>
+
+<!-- USRNAME -->
+
+<div class="row reg-field-row" ng-show="show_field('au.usrname')">
+  [% draw_field_label('au', 'usrname') %]
+  <div class="col-md-3 reg-field-input">
+    <input type="text" 
+      name='usrname'
+      aria-labelledby="{{idl_fields.au.usrname.name}}"
+      ng-required="field_required('au', 'usrname')"
+      focus-me="focus_usrname"
+      ng-change="field_modified()" 
+      ng-pattern="field_pattern('au', 'usrname')"
+      ng-blur="handle_field_changed(patron, 'usrname')"
+      class="form-control" 
+      ng-model="patron.usrname"/>
+  </div>
+  <div class="col-md-6 patron-reg-example">
+    <div ng-show="dupe_username" class="patron-reg-validation-alert">
+      <span>[% l('Username is already in use') %]</span>
+    </div>
+  </div>
+</div>
+
+<!-- PASSWD -->
+
+<div class="row reg-field-row" ng-show="show_field('au.passwd')">
+  [% draw_field_label('au', 'passwd') %]
+  [% draw_form_input('au', 'passwd'); %]
+  <div class="col-md-6 patron-reg-example">
+    <button class="btn btn-default" ng-click="generate_password()">
+      [% l('Generate Password') %]</button>
+    <button class="btn btn-default" ng-show="!patron.isnew"
+        ng-click="send_password_reset_link()">
+      [% l('Send Password Reset Link') %]</button>
+  </div>
+</div>
+
+<div class="row reg-field-row">
+  <div class="col-md-6">
+    <ul class="nav nav-pills nav-pills-like-tabs">
+      <li ng-class="{active : name_tab == 'primary'}">
+        <a ng-click="name_tab='primary'" href="#">[% l('Primary Name') %]</a>
+      </li>
+      <li ng-class="{active : name_tab == 'preferred'}">
+        <a ng-click="name_tab='preferred'" href="#">[% l('Preferred Name') %]</a>
+      </li>
+    </ul>
+  </div>
+</div>
+
+<div ng-show="name_tab == 'primary'">
+
+  <!-- PREFIX -->
+
+  <div class="row reg-field-row" ng-show="show_field('au.prefix')">
+    [% draw_field_label('au', 'prefix') %]
+    [% draw_form_input('au', 'prefix'); %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('au', 'prefix') %]
+    </div>
+  </div>
+
+  <!-- FIRST_GIVEN_NAME -->
+
+  <div class="row reg-field-row" ng-show="show_field('au.first_given_name')">
+    [% draw_field_label('au', 'first_given_name') %]
+    [% draw_form_input('au', 'first_given_name'); %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('au', 'first_given_name') %]
+    </div>
+  </div>
+
+  <!-- SECOND_GIVEN_NAME -->
+
+  <div class="row reg-field-row" ng-show="show_field('au.second_given_name')">
+    [% draw_field_label('au', 'second_given_name') %]
+    [% draw_form_input('au', 'second_given_name'); %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('au', 'second_given_name') %]
+    </div>
+  </div>
+
+  <!-- FAMILY_NAME -->
+
+  <div class="row reg-field-row" ng-show="show_field('au.family_name')">
+    [% draw_field_label('au', 'family_name') %]
+    [% draw_form_input('au', 'family_name'); %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('au', 'family_name') %]
+    </div>
+  </div>
+
+  <!-- SUFFIX -->
+
+  <div class="row reg-field-row" ng-show="show_field('au.suffix')">
+    [% draw_field_label('au', 'suffix') %]
+    [% draw_form_input('au', 'suffix'); %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('au', 'suffix') %]
+    </div>
+  </div>
+</div> <!-- ng-show == primary -->
+
+<div ng-show="name_tab == 'preferred'" class="patron-reg-pref-names">
+
+  <!-- PREFIX -->
+
+  <div class="row reg-field-row" ng-show="show_field('au.pref_prefix')">
+    [% draw_field_label('au', 'pref_prefix') %]
+    [% draw_form_input('au', 'pref_prefix'); %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('au', 'pref_prefix') %]
+    </div>
+  </div>
+
+  <!-- FIRST_GIVEN_NAME -->
+
+  <div class="row reg-field-row" ng-show="show_field('au.pref_first_given_name')">
+    [% draw_field_label('au', 'pref_first_given_name') %]
+    [% draw_form_input('au', 'pref_first_given_name'); %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('au', 'pref_first_given_name') %]
+    </div>
+  </div>
+
+  <!-- SECOND_GIVEN_NAME -->
+
+  <div class="row reg-field-row" ng-show="show_field('au.pref_second_given_name')">
+    [% draw_field_label('au', 'pref_second_given_name') %]
+    [% draw_form_input('au', 'pref_second_given_name'); %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('au', 'pref_second_given_name') %]
+    </div>
+  </div>
+
+  <!-- FAMILY_NAME -->
+
+  <div class="row reg-field-row" ng-show="show_field('au.pref_family_name')">
+    [% draw_field_label('au', 'pref_family_name') %]
+    [% draw_form_input('au', 'pref_family_name'); %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('au', 'pref_family_name') %]
+    </div>
+  </div>
+
+  <!-- SUFFIX -->
+
+  <div class="row reg-field-row" ng-show="show_field('au.pref_suffix')">
+    [% draw_field_label('au', 'pref_suffix') %]
+    [% draw_form_input('au', 'pref_suffix'); %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('au', 'pref_suffix') %]
+    </div>
+  </div>
+</div> <!-- ng-show == preferred -->
+
+<!-- indicate bottom of name tabs -->
+<div class="row reg-field-row">
+  <div class="col-md-6"><hr class="patron-reg-names-separator"/></div>
+</div>
+
+<div class="row reg-field-row" ng-show="show_field('au.name_keywords')">
+  [% draw_field_label('au', 'name_keywords') %]
+  <div class="col-md-3 reg-field-input">
+    <textarea 
+      class="form-control" 
+      aria-labelledby="{{idl_fields.au.name_keywords.name}}"
+      ng-model="patron.name_keywords"
+      ng-pattern="field_pattern('au', 'name_keywords')"
+      ng-change="field_modified()" 
+      ng-blur="handle_field_changed(patron, 'name_keywords')">
+    </textarea>
+  </div>
+  <div class="col-md-6 patron-reg-example">
+    [% draw_example_text('au', 'name_keywords') %]
+  </div>
+</div>
+
+<!-- ALIAS -->
+
+<div class="row reg-field-row" ng-show="show_field('au.alias')">
+  [% draw_field_label('au', 'alias') %]
+  [% draw_form_input('au', 'alias'); %]
+  <div class="col-md-6 patron-reg-example">
+    [% draw_example_text('au', 'alias') %]
+  </div>
+</div>
+
+<!-- DOB -->
+
+<div class="row reg-field-row" ng-show="show_field('au.dob')">
+  [% draw_field_label('au', 'dob') %]
+  <div class="col-md-3 reg-field-input">
+    <eg-date-input
+      date-aria="{{idl_fields.au.dob.name}}"
+      ng-required="field_required('au', 'dob')" 
+      ng-model="patron.dob">
+    </eg-date-input>
+  </div>
+  <div class="col-md-6 patron-reg-example">
+    [% draw_example_text('au', 'dob') %]
+  </div>
+</div>
+
+<!-- JUVENILE -->
+
+<div class="row reg-field-row" ng-show="show_field('au.juvenile')">
+  [% draw_field_label('au', 'juvenile') %]
+  <div class="col-md-3 reg-field-input">
+      <input 
+        aria-labelledby="{{idl_fields.au.juvenile.name}}"
+        ng-change="field_modified()" 
+        ng-blur="handle_field_changed(patron, 'juvenile')"
+        type='checkbox' ng-model="patron.juvenile"/>
+  </div>
+</div>
+
+<!-- GUARDIAN -->
+
+<div class="row reg-field-row" ng-show="show_field('au.guardian')">
+  [% draw_field_label('au', 'guardian') %]
+  [% draw_form_input('au', 'guardian'); %]
+  <div class="col-md-6 patron-reg-example">
+    [% draw_example_text('au', 'guardian') %]
+  </div>
+</div>
+
+<!-- ident_type -->
+
+<div class="row reg-field-row" ng-show="show_field('au.ident_type')">
+  [% draw_field_label('au', 'ident_type') %]
+  <div class="col-md-3 reg-field-input">
+    <select 
+      class="form-control" 
+      aria-labelledby="{{idl_fields.au.ident_type.name}}"
+      ng-model="patron.ident_type"
+      ng-required="field_required('au', 'ident_type')"
+      ng-blur="handle_field_changed(patron, 'ident_type')"
+      ng-options="type.name() for type in ident_types track by type.id()">
+    </select>
+  </div>
+</div>
+
+<!-- IDENT_VALUE -->
+
+<div class="row reg-field-row" ng-show="show_field('au.ident_value')">
+  [% draw_field_label('au', 'ident_value') %]
+  [% draw_form_input('au', 'ident_value') %]
+  <div class="col-md-6 patron-reg-example">
+    [% draw_example_text('au', 'ident_value') %]
+  </div>
+</div>
+
+<!-- ident_type2 -->
+
+<div class="row reg-field-row" ng-show="show_field('au.ident_type2')">
+  [% draw_field_label('au', 'ident_type2') %]
+  <div class="col-md-3 reg-field-input">
+    <select 
+      class="form-control" 
+      aria-labelledby="{{idl_fields.au.ident_type2.name}}"
+      ng-model="patron.ident_type2"
+      ng-required="field_required('au', 'ident_type2')"
+      ng-blur="handle_field_changed(patron, 'ident_type2')"
+      ng-options="type.name() for type in ident_types track by type.id()">
+    </select>
+  </div>
+</div>
+
+<!-- IDENT_VALUE2 -->
+<div class="row reg-field-row" ng-show="show_field('au.ident_value2')">
+  [% draw_field_label('au', 'ident_value2') %]
+  [% draw_form_input('au', 'ident_value2') %]
+  <div class="col-md-6 patron-reg-example">
+    [% draw_example_text('au', 'ident_value2') %]
+  </div>
+</div>
+
+<!-- PHOTO_URL -->
+<div class="row reg-field-row" ng-show="show_field('au.photo_url')">
+  [% draw_field_label('au', 'photo_url') %]
+  [% draw_form_input('au', 'photo_url', '', 'photo_url') %]
+  <div class="col-md-3 patron-reg-example">
+    <span ng-if="org_settings['ui.patron.edit.au.photo_url.example']">
+      [% l('Example: [_1]',
+        "{{org_settings['ui.patron.edit.au.photo_url.example']}}") %]
+    </span>
+  </div>
+</div>
+
+<!-- EMAIL -->
+<div class="row reg-field-row" ng-show="show_field('au.email')">
+  [% draw_field_label('au', 'email') %]
+  [% draw_form_input('au', 'email', '', 'email') %]
+  <div class="col-md-3 patron-reg-example">
+    <button class="btn btn-default" ng-show="base_email && !patron.isnew"
+      ng-disabled="reg_form['patron.email'].$dirty"
+      ng-click="send_test_email()">[% l('Send Test Email') %]</button>
+    <button ng-show="patron.email && !patron.isnew" 
+      class="btn btn-default" 
+      ng-click="invalidate_field('email')">[% l('Invalidate') %]</button>
+    <span ng-if="org_settings['ui.patron.edit.au.email.example']">
+      [% l('Example: [_1]',
+        "{{org_settings['ui.patron.edit.au.email.example']}}") %]
+    </span>
+  </div>
+</div>
+
+<div class="row reg-field-row" ng-show="show_field('au.email') && opt_in_setting_types['circ.send_email_checkout_receipts']">
+  <div class="col-md-3 reg-field-label">
+    <label id="checkoutReceipts">{{opt_in_setting_types['circ.send_email_checkout_receipts'].label()}}</label>
+  </div>
+  <div class="col-md-3 reg-field-input">
+    <input
+      aria-labelledby="checkoutReceipts"
+      ng-change="field_modified()"
+      type='checkbox' ng-model="user_settings['circ.send_email_checkout_receipts']"/>
+  </div>
+</div>
+
+<!-- DAY_PHONE -->
+
+<div class="row reg-field-row" ng-show="show_field('au.day_phone')">
+  [% draw_field_label('au', 'day_phone') %]
+  [% draw_form_input('au', 'day_phone') %]
+  <div class="col-md-6 patron-reg-example">
+    <button ng-show="patron.day_phone && !patron.isnew" 
+        class="btn btn-default" 
+        ng-click="invalidate_field('day_phone')">[% l('Invalidate') %]</button>
+    [% draw_example_text('au', 'day_phone') %]
+    <!-- phones have a fall-through example strings -->
+    <span ng-if="!org_settings['ui.patron.edit.au.day_phone.example'] && org_settings['ui.patron.edit.phone.example']">
+      [% l('Example: [_1]', 
+        "{{org_settings['ui.patron.edit.phone.example']}}") %]
+    </span>
+  </div>
+</div>
+
+<!-- EVENING_PHONE -->
+
+<div class="row reg-field-row" ng-show="show_field('au.evening_phone')">
+  [% draw_field_label('au', 'evening_phone') %]
+  [% draw_form_input('au', 'evening_phone') %]
+  <div class="col-md-6 patron-reg-example">
+    <button ng-show="patron.evening_phone && !patron.isnew" 
+        class="btn btn-default" 
+        ng-click="invalidate_field('evening_phone')">[% l('Invalidate') %]</button>
+    [% draw_example_text('au', 'evening_phone') %]
+    <!-- phones have a fall-through example strings -->
+    <span ng-if="!org_settings['ui.patron.edit.au.evening_phone.example'] && org_settings['ui.patron.edit.phone.example']">
+      [% l('Example: [_1]', 
+        "{{org_settings['ui.patron.edit.phone.example']}}") %]
+    </span>
+  </div>
+</div>
+
+<!-- OTHER_PHONE -->
+
+<div class="row reg-field-row" ng-show="show_field('au.other_phone')">
+  [% draw_field_label('au', 'other_phone') %]
+  [% draw_form_input('au', 'other_phone') %]
+  <div class="col-md-6 patron-reg-example">
+    <button ng-show="patron.other_phone && !patron.isnew" 
+        class="btn btn-default" 
+        ng-click="invalidate_field('other_phone')">[% l('Invalidate') %]</button>
+    [% draw_example_text('au', 'other_phone') %]
+    <!-- phones have a fall-through example strings -->
+    <span ng-if="!org_settings['ui.patron.edit.au.other_phone.example'] && org_settings['ui.patron.edit.phone.example']">
+      [% l('Example: [_1]', 
+        "{{org_settings['ui.patron.edit.phone.example']}}") %]
+    </span>
+  </div>
+</div>
+
+<!-- home org unit selector -->
+
+<div class="row reg-field-row" ng-show="show_field('au.home_ou')">
+  [% draw_field_label('au', 'home_ou') %]
+  <div class="col-md-3 reg-field-input">
+    <eg-org-selector 
+      selected="patron.home_ou" 
+      onchange="handle_home_org_changed"
+      org-aria="{{idl_fields.au.home_ou.name}}"
+      hidden-test="disable_home_org"
+      disable-test="disable_home_org">
+    </eg-org-selector>
+  </div>
+</div>
+
+<!-- profile selector -->
+
+<div class="row reg-field-row" ng-show="show_field('au.profile')">
+  [% draw_field_label('au', 'profile') %]
+  <div class="col-md-3 reg-field-input">
+    <div class="btn-group" uib-dropdown>
+      <button type="button" class="btn btn-default" uib-dropdown-toggle
+          aria-labelledby="{{idl_fields.au.profile.name}}"
+          ng-class="{'ng-invalid' : invalid_profile()}">
+        <span style="padding-right: 5px;">
+          {{patron.profile.name() || "[% l('Profile Group') %]"}}
+        </span>
+        <span class="caret"></span>
+      </button>
+      <ul class="scrollable-menu" uib-dropdown-menu>
+        <li ng-repeat="entry in edit_profile_entries" ng-if="edit_profile_entries.length"
+          ng-class="{disabled : entry.grp().usergroup() == 'f'}">
+          <a href 
+            style="padding-left: {{pgtde_depth(entry) * 10 + 5}}px"
+            ng-click="set_profile(entry.grp())">{{entry.grp().name()}}</a>
+        </li>
+        <li ng-repeat="grp in edit_profiles" ng-if="!edit_profile_entries.length"
+          ng-class="{disabled : grp.usergroup() == 'f'}">
+          <a href 
+            style="padding-left: {{pgt_depth(grp) * 10 + 5}}px"
+            ng-click="set_profile(grp)">{{grp.name()}}</a>
+        </li>
+      </ul>
+    </div>
+  </div>
+  <div class="col-md-3">
+    <button class="btn btn-default" ng-if="!offline" ng-disabled="!perms.CREATE_USER_GROUP_LINK"
+      ng-click="secondary_groups_dialog()">[% l('Secondary Groups') %]</button>
+  </div> 
+</div>
+
+<div class="row reg-field-row" ng-show="show_field('au.expire_date')">
+  [% draw_field_label('au', 'expire_date') %]
+  <div class="col-md-3 reg-field-input">
+    <eg-date-input
+      date-aria="{{idl_fields.au.expire_date.name}}"
+      ng-model="patron.expire_date">
+    </eg-date-input>
+  </div>
+  <div class="col-md-3">
+    <button class="btn btn-default" ng-click="set_expire_date()">
+      [% l('Update Expire Date') %]</button>
+  </div>
+</div>
+
+<!-- net_access_level -->
+
+<div class="row reg-field-row" ng-show="show_field('au.net_access_level')">
+  [% draw_field_label('au', 'net_access_level') %]
+  <div class="col-md-3 reg-field-input">
+    <select 
+      class="form-control" 
+      aria-labelledby="{{idl_fields.au.net_access_level.name}}"
+      ng-model="patron.net_access_level"
+      ng-required="field_required('au', 'net_access_level')"
+      ng-blur="handle_field_changed(patron, 'net_access_level')"
+      ng-options="level.name() for level in net_access_levels track by level.id()">
+    </select>
+  </div>
+</div>
+
+<!-- ACTIVE -->
+
+<div class="row reg-field-row" ng-show="show_field('au.active')">
+  [% draw_field_label('au', 'active') %]
+  <div class="col-md-3 reg-field-input">
+      <input 
+        aria-labelledby="{{idl_fields.au.active.name}}"
+        ng-change="field_modified()" 
+        ng-blur="handle_field_changed(patron, 'active')"
+        type='checkbox' ng-model="patron.active"/>
+  </div>
+</div>
+
+<!-- BARRED -->
+
+<div class="row reg-field-row" ng-show="show_field('au.barred')">
+  [% draw_field_label('au', 'barred') %]
+  <div class="col-md-3 reg-field-input">
+      <input 
+        aria-labelledby="{{idl_fields.au.barred.name}}"
+        ng-change="field_modified()" 
+        ng-blur="handle_field_changed(patron, 'barred')"
+        type='checkbox' ng-model="patron.barred"/>
+  </div>
+</div>
+
+<!-- MASTER_ACCOUNT -->
+
+<div class="row reg-field-row" ng-show="show_field('au.master_account')">
+  [% draw_field_label('au', 'master_account') %]
+  <div class="col-md-3 reg-field-input">
+      <input 
+        aria-labelledby="{{idl_fields.au.master_account.name}}"
+        ng-change="field_modified()" 
+        ng-blur="handle_field_changed(patron, 'master_account')"
+        type='checkbox' ng-model="patron.master_account"/>
+  </div>
+</div>
+
+<!-- CLAIMS_RETURNED_COUNT -->
+
+<div class="row reg-field-row" ng-show="show_field('au.claims_returned_count')">
+  [% draw_field_label('au', 'claims_returned_count') %]
+  [% draw_form_input('au', 'claims_returned_count', 
+    '', 'number', '!perms.UPDATE_PATRON_CLAIM_RETURN_COUNT') %]
+  <div class="col-md-6 patron-reg-example">
+    [% draw_example_text('au', 'claims_returned_count') %]
+  </div>
+</div>
+
+<!-- CLAIMS_NEVER_CHECKED_OUT_COUNT -->
+
+<div class="row reg-field-row" ng-show="show_field('au.claims_never_checked_out_count')">
+  [% draw_field_label('au', 'claims_never_checked_out_count') %]
+  [% draw_form_input('au', 'claims_never_checked_out_count',
+    '', 'number', '!perms.UPDATE_PATRON_CLAIM_NEVER_CHECKED_OUT_COUNT') %]
+  <div class="col-md-6 patron-reg-example">
+    [% draw_example_text('au', 'claims_never_checked_out_count') %]
+  </div>
+</div>
+
+<div ng-if="!offline">
+
+<div class="alert alert-success row" role="alert">
+  <div class="col-md-6">[% l('User Settings') %]</div>
+</div>
+
+<div class="row reg-field-row">
+  <div class="col-md-3 reg-field-label">
+    <label id="defaultPhone">{{user_setting_types['opac.default_phone'].label()}}</label>
+  </div>
+  <div class="col-md-3 reg-field-input">
+    <input ng-required="hold_notify_type.phone"
+      aria-labelledby="defaultPhone"
+      ng-change="field_modified()" 
+      ng-blur="handle_field_changed(user_settings, 'opac.default_phone')"
+      type='text' ng-model="user_settings['opac.default_phone']"/>
+  </div>
+</div>
+
+<div class="row reg-field-row">
+  <div class="col-md-3 reg-field-label">
+    <label id="defaultPickupLoc">
+      {{user_setting_types['opac.default_pickup_location'].label()}}
+    </label>
+  </div>
+  <div class="col-md-3 reg-field-input">
+    <eg-org-selector nodefault
+      org-aria="defaultPickupLoc"
+      disable-test="disable_pulib" 
+      selected="patron._pickup_lib"
+      onchange="handle_pulib_changed">
+    </eg-org-selector>
+  </div>
+</div>
+
+<div class="row reg-field-row" 
+    ng-if="org_settings['circ.holds.behind_desk_pickup_supported']">
+  <div class="col-md-3 reg-field-label">
+    <label id="holdsBehindDesk">
+      {{user_setting_types['circ.holds_behind_desk'].label()}}
+    </label>
+  </div>
+  <div class="col-md-3 reg-field-input">
+      <input 
+        aria-labelledby="holdsBehindDesk"
+        ng-change="field_modified()" 
+        type='checkbox' ng-model="user_settings['circ.holds_behind_desk']"/>
+  </div>
+</div>
+
+<div class="row reg-field-row" 
+  ng-if="user_setting_types['circ.collections.exempt']">
+  <div class="col-md-3 reg-field-label">
+    <label id="exempt">
+      {{user_setting_types['circ.collections.exempt'].label()}}
+    </label>
+  </div>
+  <div class="col-md-3 reg-field-input">
+      <input 
+        type='checkbox' 
+        aria-labelledby="exempt"
+        ng-change="field_modified()" 
+        ng-disabled="!perms.UPDATE_PATRON_COLLECTIONS_EXEMPT"
+        ng-model="user_settings['circ.collections.exempt']"/>
+  </div>
+</div>
+
+<div class="row reg-field-row">
+  <div class="col-md-3 reg-field-label">
+    <label id="holdsNotices">[% l('Holds Notices') %]</label>
+  </div>
+  <div class="col-md-4 reg-field-input flex-row">
+    <div class='flex-cell'>
+      <input 
+        aria-labelledby="holdsNotices holdsPhone"
+        ng-change="field_modified()"
+        type='checkbox' ng-model="hold_notify_type.phone"/>
+      <label id="holdsPhone">
+        [% l('Phone') %]
+      </label>
+    </div>
+    <div class='flex-cell'>
+      <input 
+        aria-labelledby="holdsNotices holdsEmail"
+        ng-change="field_modified()" 
+        type='checkbox' ng-model="hold_notify_type.email"/>
+      <label id="holdsEmail">
+        [% l('Email') %]
+      </label>
+    </div>
+    <div class='flex-cell' ng-if="org_settings['sms.enable']">
+      <input 
+        aria-labelledby="holdsNotices holdsSms"
+        ng-change="field_modified()" 
+        type='checkbox' ng-model="hold_notify_type.sms"/>
+      <label id="holdsSms">
+        [% l('SMS') %]
+      </label>
+    </div>
+  </div>
+</div>
+
+<div class="row reg-field-row" ng-if="org_settings['sms.enable']">
+  <div class="col-md-3 reg-field-label">
+    <label id="defaultSmsNum">[% l('Default SMS/Text Number') %]</label>
+  </div>
+  <div class="col-md-3 reg-field-input">
+    <input 
+      name="default_sms_text_number"
+      aria-labelledby="defaultSmsNum"
+      ng-required="hold_notify_type.sms"
+      ng-change="field_modified()" ng-model="user_settings['opac.default_sms_notify']"
+      ng-blur="handle_field_changed(user_settings, 'opac.default_sms_notify')"
+      type='text'/>
+  </div>
+  <div class="col-md-3" ng-if="base_default_sms && !patron.isnew">
+    <button class="btn btn-default"
+      ng-disabled="reg_form['default_sms_text_number'].$dirty || reg_form['default_sms_text_carrier'].$dirty"
+      ng-click="send_test_sms()">[% l('Send Test Text') %]</button>
+  </div>
+</div>
+
+<div class="row reg-field-row" ng-if="org_settings['sms.enable']">
+  <div class="col-md-3 reg-field-label">
+    <label id="defaultSmsCarrier">
+      [% l('Default SMS Carrier') %]
+    </label>
+  </div>
+  <div class="col-md-3 reg-field-input">
+    <span class="nullable">
+      <select str-to-int
+        class="form-control" 
+        aria-labelledby="defaultSmsCarrier"
+        name="default_sms_text_carrier"
+        ng-model="user_settings['opac.default_sms_carrier']"
+        ng-required="user_settings['opac.default_sms_notify']"
+        ng-options="c.id() as c.name() + ' (' + c.region() + ')' for c in sms_carriers | orderBy:'name()'"
+        ng-blur="handle_field_changed(user_settings, 'opac.default_sms_carrier')">
+        <option value="">Select a Carrier</option>
+      </select>
+    </span>
+  </div>
+</div>
+
+<div class="row reg-field-row" ng-repeat="type in opt_in_setting_types">
+  <div class="col-md-3 reg-field-label" ng-if="type.name() != 'circ.send_email_checkout_receipts'">
+    <label id="settingTypes">{{type.label()}}</label>
+  </div>
+  <div class="col-md-3 reg-field-input" ng-if="type.name() != 'circ.send_email_checkout_receipts'">
+    <input 
+      aria-labelledby="settingTypes"
+      ng-change="field_modified()" 
+      type='checkbox' ng-model="user_settings[type.name()]"/>
+  </div>
+</div>
+
+<div class="row reg-field-row" ng-if="org_settings['circ.privacy_waiver']">
+  <div class="col-md-3 reg-field-label">
+    <label id="privacyWaiver">[% l('Allow others to use my account') %]</label>
+  </div>
+  <div class="col-md-4 reg-field-input">
+    <div class="row" ng-repeat="waiver_entry in patron.waiver_entries" ng-hide="waiver_entry.isdeleted">
+      <div class="row flex-row">
+        <div class="flex-cell">
+          <label id="waiverName" ng-hide="true">
+            [% l('Name') %]
+          </label>
+          <input ng-change="field_modified()"
+            aria-labelledby="privacyWaiver waiverName"
+            type='text' ng-model="waiver_entry.name"/>
+        </div>
+        <div class="flex-cell">
+          <button type="button"
+            aria-label="[% l('Delete Person Allowed to Use My Account') %]"
+            ng-click="field_modified();delete_waiver_entry(waiver_entry)" 
+            class="btn btn-danger">[% l('X') %]</button>
+        </div>
+      </div>
+      <div class="row flex-row reg-field-input">
+        <div class="flex-cell">
+          <label id="waiverPlace"><input ng-change="field_modified()"
+            aria-labelledby="privacyWaiver waiverPlace"
+            type='checkbox' ng-model="waiver_entry.place_holds"/>
+            [% l('Place Holds?') %]</label>
+        </div>
+        <div class="flex-cell">
+          <label id="waiverPickup"><input ng-change="field_modified()"
+            aria-labelledby="privacyWaiver waiverPickup"
+            type='checkbox' ng-model="waiver_entry.pickup_holds"/>
+            [% l('Pick Up Holds?') %]</label>
+        </div>
+        <div class="flex-cell">
+          <label id="waiverHistory"><input ng-change="field_modified()"
+            aria-labelledby="privacyWaiver waiverHistory"
+            type='checkbox' ng-model="waiver_entry.view_history"/>
+            [% l('View Borrowing History?') %]</label>
+        </div>
+        <div class="flex-cell">
+          <label id="waiverCheckOut"><input ng-change="field_modified()"
+            aria-labelledby="privacyWaiver waiverCheckOut"
+            type='checkbox' ng-model="waiver_entry.checkout_items"/>
+            [% l('Check Out Items?') %]</label>
+        </div>
+      </div> <!-- end checkboxes -->
+    </div> <!-- end ng-repeat waiver_entry -->
+    <div class="row">
+      <div class="col-md-3 reg-field-input">
+      <button type="button"
+        ng-click="new_waiver_entry()" 
+        class="btn btn-success">[% l('Add Person') %]</button>
+      </div>
+    </div>
+  </div> <!-- end waiver entries input -->
+</div> <!-- end waiver entries row -->
+
+</div> <!-- end offline test -->
+
+<!-- addresses -->
+
+<div ng-repeat="addr in patron.addresses">
+  <div class="alert alert-success row" role="alert">
+    <div class="col-md-3">
+      <label id="address{{addr.id}}">
+        [% l('Address') %]
+      </label>
+      <div ng-show="addr._linked_owner">
+        (<a target="_blank"
+          href="/eg/staff/circ/patron/{{addr._linked_owner_id}}/edit">
+          [% l('Owned by [_1]', '{{addr._linked_owner}}') %]
+        </a>)
+      </div>
+    </div>
+    <div class="col-md-3">
+        <span class='pad-all-min'>
+          <label id="mailing{{addr.id}}">
+            [% l('Mailing') %]
+          </label>
+          <input type='checkbox' 
+            aria-labelledby="address{{addr.id}} mailing{{addr.id}}"
+            ng-change="field_modified();set_addr_type(addr, 'mailing')" 
+            ng-model="addr._is_mailing"/>
+        </span>
+        <span class='pad-all-min'>
+          <label id="physical{{addr.id}}">
+            [% l('Physical') %]
+          </label>
+           <input type='checkbox' 
+            aria-labelledby="address{{addr.id}} physical{{addr.id}}"
+            ng-change="field_modified();set_addr_type(addr, 'billing')" 
+            ng-model="addr._is_billing"/>
+        </span>
+        <span class='pad-all-min'>
+          <button type="button"
+            aria-label="[% l('Delete this address') %]"
+            ng-click="field_modified();delete_address(addr.id)"
+            class="btn btn-danger">[% l('X') %]</button>
+        </span>
+    </div>
+  </div>
+
+  <div ng-if="addr.pending" class="row">
+    <div class="col-md-6 patron-reg-pending-address">
+      <div class="row">
+        <div class="col-md-6">
+          [% l('This is a pending address') %]
+        </div>
+        <div class="col-md-6">
+          <button class="btn btn-success" 
+            ng-click="approve_pending_address(addr)">[% l('Approve') %]</button>
+        </div>
+      </div>
+      <div class="row" ng-if="addr._replaces">
+        <div class="col-md-6">
+          [% | l(
+            '{{addr._replaces.street1}}',
+            '{{addr._replaces.street2}}',
+            '<br/>'
+            '{{addr._replaces.city}}',
+            '{{addr._replaces.state}}',
+            '{{addr._replaces.post_code}}') %]
+            Replaces: [_1] [_2] [_3] [_4], [_5] [_6]
+          [% END %]
+        </div>
+      </div>
+    </div>
+    <!-- make sure we occupy the entire row -->
+    <div class="col-md-6"> </div>
+  </div>
+
+  <!-- ADDRESS_TYPE -->
+  <div class="row reg-field-row" ng-show="show_field('aua.address_type')">
+    [% draw_field_label('aua', 'address_type') %]
+    [% draw_form_input('aua', 
+      'address_type', 'addresses[$index]', '', 'addr._linked_owner') %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('aua', 'address_type') %]
+    </div>
+  </div>
+
+  <!-- POST_CODE -->
+
+  <div class="row reg-field-row" ng-show="show_field('aua.post_code')">
+    [% draw_field_label('aua', 'post_code') %]
+    [% draw_form_input('aua', 
+      'post_code', 'addresses[$index]', '', 'addr._linked_owner') %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('aua', 'post_code') %]
+    </div>
+  </div>
+
+  <!-- STREET1 -->
+
+  <div class="row reg-field-row" ng-show="show_field('aua.street1')">
+    [% draw_field_label('aua', 'street1') %]
+    [% draw_form_input('aua', 
+      'street1', 'addresses[$index]', '', 'addr._linked_owner') %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('aua', 'street1') %]
+    </div>
+  </div>
+
+  <!-- STREET2 -->
+
+  <div class="row reg-field-row" ng-show="show_field('aua.street2')">
+    [% draw_field_label('aua', 'street2') %]
+    [% draw_form_input('aua', 
+      'street2', 'addresses[$index]', '', 'addr._linked_owner') %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('aua', 'street2') %]
+    </div>
+  </div>
+
+  <!-- CITY -->
+
+  <div class="row reg-field-row" ng-show="show_field('aua.city')">
+    [% draw_field_label('aua', 'city') %]
+    [% draw_form_input('aua', 
+      'city', 'addresses[$index]', '', 'addr._linked_owner') %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('aua', 'city') %]
+    </div>
+  </div>
+
+  <!-- COUNTY -->
+
+  <div class="row reg-field-row" ng-show="show_field('aua.county')">
+    [% draw_field_label('aua', 'county') %]
+    [% draw_form_input('aua', 
+      'county', 'addresses[$index]', '', 'addr._linked_owner') %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('aua', 'county') %]
+    </div>
+  </div>
+
+  <!-- STATE -->
+
+  <div class="row reg-field-row" ng-show="show_field('aua.state')">
+    [% draw_field_label('aua', 'state') %]
+    [% draw_form_input('aua', 
+      'state', 'addresses[$index]', '', 'addr._linked_owner') %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('aua', 'state') %]
+    </div>
+  </div>
+
+  <!-- COUNTRY -->
+
+  <div class="row reg-field-row" ng-show="show_field('aua.country')">
+    [% draw_field_label('aua', 'country') %]
+    [% draw_form_input('aua', 
+      'country', 'addresses[$index]', '', 'addr._linked_owner') %]
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('aua', 'country') %]
+    </div>
+  </div>
+
+  <!-- VALID -->
+
+  <div class="row reg-field-row" ng-show="show_field('aua.valid')">
+    [% draw_field_label('aua', 'valid') %]
+    <div class="col-md-3 reg-field-input">
+        <input 
+          aria-labelledby="{{idl_fields.aua.valid.name}}"
+          type='checkbox' 
+          ng-change="field_modified()" 
+          ng-disabled='addr._linked_owner'
+          ng-blur="handle_field_changed(patron.addresses[$index], 'valid')"
+          ng-model="patron.addresses[$index].valid"/>
+    </div>
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('aua', 'valid') %]
+    </div>
+  </div>
+
+  <!-- WITHIN_CITY_LIMITS -->
+
+  <div class="row reg-field-row" ng-show="show_field('aua.within_city_limits')">
+    [% draw_field_label('aua', 'within_city_limits') %]
+    <div class="col-md-3 reg-field-input">
+        <input 
+          type='checkbox'
+          aria-labelledby="{{idl_fields.aua.within_city_limits.name}}"
+          ng-change="field_modified()" 
+          ng-disabled='addr._linked_owner'
+          ng-blur="handle_field_changed(patron.addresses[$index], 'within_city_limits')"
+          ng-model="patron.addresses[$index].within_city_limits"/>
+    </div>
+    <div class="col-md-6 patron-reg-example">
+      [% draw_example_text('aua', 'within_city_limits') %]
+    </div>
+  </div>
+
+  <!-- pending address -->
+
+</div> <!-- addresses -->
+
+<div class="row">
+  <button type="button" ng-click="new_address()" 
+    class="btn btn-success">[% l('New Address') %]</button>
+</div>
+
+<div ng-if="!offline">
+<div class="alert alert-success row" role="alert"
+    ng-show="show_field('stat_cats') || hasRequiredStatCat" ng-if="stat_cats.length > 0">
+    <div class="col-md-6">[% l('Statistical Categories') %]</div>
+</div>
+
+<div class="row reg-field-row"
+     ng-show="show_field('stat_cats') || hasRequiredStatCat" ng-repeat="cat in stat_cats">
+     <!-- Display this stat cat when displaying all stat cats
+       or when this stat cat is required.  Wrap the body of
+       stat cat display in a div for easy show/hide.  -->
+  <div ng-if="show_field('stat_cats') || cat.required() == 1">
+
+    <div class="col-md-3 reg-field-label">
+      <label id="statcat{{cat.id()}}">{{cat.name()}}</label>
+    </div>
+    <div class="col-md-3 reg-field-input">
+      <div ng-if="cat.entries().length != 0">
+        <div class="btn-group" uib-dropdown>
+          <button type="button" class="btn btn-default" 
+            aria-labelledby="statcat{{cat.id()}}"
+            ng-class="{'ng-invalid': cat.required() == 1 && !stat_cat_entry_maps[cat.id()] }" 
+            uib-dropdown-toggle>
+            <span style="padding-right: 5px;">
+              {{stat_cat_entry_maps[cat.id()]}}</span>
+            <span class="caret"></span>
+          </button>
+          <ul uib-dropdown-menu>
+            <li ng-repeat="entry in cat.entries()">
+              <a href
+                ng-click="field_modified();stat_cat_entry_maps[cat.id()]=entry.value()">
+                {{entry.value()}}
+              </a>
+            </li>
+          </ul>
+        </div>
+      </div>
+    </div>
+
+    <!-- Stat cat retrieval API uses open-ils.storage under the covers
+        which represents DB bools at 1/0 instead of cstore-style t/f -->
+    <div class="col-md-3 reg-field-input"
+      ng-show="show_field('stat_cats') || hasRequiredStatCat"
+      ng-if="cat.allow_freetext() == '1'">
+      <input type="text" 
+        aria-labelledby="statcat{{cat.id()}}"
+        ng-model="stat_cat_entry_maps[cat.id()]"
+        class="form-control" ng-required="cat.required() == 1"/>
+    </div>
+
+  </div><!-- show/hide wrapper -->
+</div>
+</div>
+
+<!-- surveys -->
+
+<div class="alert alert-success row" role="alert" 
+    ng-show="show_field('surveys')" ng-if="surveys.length > 0">
+    <div class="col-md-6">[% l('Surveys') %]</div>
+</div>
+
+<div class="row reg-field-row" 
+    ng-show="show_field('surveys')" ng-repeat="survey in surveys">
+  <div class="col-md-3 reg-field-label">
+    <label>{{survey.name()}}</label>
+  </div>
+  <div class="col-md-6 reg-field-input">
+    <div class="row" ng-repeat="question in survey.questions()" 
+      style="margin-bottom: 10px;">
+      <div class="col-md-6">{{question.question()}}</div>
+      <div class="col-md-6">
+        <div class="btn-group" uib-dropdown>
+          <button type="button" class="btn btn-default" uib-dropdown-toggle>
+            <span style="padding-right: 5px;">
+              {{survey_responses[question.id()].answer()}}
+            </span>
+            <span class="caret"></span>
+          </button>
+          <ul uib-dropdown-menu>
+            <li ng-repeat="answer in question.answers()">
+              <a href 
+                ng-click="field_modified();survey_responses[question.id()] = answer"> 
+                {{answer.answer()}} 
+              </a>
+            </li>
+          </ul>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+
+</div><!-- /form wrapper -->
diff --git a/Open-ILS/src/templates_cons/staff/circ/patron/t_summary.tt2 b/Open-ILS/src/templates_cons/staff/circ/patron/t_summary.tt2
new file mode 100644 (file)
index 0000000..af98a66
--- /dev/null
@@ -0,0 +1,221 @@
+
+<div ng-cloak class="patron-summary-grid-wrapper">
+  <div ng-show="patron()" id="patron-summary-grid">
+    <div class="row" 
+      ng-class="{'patron-summary-divider' : !$index}"
+      ng-repeat="penalty in alert_penalties()">
+      <div 
+        class="col-md-9 patron-summary-alert"
+        title="{{penalty.standing_penalty().name()}} (id {{penalty.id()}}): {{penalty.usr_message().message()}}">
+        {{penalty.usr_message().title() || penalty.standing_penalty().label() | limitTo: 40}}
+      </div>
+      <div class="col-md-3">
+        {{penalty.set_date() | date:$root.egDateFormat}}
+      </div>
+    </div>
+    <div class="row" ng-class="{'patron-summary-alert' : doesPatronExpireSoon()}">
+      <div ng-if="doesPatronExpireSoon()" class="col-md-12">[% l('Patron account will expire soon.  Please renew.') %]</div>
+    </div>
+    <div ng-if="patron().photo_url()" class="row">
+         <div class="col-md-8 patron_photo_wrap"><img class="img-responsive img-rounded" src="{{patron().photo_url()}}" alt=""></div>
+    </div>
+    <div class="row" 
+      ng-class="{'patron-summary-divider' : alert_penalties().length}">
+      <div class="col-md-5">[% l('Profile') %]</div>
+      <div class="col-md-7">{{patron().profile().name()}}</div>
+    </div>
+    <div class="row" ng-if="show_name()">
+      <div class="col-md-5">[% l('ID') %]</div>
+      <div class="col-md-7">{{patron().id()}}</div>
+    </div>
+    <div class="row" ng-if="show_name()">
+      <div class="col-md-5">[% l('Name') %]</div>
+      <div class="col-md-7">
+                    [% l('[_1], [_2] [_3]',
+                '{{patron().pref_family_name() || patron().family_name()}}',
+                '{{patron().pref_first_given_name() || patron().first_given_name()}}',
+                '{{patron().pref_second_given_name() || patron().second_given_name()}}') %]
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Home Library') %]</div>
+      <div class="col-md-7" title="{{patron().home_ou().name()}}">{{patron().home_ou().shortname()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Net Access') %]</div>
+      <div class="col-md-7">{{patron().net_access_level().name()}}</div>
+    </div>
+    <div class="row"
+      ng-class="{'patron-summary-alert' : !patron().dob()}">
+      <a class="col-md-5" ng-if="obscure_dob()" ng-click="show_dob(true)">[% l('Date of Birth') %]</a>
+      <div class="col-md-5" ng-if="!obscure_dob()">[% l('Date of Birth') %]</div>
+      <div class="col-md-7" ng-show="now_show_dob()">{{patron().dob() | date:$root.egDateFormat}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Parent/Guardian') %]</div>
+      <div class="col-md-7">{{patron().guardian()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Last Activity') %]</div>
+      <div class="col-md-7" title="{{patron().usr_activity()[0].etype().label()}}">{{patron().usr_activity()[0].event_time() | date:$root.egDateFormat}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Last Updated') %]</div>
+      <div class="col-md-7">{{patron().last_update_time() | date:$root.egDateFormat}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Create Date') %]</div>
+      <div class="col-md-7">{{patron().create_date() | date:$root.egDateFormat}}</div>
+    </div>
+    <div class="row"
+      ng-class="{'patron-summary-alert' : isPatronExpired()}">
+      <div class="col-md-5">[% l('Expire Date') %]</div>
+      <div class="col-md-7">{{patron().expire_date() | date:$root.egDateFormat}}</div>
+    </div>
+    <div class="row patron-summary-divider" 
+      ng-class="{'patron-summary-alert' : patron_stats().fines.balance_owed}">
+      <div class="col-md-5">[% l('Fines Owed') %]</div>
+      <div class="col-md-7">
+        {{patron_stats().fines.balance_owed | currency}}
+      </div>
+    </div>
+    <div class="row"
+      ng-show="patron_stats().fines.group_balance_owed > patron_stats().fines.balance_owed"
+      ng-class="{'patron-summary-alert' : patron_stats().fines.group_balance_owed}">
+      <div class="col-md-5">[% l('Group Fines') %]</div>
+      <div class="col-md-7">
+        {{patron_stats().fines.group_balance_owed | currency}}
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Items Out') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.total_out}}</div>
+    </div>
+    <div class="row" 
+      ng-class="{'patron-summary-alert' : patron_stats().checkouts.overdue}">
+      <div class="col-md-5">[% l('Overdue') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.overdue}}</div>
+    </div>
+    <div class="row" 
+      ng-class="{'patron-summary-alert' : patron_stats().checkouts.long_overdue}">
+      <div class="col-md-5">[% l('Long Overdue') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.long_overdue}}</div>
+    </div>
+    <div class="row" 
+      ng-class="{'patron-summary-alert' : patron_stats().checkouts.claims_returned}">
+      <div class="col-md-5">[% l('Claimed Returned') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.claims_returned}}</div>
+    </div>
+    <div class="row" 
+      ng-class="{'patron-summary-alert' : patron_stats().checkouts.lost}">
+      <div class="col-md-5">[% l('Lost') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.lost}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Non-Cataloged') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.noncat}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Holds') %]</div>
+      <div class="col-md-7">
+        {{patron_stats().holds.ready}} / {{patron_stats().holds.total}}
+      </div>
+    </div>
+    <div class="row patron-summary-divider">
+      <div class="col-md-5">[% l('Card') %]</div>
+      <div class="col-md-7">{{patron().card().barcode()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Username') %]</div>
+      <div class="col-md-7">{{patron().usrname()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Day Phone') %]</div>
+      <div class="col-md-7">{{patron().day_phone()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Evening Phone') %]</div>
+      <div class="col-md-7">{{patron().evening_phone()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Other Phone') %]</div>
+      <div class="col-md-7">{{patron().other_phone()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('ID1') %]&nbsp;<span ng-if="hasIdentTypeName" class="ident_type">({{patron().ident_type().name()}})</span></div>
+      <div class="col-md-7">{{patron().ident_value()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('ID2') %]</div>
+      <div class="col-md-7">{{patron().ident_value2()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Legal Name') %]</div>
+      <div class="col-md-7">
+        [% l('[_1] [_2], [_3] [_4] [_5]',
+                '{{patron().prefix()}}',
+                '{{patron().family_name()}}',
+                '{{patron().first_given_name()}}',
+                '{{patron().second_given_name()}}',
+                '{{patron().suffix()}}') %]
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Email') %]</div>
+         <!-- Bound href="mailto: patron().email()" to an anchor tag to allow the patron's email address to be clicked directly from the summary. -->
+      <div class="col-md-7"><a ng-href="mailto:{{patron().email()}}">{{patron().email()}}</a></div>
+    </div>
+    <div class="row" ng-repeat="map in summary_stat_cats()">
+      <div class="col-md-5">{{map.stat_cat().name()}}</div>
+      <div class="col-md-7">{{map.stat_cat_entry()}}</div>
+    </div>
+    <div class="row" ng-if="patron().name_keywords()">
+      <div class="col-md-5">[% l('Name Keywords') %]</div>
+      <div class="col-md-7">{{patron().name_keywords()}}</div>
+    </div>
+    <div class="row patron-summary-divider" ng-if="patron().waiver_entries().length > 0">
+      [% l('Allow others to use my account') %]
+    </div>
+    <div class="row" ng-repeat="waiver in patron().waiver_entries()">
+      <div class="col-md-5">{{waiver.name()}}</div>
+      <div class="col-md-7">
+        <ul>
+          <li ng-show="waiver.place_holds() == 't'">[% l('Place holds') %]</li>
+          <li ng-show="waiver.pickup_holds() == 't'">[% l('Pick up holds') %]</li>
+          <li ng-show="waiver.view_history() == 't'">[% l('View borrowing history') %]</li>
+          <li ng-show="waiver.checkout_items() == 't'">[% l('Check out items') %]</li>
+        </ul>
+      </div>
+    </div>
+  </div>
+
+  <div class="row" ng-repeat="addr in patron().addresses()">
+    <div class="panel">
+      <div class="panel-body">
+        <fieldset>
+          <legend ng-class="{'patron-summary-alert': addr.valid() == 'f'}">
+            {{addr.address_type()}} 
+            (<a href class="patron-summary-act-link" 
+                ng-click="copy_address(addr)">[%- l('copy') -%]</a><a 
+                href class="patron-summary-act-link" 
+                ng-click="print_address(addr)">[%- l('/print') -%]</a>)
+          </legend>
+          <div>{{addr.street1()}} {{addr.street2()}}</div>
+          <div>{{addr.city()}}, {{addr.state()}} {{addr.post_code()}}</div>
+        </fieldset>
+        <textarea id="patron-address-copy-{{addr.id()}}" rows="2" 
+          style="visibility:hidden">[%- l(
+            '[_1] [_2] [_3]&#13;&#10;[_4] [_5]&#13;&#10;[_6], [_7] [_8]', 
+            '{{patron().first_given_name()}}',
+            '{{patron().second_given_name()}}',
+            '{{patron().family_name()}}',
+            '{{addr.street1()}}',
+            '{{addr.street2()}}',
+            '{{addr.city()}}',
+            '{{addr.state()}}',
+            '{{addr.post_code()}}') 
+          -%]</textarea>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates_cons/staff/t_splash.tt2 b/Open-ILS/src/templates_cons/staff/t_splash.tt2
new file mode 100644 (file)
index 0000000..6dc92d1
--- /dev/null
@@ -0,0 +1,168 @@
+<div class="container">
+  <div class="row">
+    <div class="col-md-12 text-center">
+      <img src="[% ctx.media_prefix %]/images/portal/logo.png" alt="Evergreen" />
+      <h1 class="sr-only" i18n>Evergreen Staff Client Home Page</h1>
+      <br/>
+      <strong style="color:red;font-size:20px;">TRAINING SERVER - DO NOT USE FOR LIVE TRANSACTIONS</strong>
+    </div>
+  </div>
+  <br/>
+  <div class="row" id="splash-nav">
+
+    <div class="col-md-4">
+      <div class="panel panel-success">
+        <div class="panel-heading">
+          <h2 class="panel-title text-center">[% l('Circulation and Patrons') %]</h2>
+        </div>
+        <div class="panel-body">
+          <div>
+            <a target="_self" href="./circ/patron/bcsearch">
+              <img src="[% ctx.media_prefix %]/images/portal/forward.png" alt="" role="presentation"/>
+              [% l('Check Out Items') %]
+            </a>
+          </div>
+          <div>
+            <a target="_self" href="./circ/checkin/index">
+              <img src="[% ctx.media_prefix %]/images/portal/back.png" alt="" role="presentation"/>
+              [% l('Check In Items') %]
+            </a>
+          </div>
+          <div>
+            <a href="./circ/patron/register" target="_self"
+              eg-accesskey="[% l('shift+f1') %]"
+              eg-accesskey-desc="[% l('Register Patron') %]">
+              <img src="[% ctx.media_predix %]/images/portal/registerpatron.png" alt="" role="presentation"/>
+              <span class="glyphicon glyphicon-user"></span>
+              [% l('Register Patron') %]
+            </a>
+          </div>
+          <div>
+            <a target="_self" href="./circ/patron/search">
+              <img src="[% ctx.media_prefix %]/images/portal/retreivepatron.png" alt="" role="presentation"/>
+              [% l('Search For Patron By Name') %]
+            </a>
+          </div>
+          <div>
+            <a href="./circ/holds/pull" target="_self">
+              <img src="[% ctx.media_prefix %]/images/portal/holds.png" alt="" role="presentation"/>
+              <span class="glyphicon glyphicon-th-list"></span>
+              [% l('Pull List for Hold Requests') %]
+            </a>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="col-md-4">
+      <div class="panel panel-success">
+        <div class="panel-heading">
+          <h2 class="panel-title text-center">[% l('Item Search and Cataloging') %]</h2>
+        </div>
+        <div class="panel-body">
+          <div>
+            <div class="input-group">
+                <input focus-me="focus_search" 
+                    aria-label="[% l('Search for...') %]"
+                    class="form-control" ng-model="cat_query" type="text" 
+                    ng-keypress="catalog_search($event)"
+                    placeholder="[% l('Search for...') %]"/>
+                <span class="input-group-btn">
+                    <button class='btn btn-default' ng-click="catalog_search()">
+                        [% l('Search Catalog') %]
+                    </button>
+                </span>
+            </div>
+          </div>
+          <div>
+            <a href="./cat/item/search" target="_self">
+            <img src="[% ctx.media_prefix %]/images/portal/book.png" alt="" role="presentation"/>
+              <span class="glyphicon glyphicon-saved"></span>
+              <span>[% l('Item Status') %]</span>
+            </a>
+          </div>
+          <div>
+            <a href="./cat/catalog/vandelay" target="_self">
+            <img src="[% ctx.media_prefix %]/images/portal/batchimport.png" alt="" role="presentation"/>
+              <span class="glyphicon glyphicon-transfer"></span>
+              [% l('MARC Batch Import/Export') %]
+            </a>
+          </div>
+          <div>
+            <a href="./cat/z3950/index" target="_self">
+            <img src="[% ctx.media_prefix %]/images/portal/z3950.png" alt="" role="presentation"/>
+              <span class="glyphicon glyphicon-cloud-download"></span>
+              [% l('Import Record from Z39.50') %]
+            </a>
+          </div>
+          <div>
+            <a target="_self" href="./cat/bucket/copy/">
+            <img src="[% ctx.media_prefix %]/images/portal/bucket.png" alt="" role="presentation"/>
+            [% l('Item Buckets') %]
+            </a>
+          </div>
+          <div>
+            <a target="_self" href="./cat/bucket/record/">
+            <img src="[% ctx.media_prefix %]/images/portal/bucket.png" alt="" role="presentation"/>
+            [% l('Record Buckets') %]
+            </a>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="col-md-4">
+      <div class="panel panel-success">
+        <div class="panel-heading">
+          <h2 class="panel-title text-center">[% l('Administration') %]</h2>
+        </div>
+        <div class="panel-body">
+          <div>
+            <a target="_top" href="./reporter/legacy/main">
+            <img src="[% ctx.media_prefix %]/images/portal/reports.png" alt="" role="presentation"/>
+              [% l('Reports') %]
+            </a>
+          </div>
+        <div>
+          <a target="_self" href="./admin/workstation/print/templates">
+          <img src="[% ctx.media_prefix %]/images/portal/receipt_editor.png" alt="" role="presentation"/>
+          <span class="glyphicon glyphicon-film"></span>
+            [% l('Print Templates') %]
+          </a>
+        </div>
+        <div>
+          <a target="_blank" href="https://www.cwmars.org/memberlibraries">
+            <img src="[% ctx.media_prefix %]/images/portal/libraries.png" alt="" role="presentation"/>
+            [% l('Member Libraries') %]
+          </a>
+          </div>
+          <div>
+          <a target="_blank" href="https://accounts.google.com/AccountChooser?continue=https://sites.google.com/a/cwmars.org/staff">
+              [% l('Library Staff Site - login required') %]
+          </a>
+          </div>
+          <div>
+          <a target="_blank" href="https://www.cwmars.org/help">
+              [% l('Patron FAQ') %]
+          </a>
+          </div>
+          <div>
+            <a target="_top" href="./admin/workstation/index">
+              <img src="[% ctx.media_prefix %]/images/portal/helpdesk.png" alt="" role="presentation"/>
+              [% l('Workstation Administration') %]
+            </a>
+          </div>
+          <div>
+     
+          <div>
+            <a target="_top" href="http://docs.evergreen-ils.org/">
+              <img src="[% ctx.media_prefix %]/images/portal/helpdesk.png" alt="" role="presentation"/>
+              [% l('Evergreen Community Documentation') %]
+            </a>
+          </div>
+        </div>
+      </div>
+    </div>
+
+  </div>
+</div>