/* * Plugin dealing with the Google API based on jQuery autofill plugin * https://plugins.jquery.com/autofill/ * * Automatically fills form inputs with relevant data based on search result * Modified for OPAC Suggestion form */ (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; var MSG_UNDO_AUTOFILL_SUGGESTION = __("Clear form"); var MSG_SEARCH_GOOGLE_BOOKS = __("Search Google Books"); /* decorate element as autofiller */ self.$undo = $(''); self.$fillbtn = $(''); self.$error = $(''); 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(){ /* clear fields first */ for(var key in self.fields) { var field = self.fields[key]; field.$target.trigger('autofill-undo'); } /* 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.val(""); field.$target.trigger('autofill-undo'); } $(":input[type='text']").each(function(){ $(this).val(""); }); 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); if ( self.$elm.val()) { var gAPI = 'https://www.googleapis.com/books/v1/volumes?q='; gAPI += self.$elm.val().replace(/\-/g, ''); 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; /* format copyrightdate */ if ( field.target == 'copyrightdate' ) { if ( value.indexOf('-') > -1 ) { var hyphenIndex = value.indexOf('-'); var newval = value.slice(0, hyphenIndex); value = newval; } } /* 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 * 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));