1(function ($) { 2 3/* 4* 5* provides feedback form for zammad 6* 7 8<button id="zammad-feedback-form">Feedback</button> 9 10<script id="zammad_form_script" src="http://localhost:3000/assets/form/form.js"></script> 11<script> 12$(function() { 13 $('#zammad-feedback-form').ZammadForm({ 14 messageTitle: 'Feedback Form', // optional 15 messageSubmit: 'Submit', // optional 16 messageThankYou: 'Thank you for your inquiry (#%s)! We\'ll contact you as soon as possible.', // optional 17 messageNoConfig: 'Unable to load form config from server. Maybe feature is disabled.', // optional 18 showTitle: true, 19 lang: 'de', // optional, <html lang="xx"> will be used per default 20 modal: true, 21 attachmentSupport: false, 22 attributes: [ 23 { 24 display: 'Name', 25 name: 'name', 26 tag: 'input', 27 type: 'text', 28 placeholder: 'Your Name', 29 defaultValue: '', 30 }, 31 { 32 display: 'Email', 33 name: 'email', 34 tag: 'input', 35 type: 'email', 36 required: true, 37 placeholder: 'Your Email', 38 defaultValue: function () {return User.email;}, 39 }, 40 { 41 display: 'Message', 42 name: 'body', 43 tag: 'textarea', 44 required: true, 45 placeholder: 'Your Messageâ¦', 46 defaultValue: '', 47 rows: 7, 48 }, 49 { 50 display: 'Attachments', 51 name: 'file[]', 52 tag: 'input', 53 type: 'file', 54 repeat: 3, 55 }, 56 ] 57 }); 58}); 59</script> 60 61*/ 62 63 var pluginName = 'ZammadForm', 64 defaults = { 65 lang: undefined, 66 debug: false, 67 noCSS: false, 68 prefixCSS: 'zammad-form-', 69 showTitle: false, 70 messageTitle: 'Zammad Form', 71 messageSubmit: 'Submit', 72 messageThankYou: 'Thank you for your inquiry! We\'ll contact you as soon as possible.', 73 messageNoConfig: 'Unable to load form config from server. Maybe feature is disabled.', 74 attachmentSupport: false, 75 attributes: [ 76 { 77 display: 'Name', 78 name: 'name', 79 tag: 'input', 80 type: 'text', 81 id: 'zammad-form-name', 82 required: true, 83 placeholder: 'Your Name', 84 defaultValue: '', 85 }, 86 { 87 display: 'Email', 88 name: 'email', 89 tag: 'input', 90 type: 'email', 91 id: 'zammad-form-email', 92 required: true, 93 placeholder: 'Your Email', 94 defaultValue: '', 95 }, 96 { 97 display: 'Message', 98 name: 'body', 99 tag: 'textarea', 100 id: 'zammad-form-body', 101 required: true, 102 placeholder: 'Your Messageâ¦', 103 defaultValue: '', 104 rows: 7, 105 }, 106 ], 107 translations: { 108 // ZAMMAD_TRANSLATIONS_START 109 'cs': { 110 'Attachments': 'PÅÃlohy', 111 'Email': 'Email', 112 'Message': 'Zpráva', 113 'Name': 'Jméno', 114 'Your Email': 'Váš e-mail', 115 'Your Messageâ¦': 'VaÅ¡e zprávaâ¦', 116 'Your Name': 'VaÅ¡e jméno', 117 }, 118 'de': { 119 'Attachments': 'Anhänge', 120 'Email': 'E-Mail', 121 'Message': 'Nachricht', 122 'Name': 'Name', 123 'Your Email': 'Ihre E-Mail', 124 'Your Messageâ¦': 'Ihre Nachrichtâ¦', 125 'Your Name': 'Ihr Name', 126 }, 127 'es': { 128 'Attachments': 'Adjuntos', 129 'Email': 'Correo electrónico', 130 'Message': 'Mensaje', 131 'Name': 'Nombre', 132 'Your Email': 'Tu correo electrónico', 133 'Your Messageâ¦': 'Su mensajeâ¦', 134 'Your Name': 'tu Nombre', 135 }, 136 'et': { 137 'Attachments': 'Manused', 138 'Email': 'E-post', 139 'Message': 'Teade', 140 'Name': 'Nimi', 141 'Your Email': 'Sinu Meiliaadress', 142 'Your Messageâ¦': 'Sinu Teadeâ¦', 143 'Your Name': 'Sinu Nimi', 144 }, 145 'fa': { 146 'Attachments': 'ض٠اÛÙ ', 147 'Email': 'Ø±Ø§ÛØ§Ùا٠Ù', 148 'Message': 'Ù¾ÛØ§Ù ', 149 'Name': 'ÙØ§Ù ', 150 'Your Email': 'اÛÙ Û٠ش٠ا', 151 'Your Messageâ¦': 'Ù¾ÛØ§Ù ش٠اâ¦', 152 'Your Name': 'ÙØ§Ù ش٠ا', 153 }, 154 'fr': { 155 'Attachments': 'Pièces jointes', 156 'Email': 'E-mail', 157 'Message': 'Message',
158 'Name': 'Nom', 159 'Your Email': 'Votre email', 160 'Your Messageâ¦': 'Votre messageâ¦', 161 'Your Name': 'Votre nom', 162 }, 163 'hr': { 164 'Attachments': 'Privici', 165 'Email': 'E-Mail', 166 'Message': 'Poruka', 167 'Name': 'Ime', 168 'Your Email': 'VaÅ¡ e-mail', 169 'Your Messageâ¦': 'VaÅ¡a porukaâ¦', 170 'Your Name': 'VaÅ¡e ime', 171 }, 172 'hu': { 173 'Attachments': 'Csatolmányok', 174 'Email': 'E-mail', 175 'Message': 'Ãzenet', 176 'Name': 'Név', 177 'Your Email': 'Az Ãn e-mail cÃme', 178 'Your Messageâ¦': 'Az Ãn üzeneteâ¦', 179 'Your Name': 'Az Ãn neve', 180 }, 181 'it': { 182 'Attachments': 'Allegati', 183 'Email': 'Email', 184 'Message': 'Messaggio', 185 'Name': 'Nome', 186 'Your Email': 'Il tuo indirizzo e-mail', 187 'Your Messageâ¦': 'Il tuo messaggioâ¦', 188 'Your Name': 'Il tuo nome', 189 }, 190 'lt': { 191 'Attachments': 'Prisegtukai', 192 'Email': 'El. paÅ¡tas', 193 'Message': 'ŽinutÄ', 194 'Name': 'Vardas', 195 'Your Email': 'JÅ«sų el. paÅ¡tas', 196 'Your Messageâ¦': 'JÅ«sų žinutÄâ¦', 197 'Your Name': 'JÅ«sų vardas', 198 }, 199 'nl': { 200 'Attachments': 'Bijlagen', 201 'Email': 'E-mail', 202 'Message': 'Bericht', 203 'Name': 'Naam', 204 'Your Email': 'Je e-mailadres', 205 'Your Messageâ¦': 'Je berichtâ¦', 206 'Your Name': 'Je naam', 207 }, 208 'pl': { 209 'Attachments': 'ZaÅÄ czniki', 210 'Email': 'E-mail', 211 'Message': 'WiadomoÅÄ', 212 'Name': 'Nazwa', 213 'Your Email': 'Adres e-mail', 214 'Your Messageâ¦': 'Twoja wiadomoÅÄâ¦', 215 'Your Name': 'ImiÄ i nazwisko', 216 }, 217 'pt-br': { 218 'Attachments': 'Anexos', 219 'Email': 'Email', 220 'Message': 'Mensagem', 221 'Name': 'Nome', 222 'Your Email': 'Seu Email', 223 'Your Messageâ¦': 'Sua Mensagemâ¦', 224 'Your Name': 'Seu nome', 225 }, 226 'ro': { 227 'Attachments': 'AtaÈamente', 228 'Email': 'E-mail', 229 'Message': 'Mesaj', 230 'Name': 'Nume', 231 'Your Email': 'AdresÄ de e-mail', 232 'Your Messageâ¦': 'Mesajul tÄuâ¦', 233 'Your Name': 'Numele tÄu', 234 }, 235 'ru': { 236 'Attachments': 'ÐложениÑ', 237 'Email': 'ÐлекÑÑÐ¾Ð½Ð½Ð°Ñ Ð¿Ð¾ÑÑа', 238 'Message': 'СообÑение', 239 'Name': 'ÐмÑ', 240 'Your Email': 'ÐаÑа поÑÑа', 241 'Your Messageâ¦': 'ÐаÑе ÑообÑениеâ¦', 242 'Your Name': 'ÐаÑе имÑ', 243 }, 244 'sk': { 245 'Attachments': 'PrÃlohy', 246 'Email': 'E-mail', 247 'Message': 'Správa', 248 'Name': 'Meno', 249 'Your Email': 'Váš e-mail', 250 'Your Messageâ¦': 'VaÅ¡a správaâ¦', 251 'Your Name': 'VaÅ¡e meno', 252 }, 253 'sr': { 254 'Attachments': 'ÐÑилози', 255 'Email': 'ÐмеÑл', 256 'Message': 'ÐоÑÑка', 257 'Name': 'Ðазив', 258 'Your Email': 'ÐÐ°Ñ Ð¸Ð¼ÐµÑл', 259 'Your Messageâ¦': 'ÐаÑа поÑÑкаâ¦', 260 'Your Name': 'ÐаÑе име', 261 }, 262 'sr-latn-rs': { 263 'Attachments': 'Prilozi', 264 'Email': 'Imejl', 265 'Message': 'Poruka', 266 'Name': 'Naziv', 267 'Your Email': 'VaÅ¡ imejl', 268 'Your Messageâ¦': 'VaÅ¡a porukaâ¦', 269 'Your Name': 'VaÅ¡e ime', 270 }, 271 'sv': { 272 'Attachments': 'Bilagor', 273 'Email': 'E-post', 274 'Message': 'Meddelande', 275 'Name': 'Namn', 276 'Your Email': 'Din mejl', 277 'Your Messageâ¦': 'Ditt meddelandeâ¦', 278 'Your Name': 'Ditt namn', 279 }, 280 'tr': { 281 'Attachments': 'Ekler', 282 'Email': 'Eposta', 283 'Message': 'Mesaj', 284 'Name': 'Isim', 285 'Your Email': 'E-posta adresiniz', 286 'Your Messageâ¦': 'Mesajınızâ¦', 287 'Your Name': 'Adınız', 288 }, 289 'uk': { 290 'Attachments': 'ÐкладеннÑ', 291 'Email': 'Email', 292 'Message': 'ÐовÑдомленнÑ', 293 'Name': 'Ðм\'Ñ', 294 'Your Email': 'ÐаÑа елекÑÑонна поÑÑа', 295 'Your Messageâ¦': 'ÐаÑе повÑдомленнÑâ¦', 296 'Your Name': 'ÐаÑе Ñм\'Ñ', 297 }, 298 'zh-cn': { 299 'Attachments': 'éä»¶', 300 'Email': 'é®ä»¶å°å', 301 'Message': 'æ¶æ¯',
302 'Name': 'åç§°', 303 'Your Email': 'æ¨çé®ä»¶å°å', 304 'Your Messageâ¦': '', 305 'Your Name': 'æ¨çå°å§å¤§å', 306 }, 307 'zh-tw': { 308 'Attachments': 'éä»¶', 309 'Email': 'é»åéµä»¶', 310 'Message': 'è¨æ¯', 311 'Name': 'å稱', 312 'Your Email': 'è«ç䏿¨çé»åéµä»¶å°å', 313 'Your Messageâ¦': 'è«å¯«ä¸æ¨ççè¨â¦', 314 'Your Name': 'æ¨çå°å§å¤§å', 315 }, 316 // ZAMMAD_TRANSLATIONS_END 317 } 318 }; 319 320 function Plugin(element, options) { 321 this.element = element 322 this.$element = $(element) 323 324 this._defaults = defaults; 325 this._name = pluginName; 326 327 this._endpoint_config = '/api/v1/form_config' 328 this._endpoint_submit = '/api/v1/form_submit' 329 this._script_location = '/assets/form/form.js' 330 this._css_location = '/assets/form/form.css' 331 332 this._src = document.getElementById('zammad_form_script').src 333 this.css_location = this._src.replace(this._script_location, this._css_location) 334 this.endpoint_config = this._src.replace(this._script_location, this._endpoint_config) 335 this.endpoint_submit = this._src.replace(this._script_location, this._endpoint_submit) 336 337 this.options = $.extend(true, {}, defaults, options) 338 if (!this.options.lang) { 339 this.options.lang = $('html').attr('lang') 340 } 341 if (this.options.lang) { 342 this.options.lang = this.options.lang.replace(/-.+?$/, '') 343 this.log('debug', "lang: " + this.options.lang) 344 } 345 346 this._config = {} 347 this._token = '' 348 349 this.init() 350 } 351 352 Plugin.prototype.init = function () { 353 var _this = this, 354 params = {} 355 356 _this.log('debug', 'init', this._src) 357 358 if (!_this.options.noCSS) { 359 _this.loadCss(_this.css_location) 360 } 361 if (_this.options.attachmentSupport === true || _this.options.attachmentSupport === 'true') { 362 var attachment = { 363 display: 'Attachments', 364 name: 'file[]', 365 tag: 'input', 366 type: 'file', 367 repeat: 1, 368 } 369 _this.options.attributes.push(attachment) 370 } 371 if (_this.options.agreementMessage) { 372 var agreement = { 373 display: _this.options.agreementMessage, 374 name: 'agreement', 375 tag: 'input', 376 type: 'checkbox', 377 id: 'zammad-form-agreement', 378 required: true, 379 defaultValue: '', 380 } 381 _this.options.attributes.push(agreement) 382 } 383 384 _this.log('debug', 'endpoint_config: ' + _this.endpoint_config) 385 _this.log('debug', 'endpoint_submit: ' + _this.endpoint_submit) 386 387 // load config 388 if (this.options.test) { 389 params.test = true 390 } 391 392 params.fingerprint = this.fingerprint() 393 394 $.ajax({ 395 method: 'post', 396 url: _this.endpoint_config, 397 cache: false, 398 processData: true, 399 data: params 400 }).done(function(data) { 401 _this.log('debug', 'config:', data) 402 _this._config = data 403 }).fail(function(jqXHR, textStatus, errorThrown) { 404 if (jqXHR.status == 401) { 405 _this.log('error', 'Faild to load form config, wrong authentication data!') 406 } 407 else if (jqXHR.status == 403) { 408 _this.log('error', 'Faild to load form config, feature is disabled or request is wrong!') 409 } 410 else { 411 _this.log('error', 'Faild to load form config!') 412 } 413 _this.noConfig() 414 }); 415 416 // show form 417 if (!this.options.modal) { 418 _this.render() 419 } 420 421 // bind form on call 422 else { 423 this.$element.off('click.zammad-form').on('click.zammad-form', function (e) { 424 e.preventDefault() 425 _this.render() 426 return true 427 }) 428 } 429 } 430 431 // load css 432 Plugin.prototype.loadCss = function(filename) { 433 if (document.createStyleSheet) { 434 document.createStyleSheet(filename) 435 } 436 else { 437 $('<link rel="stylesheet" type="text/css" href="' + filename + '" />').appendTo('head') 438 } 439 } 440 441 // send 442 Plugin.prototype.submit = function() { 443 var _this = this 444 445 // check min modal open time 446 if (_this.modalOpenTime) { 447 var currentTime = new Date().getTime() 448 var diff = currentTime - _this.modalOpenTime.getTime() 449 _this.log('debug', 'currentTime', currentTime) 450 _this.log('debug', 'modalOpenTime', _this.modalOpenTime.getTime()) 451 _this.log('debug', 'diffTime', diff) 452 if (diff < 1000*10) { 453 alert('Sorry, you look like a robot!') 454 return 455 } 456 } 457 458 // disable form 459 _this.$form.find('button').prop('disabled', true) 460 461 $.ajax({ 462 method: 'post', 463 url: _this.endpoint_submit, 464 data: _this.getParams(), 465 cache: false, 466 contentType: false, 467 processData: false, 468 }).done(function(data) { 469 470 // Remove the errors from the form. 471 _this.$form.find('.zammad-form-group--has-error').removeClass('zammad-form-group--has-error') 472 // Deprecated code, can be removed in future versions: 473 _this.$form.find('.has-error').removeClass('has-error') 474 475 // set errors 476 if (data.errors) { 477 $.each(data.errors, function( key, value ) { 478 _this.$form.find('[name=' + key + ']').closest('.'+ _this.options.prefixCSS +'group').addClass('zammad-form-group--has-error') 479 // Deprecated code, can be removed in future versions: 480 _this.$form.find('[name=' + key + ']').closest('.form-group').addClass('has-error') 481 }) 482 if (data.errors.token) { 483 alert(data.errors.token) 484 } 485 _this.$form.find('button').prop('disabled', false) 486 return 487 } 488 489 // ticket has been created 490 _this.thanks(data) 491 492 }).fail(function() { 493 _this.$form.find('button').prop('disabled', false) 494 alert('The form could not be submitted!') 495 }); 496 } 497 498 // get params 499 Plugin.prototype.getParams = function() { 500 var _this = this 501 502 var formData = new FormData(_this.$form[0]) 503
504 /* unfortunaly not working in safari and some IEs - https://developer.mozilla.org/en-US/docs/Web/API/FormData 505 if (!formData.has('title')) { 506 formData.append('title', this.options.messageTitle) 507 } 508 */ 509 if (!_this.$form.find('[name=title]').val()) { 510 formData.append('title', this.options.messageTitle) 511 } 512 513 if (this.options.test) { 514 formData.append('test', true) 515 } 516 formData.append('token', this._config.token) 517 518 formData.append('fingerprint', this.fingerprint()) 519 _this.log('debug', 'formData', formData) 520 521 return formData 522 } 523 524 Plugin.prototype.closeModal = function() { 525 if (this.$modal) { 526 this.$modal.remove() 527 } 528 } 529 530 // render form 531 Plugin.prototype.render = function(e) { 532 var _this = this 533 _this.closeModal() 534 _this.modalOpenTime = new Date() 535 _this.log('debug', 'modalOpenTime:', _this.modalOpenTime) 536 537 var element = "<div class=\"" + _this.options.prefixCSS + "modal\">\ 538 <div class=\"" + _this.options.prefixCSS + "modal-backdrop js-zammad-form-modal-backdrop\"></div>\ 539 <div class=\"" + _this.options.prefixCSS + "modal-body js-zammad-form-modal-body\">\ 540 <form class=\"zammad-form\"></form>\ 541 </div>\ 542 </div>" 543 544 if (!this.options.modal) { 545 element = '<div><form class="zammad-form"></form></div>' 546 } 547 548 var $element = $(element) 549 var $form = $element.find('form') 550 if (this.options.showTitle && this.options.messageTitle != '') { 551 $form.append('<h2>' + this.options.messageTitle + '</h2>') 552 } 553 $.each(this.options.attributes, function(index, value) { 554 var valueId = _this.options.modal ? value.id + '-modal' : value.id + '-inline' 555 var item 556 if (value.type == 'checkbox'){ 557 item = $('<div class="form-group '+ _this.options.prefixCSS +'group"></div>'); 558 } else { 559 // Deprecated class "form-group" can be removed in future versions. 560 item = $('<div class="form-group '+ _this.options.prefixCSS +'group"><label for="' + valueId +'"> ' + _this.T(value.display) + '</label></div>'); 561 } 562 var defaultValue = (typeof value.defaultValue === 'function') ? value.defaultValue() : value.defaultValue; 563 for (var i=0; i < (value.repeat ? value.repeat : 1); i++) { 564 if (value.tag === 'input') { 565 if (value.type === 'checkbox'){ 566 var label = $('<label for="' + valueId + '"><input type="' + value.type + '" name="' + value.name + '" id="' + valueId + '" class="' + _this.options.prefixCSS + 'checkbox" ' + (value.required === true ? ' required' : '') + '>' + _this.T(value.display) + '</label>') 567 item.append(label) 568 } else { 569 // Deprecated class "form-control" can be removed in future versions. 570 item.append('<input class="form-control '+ _this.options.prefixCSS +'control" id="' + valueId + '" name="' + value.name + '" type="' + value.type + '" placeholder="' + _this.T(value.placeholder) + '" value="' + (defaultValue || '') + '"' + (value.required === true ? ' required' : '') + '>') 571 } 572 } 573 else if (value.tag == 'textarea') { 574 // Deprecated class "form-control" can be removed in future versions. 575 item.append('<textarea class="form-control '+ _this.options.prefixCSS +'control" id="' + valueId + '" name="' + value.name + '" placeholder="' + _this.T(value.placeholder) + '" rows="' + value.rows + '"' + (value.required === true ? ' required' : '') + '>' + (defaultValue || '') + '</textarea>') 576 } 577 } 578 $form.append(item) 579 }) 580 $form.append('<button type="submit" class="btn">' + this.options.messageSubmit + '</button') 581 582 this.$modal = $element 583 this.$form = $form 584 585 // bind on close 586 $element.find('.js-zammad-form-modal-backdrop').off('click.zammad-form').on('click.zammad-form', function (e) { 587 e.preventDefault() 588 _this.closeModal() 589 return true 590 }) 591 592 // bind form submit 593 $element.off('submit.zammad-form').on('submit.zammad-form', function (e) { 594 e.preventDefault() 595 _this.submit() 596 return true 597 }) 598 599 // show form 600 if (!this.options.modal) { 601 _this.$element.html($element) 602 } 603 604 // append modal to body 605 else { 606 $('body').append($element) 607 } 608 609 } 610 611 // thanks 612 Plugin.prototype.thanks = function(data) { 613 var thankYou = this.options.messageThankYou 614 if (data.ticket && data.ticket.number) { 615 thankYou = thankYou.replace('%s', data.ticket.number) 616 } 617 var message = $('<div class="js-thankyou zammad-form-thankyou">' + thankYou + '</div>') 618 this.$form.html(message) 619 } 620 621 // unable to load config 622 Plugin.prototype.noConfig = function(e) { 623 var message = $('<div class="js-noConfig">' + this.options.messageNoConfig + '</div>') 624 if (this.$form) { 625 this.$form.html(message) 626 } 627 this.$element.html(message) 628 } 629 630 // log method 631 Plugin.prototype.log = function() { 632 var args = Array.prototype.slice.call(arguments) 633 var level = args.shift() 634 if (!this.options.debug && level == 'debug') { 635 return 636 } 637 args.unshift(this._name + '||' + level) 638 console.log.apply(console, args) 639 640 var logString = '' 641 $.each( args, function(index, item) { 642 logString = logString + ' ' 643 if (typeof item == 'object') { 644 logString = logString + JSON.stringify(item) 645 } 646 else if (item && item.toString) { 647 logString = logString + item.toString() 648 } 649 else { 650 logString = logString + item 651 } 652 }) 653 $('.js-logDisplay').prepend('<div>' + logString + '</div>') 654 } 655 656 // translation method 657 Plugin.prototype.T = function() { 658 var string = arguments[0] 659 var items = 2 <= arguments.length ? slice.call(arguments, 1) : [] 660 if (this.options.lang && this.options.lang !== 'en') { 661 if (!this.options.translations[this.options.lang]) { 662 this.log('debug', "Translation '" + this.options.lang + "' needed!") 663 } 664 else { 665 translations = this.options.translations[this.options.lang] 666 if (!translations[string]) { 667 this.log('debug', "Translation needed for '" + this.options.lang + "' " + string + "'") 668 }
669 string = translations[string] || string 670 } 671 } 672 if (items) { 673 for (i = 0, len = items.length; i < len; i++) { 674 item = items[i] 675 string = string.replace(/%s/, item) 676 } 677 } 678 return string 679 } 680 681 Plugin.prototype.fingerprint = function () { 682 var canvas = document.createElement('canvas') 683 var ctx = canvas.getContext('2d') 684 var txt = 'https://zammad.com' 685 ctx.textBaseline = 'top' 686 ctx.font = '12px \'Arial\'' 687 ctx.textBaseline = 'alphabetic' 688 ctx.fillStyle = '#f60' 689 ctx.fillRect(125,1,62,20) 690 ctx.fillStyle = '#069' 691 ctx.fillText(txt, 2, 15) 692 ctx.fillStyle = 'rgba(100, 200, 0, 0.7)' 693 ctx.fillText(txt, 4, 17) 694 return canvas.toDataURL() 695 } 696 697 $.fn[pluginName] = function (options) { 698 return this.each(function () { 699 var instance = $.data(this, 'plugin_' + pluginName) 700 if (instance) { 701 instance.$element.empty() 702 $.data(this, 'plugin_' + pluginName, undefined) 703 } 704 $.data( 705 this, 'plugin_' + pluginName, 706 new Plugin(this, options) 707 ); 708 }); 709 } 710 711}(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.