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

(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 365-370 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
365
('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'),
365
('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'),
366
('OAI-PMH:MaxCount','50',NULL,'OAI-PMH maximum number of records by answer to ListRecords and ListIdentifiers queries','Integer'),
366
('OAI-PMH:MaxCount','50',NULL,'OAI-PMH maximum number of records by answer to ListRecords and ListIdentifiers queries','Integer'),
367
('OPACAcquisitionDetails','0','','Show the acquisition details at the OPAC','YesNo'),
367
('OPACAcquisitionDetails','0','','Show the acquisition details at the OPAC','YesNo'),
368
('OPACAutoFill','0',NULL,'Automaticly fill forms with data from Google Books API','YesNo'),
368
('OpacAddMastheadLibraryPulldown','0','','Adds a pulldown menu to select the library to search on the opac masthead.','YesNo'),
369
('OpacAddMastheadLibraryPulldown','0','','Adds a pulldown menu to select the library to search on the opac masthead.','YesNo'),
369
('OpacAdvSearchMoreOptions','pubdate,itemtype,language,subtype,sorting,location','Show search options for the expanded view (More options)','pubdate|itemtype|language|subtype|sorting|location','multiple'),
370
('OpacAdvSearchMoreOptions','pubdate,itemtype,language,subtype,sorting,location','Show search options for the expanded view (More options)','pubdate|itemtype|language|subtype|sorting|location','multiple'),
370
('OpacAdvSearchOptions','pubdate,itemtype,language,sorting,location','Show search options','pubdate|itemtype|language|subtype|sorting|location','multiple'),
371
('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 527-532 OPAC: Link Here
527
                  no: Don't display
527
                  no: Don't display
528
            - a library selection list for news items in the OPAC.
528
            - a library selection list for news items in the OPAC.
529
        -
529
        -
530
            - pref: OPACAutoFill
531
              default: 0
532
              choices:
533
                  yes: Enable
534
                  no: Disable
535
            - automatic form filling with data from Google Books API.
536
        -
530
            - "Use the following as the OPAC ISBD template:"
537
            - "Use the following as the OPAC ISBD template:"
531
            - pref: OPACISBD
538
            - pref: OPACISBD
532
              type: textarea
539
              type: textarea
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-bottom.inc (+4 lines)
Lines 279-284 $.widget.bridge('uitooltip', $.ui.tooltip); Link Here
279
    </script>
279
    </script>
280
[% END %]
280
[% END %]
281
281
282
[% IF ( Koha.Preference('OPACAutoFill') ) %]
283
    <script type="text/javascript" src="[% interface %]/[% theme %]/js/autofill.js"></script>
284
[% END %]
285
282
[% IF ( BakerTaylorEnabled ) %]
286
[% IF ( BakerTaylorEnabled ) %]
283
    [% Asset.js("js/bakertaylorimages.js") | $raw %]
287
    [% Asset.js("js/bakertaylorimages.js") | $raw %]
284
    <script>
288
    <script>
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-suggestions.tt (-11 / +31 lines)
Lines 64-70 Link Here
64
                            [% END %]
64
                            [% END %]
65
65
66
                            <form action="/cgi-bin/koha/opac-suggestions.pl" method="post" id="add_suggestion_form">
66
                            <form action="/cgi-bin/koha/opac-suggestions.pl" method="post" id="add_suggestion_form">
67
                                <fieldset class="rows">
67
                                [% IF Koha.Preference( 'OPACAutoFill' ) %]
68
                                <fieldset class="rows well" style="margin-bottom: 3em;padding-top: 5px;">
69
                                    <label for="isbn">Standard number (ISBN, ISSN or other):</label><input type="text" id="isbn" name="isbn"  maxlength="80" />
70
                                </fieldset>
71
                                [% END %]
72
                                    <fieldset class="rows [% IF Koha.Preference( 'OPACAutoFill' ) %]well[% END %]">
68
                                    <ol>
73
                                    <ol>
69
                                        <li>
74
                                        <li>
70
                                            [% IF ( title_required ) %]
75
                                            [% IF ( title_required ) %]
Lines 98-113 Link Here
98
                                                [% END %]
103
                                                [% END %]
99
                                            </div>
104
                                            </div>
100
                                        </li>
105
                                        </li>
101
                                        <li>
106
                                        [% UNLESS Koha.Preference( 'OPACAutoFill' ) %]
102
                                            [% IF ( isbn_required ) %]
107
                                            <li>
103
                                                <label for="isbn" class="required">Standard number (ISBN, ISSN or other):</label>
108
                                                [% IF ( isbn_required ) %]
104
                                                <input type="text" id="isbn" name="isbn"  maxlength="80" value="[% isbn | html %]" required="required" />
109
                                                    <label for="isbn" class="required">Standard number (ISBN, ISSN or other):</label>
105
                                                <span class="required">Required</span>
110
                                                    <input type="text" id="isbn" name="isbn"  maxlength="80" value="[% isbn | html %]" required="required" />
106
                                            [% ELSE %]
111
                                                    <span class="required">Required</span>
107
                                                <label for="isbn">Standard number (ISBN, ISSN or other):</label>
112
                                                [% ELSE %]
108
                                                <input type="text" id="isbn" name="isbn"  maxlength="80" value="[% isbn | html %]" />
113
                                                    <label for="isbn">Standard number (ISBN, ISSN or other):</label>
109
                                            [% END %]
114
                                                    <input type="text" id="isbn" name="isbn"  maxlength="80" value="[% isbn | html %]" />
110
                                        </li>
115
                                                [% END %]
116
                                            </li>
117
                                        [% END %]
111
                                        <li>
118
                                        <li>
112
                                            [% IF ( publishercode_required ) %]
119
                                            [% IF ( publishercode_required ) %]
113
                                                <label for="publishercode" class="required">Publisher:</label>
120
                                                <label for="publishercode" class="required">Publisher:</label>
Lines 462-467 Link Here
462
        }
469
        }
463
    [% END %]
470
    [% END %]
464
471
472
    [% IF Koha.Preference( 'OPACAutoFill' ) %]
473
    $(function() {
474
        $('#isbn').autofill({
475
            'volumeInfo.title': {target: 'title', effect: 'flash'},
476
            'volumeInfo.authors': {target: 'author', effect: 'flash'},
477
            'volumeInfo.publisher': {target: 'publishercode', effect: 'flash'},
478
            /* google books api seem to only have books, so if we got a result
479
             * item, type will be a book, so set to BK (book). */
480
            'kind': {target: 'itemtype', handle: function(t,v) { t.val('BK'); },},
481
        });
482
    });
483
    [% END %]
484
465
    $(function() {
485
    $(function() {
466
        $("#suggestt").dataTable($.extend(true, {}, dataTablesDefaults, {
486
        $("#suggestt").dataTable($.extend(true, {}, dataTablesDefaults, {
467
            "order": [[ 1, "asc" ]],
487
            "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