PageSourceSearch

https://cvety-vanilla.ru/bitrix/js/acrit.bonus/bonus_integration.js?176652212620122

js cvety-vanilla.ru collected 2026-10-06 23:50:17 UTC 20,122 bytes, 623 lines download raw bytes

1function slog(str) {
2	try {
3		console.log(str);
4	} catch (e) {}
5}
6
7(function (window) {
8	'use strict';
9	if (window.AcritBonusIntegration) {
10		return;
11	}
12
13	/*/
14	 BX.onCustomEvent = function (eventObject, eventName) {
15	 console.log('onCustomEvent');
16	 console.log(eventName);
17	 console.log(eventObject);
18	 //console.log(arEventParams);
19	 console.log('====================');
20	 };
21	/**/
22
23	/**
24	 * @param arParams
25	 * @constructor
26	 */
27	window.AcritBonusIntegration = function (arParams) {
28		if (typeof arParams === 'object') {
29			this.Params = arParams;
30			this.elementcount = 0;
31			this.elementID = 0;
32		}
33		slog('window.AcritBonusIntegration');
34
35		// custom product autointegration with definition of productId outside
36		if (typeof productId != 'undefined') {
37			this.elementID = productId;
38			this.elementcount = 1;
39			this.ElementBonus();
40		}
41
42		// basket and product
43		BX.addCustomEvent('onCatalogElementChangeOffer', BX.proxy(this.DetailElement, this));
44		this.BasketAllBonus();
45		if (BX.Sale) {
46			BX.addCustomEvent('OnBasketChange', BX.proxy(this.BasketAllBonus, this));
47		}
48
49		// old
50		////BX.addCustomEvent('quantityChange', BX.proxy(this.ChangeQuantity, this));
51		////BX.addCustomEvent('quantityUp', BX.proxy(this.ChangeQuantity, this));
52		////BX.addCustomEvent('ChangeQuantity', BX.proxy(this.ChangeQuantity, this));
53
54		// order
55		if (BX.Sale) {
56			this.SOAAjax();
57		}
58		BX.addCustomEvent('onAjaxSuccess', BX.proxy(this.SOAAjax, this));
59
60		this.PersonalPage();
61	};
62	window.AcritBonusIntegration.prototype.UpdateBonus = function ()
63	{
64	};
65	window.AcritBonusIntegration.prototype = {
66		ErrorNotFoundClass: function (className, id, functionBlock = false) {
67			if (functionBlock != false) {
68				console.log('acrit.bonus warning: Block [' + functionBlock + '] not found class[' + className + '] in id[' + id + ']');
69			} else {
70				console.log('acrit.bonus warning: not found class[' + className + '] in id[' + id + ']');
71			}
72		},
73		ErrorNotFoundId: function (id, functionBlock = false) {
74			if (functionBlock != false) {
75				console.error('acrit.bonus warning: Block [' + functionBlock + '] not found id[' + id + ']');
76			} else {
77				console.error('acrit.bonus warning: not found id[' + id + ']');
78			}
79		},
80		PersonalPage: function () {
81			var params = this.Params.PERSONAL;
82			if (params.ON != undefined && params.ON) {
83				let blockId = this.getBlockId(params.BLOCK_ID);
84
85				if (params.BALANCE != undefined) {
86					if (! document.querySelector(blockId)) {
87						this.ErrorNotFoundId(blockId);
88						return;
89					}
90					var block = BX.findChild(document.querySelector(blockId), {
91						'tag': 'div',
92						'class': params.BLOCK_CLASS
93					}, true);
94					if (!block) {
95						this.ErrorNotFoundClass(params.BLOCK_CLASS, blockId, 'Personal page');
96						return;
97					}
98
99					var html = BX.create('DIV', {props: {className: 'acrit-bonus-personal-balance'}, html: params.BALANCE_TEXT + ' ' + params.BALANCE});
100					if (block) {
101						BX.prepend(html, block)
102					}
103				}
104				if (params.ORDERS != undefined) {
105					// insert bonus on page /personal/orders/?filter_history=Y
106					var fields = BX.findChild(BX(params.BLOCK_ID), {class: 'sale-order-list-about-link'}, true, true);
107					var href = '';
108					var orderId = '';
109					fields.forEach(function (element) {
110						href = element.getAttribute('href');
111						orderId = href.replace('/personal/orders/', '');
112						if (params.ORDERS[orderId] != undefined) {
113							var html = BX.create('DIV', {props: {className: 'acrit-bonus-personal-order-bonus'}, html: params.ORDERS_TEXT + ' ' + params.ORDERS[orderId]});
114							BX.insertAfter(html, element);
115						}
116					});
117				}
118			}
119
120		},
121		BasketAllBonus: function () {
122			if (this.Params.CART.ON != true) {
123				return;
124			}
125
126			if (!BX.Sale || !BX.Sale.BasketComponent || !BX.Sale.BasketComponent.result) {
127				return;
128			}
129			if (!BX.Sale.BasketComponent.result.GRID.ROWS && BX.Sale.BasketComponent.result.BASKET_ITEM_RENDER_DATA) {
130				BX.Sale.BasketComponent.result.GRID.ROWS = BX.Sale.BasketComponent.result.BASKET_ITEM_RENDER_DATA;
131			}
132			if (!BX.Sale.BasketComponent.result.GRID.ROWS) {
133				return;
134			}
135
136			const _this = this;
137			const params = {
138				ACTION: 'BASKET',
139				AJAX: 'Y',
140				SITE_ID: this.Params.SITE_ID,
141				TYPE: 'CART',
142				ENDTOEND: 'Y',
143				/*GRID: BX.Sale.BasketComponent.result.GRID.ROWS,*/
144				COUNTS: 1,
145			};
146
147			const createBonusBlock = function () {
148				const blockId = _this.getBlockId(_this.Params.CART.MAIN_BLOCK);
149				if (! document.querySelector(blockId)) {
150					_this.ErrorNotFoundId(blockId, 'BASKET');
151					return;
152				}
153
154				const itog_block = BX.findChild(document.querySelector(blockId), {
155					'tag': 'div',
156					'class': _this.Params.CART.OUT_BLOCK
157				}, true);
158				const bonus_all = BX.create('DIV', {props: {id: 'bonus_all'}});
159				if (! itog_block) {
160					_this.ErrorNotFoundClass(_this.Params.CART.OUT_BLOCK, blockId, 'BASKET');
161				} else {
162					itog_block.appendChild(bonus_all);
163				}
164				return bonus_all;
165			};
166
167			BX.ajax({
168				url: this.Params.CART.PATH,
169				data: params,
170				method: 'POST',
171				dataType: 'json',
172				timeout: 60,
173				async: true,
174				processData: true,
175				scriptsRunFirst: true,
176				emulateOnload: true,
177				start: true,
178				cache: false,
179				onsuccess: function (data) {
180					window.setTimeout(function() {
181						let bonus_all = document.getElementById('bonus_all');
182						if (typeof data.ALLBONUS != 'undefined' && data.ALLBONUS != '') {
183							if (! bonus_all) {
184								bonus_all = createBonusBlock();
185							}
186							BX.adjust(bonus_all, {html: _this.Params.CART.LANG_BONUS + ' ' + data.ALLBONUS});
187						} else if (bonus_all) {
188							BX.remove(bonus_all);
189						}
190					}, _this.getWaitBxAjaxTimeout());
191					/*
192					if (_this.Params.CART.BONUS_OFFER == true) {
193						for (var id in data.ITEMS) {
194							var item = data.ITEMS[id];
195							var product_block = BX('basket-item-' + item.ID);
196							var price_blocks = BX.findChild(product_block, {
197								'tag': 'div',
198								'class': 'basket-item-block-price'
199							}, true, true);
200							var price_for_item = price_blocks[1];
201							var bonus_item = BX.create('DIV', {
202								props: {
203									id: 'bonus_item_' + item.ID,
204									className: 'bonus bonus_item_cart'
205								}, html: _this.Params.CART.OFFER_LANG_BONUS + ' ' + item.BONUS
206							});
207							BX.remove(BX('bonus_item_' + item.ID));
208							if (parseFloat(item.BONUS) > 0)
209								price_for_item.appendChild(bonus_item);
210						}
211					}
212					if (_this.Params.CARTBONUSPAY.ON == true) {
213						var bonuspay_block = BX.findChild(BX(_this.Params.CARTBONUSPAY.MAIN_BLOCK), {
214							'tag': 'div',
215							'class': _this.Params.CARTBONUSPAY.OUT_BLOCK
216						}, true);
217						var bonuspay = BX.create('DIV', {
218							props: {id: 'bonuspay'},
219							html: 'bonuspay for cart (test) !!!not use!!!'
220						});
221						bonuspay_block.appendChild(bonuspay);
222					}
223					*/
224				},
225				onfailure: function () {
226				}
227			});
228		},
229		SOAAjax: function (ajaxResult) {
230			// here may pass other ajax-calls
231			if (!BX.Sale || (BX.Sale.OrderAjaxComponent == undefined) || (typeof ajaxResult !== 'undefined' && typeof ajaxResult.order === 'undefined')) {
232				return;
233			}
234			const _this = this;
235			window.setTimeout(function (){
236				_this.payBonusElement(BX.Sale.OrderAjaxComponent.result);
237			}, _this.getWaitBxAjaxTimeout());
238		},
239		payBonusElement: function (result) {
240			if (typeof result === 'undefined' || !this.Params.SOA.ON) {
241				return;
242			}
243			BX.remove(BX('bonus_order'));
244			BX.remove(BX('bonus_pay'));
245
246			// region BONUS.TOTAL BLOCK
247			if (this.Params.SOA.MAIN_BLOCK) {
248				const total_block = BX.findChild(BX(this.Params.SOA.MAIN_BLOCK), {
249					'tag': 'div',
250					'class': this.Params.SOA.OUT_BLOCK
251				}, true, true);
252
253				// when total_block is multiple:
254
255				/**
256				 * Inserts a specified block element after each block in a list of provided blocks.
257				 *
258				 * @param {HTMLElement} block - The block element to insert.
259				 * @param {HTMLElement[]} afterBlocks - An array of block elements after which the specified block will be inserted.
260				 */
261				const insertAfterBlock = function (block, afterBlocks) {
262					afterBlocks.forEach(function (afterBlock) {
263						BX.insertAfter(block, afterBlock);
264					});
265				};
266
267				if (parseFloat(result.TOTAL.BONUS_PAY_USER_INPUT) > 0) {
268					BX.remove(BX('acrit-bonus-total-pay-by-bonus'));
269					var totalPayByBonus = BX.create('DIV', {
270						attrs: {className: 'bx-soa-cart-total-line', id: 'acrit-bonus-total-pay-by-bonus'},
271						html: '<div id="acrit-bonus-total-pay-by-bonus-block"><span class="bx-soa-cart-t">' + result.TOTAL.TOTAL_BONUS_PAY_TITLE + '</span><span class="bx-soa-cart-d">' + result.TOTAL.BONUS_PAY_USER_INPUT_FORMAT + '</span></div>'
272					});
273					if (total_block.length && totalPayByBonus) {
274						insertAfterBlock(totalPayByBonus, total_block);
275					} else {
276						console.log('Warning: cant add item acrit-bonus-total-pay-by-bonus');
277					}
278				}
279				if (parseFloat(result.TOTAL.BONUS_ORDER) > 0) {
280					BX.remove(BX('bonus_order'));
281					var block_order_bonus = BX.create('DIV', {
282						attrs: {className: 'bx-soa-cart-total-line', id: 'bonus_order'},
283						html: '<div id="order_bonus"><span class="bx-soa-cart-t">' + this.Params.SOA.LANG_BONUS + '</span><span class="bx-soa-cart-d">' + result.TOTAL.BONUS_ORDER_FORMAT + '</span></div>'
284					});
285					if (total_block.length && block_order_bonus) {
286						insertAfterBlock(block_order_bonus, total_block);
287					} else {
288						console.log('Warning: cant add item #order_bonus');
289					}
290				}
291				if (parseFloat(result.TOTAL.BONUS_PAY) > 0) {
292					BX.remove(BX('bonus_pay'));
293					var block_bonus_pay = BX.create('DIV', {
294						attrs: {className: 'bx-soa-cart-total-line', id: 'bonus_pay'},
295						html: '<div id="order_bonuspay"><span class="bx-soa-cart-t">' + this.Params.SOA.LANG_BONUSPAY + '</span><span class="bx-soa-cart-d">' + result.TOTAL.BONUS_PAY + '</span></div>'
296					});
297					if (total_block.length && block_bonus_pay) {
298						insertAfterBlock(block_bonus_pay, total_block);
299					} else {
300						console.log('Warning: cant add item #order_bonuspay');
301					}
302				}
303			}
304			// endregion
305
306			// region BONUSPAY form DISPLAY
307			if (result.BONUSPAY && result.BONUSPAY.DISPLAY == true) {
308				var payment_block = BX.create('DIV', {
309					attrs: {
310						id: 'acrit-bonus-paysystem',
311						className: 'bx-soa-section'
312					}
313				});
314				var title = BX.create('DIV', {
315					attrs: {className: 'bx-soa-section-title-container'},
316					html: '<h2 class="bx-soa-section-title col-sm-9">
316' +
317							'<span class="bx-soa-section-title-count"></span>' + result.BONUSPAY.NAME + '</h2>'
318				});
319				var con = BX.create('DIV', {attrs: {className: 'bx-soa-section-content container-fluid'}});
320				var container = BX.create('DIV', {attrs: {className: 'bx-soa-pp row'}});
321				var container_in = BX.create('DIV', {attrs: {className: 'col-sm-9 bx-soa-pp-item-container'}});
322				var container_inpic = BX.create('DIV', {attrs: {className: 'col-sm-2 bx-soa-pp-item-container'}});
323				payment_block.appendChild(title);
324				var comment_block = BX.create('DIV', {
325					props: {className: 'bonus_comment'},
326					children: [
327						BX.create('strong', {html: this.Params.SOA.INTEGRATION_ORDER_TEXT_IN_YOU_ACCOUNT.replace("#SUMMA#", result.BONUSPAY.CURRENT_BONUS_BUDGET_FORMATED.replace("", " "))})
328					]
329				});
330				var max_pay = BX.create('span', {html: '<br />' + this.Params.SOA.INTEGRATION_ORDER_TXT_YOU_MUST_PAY.replace("#PERCENT#", result.BONUSPAY.ORDER_PAY_PERCENT).replace("#MAXPAY#", result.BONUSPAY.MAXPAY_FORMATTED)});
331				var pay_field_block = BX.create('DIV', {
332					props: {id: 'bonus_payfield_block'},
333					children: [BX.create('strong', {text: result.BONUSPAY.USER_INPUT == true ? this.Params.SOA.INTEGRATION_ORDER_TXT_HOW_MUCH_BONUS : ''})]
334				});
335				var non_bonuspay = BX.create('DIV', {
336					props: {className: 'bonus_comment'},
337					children: [
338						BX.create('strong', {text: this.Params.SOA.ITR_BONUS_NONE_PAYBONUS})
339					]
340				});
341				var input_field = BX.create('input', {
342					attrs: {
343						type: 'text',
344						id: 'BONUS_CNT',
345						value: result.BONUSPAY.USER_VALUE,
346						name: 'BONUS_CNT',
347						disabled: result.PAY_BONUS_ACCOUNT ? 'disable' : '',
348						pattern: "\\d+(\\.\\d+)?"
349					},
350					style: {
351						'width': '150px'
352					},
353				});
354				if (this.Params.CHECK_SMS.ON == 'Y') {
355					var sms_field_block = BX.create('DIV', {
356						props: {id: 'sms_payfield_block'},
357						children: [BX.create('strong', {text: this.Params.CHECK_SMS.SMSTEXT})]
358					});
359					var sms_code = BX.create('input', {
360						attrs: {
361							type: 'text',
362							id: 'SMSCODE',
363							value: result.SMSCODE ? result.SMSCODE : '',
364							name: 'SMSCODE',
365							disabled: result.CHECKSMS ? 'disable' : '',
366						},
367						style: {
368							'width': '150px'
369						}
370					});
371					var checksms = BX.create('LABEL', {
372						props: {className: 'bxr-subscribe-tab-link bxr-font-color bxr-border-color'},
373						children: [
374							BX.create('INPUT', {
375								attrs: {
376									type: 'checkbox',
377									id: 'CHECK_SMS',
378									name: 'CHECK_SMS',
379									value: 'Y',
380									checked: result.CHECKSMS
381								},
382								style: {
383									'display': 'none',
384								},
385								events: {
386									click: BX.proxy(this.checksms, this)
387								}
388							}),
389							BX.create('SPAN', {
390								text: (result.CHECKSMS ? this.Params.SOA.ITR_BONUS_TXT_BONUSPAY_CANCEL : this.Params.SOA.ITR_BONUS_TXT_BONUSPAY_OK)
391							})
392						],
393						style: {
394							'border': '1px solid #e3e6e8',
395							'padding': '2px',
396							'margin-left': '10px',
397							'cursor': 'pointer',
398						},
399					});
400				}
401
402				var input_field_hidden = BX.create('input', {
403					attrs: {
404						type: 'hidden',
405						id: 'BONUS_CNT',
406						value: result.BONUSPAY.MAXPAY,
407						name: 'BONUS_CNT',
408					},
409				});
410				var hiddenpay = BX.create('INPUT', {
411					attrs: {
412						type: 'hidden',
413						name: 'PAY_BONUS_ACCOUNT',
414						value: 'N',
415					},
416				});
417				var label = BX.create('LABEL', {
418					props: {className: 'bxr-subscribe-tab-link bxr-font-color bxr-border-color'},
419					children: [
420						BX.create('INPUT', {
421							attrs: {
422								type: 'checkbox',
423								id: 'PAY_BONUS_ACCOUNT',
424								name: 'PAY_BONUS_ACCOUNT',
425								value: 'Y',
426								checked: result.PAY_BONUS_ACCOUNT
427							},
428							style: {
429								'display': 'none',
430							},
431							events: {
432								click: BX.proxy(this.selectBonusPaySystem, this)
433							}
434						}),
435						BX.create('SPAN', {
436							text: (result.PAY_BONUS_ACCOUNT ? this.Params.SOA.PAY_BONUS_APPLY_BUTTON_CANCEL : this.Params.SOA.PAY_BONUS_APPLY_BUTTON_OK)
437						})
438					],
439					style: {
440						'border': '1px solid #e3e6e8',
441						'padding': '2px',
442						'margin-left': '10px',
443						'cursor': 'pointer',
444					},
445				}
446				);
447				var help = BX.create('DIV', {
448					props: {},
449					children: [
450						BX.create('A', {
451							props: {href: BX.util.htmlspecialchars(this.Params.SOA.INTEGRATION_ORDER_PATH_TO_HELP)},
452							html: BX.util.htmlspecialchars(this.Params.SOA.ITR_BONUS_TEXT_TO_HELP)
453						}),
454					],
455				}
456				);
457				var logoNode = BX.create('DIV', {props: {className: 'bx-soa-pp-company-image'}});
458				var logotype = result.BONUSPAY.LOGOTIP_SRC;
459				if (logotype) {
460					logoNode.setAttribute('style',
461							'background-image: url(' + logotype + ');' +
462							'background-image: -webkit-image-set(url(' + logotype + ') 1x, url(' + logotype + ') 2x)'
463							);
464				}
465				var pic_con = BX.create('DIV', {attrs: {className: 'bx-soa-pp-company-graf-container'}});
466				pic_con.appendChild(logoNode);
467				container_inpic.appendChild(pic_con);
468				container_in.appendChild(comment_block);
469				if (result.BONUSPAY.MAXPAY > 0) {
470					container_in.appendChild(max_pay);
471					container_in.appendChild(pay_field_block);
472
473					if (result.BONUSPAY.USER_INPUT == true) {
474						container_in.appendChild(input_field);
475					} else {
476						container_in.appendChild(input_field_hidden);
477						container_in.appendChild(hiddenpay);
478					}
479					container_in.appendChild(label);
480					if (this.Params.CHECK_SMS.ON == 'Y' && result.PAY_BONUS_ACCOUNT) {
481						container_in.appendChild(sms_field_block);
482						container_in.appendChild(sms_code);
483						container_in.appendChild(checksms);
484					}
485				} else {
486					container_in.appendChild(non_bonuspay);
487				}
488				container_in.appendChild(help);
489
490				BX.remove(BX('acrit-bonus-paysystem'));
491				container.appendChild(container_inpic);
492				container.appendChild(container_in);
493				con.appendChild(container);
494				payment_block.appendChild(con);
495
496				BX.addClass(payment_block, this.Params.SOA.BONUSPAY_OUT_BLOCK);
497
498				let blockId = this.getBlockId(this.Params.SOA.BONUSPAY_MAIN_BLOCK);
499				BX.insertAfter(payment_block, document.querySelector(blockId));
500			} else {
501				BX.remove(BX('acrit-bonus-paysystem'));
502			}
503
504			if (document.getElementById('BONUS_CNT')) {
505				document.getElementById('BONUS_CNT').addEventListener('keydown', (e) => {
506					if (e.key === 'Enter') {
507						e.stopPropagation();
508						return false;
509					}
510				});
511				document.getElementById('BONUS_CNT').addEventListener('input', function (e) {
512					this.value = this.value.replace(/[^0-9+.]/g, '');
513				});
514			}
515			// endregion
516		},
517		checksms: function () {
518			BX.Sale.OrderAjaxComponent.sendRequest();
519		},
520		selectBonusPaySystem: function () {
521			BX.Sale.OrderAjaxComponent.sendRequest();
522		},
523		DetailElement: function (eventData, eventname) {
524			slog('DetailElement');
525			if (eventData) {
526				const _this = this;
527				window.setTimeout(function (){
528					_this.elementID = eventData.newId;
529					_this.ElementBonus();
530				}, _this.getWaitBxAjaxTimeout())
531			}
532		},
533		ChangeQuantity: function (eventData) {
534			slog(eventData);
535			this.elementID = eventData.newId;
536			this.elementcount = eventData.Qua;
537			this.ElementBonus();
538		},
539		ElementBonus: function () {
540			slog('ElementBonus')
541			if (this.Params.DETAIL.ON != true) {
542				return;
543			}
544			let params = {
545				AJAX: 'Y',
546				SITE_ID: this.Params.SITE_ID,
547				PRODUCT_ID: this.elementID,
548				COUNTS: this.elementcount
549			};
550			const _this = this;
551			const isDoubleElementId = (this.productPageElementId != undefined && this.productPageElementId == this.elementID);
552			const isDoubleElementCount = (this.productPageElementCount != undefined && this.productPageElementCount == this.elementcount);
553			if (isDoubleElementId && isDoubleElementCount) {
554				slog('double');
555				return;
556			}
557
558			this.timestamp = Date.now();
559			this.productPageElementId = this.elementID;
560			this.productPageElementCount = this.elementcount;
561
562			BX.ajax({
563				url: this.Params.DETAIL.PATH,
564				data: params,
565				method: 'POST',
566				dataType: 'html',
567				timeout: 60,
568				async: true,
569				processData: true,
570				scriptsRunFirst: true,
571				emulateOnload: true,
572				start: true,
573				cache: false,
574				onsuccess: function (data) {
575					let bonus_all;
576					if (data.toString().trim() == '') {
577						return;
578					}
579
580					window.setTimeout(function () {
581						let blockId = _this.getBlockId(_this.Params.DETAIL.MAIN_BLOCK);
582
583						const itog_block = BX.findChild(
584							document.querySelector(blockId),
585							{'tag': 'div', 'class': _this.Params.DETAIL.OUT_BLOCK}, true
586						);
587						if (!itog_block) {
588							if (! document.querySelector(blockId)) {
589								_this.ErrorNotFoundId(blockId);
590							} else {
591								_this.ErrorNotFoundClass(blockId, _this.Params.DETAIL.OUT_BLOCK, 'PRODUCT PAGE');
592							}
593						}
594						if (_this.Params.DETAIL.COMP_TEMPLATE == '') {
595							bonus_all = BX.create('DIV', {props: {id: 'bonus_all'}, html: _this.Params.DETAIL.LANG_BONUS + ' ' + data});
596						} else {
597							bonus_all = BX.create('DIV', {props: {id: 'bonus_all'}, html: data});
598						}
599						BX.remove(BX('bonus_all'));
600						itog_block.appendChild(bonus_all);
601					}, _this.getWaitBxAjaxTimeout());
602				},
603				onfailure: function () {
604				}
605			});
606		},
607
608		getBlockId: function (blockId) {
609			if (typeof blockId === 'undefined') {
610				return false;
611			}
612			blockId = blockId.toString().trim();
613			if (blockId[0] !== '#' && blockId[0] !== '.') {
614				blockId = '#' + blockId;
615			}
616			return blockId;
617		},
618
619		getWaitBxAjaxTimeout: function() {
620			return 800; // bx basket uses ajax, wait it
621		}
622	};
623})(window);

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.