View | Details | Raw Unified | Return to bug 14242
Collapse All | Expand All

(-)a/installer/data/mysql/atomicupdate/bug_14242-autofill_syspref.sql (+1 lines)
Line 0 Link Here
1
INSERT IGNORE INTO systempreferences (`variable`, `value`, `options`, `explanation`,`type`) VALUES ('OPACAutoFill', '0', NULL, 'Automaticly fill forms with data from Google Books API','YesNo');
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 340-345 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
340
('OAI-PMH:DeletedRecord','persistent','Koha\'s deletedbiblio table will never be deleted (persistent), might be deleted (transient), or will never have any data in it (no)','transient|persistent|no','Choice'),
340
('OAI-PMH:DeletedRecord','persistent','Koha\'s deletedbiblio table will never be deleted (persistent), might be deleted (transient), or will never have any data in it (no)','transient|persistent|no','Choice'),
341
('OAI-PMH:MaxCount','50',NULL,'OAI-PMH maximum number of records by answer to ListRecords and ListIdentifiers queries','Integer'),
341
('OAI-PMH:MaxCount','50',NULL,'OAI-PMH maximum number of records by answer to ListRecords and ListIdentifiers queries','Integer'),
342
('OPACAcquisitionDetails','0','','Show the acquisition details at the OPAC','YesNo'),
342
('OPACAcquisitionDetails','0','','Show the acquisition details at the OPAC','YesNo'),
343
('OPACAutoFill','0',NULL,'Automaticly fill forms with data from Google Books API','YesNo'),
343
('OpacAddMastheadLibraryPulldown','0','','Adds a pulldown menu to select the library to search on the opac masthead.','YesNo'),
344
('OpacAddMastheadLibraryPulldown','0','','Adds a pulldown menu to select the library to search on the opac masthead.','YesNo'),
344
('OpacAdvSearchMoreOptions','pubdate,itemtype,language,subtype,sorting,location','Show search options for the expanded view (More options)','pubdate|itemtype|language|subtype|sorting|location','multiple'),
345
('OpacAdvSearchMoreOptions','pubdate,itemtype,language,subtype,sorting,location','Show search options for the expanded view (More options)','pubdate|itemtype|language|subtype|sorting|location','multiple'),
345
('OpacAdvSearchOptions','pubdate,itemtype,language,sorting,location','Show search options','pubdate|itemtype|language|subtype|sorting|location','multiple'),
346
('OpacAdvSearchOptions','pubdate,itemtype,language,sorting,location','Show search options','pubdate|itemtype|language|subtype|sorting|location','multiple'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (+7 lines)
Lines 530-535 OPAC: Link Here
530
                  no: Don't display
530
                  no: Don't display
531
            - a branch selection list for news items in the OPAC.
531
            - a branch selection list for news items in the OPAC.
532
        -
532
        -
533
            - pref: OPACAutoFill
534
              default: 0
535
              choices:
536
                  yes: Enable
537
                  no: Disable
538
            - automatic form filling with data from Google Books API.
539
        -
533
            - "Use the following as the OPAC ISBD template:"
540
            - "Use the following as the OPAC ISBD template:"
534
            - pref: OPACISBD
541
            - pref: OPACISBD
535
              type: textarea
542
              type: textarea
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-bottom.inc (+4 lines)
Lines 250-255 $.widget.bridge('uitooltip', $.ui.tooltip); Link Here
250
    </script>
250
    </script>
251
[% END %]
251
[% END %]
252
252
253
[% IF ( Koha.Preference('OPACAutoFill') ) %]
254
    <script type="text/javascript" src="[% interface %]/[% theme %]/js/autofill.js"></script>
255
[% END %]
256
253
[% IF ( BakerTaylorEnabled ) %]
257
[% IF ( BakerTaylorEnabled ) %]
254
    [% Asset.js("js/bakertaylorimages.js") | $raw %]
258
    [% Asset.js("js/bakertaylorimages.js") | $raw %]
255
    <script>
259
    <script>
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-suggestions.tt (-11 / +33 lines)
Lines 41-47 Link Here
41
                            <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>
41
                            <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>
42
42
43
                            <form action="/cgi-bin/koha/opac-suggestions.pl" method="post" id="add_suggestion_form">
43
                            <form action="/cgi-bin/koha/opac-suggestions.pl" method="post" id="add_suggestion_form">
44
                                <fieldset class="rows">
44
                                [% IF Koha.Preference( 'OPACAutoFill' ) %]
45
                                <fieldset class="rows well" style="margin-bottom: 3em;padding-top: 5px;">
46
                                    <label for="isbn">Standard number (ISBN, ISSN or other):</label><input type="text" id="isbn" name="isbn"  maxlength="80" />
47
                                </fieldset>
48
                                [% END %]
49
                                    <fieldset class="rows [% IF Koha.Preference( 'OPACAutoFill' ) %]well[% END %]">
45
                                    <ol>
50
                                    <ol>
46
                                        <li>
51
                                        <li>
47
                                            [% IF ( title_required ) %]
52
                                            [% IF ( title_required ) %]
Lines 75-90 Link Here
75
                                                [% END %]
80
                                                [% END %]
76
                                            </div>
81
                                            </div>
77
                                        </li>
82
                                        </li>
78
                                        <li>
83
79
                                            [% IF ( isbn_required ) %]
84
                                        [% IF NOT Koha.Preference( 'OPACAutoFill' ) %]
80
                                                <label for="isbn" class="required">Standard number (ISBN, ISSN or other):</label>
85
                                            <li>
81
                                                <input type="text" id="isbn" name="isbn"  maxlength="80" required="required" />
86
                                                [% IF ( isbn_required ) %]
82
                                                <span class="required">Required</span>
87
                                                    <label for="isbn" class="required">Standard number (ISBN, ISSN or other):</label>
83
                                            [% ELSE %]
88
                                                    <input type="text" id="isbn" name="isbn"  maxlength="80" required="required" />
84
                                                <label for="isbn">Standard number (ISBN, ISSN or other):</label>
89
                                                    <span class="required">Required</span>
85
                                                <input type="text" id="isbn" name="isbn"  maxlength="80" />
90
                                                [% ELSE %]
86
                                            [% END %]
91
                                                    <label for="isbn">Standard number (ISBN, ISSN or other):</label>
87
                                        </li>
92
                                                    <input type="text" id="isbn" name="isbn"  maxlength="80" />
93
                                                [% END %]
94
                                            </li>
95
                                        [% END %]
96
88
                                        <li>
97
                                        <li>
89
                                            [% IF ( publishercode_required ) %]
98
                                            [% IF ( publishercode_required ) %]
90
                                                <label for="publishercode" class="required">Publisher:</label>
99
                                                <label for="publishercode" class="required">Publisher:</label>
Lines 396-401 Link Here
396
        }
