Bugzilla – Attachment 102295 Details for
Bug 25031
Improve handling of multiple covers on the biblio detail page in the staff client
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 25031: Improve handling of multiple covers on the biblio detail page in the staff client
Bug-25031-Improve-handling-of-multiple-covers-on-t.patch (text/plain), 22.26 KB, created by
Owen Leonard
on 2020-04-02 12:33:49 UTC
(
hide
)
Description:
Bug 25031: Improve handling of multiple covers on the biblio detail page in the staff client
Filename:
MIME Type:
Creator:
Owen Leonard
Created:
2020-04-02 12:33:49 UTC
Size:
22.26 KB
patch
obsolete
>From 0d36279312f126029730ee624f6d470054c60868 Mon Sep 17 00:00:00 2001 >From: Owen Leonard <oleonard@myacpl.org> >Date: Tue, 31 Mar 2020 21:37:18 +0000 >Subject: [PATCH] Bug 25031: Improve handling of multiple covers on the biblio > detail page in the staff client > >This patch modifies the template, JS, and CSS for the bibliographic >detail page in order to gracefully handle multiple cover images. > >The changed version loops through any cover images which might be >embedded and checks that they are successfully loaded. Only >successfully-loaded images are shown. Only the first image is shown, and >the others can be "paged through" using generated navigation controls. > >To test, apply the page and rebuild the staff client CSS >(https://wiki.koha-community.org/wiki/Working_with_SCSS_in_the_OPAC_and_staff_client). > >Enable multiple cover image services. The patch was developed with these >services available: > > - Amazon > - Local cover images (including multiple local cover images) > - Coce (serving up Amazon, Google, and OpenLibrary images) > - Images from the CustomCoverImages preference > >View a variety of titles and confirm that the cover images are >displaying correctly, whether there be 0, 1, 2, or more covers >available. >--- > koha-tmpl/intranet-tmpl/js/coce.js | 78 +++++----- > .../intranet-tmpl/prog/css/src/staff-global.scss | 39 ++++- > .../intranet-tmpl/prog/en/includes/js_includes.inc | 3 - > .../prog/en/modules/catalogue/detail.tt | 172 +++++++++++++++------ > koha-tmpl/intranet-tmpl/prog/js/localcovers.js | 50 +++--- > 5 files changed, 220 insertions(+), 122 deletions(-) > >diff --git a/koha-tmpl/intranet-tmpl/js/coce.js b/koha-tmpl/intranet-tmpl/js/coce.js >index 930d7c1647..f6815ac5bd 100644 >--- a/koha-tmpl/intranet-tmpl/js/coce.js >+++ b/koha-tmpl/intranet-tmpl/js/coce.js >@@ -6,45 +6,45 @@ if (KOHA === undefined || !KOHA) { var KOHA = {}; } > */ > KOHA.coce = { > >- /** >- * Search all: >- * <div title="biblionumber" id="isbn" class="coce-thumbnail"></div> >- * or >- * <div title="biblionumber" id="isbn" class="coce-thumbnail-preview"></div> >- * and run a search with all collected isbns to coce cover service. >- * The result is asynchronously returned, and used to append <img>. >- */ >- getURL: function(host,provider,newWindow) { >- var ids = []; >- $("[id^=coce-thumbnail]").each(function(i) { >- var id = $(this).attr("class"); // id=isbn >- if ( id !== '' ) { ids.push(id); } >- }); >- if (ids.length == 0) return; >- ids = ids.join(','); >- var coceURL = host + '/cover?id=' + ids + '&provider=' + provider; >- $.ajax({ >- url: coceURL, >- dataType: 'jsonp', >- success: function(urlPerID){ >- for (var id in urlPerID) { >- var url = urlPerID[id]; >- $("[id^=coce-thumbnail]."+id).each(function() { >- var img = document.createElement("img"); >- img.src = url; >- img.classList.add("thumbnail"); >- img.alt = "Cover image"; >- img.onload = function(){ >- // image dimensions can't be known until image has loaded >- if( img.height == 1 && img.width == 1 ){ >- $(this).remove(); >+ /** >+ * Search all: >+ * <div title="biblionumber" id="isbn" class="coce-thumbnail"></div> >+ * or >+ * <div title="biblionumber" id="isbn" class="coce-thumbnail-preview"></div> >+ * and run a search with all collected isbns to coce cover service. >+ * The result is asynchronously returned, and used to append <img>. >+ */ >+ getURL: function(host, provider, newWindow) { >+ var ids = []; >+ $("[id^=coce-thumbnail]").each(function(i) { >+ var id = $(this).attr("class"); // id=isbn >+ if (id !== '') { ids.push(id); } >+ }); >+ if (ids.length == 0) return; >+ ids = ids.join(','); >+ var coceURL = host + '/cover?id=' + ids + '&provider=' + provider; >+ $.ajax({ >+ url: coceURL, >+ dataType: 'jsonp', >+ success: function(urlPerID) { >+ for (var id in urlPerID) { >+ var url = urlPerID[id]; >+ $("[id^=coce-thumbnail]." + id).each(function() { >+ var img = document.createElement("img"); >+ img.src = url; >+ img.alt = "Cover image"; >+ img.onload = function() { >+ // image dimensions can't be known until image has loaded >+ if (img.height == 1 && img.width == 1) { >+ $(this).remove(); >+ } >+ }; >+ $(this).html(img); >+ }); > } >- } >- $(this).html(img); >- }); >- } >- } >- }); >- } >+ }, >+ >+ }); >+ } > > }; >diff --git a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss >index 0a704fa499..67cb766890 100644 >--- a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss >+++ b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss >@@ -4,7 +4,7 @@ > ::selection { > background: #538200; > color: #FFFFFF; >-} >+} > > a { > &:link, >@@ -2091,6 +2091,43 @@ li { > } > } > >+#cover-slides { >+ background: #FFF url("[% interface | html %]/[% theme | html %]/img/spinner-small.gif") center center no-repeat; >+ border: 1px solid #b9d8d9; >+ border-radius: 3px; >+ margin: 5px; >+ padding: 10px 5px 5px 5px; >+ min-height: 175px; >+ >+ .hint { >+ font-size: 90%; >+ padding: .5em 0; >+ } >+ >+ a { >+ &.nav-active { >+ &:link, >+ &:visited { >+ color: #85ca11; >+ } >+ } >+ } >+} >+ >+.cover-image { >+ display: none; >+ >+ img { >+ height: auto; >+ max-width: 100%; >+ } >+} >+ >+.cover-nav { >+ display: inline-block; >+ padding: 3px 4px; >+} >+ > .searchhighlightblob { > font-size: 75%; > font-style: italic; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/js_includes.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/js_includes.inc >index daf0dc7935..9fce02ac1a 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/js_includes.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/js_includes.inc >@@ -57,9 +57,6 @@ > > [% IF LocalCoverImages %] > [% Asset.js("js/localcovers.js") | $raw %] >- <script> >- var NO_LOCAL_JACKET = _("No cover image available"); >- </script> > [% END %] > > [% IF Koha.Preference('AudioAlerts') || AudioAlertsPage %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt >index 3751bde157..f5737d4656 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt >@@ -136,36 +136,63 @@ > [% END %] > > [% IF ( AmazonCoverImages || LocalCoverImages || AdlibrisEnabled || IntranetCoce || (Koha.Preference('CustomCoverImages') && Koha.Preference('CustomCoverImagesURL')) ) %] >- </div><div class="col-xs-3" id="bookcoverimg"> >- [% IF ( LocalCoverImages ) %] >- <div title="[% biblionumber |url %]" class="[% biblionumber | html %]" id="local-thumbnail-preview"></div> >- [% END %] >- [% IF ( AdlibrisEnabled && normalized_isbn ) %] >- <a href="[% AdlibrisURL | url %]?isbn=[% normalized_isbn | uri %]"><img src="[% AdlibrisURL | url %]?isbn=[% normalized_isbn | uri %]" class="adlibris-cover-big" alt="Adlibris cover image" /></a> >- [% END %] >- [% IF ( AmazonCoverImages && normalized_isbn) %] >- <div id="amazon-bookcoverimg"> >- <a href="http://www.amazon[% AmazonTld | uri %]/gp/reader/[% normalized_isbn | uri %][% AmazonAssocTag | uri %]#reader-link"> >- <img src="https://images-na.ssl-images-amazon.com/images/P/[% normalized_isbn | html %].01.MZZZZZZZ.jpg" alt="" /> >- </a></div> >- [% END %] >- [% IF ( IntranetCoce && CoceProviders ) %] >- [% coce_id = normalized_ean || normalized_isbn %] >- <a class="p1" href="/cgi-bin/koha/catalogue/[% DetailPage | html %]?biblionumber=[% biblionumber | url %]"> >- [% IF ( coce_id ) %] >- <span style="block" title="[% biblionumber | url %]" class="[% coce_id | html %]" id="coce-thumbnail-preview"></span> >- [% ELSE %] >- <span class="no-image">No cover image available</span> >- [% END %] >- </a> >- [% END %] >+ </div> >+ <div class="col-xs-3" id="bookcoverimg"> >+ <div id="cover-slides"> >+ [% IF ( LocalCoverImages ) %] >+ [% IF ( localimages.0 ) %] >+ [% FOREACH image IN localimages %] >+ [% IF image %] >+ <div class="cover-image local-coverimg"> >+ <a href="/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=[% biblionumber | uri %]&imagenumber=[% image | uri %]"> >+ <img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&imagenumber=[% image | uri %]" alt="Local cover image" /> >+ </a> >+ <div class="hint">Local cover image</div> >+ </div> >+ [% END %] >+ [% END %] >+ [% END %] >+ [% END %] > >- [% IF Koha.Preference('CustomCoverImages') && Koha.Preference('CustomCoverImagesURL') %] >- <a class="custom_cover_image" href="[% biblio.custom_cover_image_url | url %]"><img alt="Cover image" src="[% biblio.custom_cover_image_url | url %]" /></a> >- [% END %] >- [% END %] >+ [% IF ( AdlibrisEnabled && normalized_isbn ) %] >+ <div class="cover-image" id="adlibris-coverimg"> >+ <a href="[% AdlibrisURL | url %]?isbn=[% normalized_isbn | uri %]"> >+ <img src="[% AdlibrisURL | url %]?isbn=[% normalized_isbn | uri %]" class="adlibris-cover-big" alt="Adlibris cover image" /> >+ </a> >+ <div class="hint">Image from Adlibris</div> >+ </div> >+ [% END %] >+ [% IF ( AmazonCoverImages && normalized_isbn) %] >+ <div class="cover-image" id="amazon-bookcoverimg"> >+ <a href="http://www.amazon[% AmazonTld | uri %]/gp/reader/[% normalized_isbn | uri %][% AmazonAssocTag | uri %]#reader-link"> >+ <img src="https://images-na.ssl-images-amazon.com/images/P/[% normalized_isbn | html %].01.MZZZZZZZ.jpg" alt="Amazon cover image" /> >+ </a> >+ <div class="hint">Image from Amazon.com</div> >+ </div> >+ [% END %] >+ [% IF ( IntranetCoce && CoceProviders && normalized_isbn ) %] >+ [% coce_id = normalized_ean || normalized_isbn %] >+ <div class="cover-image" id="coce-coverimg"> >+ [% IF ( coce_id ) %] >+ <span title="[% biblionumber | url %]" class="[% coce_id | html %]" id="coce-thumbnail-preview"></span> >+ [% ELSE %] >+ <span class="no-image">No cover image available</span> >+ [% END %] >+ <div class="hint">Image from Coce</div> >+ </div> >+ [% END %] > >-</div> >+ [% IF Koha.Preference('CustomCoverImages') && Koha.Preference('CustomCoverImagesURL') %] >+ <div class="cover-image" id="custom-coverimg"> >+ <a class="custom_cover_image" href="[% biblio.custom_cover_image_url | url %]"> >+ <img id="custom-img" alt="Custom cover image" src="[% biblio.custom_cover_image_url | url %]" /> >+ </a> >+ <div class="hint">Custom cover image</div> >+ </div> >+ [% END %] >+ </div> >+ </div> <!-- /#bookcoverimg --> >+ [% END %] > </div> > <div id="bibliodetails" class="toptabs"> > >@@ -825,30 +852,73 @@ Note that permanent location is a code, and location may be an authval. > var theme = "[% theme | html %]"; > // http://www.oreillynet.com/pub/a/javascript/2003/10/21/amazonhacks.html > function verify_images() { >- $("#bookcoverimg").each(function(i){ >- $(this).find('img').each(function(i){ >- if ((this.src.indexOf('images.amazon.com') >= 0) || (this.src.indexOf('g-images.amazon.com') >=0) || (this.src.indexOf('images-na.ssl-images-amazon.com'))) { >- w = this.width; >- h = this.height; >- if ((w == 1) || (h == 1)) { >- $("#amazon-bookcoverimg").remove(); >- } else if ((this.complete != null) && (!this.complete)) { >- $("#amazon-bookcoverimg").remove(); >+ // Loop over each container in the template which contains covers >+ var coverSlides = $(".cover-image"); >+ coverSlides.each( function( index ){ >+ var div = $(this); >+ // Find the image in the container >+ var img = div.find("img")[0]; >+ if( $(img).length > 0 ){ >+ if( (img.complete != null) && (!img.complete) || img.naturalHeight == 0 ){ >+ // No image loaded in the container. Remove the slide >+ div.remove(); >+ } else { >+ // All slides start hidden. If this is the first one, show it. >+ if( index == 0 ){ >+ div.show(); >+ } >+ // Check if Amazon image is present >+ if ( div.attr("id") == "amazon-bookcoverimg" ) { >+ w = img.width; >+ h = img.height; >+ if ((w == 1) || (h == 1)) { >+ // Amazon returned single-pixel placeholder >+ // Remove the container >+ div.remove(); >+ } >+ } >+ if( div.attr("id") == "custom-img" ){ >+ if ( (img.complete != null) && (!img.complete) || img.naturalHeight == 0 ) { >+ // No image was loaded via the CustomCoverImages system preference >+ // Remove the container >+ div.remove(); >+ } >+ } >+ if( div.attr("id") == "coce-coverimg" ){ >+ // Identify which service's image is being loaded by Coce >+ if( $(img).attr("src").indexOf('amazon.com') >= 0 ){ >+ div.find(".hint").html(_("Coce image from Amazon.com")); >+ } else if( $(img).attr("src").indexOf('google.com') >= 0 ){ >+ div.find(".hint").html(_("Coce image from Google Books")); >+ } else if( $(img).attr("src").indexOf('openlibrary.org') >= 0 ){ >+ div.find(".hint").html(_("Coce image from Open Library")); >+ } >+ } >+ // If more that one slide is present, add a navigation link >+ // for activating the slide >+ if( coverSlides.length > 1 ){ >+ var covernav = $("<a href=\"#\" data-num=\"" + index + "\" class=\"cover-nav\"></a>"); >+ if( index == 0 ){ >+ // Set the first navigation link as active >+ $(covernav).addClass("nav-active"); >+ } >+ $(covernav).html("<i class=\"fa fa-circle\"></i>"); >+ $("#cover-slides").append( covernav ); > } > } >- }); >- if( $(this).find('img').length < 1 ){ >- $(this).remove(); >- $("#catalogue_detail_biblio").attr("class","col-xs-12"); > } > }); >+ if( $(".cover-image:visible").length < 1 ){ >+ $("#cover-slides").remove(); >+ } >+ > $("#editions img").each(function(i){ >- if ((this.src.indexOf('images.amazon.com') >= 0) || (this.src.indexOf('g-images.amazon.com') >=0) || (this.src.indexOf('images-na.ssl-images-amazon.com'))) { >+ if ( this.src.indexOf('amazon.com') >= 0 ) { > w = this.width; > h = this.height; > if ((w == 1) || (h == 1)) { > this.src = 'https://images-na.ssl-images-amazon.com/images/G/01/x-site/icons/no-img-sm.gif'; >- } else if ((this.complete != null) && (!this.complete)) { >+ } else if ( (this.complete != null) && (!this.complete) || this.naturalHeight == 0 ) { > this.src = 'https://images-na.ssl-images-amazon.com/images/G/01/x-site/icons/no-img-sm.gif'; > } > } >@@ -981,10 +1051,6 @@ Note that permanent location is a code, and location may be an authval. > > return false; > }); >- [%# inject no images message %] >- [% IF LocalCoverImages %] >- KOHA.LocalCover.GetCoverFromBibnumber(true); >- [% END %] > [% IF ( IntranetCoce && CoceProviders ) %] > KOHA.coce.getURL('[% CoceHost | html %]', '[% CoceProviders | html %]'); > [% END %] >@@ -1017,11 +1083,19 @@ Note that permanent location is a code, and location may be an authval. > link = $(this).attr("href"); > openWindow(link,"Print spine label",400,400); > }); >+ $("#cover-slides").on("click",".cover-nav", function(){ >+ // Adding click handler for cover image navigation links >+ var num = $(this).data("num"); >+ $(".cover-nav").removeClass("nav-active"); >+ $(this).addClass("nav-active"); >+ $(".cover-image").hide(); >+ $(".cover-image").eq( num ).show(); >+ }); > }); > >- [% IF ( AmazonCoverImages || LocalCoverImages ) %]$(window).load(function() { >+ $(window).load(function() { > verify_images(); >- });[% END %] >+ }); > </script> > [% IF ( Koha.Preference('NovelistSelectStaffEnabled') && Koha.Preference('NovelistSelectStaffProfile') && ( normalized_isbn || normalized_upc ) ) %] > <script src="https://imageserver.ebscohost.com/novelistselect/ns2init.js"></script> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/localcovers.js b/koha-tmpl/intranet-tmpl/prog/js/localcovers.js >index fe6aeac897..a25d7c73f4 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/localcovers.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/localcovers.js >@@ -1,3 +1,5 @@ >+/* global _ */ >+ > if (typeof KOHA == "undefined" || !KOHA) { > var KOHA = {}; > } >@@ -18,42 +20,30 @@ KOHA.LocalCover = { > * olCallBack(). > */ > GetCoverFromBibnumber: function(uselink) { >- $("div [id^=local-thumbnail]").each(function(i) { >- var mydiv = this; >- var message = document.createElement("span"); >- $(message).attr("class","no-image"); >- $(message).html(NO_LOCAL_JACKET); >- $(mydiv).parent().find('.no-image').remove(); >- $(mydiv).append(message); >- var img = $("<img />").attr('src', >- '/cgi-bin/koha/catalogue/image.pl?thumbnail=1&biblionumber=' + $(mydiv).attr("class")) >- .load(function () { >- if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth <= 1) { >- //IE HACK >- try { >- $(mydiv).remove(); >- } >- catch(err){ >- } >- } else { >- if (uselink) { >- var a = $("<a />").attr('href', '/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=' + $(mydiv).attr("class")); >- $(a).append(img); >- $(mydiv).append(a); >- } else { >- $(mydiv).append(img); >- } >- $(mydiv).children('.no-image').remove(); >- } >- }); >- }); >+ var mydiv = $("#local-thumbnail-preview"); >+ var biblionumber = mydiv.data("biblionumber"); >+ var img = document.createElement("img"); >+ img.src = "/cgi-bin/koha/catalogue/image.pl?thumbnail=1&biblionumber=" + biblionumber; >+ img.onload = function() { >+ // image dimensions can't be known until image has loaded >+ if ( (img.complete != null) && (!img.complete) ) { >+ mydiv.remove(); >+ } >+ }; >+ if (uselink) { >+ var a = $("<a />").attr('href', '/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=' + $(mydiv).attr("class")); >+ $(a).append(img); >+ mydiv.append(a); >+ } else { >+ mydiv.append(img); >+ } > }, > LoadResultsCovers: function(){ > $("div [id^=local-thumbnail]").each(function(i) { > var mydiv = this; > var message = document.createElement("span"); > $(message).attr("class","no-image thumbnail"); >- $(message).html(NO_LOCAL_JACKET); >+ $(message).html( _("No cover image available") ); > $(mydiv).append(message); > var img = $("<img />"); > img.attr('src','/cgi-bin/koha/catalogue/image.pl?thumbnail=1&biblionumber=' + $(mydiv).attr("class")) >-- >2.11.0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 25031
:
102162
|
102295
|
103040
|
103079
|
105986
|
105987
|
106612
|
106613
|
107272
|
107310