Ticket #1604: isbn.js

File isbn.js, 2.9 KB (added by ajlyon, 7 years ago)
Line 
1// Implementation of ISBN check-digit verification
2// Based on ISBN Users' Manual (http://www.isbn.org/standards/home/isbn/international/html/usm4.htm)
3// and the Wikipedia treatment of ISBN (http://en.wikipedia.org/wiki/International_Standard_Book_Number)
4
5// This does not validate multiple ISBNs in one field,
6// but it will gracefully ignore all non-number detritus,
7// such as hyphens, spaces, and comments.
8
9// Takes the first 10 valid digits and tries to read an ISBN 10,
10// and takes the first 13 valid digits to try to read an ISBN 13
11// Returns an four-element array:
12//      [0] the validity as an ISBN 10
13//      [1] detected ISBN 10 that checks
14//      [2] validity as an ISBN 13
15//      [3] detected ISBN 13 that checks
16// If there is no valid ISBN of a type detected, then elements 1 and/or 3 will
17// be empty. There could conceivably be a valid ISBN-13 with an ISBN-10
18// substring; this should probably be interpreted as the latter, but it is a
19// client UI issue.
20ISBNCheck = function(isbn) {
21        // For ISBN 10, multiple by these coefficients, take the sum mod 11
22        // and subtract from 11
23        var isbn10 = [10, 9, 8, 7, 6, 5, 4, 3, 2];
24
25        // For ISBN 13, multiple by these coefficients, take the sum mod 10
26        // and subtract from 10
27        var isbn13 = [1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3];
28
29        // We make a single pass through the provided string, interpreting the
30        // first 10 valid characters as an ISBN-10, and the first 13 as an
31        // ISBN-13. We then return an array of booleans and valid detected
32        // ISBNs.
33
34        var j = 0;
35        var sum10 = 0;
36        var num10 = "";
37        var sum13 = 0;
38        var num13 = "";
39        var chars = [];
40
41        for (var i=0; i < isbn.length; i++) {
42                if (isbn.charAt(i) == " ") {
43                        // Since the space character evaluates as a number,
44                        // it is a special case.
45                } else if (j < 9 && ((isbn.charAt(i) - 0) == isbn.charAt(i))) {
46                        sum10 += isbn.charAt(i) * isbn10[j];
47                        sum13 += isbn.charAt(i) * isbn13[j];
48                        num10 += isbn.charAt(i);
49                        num13 += isbn.charAt(i);
50                        j++;
51                } else if (j == 9 &&
52                        (isbn.charAt(i) == "X" || isbn.charAt(i) == "x" ||
53                                ((isbn.charAt(i) - 0) == isbn.charAt(i)))) {
54                        // In ISBN-10, an X represents the check digit "10".
55                        if(isbn.charAt(i) == "X" || isbn.charAt(i) == "x") {
56                                var check10 = 10;
57                                num10 += "X";
58                        } else {
59                                var check10 = isbn.charAt(i);
60                                sum13 += isbn.charAt(i) * isbn13[j];
61                                num10 += isbn.charAt(i);
62                                num13 += isbn.charAt(i);
63                                j++;
64                        }
65                } else if(j < 12 && ((isbn.charAt(i) - 0) == isbn.charAt(i))) {
66                        sum13 += isbn.charAt(i) * isbn13[j];
67                        num13 += isbn.charAt(i);
68                        j++;
69                } else if (j == 12 && ((isbn.charAt(i) - 0) == isbn.charAt(i))) {
70                        var check13 = isbn.charAt(i);
71                        num13 += isbn.charAt(i);
72                }
73        }
74        var valid10 = (11 - (sum10 % 11) == check10);
75        var valid13 = (10 - (sum13 % 10) == check13);
76        if(!valid10) {num10 = ""};
77        if(!valid13) {num13 = ""};
78        return [valid10, num10, valid13, num13];
79}