import { useEffect, useRef } from 'react';
import gsap from 'gsap';
import ScrollTrigger from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
export default function HorizontalContent() {
const itemsRef = useRef(null);
const triggerRef = useRef(null);
useEffect(() => {
const items = itemsRef.current;
const savedPosition = sessionStorage.getItem('animationPosition');
const initialPosition = savedPosition ? JSON.parse(savedPosition) : { translateX: 0 };
const pin = gsap.fromTo(
items,
initialPosition,
{
translateX: '-300vw',
ease: 'none',
duration: 1,
scrollTrigger: {
trigger: triggerRef.current,
start: 'top top',
end: '2000 top',
scrub: 0.6,
pin: true,
},
}
);
ScrollTrigger.addEventListener('refresh', () => {
// Сохраняем текущую позицию анимации
sessionStorage.setItem('animationPosition', JSON.stringify({ translateX: pin.progress() * -300 }));
// Очищаем анимацию
pin.kill();
// Восстанавливаем исходное состояние анимации
pin.progress(0).invalidate().restart();
});
return () => {
pin.kill();
};
}, []);
return (
<div className={styles.content}>
<div className={styles.container}>
<div ref={triggerRef}>
<div ref={itemsRef} className={styles.items}>
<div className={styles.item}>
<Efficiency />
</div>
<div className={styles.item}>
<h3>Section 2</h3>
</div>
<div className={styles.item}>
<h3>Section 3</h3>
</div>
<div className={styles.item}>
<h3>Section 4</h3>
</div>
</div>
</div>
</div>
</div>
);
};
import { useHistory } from 'react-router-dom';
function ModalComponent() {
const history = useHistory();
const handleCloseModal = () => {
// Закрытие модального окна и замена текущего пути новым путем (например, '/')
history.replace('/');
};
return (
<div>
{/* Ваше содержимое модального окна */}
<button onClick={handleCloseModal}>Закрыть</button>
</div>
);
}
// может использовать onCanPlayThrough ? Или onCanPlay / onPlay
const handleOnCanPlayThrough = () => {
setLoading(false)
console.log('Video loaded')
}
<video
onCanPlayThrough={handleOnCanPlayThrough}
// ...
>
<div class="chart-container">
<canvas id="myChart"></canvas>
<div class="tooltip-line"></div>
</div>
.chart-container {
position: relative;
}
.tooltip-line {
position: absolute;
display: none;
width: 1px;
height: 100%;
background-color: black;
opacity: 0.5;
pointer-events: none;
border: dashed;
}
const chart = new Chart(document.getElementById('myChart'), {
// Конфигурация графика Chart.js
// ...
});
const tooltipLine = document.querySelector('.tooltip-line');
chart.canvas.addEventListener('mousemove', function(e) {
const rect = chart.canvas.getBoundingClientRect();
const xPos = e.clientX - rect.left;
tooltipLine.style.left = xPos + 'px';
tooltipLine.style.display = 'block';
});
chart.canvas.addEventListener('mouseout', function(e) {
tooltipLine.style.display = 'none';
});
self.skipWaiting()
в Service Worker можно отправить сообщение об успешном сбросе кеша обратно в клиентскую часть приложения, используя postMessage()
. В клиентской части вы можете прослушивать это сообщение и выполнить обновление страницы с помощью location.reload()
или другого подходящего метода.// Service Worker
self.addEventListener('message', event => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
event.source.postMessage({ type: 'CACHE_RESET_SUCCESS' });
}
});
// client
navigator.serviceWorker.addEventListener('message', event => {
if (event.data && event.data.type === 'CACHE_RESET_SUCCESS') {
location.reload();
}
});
controllerchange
на объекте navigator.serviceWorker
. Когда Service Worker сбрасывается и становится активным контроллером, будет вызвано событие controllerchange, и вы можете выполнить обновление страницы.navigator.serviceWorker.addEventListener('controllerchange', () => {
location.reload();
});
element
в консоль при querySelectorAll
и понять, что это массив. Тогда для присвоения доп. класса надо пройти по этому массиву и добавить этот самый класс.let elements = document.querySelectorAll('.advantages__item');
window.addEventListener('scroll', check, false);
function check() {
if (window.scrollY > 300) {
elements.forEach(function(element) {
element.classList.add('show');
});
} else {
elements.forEach(function(element) {
element.classList.remove('show');
});
}
}
console.log()
сила! ($('form').submit(...))
или метод window.location.href
для перехода по ссылке.$(function() {
$('a').click(function(event) {
event.preventDefault(); // Отменяет переход по ссылке
var url = $(this).attr('href');
$(".loader_inner").fadeIn();
$(".loader").fadeIn();
setTimeout(function() {
window.location.href = url; // Переход по ссылке после отображения прелоадера
}, 400); // Задержка, чтобы прелоадер успел отобразиться
});
});
$(window).on('load', function() {
$(".loader_inner").fadeOut();
$(".loader").delay(400).fadeOut("slow");
});
function add_yandex_metric_goal() {
if (is_singular()) {
global $post;
$content = $post->post_content;
// Поиск всех ссылок с префиксом /go/
preg_match_all('/<a href="\/go\/(.*?)"/', $content, $matches);
// Добавление JavaScript-кода для цели Яндекс Метрики к найденным ссылкам
if (!empty($matches[1])) {
$goal_code = "ym(83804250, 'reachGoal', 'goshop'); return true;";
$replacement = '<a href="/go/$1" onclick="' . $goal_code . '"';
$content = preg_replace('/<a href="\/go\/(.*?)"/', $replacement, $content);
// Обновление контента поста
$post->post_content = $content;
wp_update_post($post);
}
}
}
add_action('wp', 'add_yandex_metric_goal');
// .eslintrc.modules.json
{
"extends": "./.eslintrc.json",
"parserOptions": {
"sourceType": "module"
},
}
var
и перейти на let
и const
const bannersClick = document.querySelector('.banners__click');
const bannersInfo = document.querySelector('.banners');
const bannersClose = document.querySelector('.banners__close');
function addClass(element, className) {
element.classList.add(className);
}
function setRightStyle(element, value) {
element.style.right = value;
}
function handleClick() {
addClass(this, 'slideInRight');
setRightStyle(this, '400px');
bannersInfo.classList.remove('slideOutLeft');
addClass(bannersInfo, 'slideInRight');
setRightStyle(bannersInfo, '0');
}
function handleClose() {
bannersInfo.classList.remove('slideInRight');
addClass(bannersInfo, 'slideOutLeft');
setRightStyle(bannersInfo, '-410px');
setRightStyle(bannersClick, '-10px');
}
bannersClose.addEventListener('click', handleClose);
bannersClick.addEventListener('click', handleClick);
npm install mongodb
const { MongoClient } = require('mongodb');
const url = 'mongodb://localhost:27017'; // URL базы данных
const dbName = 'mydatabase'; // Имя базы данных
const client = new MongoClient(url);
async function connectToDatabase() {
try {
await client.connect();
console.log('Connected to the database');
return client.db(dbName);
} catch (error) {
console.error('Error connecting to the database:', error);
}
}
module.exports = connectToDatabase;
const express = require('express');
const connectToDatabase = require('./db'); // Путь к файлу подключения к базе данных
const app = express();
app.use(express.json());
// Маршрут для сохранения данных в базу данных
app.post('/data', async (req, res) => {
const { email, phoneNumber, fullName } = req.body;
try {
const db = await connectToDatabase();
const collection = db.collection('data'); // Имя коллекции
const result = await collection.insertOne({
email,
phoneNumber,
fullName,
});
res.status(201).json(result.ops[0]); // Отправить сохраненный документ обратно клиенту
} catch (error) {
console.error('Error saving data to the database:', error);
res.status(500).json({ error: 'An error occurred' });
}
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
<form action="/data" method="POST">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="phoneNumber">Phone Number:</label>
<input type="tel" id="phoneNumber" name="phoneNumber" required>
<label for="fullName">Full Name:</label>
<input type="text" id="fullName" name="fullName" required>
<button type="submit">Submit</button>
</form>
const array = [
{id: 1, name: 'Test_1'},
{id: 2, name: 'Test_2'},
{id: 3, name: 'Test_3'},
{id: 4, name: 'Test_1'},
{id: 5, name: 'Test_2'}
];
const groupedArrays = array.reduce((result, obj) => {
// Проверяем, существует ли уже массив с данным значением name
const existingArray = result.find(arr => arr[0].name === obj.name);
// Если такой массив уже существует, добавляем текущий объект в него
if (existingArray) {
existingArray.push(obj);
} else {
// Если такого массива еще нет, создаем новый массив с текущим объектом
result.push([obj]);
}
return result;
}, []);
// Печатаем результат
groupedArrays.forEach(arr => {
console.log('____');
console.log(arr);
});