Как по клику прервать выполнение предыдущего скрипта. JS
У меня есть такой эффект печатающей машинки. Сайт у меня 3-х язычный. При смене языка я хочу, чтобы скрипт выполнялся повторно с новым языком. Для этого я добавил событие onclick. Все работает, но есть баг, если мы изменим язык во время выполнения скрипта, новый будет выполняться поверх старого.
Как в моем случае я могу остановить старый сценарий и выполнить новый?
Я попытался использовать return, как писали в других ответах, попытался использовать clearTimeout, но все равно не работает.
var isTag, text, langText, i = 0;
langText = "Hi!<br>Text,<br>Text ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
setTimeout(e, 100);
}
}());
document.querySelector('.en').onclick = function() {
var isTag, text, langText, i = 0;
langText = "Hi!<br>Text,<br>Text ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
setTimeout(e, 100);
}
}());
};
document.querySelector('.de').onclick = function() {
var isTag, text, langText, i = 0;
langText = "Hallo!<br>Text,<br>Text ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
setTimeout(e, 100);
}
}());
};
document.querySelector('.ru').onclick = function() {
var isTag, text, langText, i = 0;
langText = "Привет!<br>Текст,<br>Текст ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
setTimeout(e, 100);
}
}());
};
.lang{
display: flex;
}
.lang a{
color: #000;
width: 100px;
display: block;
transition: .5s;
font-weight: bold;
text-align: center;
text-decoration: none;
border: 1px solid #000;
}
.lang a:not(:last-child){
margin-right: 10px;
}
.lang a:hover{
color: #fff;
transition: .5s;
background-color: #000;
}
.index-title-main{
padding-left: 50px;
}
<div class="lang">
<a class="en" href="#">English</a>
<a class="de" href="#">Deutsche</a>
<a class="ru" href="#">Русский</a>
</div>
<div class="index-title-main">
<h1></h1>
</div>
Ответы (3 шт):
Возможно вы не до конца поняли как пользоваться clearTimeout, у меня получилось при помощи него решить задачу. Подробнее о clearTimeout смотрите тут: https://developer.mozilla.org/ru/docs/Web/API/WindowOrWorkerGlobalScope/clearTimeout
// здесь будет наш идентификатор таймаута
var mytimeout = 0;
//
var isTag, text, langText, i = 0;
langText = "Hi!<br>Text,<br>Text ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
mytimeout = setTimeout(e, 100);
}
}());
document.querySelector('.en').onclick = function() {clearTimeout(mytimeout) //очищаем Timeout при новом запуске
var isTag, text, langText, i = 0;
langText = "Hi!<br>Text,<br>Text ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
mytimeout = setTimeout(e, 100);
}
}());
};
document.querySelector('.de').onclick = function() {clearTimeout(mytimeout)//очищаем Timeout при новом запуске
var isTag, text, langText, i = 0;
langText = "Hallo!<br>Text,<br>Text ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
mytimeout = setTimeout(e, 100);
}
}());
};
document.querySelector('.ru').onclick = function() {clearTimeout(mytimeout)//очищаем Timeout при новом запуске
var isTag, text, langText, i = 0;
langText = "Привет!<br>Текст,<br>Текст ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
mytimeout = setTimeout(e, 100);
}
}());
};
.lang{
display: flex;
}
.lang a{
color: #000;
width: 100px;
display: block;
transition: .5s;
font-weight: bold;
text-align: center;
text-decoration: none;
border: 1px solid #000;
}
.lang a:not(:last-child){
margin-right: 10px;
}
.lang a:hover{
color: #fff;
transition: .5s;
background-color: #000;
}
.index-title-main{
padding-left: 50px;
}
<div class="lang">
<a class="en" href="#">English</a>
<a class="de" href="#">Deutsche</a>
<a class="ru" href="#">Русский</a>
</div>
<div class="index-title-main">
<h1></h1>
</div>
Как вариант. Простите, что несколько переиначил. К тому же, я не эксперт в JS, пусть знающие поправят, если можно лучше)
let PRINT_INTERVAL = 100;
let STR = {};
STR.en = "Hi!\nText,\nText ";
STR.de = "Hallo!\nText,\nText ";
STR.ru = "Привет!\nТекст,\nТекст ";
let timeout = null;
// Функция печати
function type(str, index = 0)
{
if(index === 0)
contents.innerHTML = "";
if(str[index] !== undefined)
{
let symbol = str[index];
if(symbol === "\n")
symbol = "<br>";
contents.innerHTML += symbol;
}
timeout = setTimeout(function()
{
type(str, index + 1);
}, PRINT_INTERVAL);
}
type(STR.en); // Печатаем текст по умолчанию при загрузке
// Проставляем события для каждой кнопки
let buttons = document.querySelectorAll("div.lang > a");
buttons.forEach(function(buttonElement)
{
let lang = buttonElement.className;
buttonElement.onclick = function()
{
clearTimeout(timeout); // Отменяем ранее запущенную печать
// Делаем крошечный таймаут, чтобы избежать потенциальной гонки данных
setTimeout(function()
{
type(STR[lang]);
}, 1);
}
});
.lang {
display: flex;
}
.lang a {
color: #000;
width: 100px;
display: block;
transition: .5s;
font-weight: bold;
text-align: center;
text-decoration: none;
border: 1px solid #000;
}
.lang a:not(:last-child) {
margin-right: 10px;
}
.lang a:hover{
color: #fff;
transition: .5s;
background-color: #000;
}
.index-title-main{
padding-left: 50px;
}
<div class="lang">
<a class="en" href="#">English</a>
<a class="de" href="#">Deutsche</a>
<a class="ru" href="#">Русский</a>
</div>
<div class="index-title-main">
<h1 id="contents"></h1>
</div>
Как то дико много кода
async function* generator(text, t = 100) {
text = [...text]
while (text.length) {
await new Promise((s) => setTimeout(s, t))
yield text.shift()
}
}
let gen = { return: () => null }
async function writer(text, textArea) {
await gen.return()
textArea.textContent = ''
gen = generator(text)
let temp
while ((temp = await gen.next(), !temp.done)) {
textArea.textContent += temp.value
}
}
// +++ test
const text = {
en: 'I have this typewriter effect.',
ru: 'У меня есть такой эффект печатающей машинки.'
}
const textArea = document.querySelector('[data-text]');
['en', 'ru'].forEach((v) => document.querySelector(`[data-${v}]`)
.addEventListener('click', () => writer(text[v], textArea))
)
// default
writer(text.ru, textArea)
<button data-en>en</button>
<button data-ru>ru</button>
<div data-text></div>