1/* 2 * 3 * Copyright (c) 2006-2011 Sam Collett (http://www.texotela.co.uk) 4 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 5 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 6 * 7 * Version 1.3 8 * Demo: http://www.texotela.co.uk/code/jquery/numeric/ 9 * 10 */ 11(function($) { 12/* 13 * Allows only valid characters to be entered into input boxes. 14 * Note: fixes value when pasting via Ctrl+V, but not when using the mouse to paste 15 * side-effect: Ctrl+A does not work, though you can still use the mouse to select (or double-click to select all) 16 * 17 * @name numeric 18 * @param config { decimal : "." , negative : true } 19 * @param callback A function that runs if the number is not valid (fires onblur) 20 * @author Sam Collett (http://www.texotela.co.uk) 21 * @example $(".numeric").numeric(); 22 * @example $(".numeric").numeric(","); // use , as separater 23 * @example $(".numeric").numeric({ decimal : "," }); // use , as separator 24 * @example $(".numeric").numeric({ negative : false }); // do not allow negative values 25 * @example $(".numeric").numeric(null, callback); // use default values, pass on the 'callback' function 26 * 27 */ 28$.fn.numeric = function(config, callback) 29{ 30 if(typeof config === 'boolean') 31 { 32 config = { decimal: config }; 33 } 34 config = config || {}; 35 // if config.negative undefined, set to true (default is to allow negative numbers) 36 if(typeof config.negative == "undefined") config.negative = true; 37 // set decimal point 38 var decimal = (config.decimal === false) ? "" : config.decimal || "."; 39 // allow negatives 40 var negative = (config.negative === true) ? true : false; 41 // callback function 42 var callback = typeof callback == "function" ? callback : function(){}; 43 // set data and methods 44 return this.data("numeric.decimal", decimal).data("numeric.negative", negative).data("numeric.callback", callback).keypress($.fn.numeric.keypress).keyup($.fn.numeric.keyup).blur($.fn.numeric.blur); 45} 46 47$.fn.numeric.keypress = function(e) 48{ 49 // get decimal character and determine if negatives are allowed 50 var decimal = $.data(this, "numeric.decimal"); 51 var negative = $.data(this, "numeric.negative"); 52 // get the key that was pressed 53 var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0; 54 // allow enter/return key (only when in an input box) 55 if(key == 13 && this.nodeName.toLowerCase() == "input") 56 { 57 return true; 58 } 59 else if(key == 13) 60 { 61 return false; 62 } 63 var allow = false; 64 // allow Ctrl+A 65 if((e.ctrlKey && key == 97 /* firefox */) || (e.ctrlKey && key == 65) /* opera */) return true; 66 // allow Ctrl+X (cut) 67 if((e.ctrlKey && key == 120 /* firefox */) || (e.ctrlKey && key == 88) /* opera */) return true; 68 // allow Ctrl+C (copy) 69 if((e.ctrlKey && key == 99 /* firefox */) || (e.ctrlKey && key == 67) /* opera */) return true; 70 // allow Ctrl+Z (undo) 71 if((e.ctrlKey && key == 122 /* firefox */) || (e.ctrlKey && key == 90) /* opera */) return true; 72 // allow or deny Ctrl+V (paste), Shift+Ins 73 if((e.ctrlKey && key == 118 /* firefox */) || (e.ctrlKey && key == 86) /* opera */ 74 || (e.shiftKey && key == 45)) return true; 75 // if a number was not pressed 76 if(key < 48 || key > 57) 77 { 78 /* '-' only allowed at start and if negative numbers allowed */ 79 if(this.value.indexOf("-") != 0 && negative && key == 45 && (this.value.length == 0 || ($.fn.getSelectionStart(this)) == 0)) return true; 80 /* only one decimal separator allowed */ 81 if(decimal && key == decimal.charCodeAt(0) && this.value.indexOf(decimal) != -1) 82 { 83 allow = false; 84 } 85 // check for other keys that have special purposes 86 if( 87 key != 8 /* backspace */ && 88 key != 9 /* tab */ && 89 key != 13 /* enter */ && 90 key != 35 /* end */ && 91 key != 36 /* home */ && 92 key != 37 /* left */ && 93 key != 39 /* right */ && 94 key != 46 /* del */ 95 ) 96 { 97 allow = false; 98 } 99 else 100 { 101 // for detecting special keys (listed above) 102 // IE does not support 'charCode' and ignores them in keypress anyway 103 if(typeof e.charCode != "undefined") 104 { 105 // special keys have 'keyCode' and 'which' the same (e.g. backspace) 106 if(e.keyCode == e.which && e.which != 0) 107 { 108 allow = true; 109 // . and delete share the same code, don't allow . (will be set to true later if it is the decimal point) 110 if(e.which == 46) allow = false; 111 } 112 // or keyCode != 0 and 'charCode'/'which' = 0 113 else if(e.keyCode != 0 && e.charCode == 0 && e.which == 0) 114 { 115 allow = true; 116 } 117 } 118 } 119 // if key pressed is the decimal and it is not already in the field
120 if(decimal && key == decimal.charCodeAt(0)) 121 { 122 if(this.value.indexOf(decimal) == -1) 123 { 124 allow = true; 125 } 126 else 127 { 128 allow = false; 129 } 130 } 131 } 132 else 133 { 134 allow = true; 135 } 136 return allow; 137} 138 139$.fn.numeric.keyup = function(e) 140{ 141 var val = this.value; 142 if(val.length > 0) 143 { 144 // get carat (cursor) position 145 var carat = $.fn.getSelectionStart(this); 146 // get decimal character and determine if negatives are allowed 147 var decimal = $.data(this, "numeric.decimal"); 148 var negative = $.data(this, "numeric.negative"); 149 150 // prepend a 0 if necessary 151 if(decimal != "") 152 { 153 // find decimal point 154 var dot = val.indexOf(decimal); 155 // if dot at start, add 0 before 156 if(dot == 0) 157 { 158 this.value = "0" + val; 159 } 160 // if dot at position 1, check if there is a - symbol before it 161 if(dot == 1 && val.charAt(0) == "-") 162 { 163 this.value = "-0" + val.substring(1); 164 } 165 val = this.value; 166 } 167 168 // if pasted in, only allow the following characters 169 var validChars = [0,1,2,3,4,5,6,7,8,9,'-',decimal]; 170 // get length of the value (to loop through) 171 var length = val.length; 172 // loop backwards (to prevent going out of bounds) 173 for(var i = length - 1; i >= 0; i--) 174 { 175 var ch = val.charAt(i); 176 // remove '-' if it is in the wrong place 177 if(i != 0 && ch == "-") 178 { 179 val = val.substring(0, i) + val.substring(i + 1); 180 } 181 // remove character if it is at the start, a '-' and negatives aren't allowed 182 else if(i == 0 && !negative && ch == "-") 183 { 184 val = val.substring(1); 185 } 186 var validChar = false; 187 // loop through validChars 188 for(var j = 0; j < validChars.length; j++) 189 { 190 // if it is valid, break out the loop 191 if(ch == validChars[j]) 192 { 193 validChar = true; 194 break; 195 } 196 } 197 // if not a valid character, or a space, remove 198 if(!validChar || ch == " ") 199 { 200 val = val.substring(0, i) + val.substring(i + 1); 201 } 202 } 203 // remove extra decimal characters 204 var firstDecimal = val.indexOf(decimal); 205 if(firstDecimal > 0) 206 { 207 for(var i = length - 1; i > firstDecimal; i--) 208 { 209 var ch = val.charAt(i); 210 // remove decimal character 211 if(ch == decimal) 212 { 213 val = val.substring(0, i) + val.substring(i + 1); 214 } 215 } 216 } 217 // set the value and prevent the cursor moving to the end 218 this.value = val; 219 $.fn.setSelection(this, carat); 220 } 221} 222 223$.fn.numeric.blur = function() 224{ 225 var decimal = $.data(this, "numeric.decimal"); 226 var callback = $.data(this, "numeric.callback"); 227 var val = this.value; 228 if(val != "") 229 { 230 var re = new RegExp("^\\d+$|\\d*" + decimal + "\\d+"); 231 if(!re.exec(val)) 232 { 233 callback.apply(this); 234 } 235 } 236} 237 238$.fn.removeNumeric = function() 239{ 240 return this.data("numeric.decimal", null).data("numeric.negative", null).data("numeric.callback", null).unbind("keypress", $.fn.numeric.keypress).unbind("blur", $.fn.numeric.blur); 241} 242 243// Based on code from http://javascript.nwbox.com/cursor_position/ (Diego Perini <[email protected]>) 244$.fn.getSelectionStart = function(o) 245{ 246 if (o.createTextRange) 247 { 248 var r = document.selection.createRange().duplicate(); 249 r.moveEnd('character', o.value.length); 250 if (r.text == '') return o.value.length; 251 return o.value.lastIndexOf(r.text); 252 } else return o.selectionStart; 253} 254 255// set the selection, o is the object (input), p is the position ([start, end] or just start) 256$.fn.setSelection = function(o, p) 257{ 258 // if p is number, start and end are the same 259 if(typeof p == "number") p = [p, p]; 260 // only set if p is an array of length 2 261 if(p && p.constructor == Array && p.length == 2) 262 { 263 if (o.createTextRange) 264 { 265 var r = o.createTextRange(); 266 r.collapse(true); 267 r.moveStart('character', p[0]); 268 r.moveEnd('character', p[1]); 269 r.select(); 270 } 271 else if(o.setSelectionRange) 272 { 273 o.focus(); 274 o.setSelectionRange(p[0], p[1]); 275 } 276 } 277} 278 279})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.