Bugzilla – Attachment 56072 Details for
Bug 14242
Use ISBN-field to fill out purchase suggestions using Google Books API
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 14242: Use ISBN-field to automaticly fill out purchase suggestions
Bug-14242-Use-ISBN-field-to-automaticly-fill-out-p.patch (text/plain), 16.82 KB, created by
Marc Véron
on 2016-10-06 11:20:09 UTC
(
hide
)
Description:
Bug 14242: Use ISBN-field to automaticly fill out purchase suggestions
Filename:
MIME Type:
Creator:
Marc Véron
Created:
2016-10-06 11:20:09 UTC
Size:
16.82 KB
patch
obsolete
>From edb91dffb088dbc7327223bd6bee89471bb709c9 Mon Sep 17 00:00:00 2001 >From: Martin Stenberg <martin@xinxidi.net> >Date: Wed, 26 Aug 2015 20:22:30 +0200 >Subject: [PATCH] Bug 14242: Use ISBN-field to automaticly fill out purchase > suggestions > >Add new jQuery plugin "autofill" which transforms selected element(s) into >search fields for Google Books API and automaticly fills requested fields with >search result. > >Use in OPAC purchase suggestions to automaticly fill out fields when entering >ISBN-number. > >Test plan: >1. Run updatedatabase.pl >2. Enable system precference "OPACAutoFill" >3. Log into OPAC and go to purchase suggetions page >4. Write a valid ISBN into the ISBN field and press the edit icon next to the > field, or unfocus the field. >5. Title, Author, Publisher and Item Type fields should now be filled > automaticly. >6. Press "undo" to undo - should restore all changed fields to original values > >Tested all patches together, works as expected. >Signed-off-by: Marc <veron@veron.ch> >--- > .../atomicupdate/bug_14242-autofill_syspref.sql | 1 + > installer/data/mysql/sysprefs.sql | 1 + > .../prog/en/modules/admin/preferences/opac.pref | 7 + > .../bootstrap/en/includes/opac-bottom.inc | 4 + > .../bootstrap/en/modules/opac-suggestions.tt | 24 ++- > koha-tmpl/opac-tmpl/bootstrap/js/autofill.js | 202 +++++++++++++++++++++ > 6 files changed, 237 insertions(+), 2 deletions(-) > create mode 100644 installer/data/mysql/atomicupdate/bug_14242-autofill_syspref.sql > create mode 100644 koha-tmpl/opac-tmpl/bootstrap/js/autofill.js > >diff --git a/installer/data/mysql/atomicupdate/bug_14242-autofill_syspref.sql b/installer/data/mysql/atomicupdate/bug_14242-autofill_syspref.sql >new file mode 100644 >index 0000000..3cb4ffb >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/bug_14242-autofill_syspref.sql >@@ -0,0 +1 @@ >+INSERT IGNORE INTO systempreferences (`variable`, `value`, `options`, `explanation`,`type`) VALUES ('OPACAutoFill', '0', NULL, 'Automaticly fill forms with data from Google Books API','YesNo'); >diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql >index 169665f..9d89af6 100644 >--- a/installer/data/mysql/sysprefs.sql >+++ b/installer/data/mysql/sysprefs.sql >@@ -278,6 +278,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` > ('OAI-PMH:MaxCount','50',NULL,'OAI-PMH maximum number of records by answer to ListRecords and ListIdentifiers queries','Integer'), > ('OCLCAffiliateID','','','Use with FRBRizeEditions and XISBN. You can sign up for an AffiliateID here: http://www.worldcat.org/wcpa/do/AffiliateUserServices?method=initSelfRegister','free'), > ('OPACAcquisitionDetails','0','','Show the acquisition details at the OPAC','YesNo'), >+('OPACAutoFill','0',NULL,'Automaticly fill forms with data from Google Books API','YesNo'), > ('OpacAddMastheadLibraryPulldown','0','','Adds a pulldown menu to select the library to search on the opac masthead.','YesNo'), > ('OpacAdvSearchMoreOptions','pubdate,itemtype,language,subtype,sorting,location','Show search options for the expanded view (More options)','pubdate|itemtype|language|subtype|sorting|location','multiple'), > ('OpacAdvSearchOptions','pubdate,itemtype,language,sorting,location','Show search options','pubdate|itemtype|language|subtype|sorting|location','multiple'), >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref >index 62aaeff..1719a9c 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref >@@ -503,6 +503,13 @@ OPAC: > no: Don't display > - the acquisition details on OPAC detail pages. > - >+ - pref: OPACAutoFill >+ default: 0 >+ choices: >+ yes: Enable >+ no: Disable >+ - automatic form filling with data from Google Books API. >+ - > - "Use the following as the OPAC ISBD template:" > - pref: OPACISBD > type: textarea >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-bottom.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-bottom.inc >index 1a13370..309ae9a 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-bottom.inc >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-bottom.inc >@@ -214,6 +214,10 @@ $.widget.bridge('uitooltip', $.ui.tooltip); > </script> > [% END %] > >+[% IF ( Koha.Preference('OPACAutoFill') ) %] >+ <script type="text/javascript" src="[% interface %]/[% theme %]/js/autofill.js"></script> >+[% END %] >+ > [% IF ( BakerTaylorEnabled ) %] > <script type="text/javascript" src="[% interface %]/[% theme %]/js/bakertaylorimages.js"></script> > <script type="text/javascript"> >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-suggestions.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-suggestions.tt >index 2645905..0a155ef 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-suggestions.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-suggestions.tt >@@ -39,7 +39,12 @@ > <p>Only certain fields (marked in red) are required, but the more information you enter the easier it will be for the librarians to find the title you're requesting. The "Notes" field can be used to provide any additional information.</p> > > <form action="/cgi-bin/koha/opac-suggestions.pl" method="post" id="add_suggestion_form"> >- <fieldset class="rows"> >+ [% IF Koha.Preference( 'OPACAutoFill' ) %] >+ <fieldset class="rows well" style="margin-bottom: 3em;padding-top: 5px;"> >+ <label for="isbn">Standard number (ISBN, ISSN or other):</label><input type="text" id="isbn" name="isbn" maxlength="80" /> >+ </fieldset> >+ [% END %] >+ <fieldset class="rows [% IF Koha.Preference( 'OPACAutoFill' ) %]well[% END %]"> > <ol> > <li><label for="title">Title:</label><input type="text" id="title" name="title" class="span6" maxlength="255" /></li> > <li><label for="author">Author:</label><input type="text" id="author" name="author" class="span6" maxlength="80" /></li> >@@ -48,7 +53,9 @@ > <label for="copyrightdate">Copyright date:</label><input type="text" id="copyrightdate" name="copyrightdate" pattern="[12]\d{3}" size="4" maxlength="4" /> > </div> > </li> >- <li><label for="isbn">Standard number (ISBN, ISSN or other):</label><input type="text" id="isbn" name="isbn" maxlength="80" /></li> >+ [% IF NOT Koha.Preference( 'OPACAutoFill' ) %] >+ <li><label for="isbn">Standard number (ISBN, ISSN or other):</label><input type="text" id="isbn" name="isbn" maxlength="80" /></li> >+ [% END %] > <li><label for="publishercode">Publisher:</label><input type="text" id="publishercode" name="publishercode" class="span6" maxlength="80" /></li> > <li><label for="collectiontitle">Collection title:</label><input type="text" id="collectiontitle" name="collectiontitle" class="span6" maxlength="80" /></li> > <li><label for="place">Publication place:</label><input type="text" id="place" name="place" maxlength="80" /></li> >@@ -290,6 +297,19 @@ > } > [% END %] > >+ [% IF Koha.Preference( 'OPACAutoFill' ) %] >+ $(function() { >+ $('#isbn').autofill({ >+ 'volumeInfo.title': {target: 'title', effect: 'flash'}, >+ 'volumeInfo.authors': {target: 'author', effect: 'flash'}, >+ 'volumeInfo.publisher': {target: 'publishercode', effect: 'flash'}, >+ /* google books api seem to only have books, so if we got a result >+ * item, type will be a book, so set to BK (book). */ >+ 'kind': {target: 'itemtype', handle: function(t,v) { t.val('BK'); },}, >+ }); >+ }); >+ [% END %] >+ > $(function() { > $("#suggestt").dataTable($.extend(true, {}, dataTablesDefaults, { > "aaSorting": [[ 1, "asc" ]], >diff --git a/koha-tmpl/opac-tmpl/bootstrap/js/autofill.js b/koha-tmpl/opac-tmpl/bootstrap/js/autofill.js >new file mode 100644 >index 0000000..f6c487a >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/bootstrap/js/autofill.js >@@ -0,0 +1,202 @@ >+/* >+ * jQuery autofill plugin >+ * >+ * Automaticly fills form inputs with relevant data based on search result >+ */ >+ >+(function ($) { >+ function typeString(o) { >+ if (typeof o != 'object') >+ return typeof o; >+ >+ if (o === null) >+ return "null"; >+ >+ //object, array, function, date, regexp, string, number, boolean, error >+ var internalClass = Object.prototype.toString.call(o) >+ .match(/\[object\s(\w+)\]/)[1]; >+ >+ return internalClass.toLowerCase(); >+ } >+ >+ var AutoFiller = function (elm, fields, type) { >+ var self = this; >+ self.type = type; >+ self.$elm = $(elm); >+ self.fields = fields; >+ >+ /* decorate element as autofiller */ >+ var $inputgroup = $('<div class="input-prepend">'); >+ self.$undo = $('<span class="add-on" style="display:none;cursor:pointer;">undo</span>'); >+ self.$fillbtn = $('<span class="add-on"><i class="icon-edit" style="cursor:pointer;"></i></span>'); >+ self.$error = $('<span class="add-on" style="display:none;"></span>'); >+ self.$elm.wrap($inputgroup); >+ self.$elm.after(self.$error); >+ self.$elm.after(self.$undo); >+ self.$elm.after(self.$fillbtn); >+ >+ for(var key in fields) { >+ if( fields.hasOwnProperty(key) && typeof fields[key] === 'object' ) { >+ var $target = $('#' + self.fields[key].target); >+ self.fields[key].$target = $target; >+ } >+ } >+ >+ self.$fillbtn.click(function(){ >+ /* only allow forced update once every second */ >+ if(Date.now() - self.lastupdate > 1000) { >+ self.$elm.trigger('change'); >+ } >+ }); >+ >+ self.$undo.click(function(){ >+ for(var key in self.fields) { >+ var field = self.fields[key]; >+ field.$target.trigger('autofill-undo'); >+ } >+ self.$undo.hide(); >+ }); >+ >+ self.$elm.change(function() { >+ self.lastupdate = Date.now(); >+ self.$error.html(''); >+ self.$error.hide(); >+ /* give user some feedback that the request is in progress */ >+ self.$fillbtn.fadeOut(1000).fadeIn(1000); >+ >+ var gAPI = 'https://www.googleapis.com/books/v1/volumes?q='; >+ if(self.type) >+ gAPI += self.type + ':'; >+ gAPI += self.$elm.val(); >+ gAPI += '&maxResults=1'; >+ >+ $.getJSON(gAPI, function (response) { >+ if(response.totalItems == 0) { >+ self.$error.html('Sorry, nothing found.'); >+ self.$error.show(); >+ return; >+ } >+ >+ var undos = 0; >+ var item = response.items[0]; >+ for(var key in self.fields) { >+ var filled = false; >+ var value = eval('item.'+key); >+ var field = self.fields[key]; >+ >+ /* field handled by caller */ >+ if('handle' in field) { >+ if(typeof field.handle === 'function') >+ field.handle(field.$target, value); >+ >+ continue; /* next please */ >+ } >+ >+ /* wouldn't know what to do with result unless we have a >+ * target */ >+ if( ! field.$target ) >+ continue; >+ >+ /* handle differently depending on datatype */ >+ switch(typeString(value)) { >+ case 'array': >+ switch(field.$target.prop('nodeName').toUpperCase()) { >+ case 'TEXTAREA': >+ undos++; >+ field.$target.bind('autofill-undo', field.$target.text(), function(e){$(this).text(e.data);}); >+ field.$target.text(value.join(', ')); >+ break; >+ case 'INPUT': >+ default: >+ undos++; >+ field.$target.bind('autofill-undo', field.$target.val(), function(e){$(this).val(e.data);}); >+ field.$target.val(value.join(', ')); >+ break; >+ } >+ break; >+ default: >+ switch(field.$target.prop('nodeName').toUpperCase()) { >+ case 'TEXTAREA': >+ undos++; >+ field.$target.bind('autofill-undo', field.$target.text(), function(e){$(this).text(e.data);}); >+ field.$target.text(value); >+ break; >+ case 'SELECT': >+ case 'INPUT': >+ default: >+ undos++; >+ field.$target.bind('autofill-undo', field.$target.val(), function(e){$(this).val(e.data);}); >+ field.$target.val(value); >+ break; >+ } >+ } >+ >+ switch(field.effect) { >+ case 'flash': >+ field.$target.fadeOut(500).fadeIn(500); >+ break; >+ } >+ } >+ >+ if(undos > 0) >+ self.$undo.show(); >+ >+ }); >+ }); >+ }; >+ >+ /* >+ * @fields object: Google Books API item propreties map for >+ * mapping against a target element. Expected >+ * type: >+ * { >+ * GoogleBooksItem.property: {target: ELEM, >+ * handle: function(target, value), >+ * effect: jQuery effects, >+ * } >+ * } >+ * >+ * "target" is optional and if specified alone (i.e no >+ * handle proprety) autofill will automaticly fill this >+ * target element with returned data. >+ * >+ * "handle" is optional and will be called when ajax request >+ * has finished and target is matched. Function specifies >+ * two arguments: target and value. Target is the target >+ * element specified by "target" and value is the value >+ * returned by Google Books API for the matched property. >+ * >+ * If a handle function is given, full control of result data >+ * is given to the handle function. >+ * >+ * "effect" is optional and specifies effect name of effect >+ * to use for the target once value has been set. Can be one of: >+ * >+ * - 'flash' >+ * >+ * @type string: defines the query type, default to input name >+ * For example <input type="text" name="isbn"></input> >+ * will search for isbn by default >+ * >+ * @EXAMPLE >+ * >+ * $('#isbn').autofill({ >+ * 'volumeInfo.title': {target: 'title', effect: 'flash'}, >+ * 'volumeInfo.authors': {target: 'author'}, >+ * 'volumeInfo.publisher': {target: 'publishercode'}, >+ * 'selfLink': {handle: function(t,v){window.location=v;}} >+ * }); >+ * */ >+ $.fn.autofill = function(fields, type) { >+ if(type === undefined) // default to input name >+ type = this.attr('name'); >+ >+ return this.each(function(i){ >+ var plugin = $.data(this, "plugin_autofill"); >+ if (plugin) >+ plugin.destroy(); >+ >+ $.data(this, "plugin_autofill", new AutoFiller(this, fields, type)); >+ }); >+ }; >+}(jQuery)); >-- >2.1.4
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 14242
:
42002
|
55949
|
56061
|
56062
|
56070
|
56071
|
56072
|
56073
|
56074
|
56075
|
84760
|
84761
|
84762
|
84763
|
84764
|
84840
|
85031
|
85032
|
85033
|
85034
|
85035
|
89643
|
89662
|
90157
|
90158
|
90159
|
90160
|
90161
|
90162
|
90250
|
90251
|
90252
|
90253
|
90254
|
90255
|
103527
|
103528
|
103529
|
103530
|
103531
|
103532
|
103533
|
108695
|
108696
|
108697
|
108698
|
108699
|
108700
|
108701
|
110141
|
110142
|
110143
|
110144
|
110145
|
110146
|
110147
|
110148
|
110493
|
110494
|
110495
|
110496
|
110497
|
110498
|
110499
|
110500
|
110501
|
110990
|
112597
|
112598
|
112599
|
112600
|
112601
|
112602
|
112603
|
112604
|
112605
|
112606
|
112607
|
113162
|
113163
|
113164
|
113165
|
113166
|
113167
|
116620
|
116712
|
116968
|
116989
|
125380
|
125381
|
125382
|
131219
|
131220
|
131221
|
131222
|
133985
|
133986
|
133987
|
133988
|
134273
|
134274
|
134275
|
134276
|
134277
|
134278