PageSourceSearch

https://doc.quickrouter.ai/js/tutorial-reader.js?v=80fcf033af262494

js quickrouter.ai collected 2026-10-05 12:28:57 UTC 6,815 bytes, 146 lines download raw bytes

1(function () {
2  'use strict';
3  document.querySelectorAll('.doc-content table').forEach(function (table) {
4    if (table.closest('.reader-config')) return;
5    var wrapper = document.createElement('div');
6    wrapper.className = 'reader-table-scroll';
7    wrapper.tabIndex = 0;
8    wrapper.setAttribute('role', 'region');
9    wrapper.setAttribute('aria-label', '配置与参数表格,可横向滚动');
10    table.before(wrapper);
11    wrapper.appendChild(table);
12  });
13  var siteNav = document.getElementById('siteNav');
14  var navToggle = document.getElementById('readerNavToggle');
15  var themeButton = document.getElementById('themeToggle');
16  var loginLink = document.querySelector('.header-login');
17  loginLink.before(themeButton);
18  function reflectTheme() {
19    var dark = document.documentElement.dataset.theme === 'dark';
20    themeButton.setAttribute('aria-label', dark ? '切换到浅色主题' : '切换到深色主题');
21    themeButton.title = dark ? '切换到浅色主题' : '切换到深色主题';
22  }
23  reflectTheme();
24  new MutationObserver(reflectTheme).observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
25  function closeSiteNav() { siteNav.classList.remove('reader-nav-open'); navToggle.setAttribute('aria-expanded', 'false'); }
26  navToggle.addEventListener('click', function () {
27    var open = siteNav.classList.toggle('reader-nav-open');
28    navToggle.setAttribute('aria-expanded', String(open));
29  });
30  siteNav.addEventListener('click', function (event) { if (event.target.closest('a')) closeSiteNav(); });
31  document.addEventListener('click', function (event) { if (!siteNav.contains(event.target) && !navToggle.contains(event.target)) closeSiteNav(); });
32  document.addEventListener('keydown', function (event) {
33    if (event.key === 'Escape' && siteNav.classList.contains('reader-nav-open')) { closeSiteNav(); navToggle.focus(); }
34  });
35  document.querySelectorAll('body.tutorial-page .doc-content img').forEach(function (image) {
36    if (image.closest('dialog')) return;
37    var link = image.closest('a');
38    if (!link) {
39      link = document.createElement('a');
40      link.href = image.src;
41      image.before(link);
42      link.appendChild(image);
43    }
44    link.classList.add('reader-image');
45    link.removeAttribute('target');
46    link.setAttribute('aria-haspopup', 'dialog');
47  });
48  var dialog = document.querySelector('.reader-lightbox');
49  if (dialog) {
50  var picture = dialog.querySelector('img');
51  var zoom = dialog.querySelector('.reader-zoom');
52  var trigger;
53  var previousOverflow;
54  document.querySelectorAll('.reader-image').forEach(function (link) {
55    link.addEventListener('click', function (event) {
56      if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
57      event.preventDefault();
58      trigger = link;
59      var selectedImage = event.target.closest('img') || link.querySelector('img');
60      picture.src = selectedImage.currentSrc || selectedImage.src;
61      picture.alt = selectedImage.alt;
62      dialog.querySelector('.reader-lightbox-caption').textContent = picture.alt;
63      dialog.classList.remove('is-original');
64      zoom.setAttribute('aria-pressed', 'false');
65      zoom.textContent = '原始尺寸';
66      previousOverflow = document.body.style.overflow;
67      document.body.style.overflow = 'hidden';
68      dialog.showModal();
69      dialog.querySelector('.reader-lightbox-scroll').scrollTo(0, 0);
70    });
71  });
72  function closeLightbox() {
73    document.body.style.overflow = previousOverflow || '';
74    dialog.close();
75  }
76  dialog.querySelector('.reader-lightbox-close').addEventListener('click', closeLightbox);
77  dialog.addEventListener('cancel', function (event) {
78    event.preventDefault();
79    closeLightbox();
80  });
81  dialog.addEventListener('click', function (event) {
82    if (dialog.hasAttribute('data-close-on-empty') && !event.target.closest('img, .reader-lightbox-toolbar')) {
83      closeLightbox();
84      return;
85    }
86    if (event.target !== dialog) return;
87    var box = dialog.getBoundingClientRect();
88    if (event.clientX < box.left || event.clientX > box.right || event.clientY < box.top || event.clientY > box.bottom) closeLightbox();
89  });
90  dialog.addEventListener('close', function () {
91    document.body.style.overflow = previousOverflow || '';
92    if (trigger) trigger.focus();
93  });
94  zoom.addEventListener('click', function () {
95    var original = dialog.classList.toggle('is-original');
96    zoom.setAttribute('aria-pressed', String(original));
97    zoom.textContent = original ? '适应窗口' : '原始尺寸';
98  });
99  }
100  var status = document.querySelector('.reader-status');
101  var statusTimer;
102  document.querySelectorAll('[data-copy]').forEach(function (button) {
103    button.addEventListener('click', async function () {
104      clearTimeout(statusTimer);
105      try {
106        if (!navigator.clipboard) throw new Error('Clipboard unavailable');
107        await navigator.clipboard.writeText(button.dataset.copy);
108        status.textContent = 'API 主机已复制';
109      } catch (_) {
110        status.textContent = '复制未成功,请选择旁边的地址手动复制';
111      }
112      statusTimer = setTimeout(function () { status.textContent = ''; }, 3500);
113    });
114  });
115  function revealAnchor() {
116    var id;
117    try { id = decodeURIComponent(location.hash.slice(1)); } catch (_) { return; }
118    var target = document.getElementById(id);
119    if (!target) return;
120    var details = target.closest('details');
121    if (details) details.open = true;
122  }
123  window.addEventListener('hashchange', revealAnchor);
124  revealAnchor();
125  document.querySelectorAll('.nav-section-title').forEach(function (title) {
126    title.setAttribute('role', 'button');
127    title.tabIndex = 0;
128    function reflect() { title.setAttribute('aria-expanded', String(!title.parentElement.classList.contains('collapsed'))); }
129    reflect();
130    new MutationObserver(reflect).observe(title.parentElement, { attributes: true, attributeFilter: ['class'] });
131    title.addEventListener('keydown', function (event) {
132      if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); title.click(); }
133    });
134  });
135  var toggle = document.getElementById('sidebarToggle');
136  var sidebar = document.getElementById('sidebar');
137  toggle.setAttribute('aria-controls', 'sidebar');
138  toggle.setAttribute('aria-expanded', 'false');
139  new MutationObserver(function () { toggle.setAttribute('aria-expanded', String(sidebar.classList.contains('open'))); }).observe(sidebar, { attributes: true, attributeFilter: ['class'] });
140  document.addEventListener('keydown', function (event) {
141    if (event.key === 'Escape' && sidebar.classList.contains('open') && !(dialog && dialog.open)) {
142      document.getElementById('sidebarClose').click();
143      toggle.focus();
144    }
145  });
146})();

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.