PageSourceSearch

https://www.plantokuchnie.pl/shared-doc/WebCM/extras_noprefix/comment/jquery.alphanum.js

js plantokuchnie.pl collected 2026-10-08 06:12:27 UTC 23,349 bytes, 786 lines download raw bytes

1/********************************************************************
2* Limit the characters that may be entered in a text field
3* Common options: alphanumeric, alphabetic or numeric
4* Kevin Sheedy, 2012
5* http://github.com/KevinSheedy/jquery.alphanum
6*********************************************************************/
7(function( $ ){
8
9	// API ///////////////////////////////////////////////////////////////////
10	$.fn.alphanum = function(settings) {
11		
12		var combinedSettings = getCombinedSettingsAlphaNum(settings);
13
14		var $collection = this;
15
16		setupEventHandlers($collection, trimAlphaNum, combinedSettings);
17
18		return this;
19	};
20	
21	$.fn.alpha = function(settings) {
22		
23		var defaultAlphaSettings = getCombinedSettingsAlphaNum("alpha");
24		var combinedSettings = getCombinedSettingsAlphaNum(settings, defaultAlphaSettings);
25
26		var $collection = this;
27
28		setupEventHandlers($collection, trimAlphaNum, combinedSettings);
29
30		return this;
31	};
32	
33	$.fn.numeric = function(settings) {
34		
35		var combinedSettings = getCombinedSettingsNum(settings);
36		var $collection = this;
37
38		setupEventHandlers($collection, trimNum, combinedSettings);
39
40		$collection.blur(function(){
41			numericField_Blur(this, settings);
42		});
43
44		return this;
45	};
46	
47	// End of API /////////////////////////////////////////////////////////////
48	
49	
50	// Start Settings ////////////////////////////////////////////////////////
51	
52	var DEFAULT_SETTINGS_ALPHANUM = {
53		allow              : '',   // Allow extra characters
54		disallow           : '',   // Disallow extra characters
55		allowSpace         : true, // Allow the space character
56		allowNumeric       : true, // Allow digits 0-9
57		allowUpper         : true, // Allow upper case characters
58		allowLower         : true, // Allow lower case characters
59		allowCaseless      : true, // Allow characters that don't have both upper & lower variants - eg Arabic or Chinese
60		allowLatin         : true, // a-z A-Z
61		allowOtherCharSets : true, // eg é, Á, Arabic, Chinese etc
62		maxLength          : ''    // eg Max Length
63	}
64	
65	var DEFAULT_SETTINGS_NUM = {
66		allowPlus           : false, // Allow the + sign
67		allowMinus          : true,  // Allow the - sign
68		allowThouSep        : true,  // Allow the thousands separator, default is the comma eg 12,000
69		allowDecSep         : true,  // Allow the decimal separator, default is the fullstop eg 3.141
70		allowLeadingSpaces  : false,
71		maxDigits           : '',    // The max number of digits or '' for no max
72		maxDecimalPlaces    : '',    // The max number of decimal places or '' for no max
73		maxPreDecimalPlaces : '',    // The max number digits before the decimal point or '' for no max
74		max                 : '',    // The max numeric value allowed
75		min                 : ''     // The min numeric value allowed
76	}
77	
78	// Some pre-defined groups of settings for convenience
79	var CONVENIENCE_SETTINGS_ALPHANUM = {
80		"alpha" : {
81			allowNumeric  : false
82		},
83		"upper" : {
84			allowNumeric  : false,
85			allowUpper    : true,
86			allowLower    : false,
87			allowCaseless : true
88		},
89		"lower" : {
90			allowNumeric  : false,
91			allowUpper    : false,
92			allowLower    : true,
93			allowCaseless : true
94		}
95	};
96
97	// Some pre-defined groups of settings for convenience
98	var CONVENIENCE_SETTINGS_NUMERIC = {
99		"integer" : {
100			allowPlus    : false,
101			allowMinus   : true,
102			allowThouSep : false,
103			allowDecSep  : false
104		},
105		"positiveInteger" : {
106			allowPlus    : false,
107			allowMinus   : false,
108			allowThouSep : false,
109			allowDecSep  : false
110		}
111	};
112	
113	
114	var BLACKLIST   = getBlacklistAscii() + getBlacklistNonAscii();
115	var THOU_SEP    = ",";
116	var DEC_SEP     = ".";
117	var DIGITS      = getDigitsMap();
118	var LATIN_CHARS = getLatinCharsSet();
119	
120	// Return the blacklisted special chars that are encodable using 7-bit ascii
121	function getBlacklistAscii(){
122		var blacklist = '!@#$%^&*()+=[]\\\';,/{}|":<>?~`.-_';
123		blacklist += " "; // 'Space' is on the blacklist but can be enabled using the 'allowSpace' config entry
124		return blacklist;
125	}
126	
127	// Return the blacklisted special chars that are NOT encodable using 7-bit ascii
128	// We want this .js file to be encoded using 7-bit ascii so it can reach the widest possible audience
129	// Higher order chars must be escaped eg "\xAC"
130	// Not too worried about comments containing higher order characters for now (let's wait and see if it becomes a problem)
131	function getBlacklistNonAscii(){
132		var blacklist = 
133			  "\xAC"     // ¬
134			+ "\u20AC"   // €
135			+ "\xA3"     // £
136			+ "\xA6"     // Å 
137			;
138		return blacklist;
139	}
140	
141	// End Settings ////////////////////////////////////////////////////////
142	
143	
144	// Implementation details go here ////////////////////////////////////////////////////////
145
146	function setupEventHandlers($textboxes, trimFunction, settings) {
147
148		$textboxes.each(function(){
149
150			var $textbox = $(this);
151
152			$textbox.bind("keyup change paste", function(e){
153
154				var pastedText = "";
155
156				if(e.originalEvent && e.originalEvent.clipboardData && e.originalEvent.clipboardData.getData)
157					pastedText = e.originalEvent.clipboardData.getData("text/plain")
158
159				// setTimeout is necessary for handling the 'paste' event
160				setTimeout(function(){
161					trimTextbox($textbox, trimFunction, settings, pastedText);
162				}, 0);
163			});
164
165			$textbox.bind("keypress", function(e){
166				
167				// Determine which key is pressed.
168				// If it's a control key, then allow the event's default action to occur eg backspace, tab
169				var charCode = !e.charCode ? e.which : e.charCode;
170				if(isControlKey(charCode)
171					|| e.ctrlKey
172					|| e.metaKey ) // cmd on MacOS
173					return;
174
175				var newChar         = String.fromCharCode(charCode);
176
177				// Determine if some text was selected / highlighted when the key was pressed
178				var selectionObject = $textbox.selection();
179				var start = selectionObject.start;
180				var end   = selectionObject.end;
181
182				var textBeforeKeypress  = $textbox.val();
183				
184				// The new char may be inserted:
185				//  1) At the start
186				//  2) In the middle
187				//  3) At the end
188				//  4) User highlights some text and then presses a key which would replace the highlighted text
189				//
190				// Here we build the string that would result after the keypress.
191				// If the resulting string is invalid, we cancel the event.
192				// Unfortunately, it isn't enough to just check if the new char is valid because some chars
193				// are position sensitive eg the decimal point '.'' or the minus sign '-'' are only valid in certain positions.
194				var potentialTextAfterKeypress = textBeforeKeypress.substring(0, start) + newChar + textBeforeKeypress.substring(end);
195				var validatedText              = trimFunction(potentialTextAfterKeypress, settings);
196
197				// If the keypress would cause the textbox to contain invalid characters, then cancel the keypress event
198				if(validatedText != potentialTextAfterKeypress)
199					e.preventDefault();
200			});
201		});
202
203	}
204
205	// Ensure the text is a valid number when focus leaves the textbox
206	// This catches the case where a user enters '-' or '.' without entering any digits
207	function numericField_Blur(inputBox, settings) {
208		var fieldValueNumeric = parseFloat($(inputBox).val());
209		var $inputBox = $(inputBox);
210
211		if(isNaN(fieldValueNumeric)) {
212			$inputBox.val("");
213			return;
214		}
215
216		if(isNumeric(settings.min) && fieldValueNumeric < settings.min)
217			$inputBox.val("");
218
219		if(isNumeric(settings.max) && fieldValueNumeric > settings.max)
220			$inputBox.val("");
221	}
222
223	function isNumeric(value) {
224		return !isNaN(value);
225	}
226
227	function isControlKey(charCode) {
228
229		if(charCode >= 32)
230			return false;
231		if(charCode == 10)
232			return false;
233		if(charCode == 13)
234			return false;
235
236		return true;
237	}
238	
239	// One way to prevent a character being entered is to cancel the keypress event.
240	// However, this gets messy when you have to deal with things like copy paste which isn't a keypress.
241	// Which event gets fired first, keypress or keyup? What about IE6 etc etc?
242	// Instead, it's easier to allow the 'bad' character to be entered and then to delete it immediately after.
243	
244	function trimTextbox($textBox, trimFunction, settings, pastedText){
245		
246		var inputString = $textBox.val();
247
248		if(inputString == "" && pastedText.length > 0)
249			inputString = pastedText;
250		
251		var outputString = trimFunction(inputString, settings);
252		
253		if(inputString == outputString)
254			return;
255		
256		var caretPos = $textBox.alphanum_caret();
257		
258		$textBox.val(outputString);
259		
260		//Reset the caret position
261		if(inputString.length ==(outputString.length + 1))
262			$textBox.alphanum_caret(caretPos - 1);
263		else
264			$textBox.alphanum_caret(caretPos);
265	}
266	
267	function getCombinedSettingsAlphaNum(settings, defaultSettings){
268		if(typeof defaultSettings == "undefined")
269			defaultSettings = DEFAULT_SETTINGS_ALPHANUM;
270		var userSettings, combinedSettings = {};
271		if(typeof settings === "string")
272			userSettings = CONVENIENCE_SETTINGS_ALPHANUM[settings];
273		else if(typeof settings == "undefined")
274			userSettings = {};
275		else
276			userSettings = settings;
277		
278		$.extend(combinedSettings, defaultSettings, userSettings);
279		
280		if(typeof combinedSettings.blacklist == 'undefined')
281			combinedSettings.blacklistSet = getBlacklistSet(combinedSettings.allow, combinedSettings.disallow);
282		
283		return combinedSettings;
284	}
285	
286	function getCombinedSettingsNum(settings){
287		var userSettings, combinedSettings = {};
288		if(typeof settings === "string")
289			userSettings = CONVENIENCE_SETTINGS_NUMERIC[settings];
290		else if(typeof settings == "undefined")
291			userSettings = {};
292		else
293			userSettings = settings;
294		
295		$.extend(combinedSettings, DEFAULT_SETTINGS_NUM, userSettings);
296		
297		return combinedSettings;
298	}
299	
300	
301	// This is the heart of the algorithm
302	function alphanum_allowChar(validatedStringFragment, Char, settings){
303
304		if(settings.allow.indexOf(Char) >=0 )
305			return true;
306		
307		if(settings.allowSpace && (Char == " "))
308			return true;
309			
310		if(settings.blacklistSet.contains(Char))
311			return false;
312		
313		if(!settings.allowNumeric && DIGITS[Char])
314			return false;
315			
316		if(!settings.allowUpper && isUpper(Char))
317			return false;
318			
319		if(!settings.allowLower && isLower(Char))
320			return false;
321			
322		if(!settings.allowCaseless && isCaseless(Char))
323			return false;
324		
325		if(!settings.allowLatin && LATIN_CHARS.contains(Char))
326			return false;
327
328		if(settings.maxLength && validatedStringFragment.length >= settings.maxLength)
329			return false;
330		
331		if(!settings.allowOtherCharSets){
332			if(DIGITS[Char] || LATIN_CHARS.contains(Char))
333				return true;
334			else
335				return false;
336		}
337		
338		return true;
339	}
340	
341	function numeric_allowChar(validatedStringFragment, Char, settings){
342
343		if(DIGITS[Char]) {
344
345			if(isMaxDigitsReached(validatedStringFragment, settings))
346				return false;
347
348			if(isMaxPreDecimalsReached(validatedStringFragment, settings))
349				return false;
350
351			if(isMaxDecimalsReached(validatedStringFragment, settings))
352				return false;
353
354			if(isGreaterThanMax(validatedStringFragment + Char, settings))
355				return false;
356
357			if(isLessThanMin(validatedStringFragment + Char, settings))
358				return false;
359
360			return true;
361		}
362
363		if(settings.allowPlus && Char == '+' && validatedStringFragment == '')
364			return true;
365
366		if(settings.allowMinus && Char == '-' && validatedStringFragment == '')
367			return true;
368
369		if(Char == THOU_SEP && settings.allowThouSep && allowThouSep(validatedStringFragment, Char))
370			return true;
371
372		if(Char == DEC_SEP) {
373			// Only one decimal separator allowed
374			if(validatedStringFragment.indexOf(DEC_SEP) >= 0)
375				return false;
376			if(settings.allowDecSep)
377				return true;
378		}
379		
380		return false;
381	}
382
383	function countDigits(string) {
384
385		// Error handling, nulls etc
386		string = string + "";
387
388		// Count the digits
389		return string.replace(/[^0-9]/g,"").length;
390	}
391
392	function isMaxDigitsReached(string, settings) {
393
394		var maxDigits = settings.maxDigits;
395
396		if(maxDigits == "" || isNaN(maxDigits))
397			return false; // In this case, there is no maximum
398
399		var numDigits = countDigits(string);
400
401		if(numDigits >= maxDigits)
402			return true;
403
404		return false;
405	}
406
407	function isMaxDecimalsReached(string, settings) {
408
409		var maxDecimalPlaces = settings.maxDecimalPlaces;
410
411		if(maxDecimalPlaces == "" || isNaN(maxDecimalPlaces))
412			return false; // In this case, there is no maximum
413
414		var indexOfDecimalPoint = string.indexOf(DEC_SEP);
415
416		if(indexOfDecimalPoint == -1)
417			return false;
418
419		var decimalSubstring = string.substring(indexOfDecimalPoint);
420		var numDecimals = countDigits(decimalSubstring);
421
422		if(numDecimals >= maxDecimalPlaces)
423			return true;
424
425		return false;
426	}
427
428	function isMaxPreDecimalsReached(string, settings) {
429
430		var maxPreDecimalPlaces = settings.maxPreDecimalPlaces;
431
432		if(maxPreDecimalPlaces == "" || isNaN(maxPreDecimalPlaces))
433			return false; // In this case, there is no maximum
434
435		var indexOfDecimalPoint = string.indexOf(DEC_SEP);
436
437		if(indexOfDecimalPoint >= 0)
438			return false;
439
440		var numPreDecimalDigits = countDigits(string);
441
442		if(numPreDecimalDigits >= maxPreDecimalPlaces)
443			return true;
444
445		return false;
446	}
447
448	function isGreaterThanMax(numericString, settings) {
449
450		if(!settings.max || settings.max < 0)
451			return false;
452
453		var outputNumber = parseFloat(numericString);
454		if(outputNumber > settings.max)
455			return true;
456
457		return false;
458	}
459
460	function isLessThanMin(numericString, settings) {
461
462		if(!settings.min || settings.min > 0)
463			return false;
464
465		var outputNumber = parseFloat(numericString);
466		if(outputNumber < settings.min)
467			return true;
468
469		return false;
470	}
471	
472	/********************************
473	 * Trims a string according to the settings provided
474	 ********************************/
475	function trimAlphaNum(inputString, settings){
476		
477		if(typeof inputString != "string")
478			return inputString;
479		
480		var inChars = inputString.split("");
481		var outChars = [];
482		var i = 0;
483		var Char;
484		
485		for(i=0; i<inChars.length; i++){
486			Char = inChars[i];
487			var validatedStringFragment = outChars.join("");
488			if(alphanum_allowChar(validatedStringFragment, Char, settings))
489				outChars.push(Char);
490		}
491		
492		return outChars.join("");
493	}
494	
495	function trimNum(inputString, settings){
496		if(typeof inputString != "string")
497			return inputString;
498		
499		var inChars = inputString.split("");
500		var outChars = [];
501		var i = 0;
502		var Char;
503		
504		for(i=0; i<inChars.length; i++){
505			Char = inChars[i];
506			var validatedStringFragment = outChars.join("");
507			if(numeric_allowChar(validatedStringFragment, Char, settings))
508				outChars.push(Char);
509		}
510		
511		return outChars.join("");
512	}
513	
514	function removeUpperCase(inputString){
515		var charArray = inputString.split('');
516		var i = 0;
517		var outputArray = [];
518		var Char;
519		
520		for(i=0; i<charArray.length; i++){
521			Char = charArray[i];
522		}
523	}
524	
525	function removeLowerCase(inputString){
526		
527	}
528	
529	function isUpper(Char){
530		var upper = Char.toUpperCase();
531		var lower = Char.toLowerCase();
532		
533		if( (Char == upper) && (upper != lower))
534			return true;
535		else
536			return false;
537	}
538	
539	function isLower(Char){
540		var upper = Char.toUpperCase();
541		var lower = Char.toLowerCase();
542		
543		if( (Char == lower) && (upper != lower))
544			return true;
545		else
546			return false;
547	}
548	
549	function isCaseless(Char){
550		if(Char.toUpperCase() == Char.toLowerCase())
551			return true;
552		else
553			return false;
554	}
555	
556	function getBlacklistSet(allow, disallow){
557		
558		var setOfBadChars  = new Set(BLACKLIST + disallow);
559		var setOfGoodChars = new Set(allow);
560		
561		var blacklistSet   = setOfBadChars.subtract(setOfGoodChars);
562		
563		return blacklistSet;
564	}
565	
566	function getDigitsMap(){
567		var array = "0123456789".split("");
568		var map = {};
569		var i = 0;
570		var digit;
571		
572		for(i=0; i<array.length; i++){
573			digit = array[i];
574			map[digit] = true;
575		}
576		
577		return map;
578	}
579	
580	function getLatinCharsSet(){
581		var lower = "abcdefghijklmnopqrstuvwxyz";
582		var upper = lower.toUpperCase();
583		var azAZ = new Set(lower + upper);
584		
585		return azAZ;
586	}
587
588	function allowThouSep(currentString, Char) {
589
590		// Can't start with a THOU_SEP
591		if(currentString.length == 0)
592			return false;
593
594		// Can't have a THOU_SEP anywhere after a DEC_SEP
595		var posOfDecSep = currentString.indexOf(DEC_SEP);
596		if(posOfDecSep >= 0)
597			return false;
598
599		var posOfFirstThouSep       = currentString.indexOf(THOU_SEP);
600
601		// Check if this is the first occurrence of a THOU_SEP
602		if(posOfFirstThouSep < 0)
603			return true;
604
605		var posOfLastThouSep        = currentString.lastIndexOf(THOU_SEP);
606		var charsSinceLastThouSep   = currentString.length - posOfLastThouSep - 1;
607
608		// Check if there has been 3 digits since the last THOU_SEP
609		if(charsSinceLastThouSep < 3)
610			return false;
611
612		var digitsSinceFirstThouSep = countDigits(currentString.substring(posOfFirstThouSep));
613
614		// Check if there has been a multiple of 3 digits since the first THOU_SEP
615		if((digitsSinceFirstThouSep % 3) > 0)
616			return false;
617
618		return true;
619	}
620	
621	////////////////////////////////////////////////////////////////////////////////////
622	// Implementation of a Set
623	////////////////////////////////////////////////////////////////////////////////////
624	function Set(elems){
625		if(typeof elems == "string")
626			this.map = stringToMap(elems);
627		else
628			this.map = {};
629	}
630	
631	Set.prototype.add = function(set){
632	
633		var newSet = this.clone();
634		
635		for(var key in set.map)
636			newSet.map[key] = true;
637		
638		return newSet;
639	}
640	
641	Set.prototype.subtract = function(set){
642		
643		var newSet = this.clone();
644		
645		for(var key in set.map)
646			delete newSet.map[key];
647			
648		return newSet;
649	}
650	
651	Set.prototype.contains = function(key){
652		if(this.map[key])
653			return true;
654		else
655			return false;
656	}
657	
658	Set.prototype.clone = function(){
659		var newSet = new Set();
660		
661		for(var key in this.map)
662			newSet.map[key] = true;
663		
664		return newSet;
665	}
666	////////////////////////////////////////////////////////////////////////////////////
667	
668	function stringToMap(string){
669		var map = {};
670		var array = string.split("");
671		var i=0;
672		var Char;
673		
674		for(i=0; i<array.length; i++){
675			Char = array[i];
676			map[Char] = true;
677		}
678		
679		return map;
680	}
681	
682	// Backdoor for testing
683	$.fn.alphanum.backdoorAlphaNum = function(inputString, settings){
684		var combinedSettings = getCombinedSettingsAlphaNum(settings);
685		
686		return trimAlphaNum(inputString, combinedSettings);
687	};
688	
689	$.fn.alphanum.backdoorNumeric = function(inputString, settings){
690		var combinedSettings = getCombinedSettingsNum(settings);
691		
692		return trimNum(inputString, combinedSettings);
693	};
694
695	$.fn.alphanum.setNumericSeparators = function(settings) {
696
697		if(settings.thousandsSeparator.length != 1)
698			return;
699
700		if(settings.decimalSeparator.length != 1)
701			return;
702
703		THOU_SEP = thousandsSeparator;
704		DEC_SEP = decimalSeparator;
705	}
706
707})( jQuery );
708
709
710//Include the 3rd party lib: jquery.caret.js
711
712
713// Set caret position easily in jQuery
714// Written by and Copyright of Luke Morton, 2011
715// Licensed under MIT
716(function ($) {
717	// Behind the scenes method deals with browser
718	// idiosyncrasies and such
719	function caretTo(el, index) {
720		if (el.createTextRange) { 
721			var range = el.createTextRange(); 
722			range.move("character", index); 
723			range.select(); 
724		} else if (el.selectionStart != null) { 
725			el.focus(); 
726			el.setSelectionRange(index, index); 
727		}
728	};
729	
730	// Another behind the scenes that collects the
731	// current caret position for an element
732	
733	// TODO: Get working with Opera
734	function caretPos(el) {
735		if ("selection" in document) {
736			var range = el.createTextRange();
737			try {
738				range.setEndPoint("EndToStart", document.selection.createRange());
739			} catch (e) {
740				// Catch IE failure here, return 0 like
741				// other browsers
742				return 0;
743			}
744			return range.text.length;
745		} else if (el.selectionStart != null) {
746			return el.selectionStart;
747		}
748	};
749
750	// The following methods are queued under fx for more
751	// flexibility when combining with $.fn.delay() and
752	// jQuery effects.
753
754	// Set caret to a particular index
755	$.fn.alphanum_caret = function (index, offset) {
756		if (typeof(index) === "undefined") {
757			return caretPos(this.get(0));
758		}
759		
760		return this.queue(function (next) {
761			if (isNaN(index)) {
762				var i = $(this).val().indexOf(index);
763				
764				if (offset === true) {
765					i += index.length;
766				} else if (typeof(offset) !== "undefined") {
767					i += offset;
768				}
769				
770				caretTo(this, i);
771			} else {
772				caretTo(this, index);
773			}
774			
775			next();
776		});
777	};
778}(jQuery));
779
780/**********************************************************
781* Selection Library
782* Used to determine what text is highlighted in the textbox before a key is pressed.
783* http://donejs.com/docs.html#!jQuery.fn.selection
784* https://github.com/jupiterjs/jquerymx/blob/master/dom/selection/selection.js
785***********************************************************/
786(function(e){var t=function(e){return e.replace(/([a-z])([a-z]+)/gi,function(e,t,n){return t+n.toLowerCase()}).replace(/_/g,"")},n=function(e){return e.replace(/^([a-z]+)_TO_([a-z]+)/i,function(e,t,n){return n+"_TO_"+t})},r=function(e){return e?e.ownerDocument.defaultView||e.ownerDocument.parentWindow:window},i=function(t,n){var r=e.Range.current(t).clone(),i=e.Range(t).select(t);if(!r.overlaps(i)){return null}if(r.compare("START_TO_START",i)<1){startPos=0;r.move("START_TO_START",i)}else{fromElementToCurrent=i.clone();fromElementToCurrent.move("END_TO_START",r);startPos=fromElementToCurrent.toString().length}if(r.compare("END_TO_END",i)>=0){endPos=i.toString().length}else{endPos=startPos+r.toString().length}return{start:startPos,end:endPos}},s=function(t){var n=r(t);if(t.selectionStart!==undefined){if(document.activeElement&&document.activeElement!=t&&t.selectionStart==t.selectionEnd&&t.selectionStart==0){return{start:t.value.length,end:t.value.length}}return{start:t.selectionStart,end:t.selectionEnd}}else if(n.getSelection){return i(t,n)}else{try{if(t.nodeName.toLowerCase()=="input"){var s=r(t).document.selection.createRange(),o=t.createTextRange();o.setEndPoint("EndToStart",s);var u=o.text.length;return{start:u,end:u+s.text.length}}else{var a=i(t,n);if(!a){return a}var f=e.Range.current().clone(),l=f.clone().collapse().range,c=f.clone().collapse(false).range;l.moveStart("character",-1);c.moveStart("character",-1);if(a.startPos!=0&&l.text==""){a.startPos+=2}if(a.endPos!=0&&c.text==""){a.endPos+=2}return a}}catch(h){return{start:t.value.length,end:t.value.length}}}},o=function(e,t,n){var i=r(e);if(e.setSelectionRange){if(n===undefined){e.focus();e.setSelectionRange(t,t)}else{e.select();e.selectionStart=t;e.selectionEnd=n}}else if(e.createTextRange){var s=e.createTextRange();s.moveStart("character",t);n=n||t;s.moveEnd("character",n-e.value.length);s.select()}else if(i.getSelection){var o=i.document,u=i.getSelection(),f=o.createRange(),l=[t,n!==undefined?n:t];a([e],l);f.setStart(l[0].el,l[0].count);f.setEnd(l[1].el,l[1].count);u.removeAllRanges();u.addRange(f)}else if(i.document.body.createTextRange){var f=document.body.createTextRange();f.moveToElementText(e);f.collapse();f.moveStart("character",t);f.moveEnd("character",n!==undefined?n:t);f.select()}},u=function(e,t,n,r){if(typeof n[0]==="number"&&n[0]<t){n[0]={el:r,count:n[0]-e}}if(typeof n[1]==="number"&&n[1]<=t){n[1]={el:r,count:n[1]-e};}},a=function(e,t,n){var r,i;n=n||0;for(var s=0;e[s];s++){r=e[s];
786if(r.nodeType===3||r.nodeType===4){i=n;n+=r.nodeValue.length;u(i,n,t,r)}else if(r.nodeType!==8){n=a(r.childNodes,t,n)}}return n};jQuery.fn.selection=function(e,t){if(e!==undefined){return this.each(function(){o(this,e,t)})}else{return s(this[0])}};e.fn.selection.getCharElement=a})(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.