Вы можете обернуть основной таймер внутри интервала, и каждое событие выделения выделяется как отдельный тайм-аут.
Я бы также добавил класс к элементам, к которым вы хотите запросить запрос, или просто выберите все h1
elements.
Вы также можете указать фиксированное время ожидания, и оно рассчитает время ожидания между элементами для вас.
window.startAuto = () => {
start({
selector : '.highlighter',
timeouts : [ 1000, 2000, 1000 ], // or, for a fixed timout: 1000
callback : (el, index, activeIndex) => {
el.classList.toggle('active', index === activeIndex);
}
});
};
const defaultOptions = {
selector : '',
timeouts : [],
initialDelay : 0
};
const start = (options) => {
let opts = Object.assign({}, defaultOptions, options);
opts.elements = Array.from(document.querySelectorAll(opts.selector));
let interval = 0;
if (!Array.isArray(opts.timeouts)) {
opts.timeouts = fillArray(opts.timeouts, opts.elements.length);
}
interval = opts.timeouts.reduce((t, x) => t + x, 0);
opts.timeouts = normalizeTimeouts(opts.timeouts);
setTimeout(() => {
update(opts);
setInterval(update, interval, opts);
}, opts.initialDelay);
};
const normalizeTimeouts = (timeouts) => {
return timeouts.reduce((results, timeout, index, all) => {
return results.concat(timeout + all.slice(0, index).reduce((t, x) => t + x, 0));
}, [0]);
};
const update = (opts) => {
opts.timeouts.slice(0, opts.timeouts.length -1).forEach((timeout, index) => {
setTimeout(() => {
opts.elements.forEach((element, i) => {
return opts.callback.call(element, element, i, index);
});
}, timeout);
})
};
const fillArray = (value, count) => new Array(count).fill(value);
.active {
color: green;
}
<body onload="startAuto()">
<h1 class="highlighter" id="first">Text 1</h1>
<h1 class="highlighter" id="second">Text 2</h1>
<h1 class="highlighter" id="third">Text 3</h1>
</body>
Вот супер-динамический; многоразовый класс.
document.addEventListener('DOMContentLoaded', () => main());
const main = () => {
let looper = new Looper({
selector : '.highlighter',
timeouts : [ 1000, 2000, 1000 ], // or, for a fixed timout: 1000
callback : (el, index, activeIndex) => {
el.classList.toggle('active', index === activeIndex);
},
initialDelay : 1000,
autoStart : true
})
document.querySelector('#stop-btn').addEventListener('click', (e) => {
looper.stop();
});
document.querySelector('#restart-btn').addEventListener('click', (e) => {
looper.stop();
looper.start();
});
}
class Looper {
constructor(options) {
let opts = Object.assign({}, Looper.defaultOptions, options);
this.elements = Array.from(document.querySelectorAll(opts.selector));
if (!Array.isArray(opts.timeouts)) {
opts.timeouts = this.__fillArray(opts.timeouts, this.elements.length);
}
this.interval = opts.timeouts.reduce((t, x) => t + x, 0);
this.timeouts = this.__normalizeTimeouts(opts.timeouts);
this.initialDelay = opts.initialDelay;
this.autoStart = opts.autoStart;
this.callback = opts.callback;
this.__startupId = null;
this.__processId = null;
this.__subprocessIds = this.__fillArray(null, this.elements.length);
if (this.autoStart === true) this.start();
}
start() {
if (this.callback == null) {
throw new Error('callback function is undefined');
}
if (this.__processId == null) {
this.__startupId = setTimeout(() => {
this.__update();
this.__processId = setInterval(() => {
this.__update();
}, this.interval);
}, this.initialDelay);
}
}
stop() {
this.__subprocessIds.forEach((id, index) => {
if (id != null) {
clearTimeout(id);
this.__subprocessIds[index] = null;
}
});
if (this.__processId != null) {
clearInterval(this.__processId);
this.__processId = null;
}
if (this.__startupId != null) {
clearTimeout(this.__startupId);
this.__startupId = null;
}
}
__update() {
let self = this;
self.timeouts.slice(0, this.timeouts.length -1).forEach((timeout, index) => {
self.__subprocessIds[index] = setTimeout(() => {
self.elements.forEach((element, i) => {
return self.callback.call(element, element, i, index);
});
}, timeout);
})
}
__normalizeTimeouts(timeouts) {
return timeouts.reduce((results, timeout, index, all) => {
return results.concat(timeout + all.slice(0, index).reduce((t, x) => t + x, 0));
}, [0]);
}
__fillArray(value, count) {
return new Array(count).fill(value);
}
}
Looper.defaultOptions = {
selector : '',
timeouts : [],
initialDelay : 0,
autoStart : false
}
.active {
color: green;
}
<div>
<h2 class="highlighter" id="first">Text 1</h2>
<h2 class="highlighter" id="second">Text 2</h2>
<h2 class="highlighter" id="third">Text 3</h2>
</div>
<button id="stop-btn">Stop</button>
<button id="restart-btn">Restart</button>