405
        }
397
    [% END %]
406
    [% END %]
398
407
408
    [% IF Koha.Preference( 'OPACAutoFill' ) %]
409
    $(function() {
410
        $('#isbn').autofill({
411
            'volumeInfo.title': {target: 'title', effect: 'flash'},
412
            'volumeInfo.authors': {target: 'author', effect: 'flash'},
413
            'volumeInfo.publisher': {target: 'publishercode', effect: 'flash'},
414
            /* google books api seem to only have books, so if we got a result
415
             * item, type will be a book, so set to BK (book). */
416
            'kind': {target: 'itemtype', handle: function(t,v) { t.val('BK'); },},
417
        });
418
    });
419
    [% END %]
420
399
    $(function() {
421
    $(function() {
400
        $("#suggestt").dataTable($.extend(true, {}, dataTablesDefaults, {
422
        $("#suggestt").dataTable($.extend(true, {}, dataTablesDefaults, {
401
            "order": [[ 1, "asc" ]],
423
            "order": [[ 1, "asc" ]],
(-)a/koha-tmpl/opac-tmpl/bootstrap/js/autofill.js (-1 / +202 lines)
Line 0 Link Here
0
- 
1
/*
2
 * jQuery autofill plugin
3
 *
4
 * Automaticly fills form inputs with relevant data based on search result
5
 */
6
7
(function ($) {
8
    function typeString(o) {
9
        if (typeof o != 'object')
10
            return typeof o;
11
12
        if (o === null)
13
            return "null";
14
15
        //object, array, function, date, regexp, string, number, boolean, error
16
        var internalClass = Object.prototype.toString.call(o)
17
            .match(/\[object\s(\w+)\]/)[1];
18
19
        return internalClass.toLowerCase();
20
    }
21
22
    var AutoFiller = function (elm, fields, type) {
23
        var self = this;
24
        self.type = type;
25
        self.$elm = $(elm);
26
        self.fields = fields;
27
28
        /* decorate element as autofiller */
29
        var $inputgroup = $('<div class="input-prepend">');
30
        self.$undo = $('<span class="add-on" style="display:none;cursor:pointer;">undo</span>');
31
        self.$fillbtn = $('<span class="add-on"><i class="icon-edit" style="cursor:pointer;"></i></span>');
32
        self.$error = $('<span class="add-on" style="display:none;"></span>');
33
        self.$elm.wrap($inputgroup);
34
        self.$elm.after(self.$error);
35
        self.$elm.after(self.$undo);
36
        self.$elm.after(self.$fillbtn);
37
38
        for(var key in fields) {
39
            if( fields.hasOwnProperty(key) && typeof fields[key] === 'object' ) {
40
                var $target = $('#' + self.fields[key].target);
41
                self.fields[key].$target = $target;
42
            }
43
        }
44
45
        self.$fillbtn.click(function(){
46
            /* only allow forced update once every second */
47
            if(Date.now() - self.lastupdate > 1000) {
48
                self.$elm.trigger('change');
49
            }
50
        });
51
52
        self.$undo.click(function(){
53
            for(var key in self.fields) {
54
                var field = self.fields[key];
55
                field.$target.trigger('autofill-undo');
56
            }
57
            self.$undo.hide();
58
        });
59
60
        self.$elm.change(function() {
61
            self.lastupdate = Date.now();
62
            self.$error.html('');
63
            self.$error.hide();
64
            /* give user some feedback that the request is in progress */
65
            self.$fillbtn.fadeOut(1000).fadeIn(1000);
66
67
            var gAPI = 'https://www.googleapis.com/books/v1/volumes?q=';
68
            if(self.type)
69
                gAPI += self.type + ':';
70
            gAPI += self.$elm.val();
71
            gAPI += '&maxResults=1';
72
73
            $.getJSON(gAPI, function (response) {
74
                if(response.totalItems == 0) {
75
                    self.$error.html('Sorry, nothing found.');
76
                    self.$error.show();
77
                    return;
78
                }
79
80
                var undos = 0;
81
                var item = response.items[0];
82
                for(var key in self.fields) {
83
                    var filled = false;
84
                    var value = eval('item.'+key);
85
                    var field = self.fields[key];
86
87
                    /* field handled by caller */
88
                    if('handle' in field) {
89
                        if(typeof field.handle === 'function')
90
                            field.handle(field.$target, value);
91
92
                        continue; /* next please */
93
                    }
94
95
                    /* wouldn't know what to do with result unless we have a
96
                     * target */
97
                    if( ! field.$target )
98
                        continue;
99
100
                    /* handle differently depending on datatype */
101
                    switch(typeString(value)) {
102
                        case 'array':
103
                            switch(field.$target.prop('nodeName').toUpperCase()) {
104
                                case 'TEXTAREA':
105
                                    undos++;
106
                                    field.$target.bind('autofill-undo', field.$target.text(), function(e){$(this).text(e.data);});
107
                                    field.$target.text(value.join(', '));
108
                                    break;
109
                                case 'INPUT':
110
                                default:
111
                                    undos++;
112
                                    field.$target.bind('autofill-undo', field.$target.val(), function(e){$(this).val(e.data);});
113
                                    field.$target.val(value.join(', '));
114
                                    break;
115
                            }
116
                            break;
117
                        default:
118
                            switch(field.$target.prop('nodeName').toUpperCase()) {
119
                                case 'TEXTAREA':
120
                                    undos++;
121
                                    field.$target.bind('autofill-undo', field.$target.text(), function(e){$(this).text(e.data);});
122
                                    field.$target.text(value);
123
                                    break;
124
                                case 'SELECT':
125
                                case 'INPUT':
126
                                default:
127
                                    undos++;
128
                                    field.$target.bind('autofill-undo', field.$target.val(), function(e){$(this).val(e.data);});
129
                                    field.$target.val(value);
130
                                    break;
131
                            }
132
                    }
133
134
                    switch(field.effect) {
135
                        case 'flash':
136
                            field.$target.fadeOut(500).fadeIn(500);
137
                            break;
138
                    }
139
                }
140
141
                if(undos > 0)
142
                    self.$undo.show();
143
144
            });
145
        });
146
    };
147
148
    /*
149
     * @fields object: Google Books API item propreties map for
150
     *                 mapping against a target element. Expected
151
     *                 type:
152
     *                 {
153
     *                  GoogleBooksItem.property: {target: ELEM,
154
     *                                             handle: function(target, value),
155
     *                                             effect: jQuery effects,
156
     *                                            }
157
     *                 }
158
     *
159
     *                 "target" is optional and if specified alone (i.e no
160
     *                 handle proprety) autofill will automaticly fill this
161
     *                 target element with returned data.
162
     *
163
     *                 "handle" is optional and will be called when ajax request
164
     *                 has finished and target is matched. Function specifies
165
     *                 two arguments: target and value. Target is the target
166
     *                 element specified by "target" and value is the value
167
     *                 returned by Google Books API for the matched property.
168
     *
169
     *                 If a handle function is given, full control of result data
170
     *                 is given to the handle function.
171
     *
172
     *                 "effect" is optional and specifies effect name of effect
173
     *                 to use for the target once value has been set. Can be one of:
174
     *
175
     *                      - 'flash'
176
     *
177
     * @type string: defines the query type, default to input name
178
     *               For example <input type="text" name="isbn"></input>
179
     *               will search for isbn by default
180
     *
181
     * @EXAMPLE
182
     *
183
     *  $('#isbn').autofill({
184
     *      'volumeInfo.title': {target: 'title', effect: 'flash'},
185
     *      'volumeInfo.authors': {target: 'author'},
186
     *      'volumeInfo.publisher': {target: 'publishercode'},
187
     *      'selfLink': {handle: function(t,v){window.location=v;}}
188
     *  });
189
     * */
190
    $.fn.autofill = function(fields, type) {
191
        if(type === undefined) // default to input name
192
            type = this.attr('name');
193
194
        return this.each(function(i){
195
            var plugin = $.data(this, "plugin_autofill");
196
            if (plugin)
197
                plugin.destroy();
198
199
            $.data(this, "plugin_autofill", new AutoFiller(this, fields, type));
200
        });
201
    };
202
}(jQuery));

Return to bug 14242