Validate Library Card

Performs error detection and correction.

  1. // ==UserScript==
  2. // @name Validate Library Card
  3. // @namespace http://mailerdaemon.home.comcast.com/
  4. // @include https://*.libraryreserve.com/*/SignIn*.htm*
  5. // @include https://*.libraryreserve.com/*/LogIn*.htm*
  6. // @version 1.0
  7. // @description Performs error detection and correction.
  8. // ==/UserScript==
  9.  
  10. const extrasize = 3;
  11.  
  12. function luhn(str){
  13. if(typeof(str) !== "string")
  14. str = Array.join(str, "");
  15. if((str = str.replace(/\D/g, "")).length) {
  16. var t = [0,2,4,6,8,1,3,5,7,9]
  17. var [valid, concat] = Array.reduce(str, function([b, a], c){ let j = Number(c); return [a + j, b + t[j]];}, [0, 0]);
  18. return [str, !(valid % 10), str.concat(9 - (concat + 9) % 10)];
  19. }
  20. return [str, undefined, "0"];
  21. }
  22.  
  23. $Z("//input[(@id='card' or @name='LibraryCardNumber') and @type='text']", function(input){
  24. let checksum = document.createElement("span");
  25. insertAfter(checksum, input)
  26. let update = function (e){
  27. let value = input.value.replace(/[\s\-_]/g,'');
  28. let len = value.length;
  29. let num = Number(value);
  30. let check;
  31. if(len && !isNaN(num))
  32. {
  33. if(len < 13){
  34. input.style.backgroundColor = "";
  35. checksum.innerHTML = check = "";
  36. }
  37. else if(len == 13){
  38. checksum.innerHTML = check = luhn(value)[2].slice(-1);
  39. input.style.backgroundColor = "#AFA";
  40. }
  41. else if(len == 14){
  42. var [str, success] = luhn(value);
  43. checksum.innerHTML = ""
  44. check = str.slice(-1);
  45. if(success)
  46. input.style.backgroundColor = "#5F5";
  47. else
  48. input.style.backgroundColor = "#FAA";
  49. }
  50. else
  51. input.style.backgroundColor = "#F00";
  52. //log(value, len, check)
  53. }
  54. //else log(value, "wtf?")
  55. if(input.value.length + extrasize > input.size)
  56. input.size = input.value.length + extrasize;
  57. }
  58. addEvent(input, "keyup", update);
  59. addEvent(input, "change", update);
  60. addEvent(checksum, "click", function(){input.value += checksum.innerHTML; update();});
  61. });
  62.  
  63. function $Z(_xpath, func, node){
  64. var doc = (node && (typeof(node.ownerDocument) === "object"))?(node.ownerDocument || node):(node = document);
  65. var res = doc.evaluate(_xpath, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  66. var args = Array.prototype.slice.call(arguments, 3);
  67. var i = 0;
  68. for (; i < res.snapshotLength; ++i)
  69. func.apply(func, [res.snapshotItem(i), i].concat(args));
  70. return i;
  71. }
  72.  
  73.  
  74. function insertAfter(insert, after){return after.parentNode.insertBefore(insert, after.nextSibling);}
  75. function insertBefore(insert, before){return before.parentNode.insertBefore(insert, before);}
  76.  
  77. function addEvent( obj, type, fn, capture ) {
  78. if ( obj.attachEvent ) {
  79. obj["e"+type+fn] = fn;
  80. obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
  81. obj.attachEvent( "on"+type, obj[type+fn] );
  82. } else
  83. obj.addEventListener( type, fn, capture?capture:false );
  84. }
  85. function removeEvent( obj, type, fn, capture ) {
  86. if ( obj.detachEvent ) {
  87. obj.detachEvent( "on"+type, obj[type+fn] );
  88. obj[type+fn] = obj["e"+type+fn] = null;
  89. } else
  90. obj.removeEventListener( type, fn, capture?capture:false );
  91. }
  92. function log(){
  93. var arg;
  94. switch(arguments.length)
  95. {
  96. case 1:
  97. arg = arguments[0];
  98. break;
  99. case 0:
  100. arg = null;
  101. break;
  102. default:
  103. arg = arguments;
  104. break;
  105. }
  106. var f = arg//JSON.stringify(arg);
  107. if(typeof(unsafeWindow.console) != "undefined" && typeof(unsafeWindow.console.log) != "undefined")
  108. unsafeWindow.console.log(f);
  109. else
  110. GM_log(f);
  111. return arg;
  112. }