Как сделать моментальный скролл в поиске слова, вместо нажатия на кнопку?
Есть форма поиска, при вводе существующего слова выводится сообщение что столько то похожих слов и кнопка перейти, хотелось сделать, чтобы кнопка эта не отображалась, а сразу после верного слова происходил скролл к первому похожему.
Вот собственно сам код:
jQuery(document).ready(function() {
var minlen = 3; // минимальная длина слова
var paddingbottom = 500; // отступ сверху при прокрутке
var scrollspeed = 200; // время прокрутки
var keyint = 0; // интервал между нажатиями клавиш
var term = '';
var n = 0;
var time_keyup = 0;
var time_search = 0;
jQuery('body').delegate('#spgo', 'click', function() {
jQuery('body,html').animate({
scrollTop: jQuery('span.highlight:first').offset().top - paddingbottom
}, scrollspeed); // переход к первому фрагменту
});
function dosearch() {
term = jQuery('#spterm').val();
jQuery('span.highlight').each(function() { //удаляем старую подсветку
jQuery(this).after(jQuery(this).html()).remove();
});
var t = '';
jQuery('div#conten').each(function() { // в селекторе задаем область поиска
jQuery(this).html(jQuery(this).html().replace(new RegExp(term, 'ig'), '<span class="highlight">$&</span>')); // выделяем найденные фрагменты
n = jQuery('span.highlight').length; // количество найденных фрагментов
console.log('n = ' + n);
if (n == 0)
jQuery('#spresult').html('Ничего не найдено');
else
jQuery('#spresult').html('Найдено: ' + n + '. <span class="splink" id="spgo">Перейти</span>');
if (n > 1) // если больше одного фрагмента, то добавляем переход между ними
{
var i = 0;
jQuery('span.highlight').each(function(i) {
jQuery(this).attr('n', i++); // нумеруем фрагменты, более простого способа искать следующий элемент не нашел
});
jQuery('span.highlight').not(':last').attr({
title: 'Нажмите, чтобы перейти к следующему фрагменту'
}).click(function() { // всем фрагментам, кроме последнего, добавляем подсказку
jQuery('body,html').animate({
scrollTop: jQuery('span.highlight:gt(' + jQuery(this).attr('n') + '):first').offset().top - paddingbottom
}, scrollspeed); // переход к следующему фрагменту
});
jQuery('span.highlight:last').attr({
title: 'Нажмите, чтобы вернуться к форме поиска'
}).click(function() {
jQuery('body,html').animate({
scrollTop: jQuery('#spterm').offset().top - paddingbottom
}, scrollspeed); // переход к форме поиска
});
}
});
}
jQuery('#spterm').keyup(function() {
var d1 = new Date();
time_keyup = d1.getTime();
if (jQuery('#spterm').val() != term) // проверяем, изменилась ли строка
if (jQuery('#spterm').val().length >= minlen) { // проверяем длину строки
setTimeout(function() { // ждем следующего нажатия
var d2 = new Date();
time_search = d2.getTime();
if (time_search - time_keyup >= keyint) // проверяем интервал между нажатиями
dosearch(); // если все в порядке, приступаем к поиску
}, keyint);
}
else
jQuery('#spresult').html(' '); // если строка короткая, убираем текст из DIVа с результатом
});
if (window.location.hash != "") // бонус
{
var t = window.location.hash.substr(1, 50); // вырезаем текст
jQuery('#spterm').val(t).keyup(); // вставляем его в форму поиска
jQuery('#spgo').click(); // переходим к первому фрагменту
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="spterm" type="search" name="spterm" placeholder="Поиск..."><br />
<div id="spresult"> </div>
Буду безумно благодарен за помощь!
Ответы (1 шт):
Автор решения: Alexander Lonberg
→ Ссылка
Вопрос не воспроизводит код, что он там и как ищет неясно.
Об jQuery можно сразу сломать зрение.
Поэтому простой пример поиска с переходом к первому совпадению.
Кнопку перехода к следующему совпадению оставил - для очень длинного текста.
Ниже воспроизводимый сниппет:
const input = document.getElementById('input')
const next = document.getElementById('next')
const out = document.getElementById('out')
const delay = 300
let tid = null
let sText = ''
let sItems = []
let sRemove = []
let nextPos = -1
// родительский контейнер для поиска
const content = document.querySelector('.content')
// сюда можно добавить элементы для исключения
// если content = body, можно добавить всякие меню и input
const exclude = [document.querySelector("#exclude")]
// перемещение scroll и подсветка текущего элемента
next.addEventListener('click', nextItem)
function nextItem() {
sItems[nextPos === -1 ? sItems.length - 1 : nextPos].removeHighlight()
sItems[++nextPos].next(nextPos)
next.textContent = (nextPos + 1 === sItems.length)
? ((nextPos = -1), `Перейти к 1`)
: `Перейти к ${nextPos + 2}`
}
input.addEventListener('input', () => {
clearTimeout(tid)
tid = setTimeout(() => {
let t = input.value.trim().toLowerCase()
if (sText === t) {
return
}
sText = t
searchText()
}, delay)
})
function createSpan(text) {
let span = document.createElement('span')
span.className = 'highlight'
span.append(
document.createTextNode(text)
)
return span
}
// Дальнейший поиск, подсветка и определение позиций
function replace(parent, e, text, i) {
let origin = e.data
let alle = []
let oldi = 0
let posTop = content.getBoundingClientRect().top
do {
let l = i + sText.length
let span = createSpan(origin.slice(i, l))
let adds = [
document.createTextNode(origin.slice(oldi, i)),
span
]
adds.forEach((i) => parent.insertBefore(i, e))
alle.push(...adds)
oldi = l
// Позиция для scroll
let top = content.scrollTop + span.getBoundingClientRect().top
sItems.push(
{
next() {
span.classList.add('current')
content.scrollTop = top - posTop
},
removeHighlight() {
span.classList.remove('current')
}
}
)
} while ((i = text.indexOf(sText, oldi)) !== -1)
let end = document.createTextNode(origin.slice(oldi))
alle.push(end)
parent.insertBefore(end, e)
parent.removeChild(e)
sRemove.push(
() => {
parent.insertBefore(e, end)
alle.forEach((i) => i.remove())
}
)
}
// Обход элементов
function recursiveSearch(target) {
let ch = Array.prototype.slice.call(target.childNodes)
for (let e of ch) {
if (e.nodeType === 3) {
let st = e.data.toLowerCase()
let i = st.indexOf(sText)
if (i !== -1) {
replace(target, e, st, i)
}
} else if (e.nodeType === 1 && !exclude.includes(e)) {
recursiveSearch(e)
}
}
}
// Поиск
function searchText() {
sItems.splice(0)
while (sRemove.length) {
sRemove.pop()()
}
nextPos = -1
next.disabled = true
next.textContent = 'Disabled'
if (!sText) {
out.textContent = 'Заполните поле поиска'
return
}
recursiveSearch(content)
if (!sItems.length) {
out.textContent = 'Ничего не найдено'
return
}
next.disabled = false
next.textContent = 'Перейти к 1'
out.textContent = `Совпадений: ${sItems.length}`
nextItem()
}
body {
padding: 0;
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
header {
position: fixed;
width: 100%;
height: 3em;
background-color: #dadada;
}
.content {
position: fixed;
top: 3em;
bottom: 0px;
overflow: auto;
scroll-behavior: smooth;
}
.highlight {
background-color: yellow;
}
.highlight.current {
background-color: #8BC34A;
}
<header>
<input id='input' type="text" placeholder="Введите текст">
<button id='next' disabled>Disabled</button>
<div id='out'>Пока ничего не найдено</div>
</header>
<div class="content">
<h1>Поиск слов</h1>
<p id='exclude'>Для примера этот абзац исключен из поиска</p>
<p>Первый абзац<br>JavaScript® (часто просто JS) — это легковесный, интерпретируемый или JIT-компилируемый, объектно-ориентированный язык с функциями первого класса. Наиболее широкое применение находит как язык сценариев веб-страниц, но также используется и в других программных продуктах, например, node.js или Apache CouchDB. JavaScript это прототипно-ориентированный, мультипарадигменный язык с динамической типизацией, который поддерживает объектно-ориентированный, императивный и декларативный (например, функциональное программирование) стили программирования. Подробнее о JavaScript. Эта часть сайта посвящена самому языку JavaScript, и она не затрагивает тонкостей, связанных с веб-страницами или окружением, в котором исполняется JavaScript. Информация об API, относящихся к веб-страницам, находится в разделах, посвященных Веб-API и DOM. Стандартом языка JavaScript является ECMAScript. По состоянию на 2012, все современные браузеры полностью поддерживают ECMAScript 5.1. Старые версии браузеров поддерживают по крайней мере - ECMAScript 3. 17 июня 2015 года состоялся выпуск шестой версии ECMAScript. Эта версия официально называется ECMAScript 2015, которую чаще всего называют ECMAScript 2015 или просто ES2015. С недавнего времени стандарты ECMAScript выпускаются ежегодно. Эта документация относится к последней версии черновика, которой является ECMAScript 2018. Не следует путать JavaScript c языком программирования Java. И "Java", и "JavaScript" являются торговыми марками или зарегистрированными торговыми марками Oracle в США и других странах. Однако, у обоих языков различный синтаксис, семантика и применение.
</p>
Просто #text элемент
<p>Второй абзац<br>Веб предлагает широкий спектр интерфейсов для выполнения различных полезных задач. Они могут быть доступны с помощью кода JavaScript, и путем внесения незначительных корректив в объекты window или element. Для создания сложной графики и аудио эффектов используются такие интерфейсы как WebGL и Web Audio. Описание всех интерфейсов (APIs). Описание доступных событий (events). Объектная модель документа (DOM). DOM имеет интерфейс (API) который предоставляет возможность доступа к любой части документа. Эта модель позволяет осуществлять манипуляции над целыми разделами документа Node и отдельными элементами Element. Такие форматы как: HTML, XML и SVG используют её для решения своих специфических задач. Аппаратные интерфейсы Этот набор методов позволяет получить доступ из веб-страницы или приложения к различным датчикам устройства. Например: Ambient Light Sensor API, Battery Status API, Geolocation API, Pointer Lock API, Proximity API, Device Orientation API, Screen Orientation API, Vibration API. Интерфейсы связи Эти интерфейсы обеспечивают коммуникацию между веб-страницами и приложениями с другими страницами или устройствами. Такие как, Network Information API, Web Notifications, Simple Push API. Интерфейсы управления данными Пользовательские данные могут храниться и управляться этими интерфейсами. Например, FileHandle API, IndexedDB. В дополнение к описанным возможностям, которые доступны для любого веб-сайта или приложения, существует более мощный функционал Mozilla, доступный для привилегированных и сертифицированных приложений. Привилегированные интерфейсы При установке приложения от пользователя потребуется дать приложению специфичные права. Включают в себя: TCP Socket API, Contacts API, Device Storage API, Browser API, Camera API. Сертифицированная функциональность Сертифицированное приложение является приложением низкого уровня выполнения критических операций на операционной системе как Firefox OS. Менее привилегированные взаимодействуют с приложениями использующими Web Activities. Сертифицированные API, включают в себя: Bluetooth API, Mobile Connection API, Network Stats API, Telephony, WebSMS, WiFi Information API, Camera API, Power Management API, Settings API, Idle API, Permissions API, Time/Clock API
</p>
</div>