1//Validator 2(function($, undefined) 3{ 4 /** Vars 5 ------------------------------ **/ 6 var BASENAME = "validator"; 7 //class 8 var CLASS_FORM = BASENAME + "-form"; 9 var CLASS_INPUT = BASENAME + "-input"; 10 var CLASS_INPUTS = BASENAME + "-inputs"; 11 var CLASS_FIELD = BASENAME + "-field"; 12 var CLASS_TRIGGER = BASENAME + "-trigger"; 13 var CLASS_SUBMIT = BASENAME + "-submit"; 14 15 var CLASS_VALID = BASENAME + "-valid"; 16 var CLASS_INVALID = BASENAME + "-invalid"; 17 18 var CLASS_VALIDATE = BASENAME + "-validate"; 19 20 var CLASS_MESSAGE = BASENAME + "-message"; 21 var CLASS_MESSAGE_VALID = CLASS_MESSAGE + "-valid"; 22 var CLASS_MESSAGE_INVALID = CLASS_MESSAGE + "-invalid"; 23 24 var CLASS_IGNORE = BASENAME + "-ignore"; 25 26 var CLASS_SHAKE = BASENAME + "-shake"; 27 28 //data attr 29 var DATA_PREFIX = "data-" + BASENAME; 30 var DATA_NAME = DATA_PREFIX + "-name"; 31 var DATA_RULE = DATA_PREFIX + "-rule"; 32 33 var DATA_MESSAGE = DATA_PREFIX + "-message"; 34 var DATA_MESSAGE_VALID = DATA_MESSAGE + "-valid"; 35 var DATA_MESSAGE_INVALID = DATA_MESSAGE + "-invalid"; 36 37 var defaultOptions = 38 { 39 onValidate : function(validator) 40 { 41 if(validator.options.invalidShake) validator.$form.removeClass(CLASS_SHAKE); 42 }, 43 onValid : null, 44 onInvalid : function(validator) 45 { 46 $("html,body").animate({scrollTop : validator.$form.offset().top - 50}, {dulation : "fast", easing : "swing"}); 47 if(validator.options.invalidShake) validator.$form.addClass(CLASS_SHAKE); 48 }, 49 50 classForm : CLASS_FORM, 51 52 classValid : CLASS_VALID, 53 classInvalid : CLASS_INVALID, 54 55 classMessageValid : CLASS_MESSAGE_VALID, 56 classMessageInvalid : CLASS_MESSAGE_INVALID, 57 58 messageWrapper : "span", 59 60 blurSync : true, 61 changeSync : true, 62 keySync : true, 63 64 messages : 65 { 66 valid : "", 67 required : "å¿ é é ç®ã§ãã", 68 alphanumeric : "åè§è±æ°åã§å ¥åãã¦ãã ããã", 69 number : "æ°å¤ã§å ¥åãã¦ãã ããã", 70 url : "http:// ã¾ã㯠https:// ããå§ã¾ãURLå½¢å¼ã§å ¥åãã¦ãã ããã", 71 domain : "ãã¡ã¤ã³å½¢å¼ã§å ¥åãã¦ãã ããã", 72 email : "ã¡ã¼ã«ã¢ãã¬ã¹å½¢å¼ã§å ¥åãã¦ãã ããã", 73 zipcode : "éµä¾¿çªå·å½¢å¼ã§å ¥åãã¦ãã ããã", 74 phone : "é»è©±çªå·å½¢å¼ã§å ¥åãã¦ãã ããã", 75 date : "'/'ã¾ãã¯'-'ã§åºåã£ãæ¥ä»å½¢å¼ã§å ¥åãã¦ãã ããã", 76 checked : "鏿ãã¦ãã ããã", 77 minNumber : "{min}以ä¸ã®æ°å¤ãå ¥åãã¦ãã ããã", 78 maxNumber : "{max}以ä¸ã®æ°å¤ãå ¥åãã¦ãã ããã", 79 minLength : "{min}æå以ä¸å ¥åãã¦ãã ããã", 80 maxLength : "{max}æå以å ã§å ¥åãã¦ãã ããã", 81 //multi only 82 valuableChecked : "鏿ãã¦ãã ããã", 83 minChecked : "{min}å以ä¸é¸æãã¦ãã ããã", 84 maxChecked : "{max}å以å ã§é¸æãã¦ãã ããã", 85 //single only 86 minSize : "{min}以ä¸ã®ãã¡ã¤ã«ã鏿ãã¦ãã ããã", 87 maxSize : "{max}以ä¸ã®ãã¡ã¤ã«ã¯é¸æã§ãã¾ããã", 88 equal : "åãå¤ãå ¥åãã¦ãã ããã" 89 }, 90 //omake 91 invalidShake : false 92 } 93 94 /** Default rules **/ 95 var defaultRules = 96 { 97 required : false, 98 alphanumeric : false, 99 number : false, 100 url : false, 101 domain : false, 102 email : false, 103 phone : false, 104 zipcode : false, 105 date : false, 106 checked : false, 107 minNumber : false, 108 maxNumber : false, 109 minLength : false, 110 maxLength : false, 111 //multi only 112 valuableChecked : false, 113 minChecked : false, 114 maxChecked : false, 115 //single only 116 minSize : false, 117 maxSize : false, 118 equal : false 119 } 120 121 /** Functions 122 ------------------------------ **/ 123 var validateMethods = 124 { 125 required : function(input) 126 { 127 var length = 0; 128 if(!!input.$multiInputs) 129 { 130 input.$multiInputs.each(function() 131 { 132 if(!!this.value.length) length += this.value.length; 133 else 134 { 135 length = 0; 136 return false; 137 } 138 }); 139 } 140 else length = !!input.$input.val().trim().length; 141 return !!length; 142 }, 143 alphanumeric : function(input) 144 { 145 return this._match(input, "alphanumeric"); 146 }, 147 number : function(input) 148 { 149 return this._match(input, "number"); 150 }, 151 url : function(input) 152 { 153 return this._match(input, "url"); 154 }, 155 domain : function(input) 156 { 157 return this._match(input, "domain"); 158 }, 159 email : function(input) 160 { 161 return this._match(input, "email"); 162 }, 163 phone : function(input) 164 { 165 return this._match(input, "phone"); 166 }, 167 zipcode : function(input) 168 { 169 return this._match(input, "zipcode"); 170 }, 171 date : function(input) 172 { 173 return this._match(input, "date"); 174 }, 175 checked : function(input) 176 {
177 if(!!input.$multiInputs) 178 { 179 return !!input.$multiInputs.filter(":checked").length; 180 } 181 else return input.$base[0].checked; 182 }, 183 minNumber : function(input) 184 { 185 if(!!input.$multiInputs) 186 { 187 var results = true; 188 input.$multiInputs.each(function() 189 { 190 var result = parseInt(this.value) >= parseInt(input.rules.minNumber); 191 if(this.value.length <= 0) result = null; 192 results = result; 193 return result; 194 }); 195 return results; 196 } 197 else return (input.$input.val().length <= 0) ? null : (parseInt(input.$input.val()) >= parseInt(input.rules.minNumber)); 198 }, 199 maxNumber : function(input) 200 { 201 if(!!input.$multiInputs) 202 { 203 var results = true; 204 input.$multiInputs.each(function() 205 { 206 var result = (parseInt(this.value) <= parseInt(input.rules.maxNumber)); 207 if(this.value.length <= 0) result = null; 208 results = result; 209 return result; 210 }); 211 return results; 212 } 213 else return (input.$input.val().length <= 0) ? null : (parseInt(input.$input.val()) <= parseInt(input.rules.maxNumber)); 214 }, 215 minLength : function(input) 216 { 217 if(!!input.$multiInputs) 218 { 219 var results = true; 220 input.$multiInputs.each(function() 221 { 222 var result = (this.value.length >= input.rules.minLength); 223 results = result; 224 return result; 225 }); 226 return results; 227 } 228 else return (input.$input.val().length >= input.rules.minLength); 229 }, 230 maxLength : function(input) 231 { 232 if(!!input.$multiInputs) 233 { 234 var results = true; 235 input.$multiInputs.each(function() 236 { 237 var result = (this.value.length <= input.rules.maxLength); 238 if(this.value.length <= 0) result = null; 239 results = result; 240 return result; 241 }); 242 return results; 243 } 244 else return (input.$input.val().length <= 0) ? null : (input.$input.val().length <= input.rules.maxLength); 245 }, 246 //Multi only 247 valuableChecked : function(input) 248 { 249 if(!!input.$multiInputs) 250 { 251 var $selected = input.$multiInputs.filter(":checked"); 252 return (!!$selected.length == 1 && !!$selected.val()); 253 } 254 else return null; 255 }, 256 minChecked : function(input) 257 { 258 if(!!input.$multiInputs) 259 { 260 var checkeds = input.$multiInputs.filter(":checked").length; 261 return (checkeds >= input.rules.minChecked); 262 } 263 else return null; 264 }, 265 maxChecked : function(input) 266 { 267 if(!!input.$multiInputs) 268 { 269 var checkeds = input.$multiInputs.filter(":checked").length; 270 if(checkeds == 0) return null; 271 return (checkeds <= input.rules.maxChecked); 272 } 273 else return null; 274 }, 275 //SIngle only 276 minSize : function(input) 277 { 278 var files = input.$input[0].files; 279 if(!!input.$multiInputs || !files || !files.length) return null; 280 else 281 { 282 var files = input.$input[0].files; 283 var size = 0; 284 $.each(files, function(){ size += this.size; }); 285 286 return (size >= input.rules.minSize); 287 } 288 }, 289 maxSize : function(input) 290 { 291 var files = input.$input[0].files; 292 if(!!input.$multiInputs || !files || !files.length) return null; 293 else 294 { 295 var files = input.$input[0].files; 296 var size = 0; 297 $.each(files, function(){ size += this.size; }); 298 299 return (size <= input.rules.maxSize); 300 } 301 }, 302 equal : function(input) 303 { 304 if(!!input.$multiInputs) return null; 305 306 return (input.$input.val() == input.parent.inputs[input.rules.equal].$input.val()); 307 }, 308 //common 309 _match : function(input, pattern) 310 { 311 if(!!input.$multiInputs) 312 { 313 var results = null; 314 input.$multiInputs.each(function() 315 { 316 var result = (this.value.length) ? validateMatches[pattern](this.value) : null; 317 if(result == null) return; 318 results = result; 319 return results; 320 }); 321 return results; 322 } 323 else 324 { 325 return (input.$input.val().length) ? validateMatches[pattern](input.$input.val()) : null; 326 } 327 } 328 } 329 //matches 330 var validateMatches = 331 { 332 alphanumeric : function(value) 333 { 334 value = toOneBytes(value); 335 return !! value.match(/^[a-zA-Z0-9]+$/); 336 }, 337 number : function(value) 338 { 339 value = toOneBytes(value); 340 return !!value.match(/^[0-9]+$/); 341 }, 342 url : function(value) 343 { 344 value = toOneBytes(value); 345 return !!value.match(/^https?:\/\/.+/); 346 // return !!value.match(/^https?:\/\/[\w/:%#\$&\?\(\)~\.=\+\-]+$/); 347 }, 348 domain : function(value) 349 { 350 value = toOneBytes(value); 351 return !!value.match(/^[A-Za-z0-9][A-Za-z0-9\-]{1,61}[A-Za-z0-9]$/); 352 }, 353 email : function(value) 354 { 355 value = toOneBytes(value); 356 return !!value.match(/^[\w.\-]+@[\w\-]+\.[\w.\-]+$/); 357 }, 358 phone : function(value) 359 { 360 value = toOneBytes(value); 361 // return !!value.match(/^[\d\(\)\-]+$/); 362 return !!value.match(/^(\(?\d{2,4}\)?-?)?\(?\d{2,4}\)?-?\d{4}$/); 363 }, 364 zipcode : function(value) 365 { 366 value = toOneBytes(value); 367 return !!value.match(/^\d{3}-?\d{4}$/); 368 }, 369 date : function(value) 370 { 371 value = toOneBytes(value); 372 return !!value.match(/^\d{4}[-/\.å¹´]\d{1,2}[-/\.æ]\d{1,2}æ¥?$/); 373 } 374 } 375 //messages 376 var messageMethods = 377 { 378 minNumber : function(value, input){ 379 return value.replace(/\{min\}/g, input.rules.minNumber); 380 }, 381 maxNumber : function(value, input){ 382 return value.replace(/\{max\}/g, input.rules.maxNumber); 383 }, 384 minLength : function(value, input){ 385 return value.replace(/\{min\}/g, input.rules.minLength); 386 }, 387 maxLength : function(value, input){ 388 return value.replace(/\{max\}/g, input.rules.maxLength); 389 }, 390 minChecked : function(value, input){ 391 return value.replace(/\{min\}/g, input.rules.minChecked); 392 }, 393 maxChecked : function(value, input){ 394 return value.replace(/\{max\}/g, input.rules.maxChecked) 395 }, 396 minSize : function(value, input){ 397 var size = toFileSize(input.rules.minSize); 398 return value.replace(/\{min\}/g, size); 399 }, 400 maxSize : function(value, input){ 401 var size = toFileSize(input.rules.maxSize); 402 return value.replace(/\{max\}/g, size); 403 } 404 } 405 // åè§å 406 var toOneBytes = function(str) 407 { 408 return str.replace(/[ã¼âââã¼â]/g, "-").replace(/[A-Zï½-ï½ï¼-ï¼ï¼ï¼âï¼ï¼ï¼ ï¼âï¼ï¼ï¼ï¼ï¼ï¼ï¼ï¼ï¼¿ï¼»ï¼½ï½ï½ï¼ ï¼¾ï½ï¿¥]/g, function(s) 409 { 410 return String.fromCharCode(s.charCodeAt(0) - 65248); 411 }); 412 } 413 //ãã¡ã¤ã«ãµã¤ãº 414 var toFileSize = function(num) 415 { 416 if(num >= 1073741824) num = (num/1073741824).toFixed(1) + 'GB'; 417 else if(num >= 1048576) num = (num/1048576).toFixed(1) + 'MB'; 418 else if(num >= 1024) num = (num/1024).toFixed(1) + 'KB'; 419 // else if(num > 1) num = num + 'bytes'; 420 // else if(num == 1) num = num + 'byte'; 421 else num = num + 'byte'; 422 return num; 423 } 424 //å ¨è§å 425 var toTwoBytes = function(str) 426 { 427 return str.replace(/[A-Za-z0-9-!"#$%&'()=<>,.?_\[\]{}@^~\\]/g, function(s) 428 { 429 return String.fromCharCode(s.charCodeAt(0) + 65248); 430 }); 431 } 432 433 434 /** Class - Validator 435 ------------------------------ **/ 436 var Validator = function(form, options) 437 { 438 this.options = $.extend(true, {}, defaultOptions, options); 439 440 this.form = form; 441 this.$form = $(this.form).addClass(this.options.classForm); 442 this.$submit = $(this.form).find("." + CLASS_SUBMIT); 443 444 this.inputs = new Object(); 445 446 this.init(); 447 Validator.forms.push(this); 448 } 449 Validator.prototype = 450 { 451 init : function() 452 { 453 var _self = this; 454 455 //Single inputs 456 _self.$form.find("." + CLASS_INPUT).each(function() 457 {
458 _self.inputs[$(this).attr(DATA_NAME) || this.name] = new Input(this, _self); 459 }); 460 //Multi inputs 461 _self.$form.find("." + CLASS_INPUTS).each(function() 462 { 463 _self.inputs[$(this).attr(DATA_NAME) || this.name] = new Input(this, _self, true); 464 }); 465 //submit 466 _self.$form.submit(function() 467 { 468 var result = _self.validate(); 469 470 // _self.$submit.attr("disabled", result); 471 return result; 472 }); 473 474 //trigger 475 _self.$trigger = _self.$form.find("." + CLASS_TRIGGER); 476 if(_self.$trigger.length) _self.$trigger.bind("click." + BASENAME, function(e) 477 { 478 _self.validate(); 479 }) 480 481 // page show 482 // $(document).on("pageshow", function(e) 483 // { 484 // console.log("page show", e); 485 // }); 486 487 if(_self.$form.hasClass(CLASS_VALIDATE)) _self.validate(); 488 }, 489 validate : function() 490 { 491 var _self = this; 492 493 if(typeof _self.options.onValidate === "function") _self.options.onValidate(_self); 494 495 var invalids = 0; 496 $.each(_self.inputs, function() 497 { 498 var result = this.validate(); 499 if(result == false) invalids++; 500 }); 501 502 var results = (!invalids); 503 if(results) 504 { 505 if(typeof _self.options.onValid === "function") _self.options.onValid(_self); 506 } 507 else 508 { 509 if(typeof _self.options.onInvalid === "function") _self.options.onInvalid(_self); 510 } 511 512 return results; 513 }, 514 option : function(key, value) 515 { 516 if(value !== undefined) 517 { 518 if(typeof value === "object") $.extend(true, this.options[key], value); 519 else this.options[key] = value 520 } 521 else return this.options[key]; 522 } 523 } 524 Validator.init = function() 525 { 526 $("form." + CLASS_FORM).each(function() 527 { 528 new Validator(this); 529 }); 530 } 531 Validator.addRule = function(name, func) 532 { 533 validateMethods[name] = func; 534 } 535 Validator.addMessage = function(name, message) 536 { 537 defaultOptions.messages[name] = message; 538 } 539 Validator.methods = validateMethods; 540 Validator.forms = new Array(); 541 542 /** Class - input 543 ------------------------------ **/ 544 var Input = function(element, parent, multi) 545 { 546 var _self = this; 547 548 _self.parent = parent; 549 _self.multi = multi || false; 550 // 551 _self.element = element; 552 _self.$base = $(_self.element); 553 _self.$input = (!_self.multi) ? _self.$base : null; 554 _self.$multiInputs = (_self.multi) ? _self.$base.find(":input:not(." + CLASS_IGNORE + ")") : null; 555 //rules 556 _self.rules = _self.$base.attr(DATA_RULE) || {}; 557 //flags 558 _self.result = null; 559 _self.sync = false; 560 561 _self.init(); 562 } 563 Input.prototype = 564 { 565 init : function() 566 { 567 this.$field = this.$base.closest("." + CLASS_FIELD); 568 569 this.initEvent(); 570 this.initRules(); 571 this.initMessages(); 572 573 if(this.$base.hasClass(CLASS_VALIDATE) || this.$field.hasClass(CLASS_VALIDATE)) this.validate(); 574 }, 575 initEvent : function() 576 { 577 var _self = this; 578 if(_self.parent.options.changeSync) (_self.multi ? _self.$multiInputs : _self.$base).bind("change." + BASENAME, function(e){ _self.validate(e); }); 579 if(_self.parent.options.blurSync) (_self.multi ? _self.$multiInputs : _self.$base).bind("blur." + BASENAME, function(e){ _self.validate(e); }); 580 }, 581 initRules : function() 582 { 583 var _self = this; 584 585 if(typeof _self.rules === "object") 586 { 587 $.each(defaultRules, function(key, value) 588 { 589 _self.rules[key] = _self.$base.attr(DATA_RULE + "-" + key) || value; 590 }); 591 } 592 }, 593 initMessages : function() 594 { 595 var _self = this; 596 var $root = (_self.multi) ? _self.$base : _self.$base.parent(); 597 598 _self.messages = 599 { 600 valid : (_self.$base.attr(DATA_MESSAGE_VALID) !== undefined) ? _self.$base.attr(DATA_MESSAGE_VALID) : _self.parent.options.messages.valid, 601 invalid : (_self.$base.attr(DATA_MESSAGE_INVALID) !== undefined) ? _self.$base.attr(DATA_MESSAGE_INVALID) : null, 602 } 603 _self.$messages = 604 { 605 valid : (_self.$field.length ? _self.$field : $root).find("." + _self.parent.options.classMessageValid).hide(), 606 invalid : (_self.$field.length ? _self.$field : $root).find("." + _self.parent.options.classMessageInvalid).hide() 607 } 608 //create $messages
609 if(!_self.$messages.valid.length) 610 { 611 _self.$messages.valid = $("<" + _self.parent.options.messageWrapper + ">") 612 .addClass(_self.parent.options.classMessageValid) 613 .appendTo($root).hide(); 614 } 615 if(!_self.$messages.invalid.length) 616 { 617 _self.$messages.invalid = $("<" + _self.parent.options.messageWrapper + ">") 618 .addClass(_self.parent.options.classMessageInvalid) 619 .appendTo($root).hide(); 620 } 621 //initialized 622 if(_self.$base.hasClass(CLASS_VALID) || _self.$field.hasClass(CLASS_VALID)) _self.$messages.valid.show(); 623 if(_self.$base.hasClass(CLASS_INVALID) || _self.$field.hasClass(CLASS_INVALID)) _self.$messages.invalid.show(); 624 }, 625 validate : function(e) 626 { 627 var _self = this; 628 629 if(typeof _self.rules === "string") 630 { 631 _self.result = (typeof validateMethods[_self.rules] === "function") ? validateMethods[_self.rules](_self) : null; 632 _self.showResult(_self.result, _self.rules); 633 } 634 else if(typeof _self.rules === "object") 635 { 636 $.each(_self.rules, function(key, value) 637 { 638 if(value != false) 639 { 640 _self.result = (typeof validateMethods[key] === "function") ? validateMethods[key](_self) : null; 641 _self.showResult(_self.result, key); 642 return _self.result; 643 } 644 }); 645 } 646 //sync validate 647 if(_self.parent.options.keySync) (_self.result) ? _self.clearKeySync() : _self.setKeySync(); 648 if(!!e) e.preventDefault(); 649 return _self.result; 650 }, 651 setKeySync : function() 652 { 653 var _self = this; 654 if(!_self.sync) 655 { 656 (_self.multi ? _self.$multiInputs : _self.$base).bind("keyup." + BASENAME, function(e){ _self.validate(); }); 657 } 658 _self.sync = true; 659 }, 660 clearKeySync : function() 661 { 662 var _self = this; 663 if(_self.sync) 664 { 665 (_self.multi ? _self.$multiInputs : _self.$base).unbind("keyup." + BASENAME); 666 } 667 _self.sync = false; 668 }, 669 showResult : function(result, rule) 670 { 671 //reset 672 this.$messages.valid.hide(); 673 this.$messages.invalid.hide(); 674 this.$field.removeClass(this.parent.options.classValid).removeClass(this.parent.options.classInvalid); 675 (this.multi ? this.$multiInputs : this.$base).removeClass(this.parent.options.classValid).removeClass(this.parent.options.classInvalid); 676 677 switch(result) 678 { 679 case true : this.showValid(rule); 680 break; 681 case false : this.showInvalid(rule); 682 break; 683 default : return result; 684 } 685 }, 686 showValid : function(rule) 687 { 688 this.$messages.valid.show().html(this.messages.valid); 689 690 (this.multi ? this.$multiInputs : this.$base).addClass(this.parent.options.classValid); 691 this.$field.addClass(this.parent.options.classValid); 692 }, 693 showInvalid : function(rule) 694 { 695 var message = (this.messages.invalid != null) 696 ? this.messages.invalid 697 : (this.$base.attr(DATA_MESSAGE + "-" + rule) !== undefined) 698 ? this.$base.attr(DATA_MESSAGE + "-" + rule) 699 : (!!messageMethods[rule]) 700 ? messageMethods[rule](this.parent.options.messages[rule], this) 701 : this.parent.options.messages[rule] || defaultOptions.messages[rule]; 702 this.$messages.invalid.show().html(message); 703 704 (this.multi ? this.$multiInputs : this.$base).addClass(this.parent.options.classInvalid); 705 this.$field.addClass(this.parent.options.classInvalid); 706 } 707 } 708 709 710 /** 711 * Plugin type 712 */ 713 //ãã©ã°ã¤ã³ã¡ã½ãã 714 var pluginMethods = 715 { 716 //åæå 717 init : function(options) 718 { 719 var options = $.extend({}, defaultOptions, options); 720 return this.each(function() 721 { 722 if(!$.data(this, BASENAME)) $.data(this, BASENAME, new Validator(this, options)); 723 }); 724 }, 725 validate : function(inputName) 726 { 727 return this.each(function() 728 { 729 if(!!inputName) $.data(this, BASENAME).inputs[inputName].validate(); 730 else $.data(this, BASENAME).validate(); 731 }); 732 }, 733 //ãªãã·ã§ã³ 734 option : function(key, value) 735 { 736 return this.data(BASENAME).option(key, value); 737 } 738 } 739 $.fn[BASENAME] = function(options) 740 { 741 if(!!pluginMethods[options]) 742 { 743 return pluginMethods[options].apply(this, Array.prototype.slice.call(arguments, 1)); 744 } 745 else 746 { 747 return pluginMethods.init.apply(this, arguments); 748 } 749 } 750 // 751 window.Validator = $.validator = Validator; 752 $(function() 753 { 754 Validator.init(); 755 }); 756})(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.