1(function ($) { 2 // Header long navigation 3 $(function () { 4 var $nav = $('.hm-header__menu'); 5 var $btn = $('.hm-header__menu-toggle'); 6 var $vlinks = $('.hm-header__menu-list'); 7 var $hlinks = $('.hm-header__menu-more'); 8 9 var numOfItems = 0; 10 var totalSpace = 0; 11 var breakWidths = []; 12 13 // Get initial state 14 $vlinks.children().outerWidth(function (i, w) { 15 totalSpace += w; 16 numOfItems += 1; 17 breakWidths.push(totalSpace); 18 }); 19 20 var availableSpace, numOfVisibleItems, requiredSpace; 21 22 function check() { 23 // Get instant state 24 availableSpace = $vlinks.width() - 10; 25 numOfVisibleItems = $vlinks.children().length; 26 requiredSpace = breakWidths[numOfVisibleItems - 1]; 27 28 // There is not enought space 29 if (requiredSpace > availableSpace) { 30 $nav.removeClass('hm-header__menu--short'); 31 $vlinks.children().last().prependTo($hlinks); 32 numOfVisibleItems -= 1; 33 check(); 34 // There is more than enough space 35 } else if (availableSpace > breakWidths[numOfVisibleItems]) { 36 $nav.addClass('hm-header__menu--short'); 37 $hlinks.children().first().appendTo($vlinks); 38 numOfVisibleItems += 1; 39 } 40 // Update the button accordingly 41 $btn.attr('count', numOfItems - numOfVisibleItems); 42 if (numOfVisibleItems === numOfItems) { 43 $btn.hide(); 44 } else $btn.show(); 45 } 46 47 // Window listeners 48 $(window).resize(function () { 49 check(); 50 }); 51 52 $btn.on('click', function (e) { 53 e.preventDefault(); 54 e.stopPropagation(); 55 56 if ($hlinks.hasClass('hidden')) { 57 $hlinks.removeClass('hidden'); 58 $btn.addClass('open'); 59 60 $(document).on('click.gc-hmenu', e => { 61 $(document).off('click.gc-hmenu'); 62 $hlinks.addClass('hidden'); 63 $btn.removeClass('open'); 64 }); 65 } else { 66 $hlinks.addClass('hidden'); 67 $btn.removeClass('open'); 68 $(document).off('click.gc-hmenu'); 69 } 70 }); 71 72 check(); 73 }); 74 75 // Initialize Gecko customizer preview if needed. 76 $(function () { 77 if (window.location !== window.parent.location) { 78 if ('gecko-customizer-preview' === window.name) { 79 initCustomizerPreview(); 80 } 81 } 82 }); 83 84 // Initialize sticky sidebar. 85 $(function () { 86 function initStickySidebar() { 87 var $adminbar = $('#wpadminbar'); 88 var $header = $('.gc-js-header-wrapper').not('.gc-header__wrapper--static'); 89 var $footer = $('.gc-footer'); 90 var $bottomWidget = $('.gc-widgets--bottom'); 91 var main = document.getElementById('main'); 92 var mainStyle = main ? window.getComputedStyle(main, null) : {}; 93 var offsetTop = 94 ($adminbar.height() || 0) + 95 ($header.height() || 0) + 96 +(mainStyle.paddingTop || '').replace('px', '') - 97 1; 98 var offsetBottom = 99 (($footer.is(':visible') && $footer.height()) || 0) + 100 ($bottomWidget.outerHeight(true) || 0) + 101 +(mainStyle.paddingBottom || '').replace('px', '') - 102 1; 103 104 $('.sidebar--sticky .sidebar__inner').gc_stick_in_parent({ 105 offset_top: offsetTop, 106 offset_bottom: offsetBottom 107 }); 108 } 109 110 // Initialize on the next cycle to wait for the `gc_stick_in_parent` to be available first. 111 setTimeout(function () { 112 if ('function' === typeof $.fn.gc_stick_in_parent) { 113 initStickySidebar(); 114 } 115 }, 1); 116 }); 117 118 // Header Search Toggle 119 $('.gc-js-header__search-toggle').on('click', function () { 120 var header = $('.gc-js-header-wrapper'); 121 var header_class = 'gc-header__wrapper--search'; 122 var search = $('.gc-header__search'); 123 var search_box = $('.gc-header__search-box'); 124 var open = 'gc-header__search--open'; 125 126 $(header).toggleClass(header_class); 127 $(search).toggleClass(open); 128 $(search_box).fadeToggle(200, function () { 129 $input = $('.gc-header__search-input').add($(this).find('.ps-js-query')); 130 131 if (search.hasClass(open)) { 132 $input.focus(); 133 } else if ($input.val()) { 134 $input.val(''); 135 if ($input.hasClass('ps-js-query')) { 136 $input.trigger('input'); 137 } else { 138 let oldParams = location.search; 139 let newParams = oldParams.replace(/[\?&]s=[^&]+/, '').replace(/^&/, '?'); 140 if (oldParams !== newParams) { 141 location.href = location.href.replace(oldParams, newParams); 142 } 143 } 144 } 145 }); 146 }); 147 148 // Fixed header after scroll 149 $(window).scroll(function () { 150 var scroll = $(window).scrollTop(); 151 152 if (scroll >= 30) { 153 $('.gc-js-header-wrapper').addClass('gc-header__wrapper--scroll'); 154 } else { 155 $('.gc-js-header-wrapper').removeClass('gc-header__wrapper--scroll'); 156 } 157 }); 158 159 // // Align footer to the bottom of the window 160 // $(window).on('load', function () { 161 // function checkScreenSize() { 162 // var newWindowWidth = $(window).width(), 163 // footerHeight = 0; 164 // 165 // if (newWindowWidth >= 980) { 166 // var $footer = $('.gc-footer--sticky'); 167 // if ($footer.is(':visible')) { 168 // footerHeight = $footer.height(); 169 // } 170 // } 171 // 172 // $('body').css('padding-bottom', footerHeight); 173 // } 174 // 175 // $(window).on('resize', checkScreenSize); 176 // checkScreenSize(); 177 // }); 178 179 // Adapt body padding-top if Mobi Sticky Top widget is active 180 // $(window).on('load', function () { 181 // checkMobiScreenSize(); 182 // 183 // function checkMobiScreenSize() { 184 // var body = $('body'); 185 // var header = $('.gc-js-header-wrapper'); 186 // var wpmobileapp = ('is-wpmobileapp'); 187 // var wpadminBar = $('#wpadminbar').height() || 0; 188 // var headerHeight = $(header).height() || 0;
189 // var stickyWidgetHeight = $('.gc-js-widgets-sticky').height() || 0; 190 // var headerCombinedHeight = headerHeight + stickyWidgetHeight + wpadminBar; 191 // 192 // if (body.hasClass(wpmobileapp)) { 193 // $(body).css('--body-gap', headerCombinedHeight + 'px'); 194 // } else { 195 // $(body).css('padding-top', headerCombinedHeight); 196 // } 197 // } 198 // 199 // setInterval(checkMobiScreenSize, 1000); 200 // }); 201 202 // Check if element has fixed position 203 function elementOrParentIsFixed(element) { 204 var $element = $(element); 205 var $checkElements = $element.add($element.parents()); 206 var isFixed = false; 207 $checkElements.each(function () { 208 if ($(this).css('position') === 'fixed') { 209 isFixed = true; 210 return false; 211 } 212 }); 213 return isFixed; 214 } 215 216 $(window).on('load', function () { 217 adaptBodyGap(); 218 219 function adaptBodyGap() { 220 var body = $('body'); 221 var headerWrapper = $('.gc-js-header-wrapper'); 222 var header = $('.gc-js-header'); 223 var aboveHeaderBar = $('.gc-js-sticky-bar-above-header'); 224 var underHeaderBar = $('.gc-js-sticky-bar-under-header'); 225 var wpMobileAppBar = $('.gc-js-sticky-bar-mobile'); 226 227 var wpadminBarHeight = $('#wpadminbar').outerHeight() || 0; 228 var headerWrapperHeight = $(headerWrapper).height() || 0; 229 var aboveHeaderBarHeight = $(aboveHeaderBar).outerHeight() || 0; 230 var underHeaderBarHeight = $(underHeaderBar).outerHeight() || 0; 231 var wpMobileAppBarHeight = $(wpMobileAppBar).outerHeight() || 0; 232 233 var isFixed = elementOrParentIsFixed(headerWrapper); 234 235 if (isFixed) { 236 $(body).css('padding-top', headerWrapperHeight + wpadminBarHeight + 'px'); 237 } else { 238 $(aboveHeaderBar).css({ 239 position: 'fixed', 240 top: wpadminBarHeight, 241 left: 0, 242 right: 0, 243 'z-index': 500 244 }); 245 $(underHeaderBar).css({ 246 position: 'fixed', 247 top: wpadminBarHeight + aboveHeaderBarHeight, 248 left: 0, 249 right: 0, 250 'z-index': 450 251 }); 252 $(wpMobileAppBar).css({ 253 position: 'fixed', 254 top: wpadminBarHeight + aboveHeaderBarHeight + underHeaderBarHeight, 255 left: 0, 256 right: 0, 257 'z-index': 500 258 }); 259 $(headerWrapper).css('position', 'static'); 260 $(body).css( 261 'padding-top', 262 aboveHeaderBarHeight + 263 underHeaderBarHeight + 264 wpadminBarHeight + 265 wpMobileAppBarHeight + 266 'px' 267 ); 268 } 269 } 270 271 setInterval(adaptBodyGap, 500); 272 }); 273 274 // Modal 275 $('.gc-js-header-menu-open').on('click', function (e) { 276 e.preventDefault(); 277 e.stopPropagation(); 278 279 $('html').addClass('gc-is-header-sidebar-open'); 280 $('.gc-js-header-sidebar').addClass('gc-header__sidebar--open'); 281 }); 282 283 $('.gc-js-header-menu-close').on('click', function (e) { 284 e.preventDefault(); 285 e.stopPropagation(); 286 287 $('html').removeClass('gc-is-header-sidebar-open'); 288 $('.gc-js-header-sidebar').removeClass('gc-header__sidebar--open'); 289 }); 290 291 function check_cart() { 292 var woocart_toggle = $('.js-header-cart-toggle'); 293 var woocart_wrapper = $(woocart_toggle).parent(); 294 var woocart = $('.widget_shopping_cart_content p'); 295 296 if (woocart.hasClass('woocommerce-mini-cart__empty-message')) { 297 $(woocart_toggle).addClass('empty'); 298 $(woocart_wrapper).addClass('cart-empty'); 299 } else { 300 $(woocart_toggle).removeClass('empty'); 301 $(woocart_wrapper).removeClass('cart-empty'); 302 } 303 } 304 setInterval(check_cart, 1000); 305 306 // HEADER CART TOGGLE >>> 307 $('.js-header-cart-toggle').click(function (e) { 308 var $toggle = $(this); 309 var $document = $(document.body); 310 var $widget = $toggle.parent().find('.gc-header__cart'); 311 var is_opened = $toggle.hasClass('open'); 312 var event_name = 'click.gc-header-cart'; 313 314 // Hide widget. 315 if (is_opened) { 316 $toggle.removeClass('open'); 317 $widget.stop().fadeOut(); 318 $document.off(event_name); 319 } 320 321 // Show widget. 322 else { 323 $toggle.addClass('open'); 324 $widget.stop().fadeIn(); 325 326 // Setup autohide trigger. 327 setTimeout(function () { 328 $document.off(event_name); 329 $document.on(event_name, function (e) { 330 // Skip if click event occurs inside the widget. 331 if ($(e.target).closest($widget).length) { 332 return; 333 } 334 335 // Hide widget. 336 $toggle.removeClass('open'); 337 $widget.stop().fadeOut(); 338 $document.off(event_name); 339 }); 340 }, 1); 341 } 342 }); 343 // <<< END 344 345 // Mobile menu 346 $('.gc-header__sidebar-menu .menu-item-has-children').on('click', function (e) { 347 var xPosition = e.pageX; 348 var width = $(this).parents('.gc-header__sidebar').width(); 349 var area = width - 50; 350 var expandIcon = 50; 351 352 if (xPosition > area) { 353 $(this).find('> .sub-menu').slideToggle(); 354 $(this).toggleClass('open'); 355 356 e.stopPropagation(); 357 } 358 359 // for RTL site 360 if ($('.rtl')[0]) { 361 if (xPosition < area) { 362 $(this).find('> .sub-menu').slideToggle(); 363 $(this).toggleClass('open'); 364 365 e.stopPropagation(); 366 } 367 } 368 }); 369 370 // Scroll to top 371 $(window).scroll(function () { 372 var scroll = $(window).scrollTop(); 373 var button = '.js-scroll-top'; 374 375 if (scroll >= 100) { 376 $(button).fadeIn(); 377 } else { 378 $(button).fadeOut(); 379 } 380 }); 381 382 // Toggle header widget 383 $('.js-header-search-toggle').click(function () { 384 var toggle = $(this); 385 var headerWidget = '.header__search-bar'; 386 387 $(toggle).parent().find(headerWidget).toggle(); 388 }); 389 390 // Gecko grid arrangement using Macy.js. 391 $(function () { 392 var width = $('body').width(); 393 var macyColumnsNumber = typeof blogGridColumns !== typeof undefined ? blogGridColumns : 2; 394 395 function initMasonry($container) { 396 var instance = Macy({ 397 container: $container, 398 trueOrder: true, 399 margin: { x: 15, y: 15 }, 400 columns: macyColumnsNumber 401 }); 402 403 function _rearrange() { 404 var winWidth = $(window).width(); 405 if (winWidth < 980) { 406 instance.remove(); 407 } else { 408 instance.reInit(); 409 } 410 } 411 412 // Debounce grid rearrangement. 413 var timer = null; 414 function rearrange() { 415 clearTimeout(timer); 416 timer = setTimeout(_rearrange, 500); 417 } 418 419 _rearrange(); 420 $(window).on('load resize scroll', rearrange); 421 } 422 423 document.querySelectorAll('[data-gc-masonry]').forEach(grid => { 424 if (width > 980) initMasonry(grid); 425 grid.style.display = ''; 426 }); 427 }); 428 429 // Gecko user theme selector. 430 $(function () { 431 $('select[name=peepso_gecko_user_theme]').on('change', function () { 432 var $select = $(this), 433 $loading = $select 434 .closest('.ps-js-profile-preferences-option') 435 .find('.ps-js-loading img'), 436 counter = 0, 437 timer; 438 439 if (!$loading.length) { 440 return; 441 } 442 443 // Reload when loading indicator is finally hidden, with max delay 30s. 444 timer = setInterval(function () { 445 if ($loading.is(':hidden') || ++counter >= 60) { 446 clearInterval(timer); 447 window.location.reload(); 448 } 449 }, 500); 450 }); 451 }); 452 453 /** 454 * Initialize Gecko customizer preview. 455 */ 456 function initCustomizerPreview() { 457 // Remove adminbar on the customizer preview. 458 $('#wpadminbar').remove(); 459 $('body').removeClass('admin-bar'); 460 461 var loadedFonts = []; 462 463 // Function to handle received config update. 464 function receiveCustomizerUpdate(e) { 465 let root = document.body; 466 var data = e.data || {}; 467 var type = data.type; 468 var key = data.key; 469 var value = data.value; 470 471 if ('css' === type) { 472 if ('--GC-FONT-FAMILY' === key) { 473 // Load Google Fonts if necessary. 474 if (loadedFonts.indexOf(value) === -1) { 475 loadedFonts.push(value); 476 477 var link = document.createElement('link'); 478 link.setAttribute('rel', 'stylesheet'); 479 link.setAttribute('type', 'text/css'); 480 link.setAttribute( 481 'href',
482 'https://fonts.googleapis.com/css2?family=' + 483 value.replace(/\s/g, '+') + 484 ':wght@400;700&display=swap' 485 ); 486 document.getElementsByTagName('head')[0].appendChild(link); 487 } 488 489 value = "'" + value + "'"; 490 } 491 492 root.style.setProperty(key, value || false); 493 } 494 } 495 496 window.addEventListener('message', receiveCustomizerUpdate, false); 497 } 498 499 // Switch Register and Login form on Landing Page mobile view 500 $(function () { 501 var landingRegisterForm = $('.landing .ps-page--register-main'); 502 var linkRegister = $('.psf-login__link--register'); 503 var registerLinkWrapper = $('.landing .ps-page--register-main .ps-form__row--submit'); 504 var landingRowLogin = $('.landing__grid .landing__row:last-child'); 505 506 if ($(landingRegisterForm).is(':visible') || $(landingRegisterForm).is(':hidden')) { 507 $(linkRegister).attr('href', '#'); 508 $(linkRegister).addClass('psf-login__link--register-mobile'); 509 510 $(registerLinkWrapper).append( 511 "<a href='#' class='psf-login__link psf-login__link--login-mobile'>Login</>" 512 ); 513 } 514 515 $('.psf-login__link--register-mobile').click(function () { 516 $(landingRegisterForm).show(); 517 $(landingRowLogin).hide(); 518 }); 519 520 $('.psf-login__link--login-mobile').click(function () { 521 $(landingRegisterForm).hide(); 522 $(landingRowLogin).show(); 523 }); 524 525 // #5392 Automatically show PeepSo registration form if necessary. 526 if ($('.landing').hasClass('landing--peepso-register')) { 527 // #5426 Check the availability of the verify password field to make sure. 528 if (document.querySelector('input[name=password2]')) { 529 $(landingRegisterForm).show(); 530 $(landingRowLogin).hide(); 531 } 532 } 533 }); 534 535 /** 536 * Adaptive header sub-menu 537 */ 538 $(function () { 539 var header = $('.gc-js-header-wrapper'); 540 var headerWidth = header.width(); 541 542 // Added level attribute to each sub menu 543 var level = 1; 544 var assign_attr = function (list) { 545 list.each(function () { 546 $(this).attr('data-level', 'level-' + level); 547 level++; 548 assign_attr($(this).find('> li > ul')); 549 level--; 550 }); 551 }; 552 assign_attr($('.gc-header__menu > ul > li > ul')); 553 554 $('.gc-header__menu > ul > li').each(function () { 555 // Count level in each menu item 556 var subMenu_level = {}; 557 $(this) 558 .find('.sub-menu') 559 .each(function () { 560 var levelData = $(this).data('level'); 561 562 if (subMenu_level.hasOwnProperty(levelData) === false) { 563 subMenu_level[levelData] = 1; 564 } else { 565 subMenu_level[levelData]++; 566 } 567 }); 568 569 var levelLength = Object.keys(subMenu_level).length; 570 571 $(this) 572 .find('> ul > li') 573 .each(function () { 574 // Calculate the sub menu total width of each menu item 575 var subMenu_width = $(this).find('.sub-menu').width(), 576 total_subMenu_width = parseInt(subMenu_width) * parseInt(levelLength), 577 menu_leftPosition = $(this).parents('.menu-item').offset().left, 578 subMenu_totalWidth = 579 parseInt(total_subMenu_width) + parseInt(menu_leftPosition); 580 581 if (!$(body).hasClass('rtl')) { 582 // Compare the sub menu total width with the header menu width 583 if (subMenu_totalWidth > headerWidth) { 584 $(this).parents('.menu-item').addClass('gc-header__menu-item--reverse'); 585 } 586 } 587 }); 588 }); 589 }); 590 591 /** 592 * Add max-width & max-height to <iframe> elements, depending on their width & height props. 593 */ 594 function geckoResponsiveEmbeds() { 595 var proportion, parentWidth; 596 597 // Loop iframe elements. 598 document.querySelectorAll('iframe').forEach(function (iframe) { 599 // Only continue if the iframe has a width & height defined. 600 if (iframe.width && iframe.height) { 601 // Calculate the proportion/ratio based on the width & height. 602 proportion = parseFloat(iframe.width) / parseFloat(iframe.height); 603 // Get the parent element's width. 604 parentWidth = parseFloat( 605 window.getComputedStyle(iframe.parentElement, null).width.replace('px', '') 606 ); 607 // Set the max-width & height. 608 iframe.style.maxWidth = '100%'; 609 iframe.style.maxHeight = Math.round(parentWidth / proportion).toString() + 'px'; 610 } 611 }); 612 } 613 614 // Run on initial load. 615 geckoResponsiveEmbeds(); 616 617 // Run on resize. 618 window.onresize = geckoResponsiveEmbeds; 619 620 // Add gecko menu item class to WOO wallet 621 $('.gc-header__menu .woo-wallet-menu-contents').parent().addClass('gc-header__menu-item'); 622 623 /** 624 * Sticky PeepSo navigation bar 625 */ 626 $(function () { 627 var $header = $('.gc-header__wrapper'); 628 var $adminBar = $('#wpadminbar'); 629 var $content_width, $coverProfile_height; 630 631 // Adjust main content width and cover profile height 632 function adjustSize() { 633 $content_width = $('.peepso').width(); 634 635 if ($('.ps-focus')[0]) { 636 $coverProfile_height = $('.ps-focus').height(); 637 } else { 638 $coverProfile_height = 0; 639 } 640 } 641 642 $(window) 643 .on('resize', function () { 644 adjustSize(); 645 646 $('.gc-navbar--sticky').css({ 647 '--content-width': $content_width + 'px', 648 '--cover-height': $coverProfile_height + 'px' 649 }); 650 }) 651 .resize(); 652 653 $(window).on('scroll', function () { 654 var scroll = $(window).scrollTop(); 655 656 if (scroll >= $coverProfile_height + 300) { 657 $('.gc-navbar--sticky').addClass('gc-navbar--scroll'); 658 } else { 659 $('.gc-navbar--sticky').removeClass('gc-navbar--scroll'); 660 } 661 }); 662 663 // for WPMA: PeepSo Theme: Gecko + Native Interface 664 $(document.body).on('scroll mousewheel', function (e) { 665 var scroll = e.deltaY; 666 667 if (scroll < 0) { 668 $('.gc-navbar--sticky').addClass('gc-navbar--scroll'); 669 } else { 670 $('.gc-navbar--sticky').removeClass('gc-navbar--scroll'); 671 } 672 }); 673 674 // Check header height and existence 675 var isFixed = elementOrParentIsFixed($header); 676 var aboveHeaderBar = $('.gc-js-sticky-bar-above-header'); 677 var underHeaderBar = $('.gc-js-sticky-bar-under-header'); 678 var aboveHeaderBarHeight = $(aboveHeaderBar).outerHeight() || 0; 679 var underHeaderBarHeight = $(underHeaderBar).outerHeight() || 0; 680 681 if ($header[0]) { 682 if (isFixed) { 683 $header = $header.height(); 684 } else { 685 $header = aboveHeaderBarHeight + underHeaderBarHeight; 686 } 687 } else { 688 $header = aboveHeaderBarHeight + underHeaderBarHeight; 689 } 690 691 // Check admin bar height and existence 692 if ($adminBar[0]) { 693 if ($adminBar.css('position') == 'fixed' || $adminBar.css('position') == 'sticky') { 694 $adminBar = 32; 695 } else { 696 $adminBar = 0; 697 } 698 } else { 699 $adminBar = 0; 700 } 701 702 $('.gc-navbar--sticky').css({ 703 '--header-height': $header + 'px', 704 '--admin-height': $adminBar + 'px' 705 }); 706 707 // Set navbar position based on main content position 708 if ($('.main').hasClass('main--left')) { 709 $('.main').parents('body').find('.gc-navbar--sticky').addClass('gc-navbar--right'); 710 } else if ($('.main').hasClass('main--right')) { 711 $('.main').parents('body').find('.gc-navbar--sticky').addClass('gc-navbar--left'); 712 } 713 }); 714 715 /** 716 * Regular buttons 717 */ 718 $(function () { 719 // Define button elements that doesn't have a class 720 var $buttons = $( 721 'button:not([class]), button[type="button"]:not([class]), input[type="submit"]:not([class]), input[type="button"]:not([class])' 722 ); 723 724 // Add gc-btn class to it 725 $buttons.addClass('gc-btn'); 726 }); 727 728 /** 729 * WooCommerce "Hide if cart is empty" cart widget in header 730 */ 731 // Hide Cart dropdown by default to prevent its opens every time the page reload 732 $(function () { 733 $('.hide_cart_widget_if_empty').parent().hide(); 734 }); 735 // Hide if cart is empty 736 function check_cart_if_empty() { 737 var wocart_wrapper = $('.gc-header__cart-wrapper'); 738 var wocart_wrapper_empty = $('.gc-header__cart-wrapper.cart-empty'); 739 740 if ($(wocart_wrapper_empty).find('.hide_cart_widget_if_empty').length !== 0) { 741 $(wocart_wrapper).hide(); 742 } else { 743 $(wocart_wrapper).show(); 744 } 745 } 746 setInterval(check_cart_if_empty, 1000); 747})(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.