PageSourceSearch

https://toyota-automobile-museum.jp/assets/scripts/main.js

js toyota-automobile-museum.jp collected 2026-10-02 04:52:26 UTC 23,389 bytes, 718 lines download raw bytes

1'use strict';
2
3//サイトのドメイン名。本番環境がサブディレクトリにサイトを設置する場合、ディレクトリパスを結合してください。
4var domain = document.domain;
5
6$(function() {
7
8  // スクロールトップ
9  var headerHight = 85; //ヘッダの高さ
10  $('a[href^="#"]').on('click', function () {
11    $('body,html').animate({scrollTop: headerHight}, 800);
12    return false;
13  });
14
15  // SPのメニュー開閉
16  $('.l-menu-sp').on('click', function () {
17    $(this).toggleClass('l-menu-sp-active');
18    $('.l-nav-sp').toggleClass('l-nav-open');
19    $('html').toggleClass('fixed');
20  });
21
22  $('.l-nav-sp_item_parent').on('click', function() {
23    $(this).children('.l-nav-sp_item_open').toggleClass('l-nav-sp_item_open-active');
24    $(this).next('.l-nav-sp_child_open').toggleClass('l-nav-sp_child_open-active');
25  });
26
27
28  // イベントカテゴリーのタブ
29  $('.p-event_category_item').on('click', function () {
30    $('.p-event_category_item').removeClass('p-event_category_item-current');
31    $(this).addClass('p-event_category_item-current');
32
33    const clickCate = $(this).attr('class').split(" ")[1].replace('p-event_category_item-', '');
34
35    if(clickCate !== 'all') {
36      $('.p-event_post_item').fadeOut(0);
37      $('.p-event_post_item-' + clickCate).fadeIn(200);
38    } else {
39      $('.p-event_post_item').fadeIn(200);
40    }
41
42  });
43
44  // spアコーディオン
45  var $accordionSP = $('.accordion-sp');
46  $accordionSP.on('click', function(e) {
47    e.preventDefault();
48    if( $(window).width() < 769 ) {
49      $(this)
50        .toggleClass('accordion-sp-active')
51        .next()
52        .slideToggle();
53    }
54  });
55
56  // 汎用タブ
57  var $tabs = $('.tabs');
58
59  $tabs.each(function() {
60    var $tabsItem = $(this).find('.tabs_item'),
61        $tabsContent = $(this).find('.tabs_content');
62
63    $tabsItem.on('click', function(e) {
64      e.preventDefault();
65      var index = $(this).index();
66      $tabsItem
67        .removeClass('tabs_item-current')
68        .eq(index)
69        .addClass('tabs_item-current');
70
71      $tabsContent
72        .not(':eq('+index+')')
73        .hide()
74        .end()
75        .eq(index)
76        .fadeIn();
77    });
78    if($(this).hasClass('tabs-pc')) {
79      if($(window).width() > 768) {
80        $tabsItem.eq(0).click();
81      }
82    } else if($(this).hasClass('tabs-sp')) {
83      if($(window).width() <= 768) {
84        $tabsItem.eq(0).click();
85      }
86    } else {
87      $tabsItem.eq(0).click();
88    }
89  });
90
91  var $floormap_tab = $('body.p-visit-floormap .tabs');
92  if( $floormap_tab[0] ) {
93    var $tabsItem  = $floormap_tab.find('.tabs_item');
94    var urlParam = location.search.substring(1);
95    var floor_val = '';
96    if( urlParam ) {
97      var param = [ urlParam ];
98      if( urlParam.indexOf('&') !== -1 ) {
99        param = urlParam.split('&');
100      }
101      for ( var i = 0; i < param.length; i++) {
102        var paramItem = param[i].split('=');
103        if( paramItem[0] === 'floor') {
104          floor_val = paramItem[1];
105          break;
106        }
107      }
108    }
109    if( floor_val !== '') $tabsItem.eq(parseInt(floor_val,10)-1).click();
110  }
111
112
113  // 開館カレンダー
114  $('.calender-open').on('click', function() {
115    $(this).toggleClass('calendar-open-active');
116    $(this).closest('.month-caption').next('.week-caption').toggleClass('month-caption-open');
117    $(this).closest('thead').next('tbody').toggleClass('month-caption-open');
118  });
119
120  $('.l-nav_global_parent').on('click', function() {
121    $('.l-childNavArea').removeClass('l-childNavArea-active');
122    $(this).next('.l-childNavArea').addClass('l-childNavArea-active');
123  });
124
125  $('.l-childNav_closeBtn').on('click', function() {
126    $('.l-childNavArea').removeClass('l-childNavArea-active');
127  });
128
129  // 車両データベース 検索開閉
130  $('.p-archives-carDatabase_searchBox_more').on('click', function() {
131    $('.p-archives-carDatabase_searchBox_sort').toggleClass('p-archives-carDatabase_searchBox_sort-open');
132  });
133
134  // 車両データベース 使い方モーダル開閉
135  $('.p-archives-carDatabase_searchBox_how').on('click', function() {
136    $('.p-archives-carDatabase_howModal_box').toggleClass('p-archives-carDatabase_howModal_box-open');
137    $('.p-archives-carDatabase_howModal_overlay').toggleClass('p-archives-carDatabase_howModal_overlay-open');
138  });
139  $('.p-archives-carDatabase_howModal_close').on('click', function() {
140    $('.p-archives-carDatabase_howModal_box').removeClass('p-archives-carDatabase_howModal_box-open');
141    $('.p-archives-carDatabase_howModal_overlay').toggleClass('p-archives-carDatabase_howModal_overlay-open');
142  });
143  $('.p-archives-carDatabase_howModal_overlay').on('click', function() {
144    $('.p-archives-carDatabase_howModal_box').removeClass('p-archives-carDatabase_howModal_box-open');
145    $('.p-archives-carDatabase_howModal_overlay').toggleClass('p-archives-carDatabase_howModal_overlay-open');
146  });
147
148  // 車両データベース ヘッダーランダム表示
149  let carDatabaseMin = 1;
150  let carDatabaseMax = 18;
151  let carDatabaseRandom;
152
153  carDatabaseRandom = Math.floor( Math.random() * carDatabaseMax ) + carDatabaseMin;
154  $('#p-archives-carDatabaseHead').addClass('p-archives-carDatabaseHead-'+ carDatabaseRandom);
155
156
157  // エクセルダウンロード
158  function isIE() {
159    let userAgent = window.navigator.userAgent.toLowerCase();
160    if ( userAgent.indexOf( 'msie' ) !== -1 || userAgent.indexOf( 'trident' ) !== -1 ) {
161        return true;
162    }
163    return false;
164  }
165  $('a[href$=".xlsx"]').on('click', function () {
166    if ( isIE() ) {
167      var url = $(this).attr('href');
168      var name = url.match(".+/(.+?)([\?#;].*)?$")[1];
169
170      var xhr = new XMLHttpRequest();
171      xhr.open('GET', url);
172      xhr.responseType = 'blob';
173
174      xhr.onloadend = function() {
175      if(xhr.status !== 200) return;
176        window.navigator.msSaveBlob(xhr.response, name);
177      }
178      xhr.send();
179
180      return false;
181    }
182
183
184  })
185
186  $.ajax({
187    url: '/inc/_slider-information.html',
188    cache: false,
189    dataType: 'html',
190    success: function(data) {
191        $('#slider-information').append(data);
192          $('.slider-information').slick({
193        dots: true,
194        dotsClass: 'slider-information_dots',
195        autoplay: true,
196        infinite: true,
197        slidesToShow: 1,
198        slidesToScroll: 1,
199        prevArrow: '<button type="button" class="slider-information_prev"></button>',
200        nextArrow: '<button type="button" class="slider-information_next"></button>',
201
202        responsive: [
203          {
204            breakpoint: 768
205          }
206        ]
207      });
208    }
209  });
210
211  $.ajax({
212    url: '/en/inc/_slider-information.html',
213    cache: false,
214    dataType: 'html',
215    success: function(data) {
216        $('#slider-information-en').append(data);
217          $('.slider-information').slick({
218        dots: true,
219        dotsClass: 'slider-information_dots',
220        autoplay: true,
221        infinite: true,
222        slidesToShow: 1,
223        slidesToScroll: 1,
224        prevArrow: '<button type="button" class="slider-information_prev"></button>',
225        nextArrow: '<button type="button" class="slider-information_next"></button>',
226
227        responsive: [
228          {
229            breakpoint: 768
230          }
231        ]
232      });
233    }
234  });
235
236  // 年間パスポートページのトッピクスがない場合の処理
237  if( $('#cms_facility_topics').length ) {
238    if ( $('.p-facility_topic').length === 0 ) {
239      $('.p-event-single_annual_no').addClass('is-show');
240    }
241  }
242
243
244  // SNSシェアボタン
245  var href =location.href; //1.URLを取得しエンコードする
246  var getTitle = $('title').html(); //2.ページのタイトルを取得
247
248  var snsUrl = encodeURIComponent(href);
249  var snsTitle = encodeURIComponent(getTitle);
250
251  $('.l-footer_snsbtn').each(function(){
252
253    var sns_obj = $(this).attr('id'); //4.ID名を取得
254    var snsCase = sns_obj;
255
256    //5.IDを判定してリンク先を出力する
257    switch (snsCase){
258
259      case 'l-footer_snsbtn-twitter':
260        $(this).attr('href','http://twitter.com/share?text='+ snsTitle + '&url='+ snsUrl);
261        break;
262
263      case 'l-footer_snsbtn-facebook':
264        $(this).attr('href','http://www.facebook.com/sharer.php?u='+ snsUrl);
265        break;
266
267      case 'l-footer_snsbtn-line':
268        $(this).attr('href','http://line.me/R/msg/text/?'+ snsUrl);
269        break;
270
271      case 'l-footer_snsbtn-pinterest':
272        $(this).attr('href','http://www.pinterest.com/pin/create/button/?url='+ snsUrl +'%20description='+ snsTitle);
273        break;
274
275      case 'l-footer_snsbtn-hatena':
276        $(this).attr('href','https://b.hatena.ne.jp/entry/panel/?url='+ href +'&title='+ getTitle);
277        break;
278    }
279
280  });
281
282  // 2022/1/4の文化館入館日対応 の為
283  // if ( $('#cms_opening-calendar').length ) {
284  //   const lang = $('html').attr('lang');
285  //   let disp_calendar = '';
286  //   if ( lang === 'ja') {
287  //     disp_calendar = 'クルマ館常設展示は改修工事のため<br class="u-br-sp">ご覧いただけません。<br>2022年1月4日(火)企画展、文化館無料<br class="u-br-sp">開放';
288  //   } else {
289  //     disp_calendar = 'The exhibition in the Automobile Gallery is closed due to renovation work.<br>Tuesday, 4 January 2022: free admission';
290  //   }
291
292  //   $('.opening-calendar-caption').each(function(){
293  //     let year = $(this).children('.opening-calendar-year').html().slice( 0, 4 );
294  //     if ( year === '2022') {
295  //       $(this).append('<span><span class="culture-legend"></span><span>' + disp_calendar + '</span></span>');
296  //       $(this).next('.calendar-of-months').children('li').eq(0).find('tbody').children('tr').eq(1).children('td').eq(1).css('background-color', '#d7f07b');
297  //     }
298  //   });
299
300  // }
301
302  // 開館カレンダー 文言追加&マーク追加 対応
303  if ( $('#cms_opening-calendar').length){
304
305    const NOTE_CONFIG = {
306      ja: [
307
308        /**
309         * 注釈(NOTE_CONFIG)の1件分の定義例
310         *
311         * 【必須】
312         * - id      : 内部識別子(表示とは無関係。note-1 など)
313         * - symbol  : カレンダーに表示するマーク(※ / ※1 / * など)
314         * - dates   : 対象日付(yyyy-mm-dd)。この日付にマークが付く
315         *
316         * 【content の書き方】
317         * 1. 分岐しない場合(文字列)
318         *    content: '●●● 期間:●月●日(●)~●日(●)'
319         *
320         * 2. 年ごとに分岐する場合(オブジェクト)
321         *    content: {
322         *      '2025': '●●●(●●●●●●●●●)期間:1月1日(水)~3日(金)',
323         *      '2026': '●●●(●●●●●●●●●)期間:1月1日(木)~3日(土)',
324         *    }
325         *
326         *
327         * 【注意】
328         * - content は表示用。ロジックには dates が使われる
329         * - 曜日が変わる場合は 2. を推奨
330         */
331
332        {
333          id: 'note-1',
334          symbol: '※',
335          content: '割引対象外(身障者、学生割引除く)期間:5月2日(土)~6日(水)、8月8日(土)~16日(日)、9月19日(土)~23日(水)', 
336          dates: [
337            '2026-05-02','2026-05-03','2026-05-04','2026-05-05','2026-05-06',
338            '2026-08-08','2026-08-09','2026-08-10','2026-08-11','2026-08-12','2026-08-13','2026-08-14','2026-08-15','2026-08-16',
339            '2026-09-19','2026-09-20','2026-09-21','2026-09-22','2026-09-23',
340          ]
341        },
342      ],
343      en: [
344        {
345          id: 'note-1',
346          symbol: '*',
347          content: 'Discounts Not Applicable (Except Disability/Student) May 2–6, Aug 8–16, Sep 19–23.', 
348          dates: [
349            '2026-05-02','2026-05-03','2026-05-04','2026-05-05','2026-05-06',
350            '2026-08-08','2026-08-09','2026-08-10','2026-08-11','2026-08-12','2026-08-13','2026-08-14','2026-08-15','2026-08-16',
351            '2026-09-19','2026-09-20','2026-09-21','2026-09-22','2026-09-23',
352          ]
353        },
354      ]
355    };
356
357    const lang = $('html').attr('lang') === 'en' ? 'en' : 'ja';
358
359    //年にdata属性付与
360    setCalendarYearData()
361
362    // 言語別の注釈設定を取得
363    const noteList = NOTE_CONFIG[lang];
364
365    // 注釈文言を年ごとに表示(NOTE_CONFIGから)
366    addNoticesByYearFromNotes(noteList, lang);
367    
368    // 日付に data-status / data-noteSymbol を付与(NOTE_CONFIGから)
369    applyExcludedMarksByNotes(noteList);
370
371    // マークをつける
372    decorateMarkedCells();
373  
374  }
375});
376
377/* ----------------------------
378  マーク作成する関数(日本語用)
379---------------------------- */
380function decorateMarkedCells() {
381 const htmlLang = document.documentElement.lang || 'ja';
382  const lang = htmlLang.startsWith('en') ? 'en' : 'ja';
383
384  document.querySelectorAll('[data-status="excluded"]').forEach(td => {
385    if (td.querySelector('.excluded-mark')) return;
386
387    if (getComputedStyle(td).position === 'static') {
388      td.style.position = 'relative';
389    }
390
391    const mark = document.createElement('span');
392    mark.className = 'excluded-mark';
393    mark.style.position = 'absolute';
394    mark.style.top = '1px';
395    mark.style.right = '2px';
396    mark.style.color = '#e60020';
397    mark.style.display = 'block';
398
399    const symbol =
400      td.dataset.noteSymbols ||
401      td.dataset.noteSymbol ||
402      (lang === 'en' ? '*' : '※');
403
404    if (lang === 'en') {
405      // ★ 英語用:* を大きく
406      mark.appendChild(createEnNoteMark(symbol));
407    } else {
408      // 日本語用:そのまま
409      mark.textContent = symbol;
410      mark.style.fontSize = '58%';
411    }
412
413    td.appendChild(mark);
414  });
415}
416
417/* ----------------------------
418  マーク作成する関数(英語用)
419---------------------------- */
420function createEnNoteMark(symbol) {
421  // symbol 例: "*", "*1", "*2"
422  const wrap = document.createElement('span');
423  wrap.style.whiteSpace = 'nowrap';
424  wrap.style.display = 'flex';
425
426  // 先頭の * を大きく
427  if (symbol.startsWith('*')) {
428    const star = document.createElement('span');
429    star.textContent = '*';
430    star.style.fontSize = '120%';
431    star.style.lineHeight = '1';
432    wrap.appendChild(star);
433
434    const rest = symbol.slice(1);
435    if (rest) {
436      const num = document.createElement('span');
437      num.textContent = rest;
438      num.style.fontSize = '60%';
439      wrap.appendChild(num);
440    }
441  } else {
442    // 念のため * 以外が来た場合
443    wrap.textContent = symbol;
444  }
445
446  return wrap;
447}
448
449
450/* ----------------------------
451  「注釈説明文」を、該当する年のカレンダーの直下に自動表示する関数
452---------------------------- */
453function addNoticesByYearFromNotes(noteList, lang) {
454
455  // 注釈が関係する「年」を dates から自動抽出
456  const years = new Set();
457  noteList.forEach(note => {
458    note.dates.forEach(d => years.add(d.slice(0, 4)));
459  });
460
461  years.forEach(year => {
462    getCalendarCaptionByYear(year).forEach(captionEl => {
463
464      // 二重追加防止:すでに次に .note があれば何もしない
465      if (captionEl.nextElementSibling?.classList.contains('note')) return;
466
467      // その年に該当する注釈だけ
468      const notesForYear = noteList.filter(note =>
469        note.dates.some(d => d.startsWith(`${year}-`))
470      );
471      if (!notesForYear.length) return;
472
473      // note(外側)は年ごとに1つ
474      const wrap = document.createElement('span');
475      wrap.className = 'note';
476
477      notesForYear.forEach(note => {
478        const text =
479          typeof note.content === 'string'
480            ? note.content
481            : note.content?.[year];
482
483        if (!text) return;
484
485        const legendClass = (lang === 'en') ? 'note-legend--en' : 'note-legend';
486        const legendExtra = (lang === 'en' && note.symbol === '*') ? 'center' : '';
487
488        const item = document.createElement('span');
489        item.className = 'note__item';
490        item.innerHTML = `
491          <span class="${[legendClass, legendExtra].filter(Boolean).join(' ')}">
492            ${note.symbol}
493          </span>
494          <span class="note-text">${text}</span>
495        `.trim();
496
497        wrap.appendChild(item);
498      });
499
500      // 中身が無ければ追加しない
501      if (!wrap.children.length) return;
502
503      // ★ caption の兄弟要素として追加
504      captionEl.insertAdjacentElement('afterend', wrap);
505    });
506  });
507}
508
509/* ----------------------------
510  注釈設定(NOTE_CONFIG)を元に、カレンダーの“該当日付セル”へ ※情報を付与する関数
511---------------------------- */
512function applyExcludedMarksByNotes(noteList) {
513   const dateMap = new Map(); // ymd -> notes[]
514
515  // 日付 → 注釈配列を作る
516  noteList.forEach(note => {
517    note.dates.forEach(date => {
518      if (!dateMap.has(date)) dateMap.set(date, []);
519      dateMap.get(date).push(note);
520    });
521  });
522
523  document
524    .querySelectorAll('.opening-calendar-caption[data-year]')
525    .forEach(captionEl => {
526      const year = captionEl.dataset.year;
527
528      walkCalendarDatesByCaption(captionEl, year, ({ ymd, td }) => {
529        const notes = dateMap.get(ymd);
530        if (!notes || !notes.length) return;
531
532        td.dataset.status = 'excluded';
533
534        // ★ ここで td が使える
535        td.dataset.noteIds = notes.map(n => n.id).join(' ');
536        td.dataset.noteSymbols = notes.map(n => n.symbol).join(' '); // 2コ以上の場合横並び表示
537      });
538    });
539}
540
541/* ----------------------------
542  開館カレンダーの各年にデータ属性を付与する関数 data-year="202X"
543---------------------------- */
544function setCalendarYearData() {
545  const captions = document.querySelectorAll('.opening-calendar-caption');
546      
547  // 各'.opening-calendar-caption'に何年かわかるデータ属性を付与 例)data-year="2026"
548  captions.forEach(caption => {
549    const text = caption.textContent.trim();
550
551    // テキスト内の西暦(4桁)を取得
552    const match = text.match(/\d{4}/);
553
554    if (match) {
555      caption.dataset.year = match[0];
556    }
557    
558  });
559}
560
561/* ----------------------------
562  年のスコープをする関数
563---------------------------- */
564function walkCalendarDatesByCaption(captionEl, year, callback) {
565  if (!captionEl) return;
566
567  // caption の次の兄弟から走査して、次の caption が出るまでをその年の範囲にする
568  let node = captionEl.nextElementSibling;
569
570  while (node && !node.classList.contains('opening-calendar-caption')) {
571    // その年ブロック内の月テーブルだけ見る
572    node.querySelectorAll('.calendar-of-month').forEach(monthTable => {
573      const mm = getMonthFromMonthTable(monthTable);
574      if (!mm) return;
575
576      monthTable.querySelectorAll('tbody td').forEach(td => {
577        const dd = getDayFromTd(td);
578        if (!dd) return;
579
580        const ymd = `${year}-${mm}-${dd}`;
581        callback({ ymd, td });
582      });
583    });
584
585    node = node.nextElementSibling;
586  }
587}
588
589/* ----------------------------
590  yyyy-mm-dd を組み立てる関数
591---------------------------- */
592function walkCalendarDatesByYear(year, callback) {
593  document
594    .querySelectorAll('#cms_opening-calendar .calendar-of-month')
595    .forEach(monthTable => {
596
597      const mm = getMonthFromMonthTable(monthTable);
598      if (!mm) return;
599
600      monthTable.querySelectorAll('tbody td').forEach(td => {
601        const dd = getDayFromTd(td);
602        if (!dd) return;
603
604        const ymd = `${year}-${mm}-${dd}`;
605        callback({ ymd, td, mm, dd });
606      });
607    });
608}
609
610/* ----------------------------
611  年を取得する関数  // 例)const captions2026 = getCalendarCaptionByYear('2026');
612---------------------------- */
613function getCalendarCaptionByYear(year) {
614  return document.querySelectorAll(
615    `#cms_opening-calendar .opening-calendar-caption[data-year="${String(year)}"]`
616  );
617}
618
619/* ----------------------------
620  月を取得する関数
621---------------------------- */
622function getMonthFromMonthTable(monthTable) {
623  const span = monthTable.querySelector('.month-caption span');
624  if (!span) return null;
625
626  const raw = span.textContent.trim(); // "January" / "1" / "1月" など
627
628  // 1) 数字が入っている場合("1" や "01" や "1月" など)
629  const num = raw.match(/(\d{1,2})/);
630  if (num) return num[1].padStart(2, '0');
631
632  // 2) 英語月名の場合("January", "Feb", etc.)
633  const key = raw.toLowerCase();
634  const map = {
635    jan: '01', january: '01',
636    feb: '02', february: '02',
637    mar: '03', march: '03',
638    apr: '04', april: '04',
639    may: '05',
640    jun: '06', june: '06',
641    jul: '07', july: '07',
642    aug: '08', august: '08',
643    sep: '09', sept: '09', september: '09',
644    oct: '10', october: '10',
645    nov: '11', november: '11',
646    dec: '12', december: '12',
647  };
648
649  return map[key] || null;
650}
651
652/* ----------------------------
653  日を取得する関数
654---------------------------- */
655function getDayFromTd(td) {
656  const text = td.textContent.trim();
657  if (!text) return null;
658
659  const day = text.match(/^\d{1,2}$/);
660  return day ? day[0].padStart(2, '0') : null;
661}
662
663function get_lang() {
664  var lang = 'ja';
665  if( document.URL.match(/\/en\//)  ) {
666    lang = 'en';
667  }
668
669  return lang;
670}
671
672
673if ($('.smarthash').length) {
674  var target = document.querySelector('.smarthash > ul');
675  var observer = new MutationObserver(function (mutations) {
676    mutations.forEach(function (mutation) {
677      if (target.style.height == '0px') {
678        target.style.height = 'auto';
679      }
680    });
681  });
682  var config = {
683    attributes: true
684  };
685  observer.observe(target, config);
686}
687
688
689$('.js-jhocm-video').on('click', function() {
690  
691  if ( $(this).hasClass('is-play') ) {
692    $(this).get(0).pause();
693    $(this).removeClass('is-play');
694  } else {
695    $(this).get(0).play();
696    $(this).addClass('is-play');
697    
698    if (isMobileDevice()) {
699      // スマートフォンであれば全画面で再生を開始
700      let videoElement = $(this).get(0); // jQueryオブジェクトから生のDOM要素を取得
701      if (videoElement.requestFullscreen) {
702          videoElement.requestFullscreen();
703      } else if (videoElement.mozRequestFullScreen) { /* Firefox */
704          videoElement.mozRequestFullScreen();
705      } else if (videoElement.webkitRequestFullscreen) { /* Chrome, Safari & Opera */
706          videoElement.webkitRequestFullscreen();
707      } else if (videoElement.msRequestFullscreen) { /* IE/Edge */
708          videoElement.msRequestFullscreen();
709      }
710    }
711  }
712
713  function isMobileDevice() {
714      return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
715  }
716})
717
718    

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.