feat(pages): 1:1 网址导航 page-links (zibll links.php)
Add WP bookmarks-based navigation page with multi-category sticky nav, search-engine cover, front submit modal/AJAX, page meta, and styles.
This commit is contained in:
1 parent
fc9278e0ab
commit
c27a36faff
11 files changed
+1707
-4
No files matched your search
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* AKSRT 网址导航页 — search tabs, sticky cat nav, submit modal/AJAX.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function qs(sel, root) {
|
||||
return (root || document).querySelector(sel);
|
||||
}
|
||||
|
||||
function qsa(sel, root) {
|
||||
return Array.prototype.slice.call((root || document).querySelectorAll(sel));
|
||||
}
|
||||
|
||||
function ajaxUrl() {
|
||||
if (window.aksrtData && window.aksrtData.ajaxUrl) return window.aksrtData.ajaxUrl;
|
||||
if (window.ajaxurl) return window.ajaxurl;
|
||||
return '/wp-admin/admin-ajax.php';
|
||||
}
|
||||
|
||||
function toast(msg, type) {
|
||||
if (window.aksrt && typeof window.aksrt.toast === 'function') {
|
||||
window.aksrt.toast(msg, type || 'info');
|
||||
return;
|
||||
}
|
||||
if (window.notyf) {
|
||||
try {
|
||||
window.notyf(msg, type === 'danger' ? 'danger' : '');
|
||||
return;
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
// eslint-disable-next-line no-alert
|
||||
window.alert(msg);
|
||||
}
|
||||
|
||||
/* ---------- search engine tabs ---------- */
|
||||
function initSearchTabs() {
|
||||
var cover = qs('.link-page-search-cover');
|
||||
if (!cover) return;
|
||||
|
||||
qsa('.tab-nav-theme a[data-aksrt-tab-target]', cover).forEach(function (a) {
|
||||
a.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
var target = a.getAttribute('data-aksrt-tab-target');
|
||||
if (!target) return;
|
||||
qsa('.tab-nav-theme li', cover).forEach(function (li) {
|
||||
li.classList.remove('active');
|
||||
});
|
||||
if (a.parentElement) a.parentElement.classList.add('active');
|
||||
qsa('.tab-pane', cover).forEach(function (pane) {
|
||||
pane.classList.remove('active', 'in');
|
||||
});
|
||||
var pane = qs(target, cover);
|
||||
if (pane) pane.classList.add('active', 'in');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ---------- sticky category nav highlight ---------- */
|
||||
function initCatNav() {
|
||||
var wrap = qs('.links-page-container .fixed-wrap');
|
||||
if (!wrap) return;
|
||||
var nav = qs('.link-nav-box', wrap);
|
||||
var links = qsa('.link-nav-box a[href^="#"]', wrap);
|
||||
var sections = links
|
||||
.map(function (a) {
|
||||
var id = a.getAttribute('href');
|
||||
return id ? document.getElementById(id.replace(/^#/, '')) : null;
|
||||
})
|
||||
.filter(Boolean);
|
||||
if (!links.length || !sections.length) return;
|
||||
|
||||
links.forEach(function (a) {
|
||||
a.addEventListener('click', function (e) {
|
||||
var id = a.getAttribute('href');
|
||||
var el = id ? document.getElementById(id.replace(/^#/, '')) : null;
|
||||
if (!el) return;
|
||||
e.preventDefault();
|
||||
var top = el.getBoundingClientRect().top + window.pageYOffset - 90;
|
||||
window.scrollTo({ top: top, behavior: 'smooth' });
|
||||
});
|
||||
});
|
||||
|
||||
function updateActive() {
|
||||
var y = window.pageYOffset + 120;
|
||||
var current = sections[0];
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i].offsetTop <= y) current = sections[i];
|
||||
}
|
||||
if (!current) return;
|
||||
links.forEach(function (a) {
|
||||
var li = a.parentElement;
|
||||
if (!li) return;
|
||||
if (a.getAttribute('href') === '#' + current.id) {
|
||||
li.classList.add('active');
|
||||
} else {
|
||||
li.classList.remove('active');
|
||||
}
|
||||
});
|
||||
if (nav) nav.classList.add('affix');
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', updateActive, { passive: true });
|
||||
updateActive();
|
||||
}
|
||||
|
||||
/* ---------- submit modal ---------- */
|
||||
function initSubmitModal() {
|
||||
var modal = qs('#submit-links-modal');
|
||||
if (!modal) return;
|
||||
|
||||
function openModal(e) {
|
||||
if (e) e.preventDefault();
|
||||
modal.classList.add('is-open', 'show');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
document.documentElement.classList.add('aksrt-modal-open');
|
||||
}
|
||||
|
||||
function closeModal(e) {
|
||||
if (e) e.preventDefault();
|
||||
modal.classList.remove('is-open', 'show');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
document.documentElement.classList.remove('aksrt-modal-open');
|
||||
}
|
||||
|
||||
qsa('a[href="#submit-links-modal"], [data-toggle="modal"][href="#submit-links-modal"]').forEach(function (btn) {
|
||||
btn.addEventListener('click', openModal);
|
||||
});
|
||||
|
||||
qsa('[data-dismiss="modal"]', modal).forEach(function (btn) {
|
||||
btn.addEventListener('click', closeModal);
|
||||
});
|
||||
|
||||
modal.addEventListener('click', function (e) {
|
||||
if (e.target === modal) closeModal(e);
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape' && modal.classList.contains('is-open')) closeModal(e);
|
||||
});
|
||||
|
||||
var fileInput = qs('.aksrt-links-logo-input', modal);
|
||||
var preview = qs('.aksrt-links-logo-preview', modal);
|
||||
if (fileInput && preview) {
|
||||
fileInput.addEventListener('change', function () {
|
||||
var file = fileInput.files && fileInput.files[0];
|
||||
if (!file) return;
|
||||
var url = URL.createObjectURL(file);
|
||||
preview.src = url;
|
||||
});
|
||||
}
|
||||
|
||||
var form = qs('.aksrt-links-submit-form', modal);
|
||||
if (!form) return;
|
||||
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var btn = qs('.aksrt-links-submit-btn', form);
|
||||
if (btn) {
|
||||
btn.disabled = true;
|
||||
btn.classList.add('loading');
|
||||
}
|
||||
|
||||
var fd = new FormData(form);
|
||||
if (!fd.get('action')) fd.set('action', 'aksrt_frontend_links_submit');
|
||||
|
||||
fetch(ajaxUrl(), {
|
||||
method: 'POST',
|
||||
body: fd,
|
||||
credentials: 'same-origin',
|
||||
})
|
||||
.then(function (r) {
|
||||
return r.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
if (!data || data.error) {
|
||||
toast((data && data.msg) || '提交失败', 'danger');
|
||||
return;
|
||||
}
|
||||
toast(data.msg || '提交成功', 'success');
|
||||
if (data.reload) {
|
||||
window.setTimeout(function () {
|
||||
window.location.reload();
|
||||
}, 600);
|
||||
} else {
|
||||
closeModal();
|
||||
form.reset();
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
toast('网络错误,请稍后重试', 'danger');
|
||||
})
|
||||
.finally(function () {
|
||||
if (btn) {
|
||||
btn.disabled = false;
|
||||
btn.classList.remove('loading');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
if (!document.body.classList.contains('page-template-templates-pages-page-links-php')
|
||||
&& !qs('.page-template-links')
|
||||
&& !qs('.links-page-container')
|
||||
&& !qs('#submit-links-modal')) {
|
||||
// Still bind if modal exists alone.
|
||||
}
|
||||
initSearchTabs();
|
||||
initCatNav();
|
||||
initSubmitModal();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
Reference in new issue
Block a user