2 * Plugin dealing with the Google API based on jQuery autofill plugin
3 * https://plugins.jquery.com/autofill/
5 * Automatically fills form inputs with relevant data based on search result
6 * Modified for OPAC Suggestion form
10 function typeString(o) {
11 if (typeof o != 'object')
17 //object, array, function, date, regexp, string, number, boolean, error
18 var internalClass = Object.prototype.toString.call(o)
19 .match(/\[object\s(\w+)\]/)[1];
21 return internalClass.toLowerCase();
24 var AutoFiller = function (elm, fields, type) {
30 var MSG_UNDO_AUTOFILL_SUGGESTION = __("Clear form");
31 var MSG_SEARCH_GOOGLE_BOOKS = __("Search Google Books");
33 /* decorate element as autofiller */
34 self.$undo = $('<input type="button" class="btn btn-info btn-sm" style="display:none;margin-left:5px;" value="' + MSG_UNDO_AUTOFILL_SUGGESTION + '" />');
35 self.$fillbtn = $('<input type="button" class="btn btn-primary btn-sm" value="' + MSG_SEARCH_GOOGLE_BOOKS + '" />');
36 self.$error = $('<span class="add-on" style="display:none;padding-left:5px;"></span>');
37 self.$elm.after(self.$error);
38 self.$elm.after(self.$undo);
39 self.$elm.after(self.$fillbtn);
41 for(var key in fields) {
42 if( fields.hasOwnProperty(key) && typeof fields[key] === 'object' ) {
43 var $target = $('#' + self.fields[key].target);
44 self.fields[key].$target = $target;
48 self.$fillbtn.click(function(){
49 /* clear fields first */
50 for(var key in self.fields) {
51 var field = self.fields[key];
52 field.$target.trigger('autofill-undo');
54 /* only allow forced update once every second */
55 if(Date.now() - self.lastupdate > 1000) {
56 self.$elm.trigger('change');
60 self.$undo.click(function(){
61 for(var key in self.fields) {
62 var field = self.fields[key];
63 //field.$target.val("");
64 field.$target.trigger('autofill-undo');
66 $(":input[type='text']").each(function(){
72 self.$elm.change(function() {
73 self.lastupdate = Date.now();
76 /* give user some feedback that the request is in progress */
77 self.$fillbtn.fadeOut(1000).fadeIn(1000);
78 if ( self.$elm.val()) {
79 var gAPI = 'https://www.googleapis.com/books/v1/volumes?q=';
80 gAPI += self.$elm.val().replace(/\-/g, '');
81 gAPI += '&maxResults=1';
82 $.getJSON(gAPI, function (response) {
83 if(response.totalItems == 0) {
84 self.$error.html(__('Sorry, nothing found.'));
90 var item = response.items[0];
91 for(var key in self.fields) {
93 var value = eval('item.'+key);
94 var field = self.fields[key];
96 /* field handled by caller */
97 if('handle' in field) {
98 if(typeof field.handle === 'function')
99 field.handle(field.$target, value);
101 continue; /* next please */
104 /* wouldn't know what to do with result unless we have a
106 if( ! field.$target )
109 /* format copyrightdate */
110 if ( field.target == 'copyrightdate' ) {
111 if ( value.indexOf('-') > -1 ) {
112 var hyphenIndex = value.indexOf('-');
113 var newval = value.slice(0, hyphenIndex);
118 /* handle differently depending on datatype */
119 switch(typeString(value)) {
121 switch(field.$target.prop('nodeName').toUpperCase()) {
124 field.$target.bind('autofill-undo', field.$target.text(), function(e){$(this).text(e.data);});
125 field.$target.text(value.join(', '));
130 field.$target.bind('autofill-undo', field.$target.val(), function(e){$(this).val(e.data);});
131 field.$target.val(value.join(', '));
136 switch(field.$target.prop('nodeName').toUpperCase()) {
139 field.$target.bind('autofill-undo', field.$target.text(), function(e){$(this).text(e.data);});
140 field.$target.text(value);
146 field.$target.bind('autofill-undo', field.$target.val(), function(e){$(this).val(e.data);});
147 field.$target.val(value);
152 switch(field.effect) {
154 field.$target.fadeOut(500).fadeIn(500);
168 * @fields object: Google Books API item propreties map for
169 * mapping against a target element. Expected
172 * GoogleBooksItem.property: {target: ELEM,
173 * handle: function(target, value),
174 * effect: jQuery effects,
178 * "target" is optional and if specified alone (i.e no
179 * handle proprety) autofill will automaticly fill this
180 * target element with returned data.
182 * "handle" is optional and will be called when ajax request
183 * has finished and target is matched. Function specifies
184 * two arguments: target and value. Target is the target
185 * element specified by "target" and value is the value
186 * returned by Google Books API for the matched property.
188 * If a handle function is given, full control of result data
189 * is given to the handle function.
191 * "effect" is optional and specifies effect name of effect
192 * to use for the target once value has been set. Can be one of:
196 * @type string: defines the query type, default to input name
197 * For example <input type="text" name="isbn"></input>
198 * will search for isbn by default
202 * $('#isbn').autofill({
203 * 'volumeInfo.title': {target: 'title', effect: 'flash'},
204 * 'volumeInfo.authors': {target: 'author'},
205 * 'volumeInfo.publisher': {target: 'publishercode'},
206 * 'selfLink': {handle: function(t,v){window.location=v;}}
209 $.fn.autofill = function(fields, type) {
210 if(type === undefined) // default to input name
211 type = this.attr('name');
213 return this.each(function(i){
214 var plugin = $.data(this, "plugin_autofill");
218 $.data(this, "plugin_autofill", new AutoFiller(this, fields, type));