|
|
/**
|
|
|
* 搜索功能JavaScript文件
|
|
|
* 实现搜索框的弹出/收起动画和交互功能
|
|
|
* 包含新闻搜索模块的交互功能
|
|
|
*/
|
|
|
|
|
|
// 新闻搜索模块功能
|
|
|
(function() {
|
|
|
'use strict';
|
|
|
|
|
|
// 等待DOM加载完成
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
|
initNewsSearch();
|
|
|
});
|
|
|
|
|
|
function initNewsSearch() {
|
|
|
const searchInput = document.getElementById('news-search');
|
|
|
const categorySelect = document.getElementById('news-category');
|
|
|
const searchForm = document.querySelector('.news-search-form');
|
|
|
const suggestionsContainer = document.getElementById('search-suggestions');
|
|
|
|
|
|
if (!searchInput || !categorySelect || !searchForm) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 搜索建议数据(可以从后端获取)
|
|
|
let searchSuggestions = [];
|
|
|
let currentSuggestionIndex = -1;
|
|
|
|
|
|
// 分类下拉动画
|
|
|
categorySelect.addEventListener('focus', function() {
|
|
|
this.style.transform = 'scale(1.02)';
|
|
|
});
|
|
|
|
|
|
categorySelect.addEventListener('blur', function() {
|
|
|
this.style.transform = 'scale(1)';
|
|
|
});
|
|
|
|
|
|
// 分类选择改变时自动提交表单
|
|
|
categorySelect.addEventListener('change', function() {
|
|
|
const selectedOption = this.options[this.selectedIndex];
|
|
|
const url = selectedOption.getAttribute('data-url');
|
|
|
const searchVal = searchInput.value.trim();
|
|
|
|
|
|
// 如果搜索词为空且有目标URL,直接跳转(用于“显示全部”或切换分类)
|
|
|
if (searchVal === '' && url) {
|
|
|
window.location.href = url;
|
|
|
} else {
|
|
|
searchForm.submit();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 搜索输入框事件
|
|
|
searchInput.addEventListener('input', function() {
|
|
|
const query = this.value.trim();
|
|
|
if (query.length >= 2) {
|
|
|
fetchSearchSuggestions(query);
|
|
|
} else {
|
|
|
hideSuggestions();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 键盘事件处理
|
|
|
searchInput.addEventListener('keydown', function(e) {
|
|
|
if (e.key === 'Enter') {
|
|
|
e.preventDefault();
|
|
|
if (currentSuggestionIndex >= 0 && searchSuggestions[currentSuggestionIndex]) {
|
|
|
this.value = searchSuggestions[currentSuggestionIndex];
|
|
|
hideSuggestions();
|
|
|
}
|
|
|
searchForm.submit();
|
|
|
} else if (e.key === 'ArrowDown') {
|
|
|
e.preventDefault();
|
|
|
navigateSuggestions(1);
|
|
|
} else if (e.key === 'ArrowUp') {
|
|
|
e.preventDefault();
|
|
|
navigateSuggestions(-1);
|
|
|
} else if (e.key === 'Escape') {
|
|
|
hideSuggestions();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 点击外部隐藏建议
|
|
|
document.addEventListener('click', function(e) {
|
|
|
if (!searchInput.contains(e.target) && !suggestionsContainer.contains(e.target)) {
|
|
|
hideSuggestions();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 获取搜索建议
|
|
|
function fetchSearchSuggestions(query) {
|
|
|
// 模拟搜索建议(实际项目中应该从后端API获取)
|
|
|
const mockSuggestions = [
|
|
|
'新能源汽车',
|
|
|
'新能源政策',
|
|
|
'新能源技术',
|
|
|
'新能源发展',
|
|
|
'新能源投资',
|
|
|
'太阳能发电',
|
|
|
'风能发电',
|
|
|
'储能技术',
|
|
|
'电池技术',
|
|
|
'充电桩建设'
|
|
|
];
|
|
|
|
|
|
searchSuggestions = mockSuggestions.filter(item =>
|
|
|
item.toLowerCase().includes(query.toLowerCase())
|
|
|
).slice(0, 5);
|
|
|
|
|
|
showSuggestions();
|
|
|
}
|
|
|
|
|
|
// 显示搜索建议
|
|
|
function showSuggestions() {
|
|
|
if (searchSuggestions.length === 0) {
|
|
|
hideSuggestions();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
let html = '';
|
|
|
searchSuggestions.forEach((suggestion, index) => {
|
|
|
html += `<div class="suggestion-item" data-index="${index}">${suggestion}</div>`;
|
|
|
});
|
|
|
|
|
|
suggestionsContainer.innerHTML = html;
|
|
|
suggestionsContainer.classList.add('show');
|
|
|
|
|
|
// 绑定建议项点击事件
|
|
|
suggestionsContainer.querySelectorAll('.suggestion-item').forEach(item => {
|
|
|
item.addEventListener('click', function() {
|
|
|
searchInput.value = this.textContent;
|
|
|
hideSuggestions();
|
|
|
searchForm.submit();
|
|
|
});
|
|
|
|
|
|
item.addEventListener('mouseenter', function() {
|
|
|
currentSuggestionIndex = parseInt(this.dataset.index);
|
|
|
updateSuggestionHighlight();
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 隐藏搜索建议
|
|
|
function hideSuggestions() {
|
|
|
suggestionsContainer.classList.remove('show');
|
|
|
currentSuggestionIndex = -1;
|
|
|
}
|
|
|
|
|
|
// 导航搜索建议
|
|
|
function navigateSuggestions(direction) {
|
|
|
if (searchSuggestions.length === 0) return;
|
|
|
|
|
|
currentSuggestionIndex += direction;
|
|
|
|
|
|
if (currentSuggestionIndex < 0) {
|
|
|
currentSuggestionIndex = searchSuggestions.length - 1;
|
|
|
} else if (currentSuggestionIndex >= searchSuggestions.length) {
|
|
|
currentSuggestionIndex = 0;
|
|
|
}
|
|
|
|
|
|
updateSuggestionHighlight();
|
|
|
}
|
|
|
|
|
|
// 更新建议高亮
|
|
|
function updateSuggestionHighlight() {
|
|
|
const items = suggestionsContainer.querySelectorAll('.suggestion-item');
|
|
|
items.forEach((item, index) => {
|
|
|
if (index === currentSuggestionIndex) {
|
|
|
item.classList.add('active');
|
|
|
} else {
|
|
|
item.classList.remove('active');
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 表单提交处理
|
|
|
searchForm.addEventListener('submit', function(e) {
|
|
|
const query = searchInput.value.trim();
|
|
|
const category = categorySelect.value;
|
|
|
|
|
|
if (!query && !category) {
|
|
|
e.preventDefault();
|
|
|
searchInput.focus();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 添加加载动画
|
|
|
const searchButton = searchForm.querySelector('.search-button');
|
|
|
if (searchButton) {
|
|
|
searchButton.style.opacity = '0.7';
|
|
|
searchButton.style.transform = 'scale(0.95)';
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 平滑的焦点动画
|
|
|
searchInput.addEventListener('focus', function() {
|
|
|
this.parentElement.style.transform = 'scale(1.02)';
|
|
|
this.parentElement.style.boxShadow = '0 0 0 3px rgba(0, 123, 255, 0.1)';
|
|
|
});
|
|
|
|
|
|
searchInput.addEventListener('blur', function() {
|
|
|
this.parentElement.style.transform = 'scale(1)';
|
|
|
this.parentElement.style.boxShadow = 'none';
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 页面加载完成后初始化新闻搜索功能
|
|
|
if (document.readyState === 'loading') {
|
|
|
document.addEventListener('DOMContentLoaded', initNewsSearch);
|
|
|
} else {
|
|
|
initNewsSearch();
|
|
|
}
|
|
|
})();
|
|
|
|
|
|
(function() {
|
|
|
'use strict';
|
|
|
|
|
|
// DOM元素
|
|
|
let searchToggle, searchOverlay, searchInput, searchClose, searchForm;
|
|
|
|
|
|
// 初始化函数
|
|
|
function initSearch() {
|
|
|
// 获取DOM元素
|
|
|
searchToggle = document.getElementById('searchToggle');
|
|
|
searchOverlay = document.getElementById('searchOverlay');
|
|
|
searchInput = document.getElementById('searchInput');
|
|
|
searchClose = document.getElementById('searchClose');
|
|
|
searchForm = document.querySelector('.search-form');
|
|
|
|
|
|
if (!searchToggle || !searchOverlay) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 绑定事件
|
|
|
bindEvents();
|
|
|
|
|
|
// 初始化GSAP动画(如果可用)
|
|
|
if (typeof gsap !== 'undefined') {
|
|
|
initGSAPAnimations();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 绑定事件
|
|
|
function bindEvents() {
|
|
|
// 搜索按钮点击事件
|
|
|
searchToggle.addEventListener('click', openSearch);
|
|
|
|
|
|
// 关闭按钮点击事件
|
|
|
if (searchClose) {
|
|
|
searchClose.addEventListener('click', closeSearch);
|
|
|
}
|
|
|
|
|
|
// 遮罩层点击事件
|
|
|
searchOverlay.addEventListener('click', function(e) {
|
|
|
if (e.target === searchOverlay) {
|
|
|
closeSearch();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// ESC键关闭搜索
|
|
|
document.addEventListener('keydown', function(e) {
|
|
|
if (e.key === 'Escape' && searchOverlay.classList.contains('active')) {
|
|
|
closeSearch();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 搜索表单提交事件
|
|
|
if (searchForm) {
|
|
|
searchForm.addEventListener('submit', handleSearchSubmit);
|
|
|
}
|
|
|
|
|
|
// 搜索输入框事件
|
|
|
if (searchInput) {
|
|
|
searchInput.addEventListener('input', handleSearchInput);
|
|
|
searchInput.addEventListener('focus', handleSearchFocus);
|
|
|
searchInput.addEventListener('blur', handleSearchBlur);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 打开搜索框
|
|
|
function openSearch() {
|
|
|
searchOverlay.classList.add('active');
|
|
|
searchToggle.classList.add('active');
|
|
|
document.body.style.overflow = 'hidden';
|
|
|
|
|
|
// 延迟聚焦到输入框
|
|
|
setTimeout(() => {
|
|
|
if (searchInput) {
|
|
|
searchInput.focus();
|
|
|
}
|
|
|
}, 400);
|
|
|
|
|
|
// 触发自定义事件
|
|
|
document.dispatchEvent(new CustomEvent('searchOpened'));
|
|
|
}
|
|
|
|
|
|
// 关闭搜索框
|
|
|
function closeSearch() {
|
|
|
searchOverlay.classList.remove('active');
|
|
|
searchToggle.classList.remove('active');
|
|
|
document.body.style.overflow = '';
|
|
|
|
|
|
// 清空输入框(可选)
|
|
|
if (searchInput) {
|
|
|
// searchInput.value = '';
|
|
|
}
|
|
|
|
|
|
// 触发自定义事件
|
|
|
document.dispatchEvent(new CustomEvent('searchClosed'));
|
|
|
}
|
|
|
|
|
|
// 处理搜索表单提交
|
|
|
function handleSearchSubmit(e) {
|
|
|
const query = searchInput.value.trim();
|
|
|
|
|
|
if (!query) {
|
|
|
e.preventDefault();
|
|
|
searchInput.focus();
|
|
|
|
|
|
// 添加震动效果
|
|
|
if (typeof gsap !== 'undefined') {
|
|
|
gsap.to(searchInput, {
|
|
|
x: [-10, 10, -8, 8, -6, 6, -4, 4, -2, 2, 0],
|
|
|
duration: 0.6,
|
|
|
ease: "power2.out"
|
|
|
});
|
|
|
} else {
|
|
|
searchInput.classList.add('shake');
|
|
|
setTimeout(() => {
|
|
|
searchInput.classList.remove('shake');
|
|
|
}, 600);
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 可以在这里添加搜索分析代码
|
|
|
if (typeof gtag !== 'undefined') {
|
|
|
gtag('event', 'search', {
|
|
|
search_term: query
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 处理搜索输入
|
|
|
function handleSearchInput(e) {
|
|
|
const query = e.target.value.trim();
|
|
|
|
|
|
// 可以在这里实现实时搜索建议
|
|
|
if (query.length >= 2) {
|
|
|
// debounce搜索请求
|
|
|
clearTimeout(handleSearchInput.timeout);
|
|
|
handleSearchInput.timeout = setTimeout(() => {
|
|
|
fetchSearchSuggestions(query);
|
|
|
}, 300);
|
|
|
} else {
|
|
|
hideSuggestions();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 搜索输入框获得焦点
|
|
|
function handleSearchFocus() {
|
|
|
searchInput.parentElement.classList.add('focused');
|
|
|
}
|
|
|
|
|
|
// 搜索输入框失去焦点
|
|
|
function handleSearchBlur() {
|
|
|
searchInput.parentElement.classList.remove('focused');
|
|
|
}
|
|
|
|
|
|
// 获取搜索建议(示例实现)
|
|
|
function fetchSearchSuggestions(query) {
|
|
|
// 这里可以实现AJAX搜索建议
|
|
|
// 示例:向WordPress REST API发送请求
|
|
|
/*
|
|
|
fetch(`${themeData.ajaxUrl}?action=search_suggestions&query=${encodeURIComponent(query)}&nonce=${themeData.nonce}`)
|
|
|
.then(response => response.json())
|
|
|
.then(data => {
|
|
|
if (data.success) {
|
|
|
showSuggestions(data.data);
|
|
|
}
|
|
|
})
|
|
|
.catch(error => {
|
|
|
console.error('搜索建议获取失败:', error);
|
|
|
});
|
|
|
*/
|
|
|
}
|
|
|
|
|
|
// 显示搜索建议
|
|
|
function showSuggestions(suggestions) {
|
|
|
let suggestionsContainer = document.querySelector('.search-suggestions');
|
|
|
|
|
|
if (!suggestionsContainer) {
|
|
|
suggestionsContainer = document.createElement('div');
|
|
|
suggestionsContainer.className = 'search-suggestions';
|
|
|
searchInput.parentElement.appendChild(suggestionsContainer);
|
|
|
}
|
|
|
|
|
|
if (suggestions && suggestions.length > 0) {
|
|
|
suggestionsContainer.innerHTML = suggestions.map(item =>
|
|
|
`<div class="search-suggestion-item" data-value="${item.title}">${item.title}</div>`
|
|
|
).join('');
|
|
|
|
|
|
// 绑定建议项点击事件
|
|
|
suggestionsContainer.querySelectorAll('.search-suggestion-item').forEach(item => {
|
|
|
item.addEventListener('click', function() {
|
|
|
searchInput.value = this.dataset.value;
|
|
|
hideSuggestions();
|
|
|
searchForm.submit();
|
|
|
});
|
|
|
});
|
|
|
|
|
|
suggestionsContainer.classList.add('show');
|
|
|
} else {
|
|
|
hideSuggestions();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 隐藏搜索建议
|
|
|
function hideSuggestions() {
|
|
|
const suggestionsContainer = document.querySelector('.search-suggestions');
|
|
|
if (suggestionsContainer) {
|
|
|
suggestionsContainer.classList.remove('show');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 初始化GSAP动画
|
|
|
function initGSAPAnimations() {
|
|
|
// 注册ScrollTrigger插件(如果可用)
|
|
|
if (typeof ScrollTrigger !== 'undefined') {
|
|
|
gsap.registerPlugin(ScrollTrigger);
|
|
|
}
|
|
|
|
|
|
// 搜索按钮悬停动画
|
|
|
searchToggle.addEventListener('mouseenter', function() {
|
|
|
gsap.to(this.querySelector('.search-icon'), {
|
|
|
rotation: 90,
|
|
|
scale: 1.1,
|
|
|
duration: 0.3,
|
|
|
ease: "back.out(1.7)"
|
|
|
});
|
|
|
});
|
|
|
|
|
|
searchToggle.addEventListener('mouseleave', function() {
|
|
|
gsap.to(this.querySelector('.search-icon'), {
|
|
|
rotation: 0,
|
|
|
scale: 1,
|
|
|
duration: 0.3,
|
|
|
ease: "back.out(1.7)"
|
|
|
});
|
|
|
});
|
|
|
|
|
|
// 自定义搜索框打开动画
|
|
|
document.addEventListener('searchOpened', function() {
|
|
|
const searchBox = document.querySelector('.search-box');
|
|
|
const searchInputWrapper = document.querySelector('.search-input-wrapper');
|
|
|
const searchSubmit = document.querySelector('.search-submit');
|
|
|
|
|
|
// 重置初始状态
|
|
|
gsap.set([searchBox, searchInputWrapper, searchSubmit], {
|
|
|
opacity: 0,
|
|
|
y: 30,
|
|
|
scale: 0.9
|
|
|
});
|
|
|
|
|
|
// 创建时间线动画
|
|
|
const tl = gsap.timeline();
|
|
|
|
|
|
tl.to(searchBox, {
|
|
|
opacity: 1,
|
|
|
y: 0,
|
|
|
scale: 1,
|
|
|
duration: 0.4,
|
|
|
ease: "back.out(1.7)"
|
|
|
})
|
|
|
.to(searchInputWrapper, {
|
|
|
opacity: 1,
|
|
|
y: 0,
|
|
|
scale: 1,
|
|
|
duration: 0.3,
|
|
|
ease: "power2.out"
|
|
|
}, "-=0.2")
|
|
|
.to(searchSubmit, {
|
|
|
opacity: 1,
|
|
|
y: 0,
|
|
|
scale: 1,
|
|
|
duration: 0.3,
|
|
|
ease: "power2.out"
|
|
|
}, "-=0.1");
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 工具函数:防抖
|
|
|
function debounce(func, wait) {
|
|
|
let timeout;
|
|
|
return function executedFunction(...args) {
|
|
|
const later = () => {
|
|
|
clearTimeout(timeout);
|
|
|
func(...args);
|
|
|
};
|
|
|
clearTimeout(timeout);
|
|
|
timeout = setTimeout(later, wait);
|
|
|
};
|
|
|
}
|
|
|
|
|
|
// 工具函数:节流
|
|
|
function throttle(func, limit) {
|
|
|
let inThrottle;
|
|
|
return function() {
|
|
|
const args = arguments;
|
|
|
const context = this;
|
|
|
if (!inThrottle) {
|
|
|
func.apply(context, args);
|
|
|
inThrottle = true;
|
|
|
setTimeout(() => inThrottle = false, limit);
|
|
|
}
|
|
|
};
|
|
|
}
|
|
|
|
|
|
// 页面加载完成后初始化
|
|
|
if (document.readyState === 'loading') {
|
|
|
document.addEventListener('DOMContentLoaded', initSearch);
|
|
|
} else {
|
|
|
initSearch();
|
|
|
}
|
|
|
|
|
|
// 导出到全局(用于调试)
|
|
|
window.ThemeSearch = {
|
|
|
open: openSearch,
|
|
|
close: closeSearch,
|
|
|
toggle: function() {
|
|
|
if (searchOverlay && searchOverlay.classList.contains('active')) {
|
|
|
closeSearch();
|
|
|
} else {
|
|
|
openSearch();
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
|
|
|
})(); |