371 lines
15 KiB
JavaScript
371 lines
15 KiB
JavaScript
document.addEventListener('DOMContentLoaded', function () {
|
||
// Модалка с вузами
|
||
const universitiesModal = document.getElementById('universitiesModal');
|
||
const openUniversitiesBtn = document.getElementById('showModalBtn');
|
||
const closeUniversitiesBtn = document.getElementById('closeModalBtn');
|
||
|
||
function openUniversitiesModal(e){
|
||
e.preventDefault();
|
||
document.body.style.overflow = 'hidden';
|
||
universitiesModal.style.display = 'block';
|
||
setTimeout(() => universitiesModal.classList.add('active'), 10);
|
||
}
|
||
|
||
function closeUniversitiesModal(){
|
||
universitiesModal.classList.remove('active');
|
||
setTimeout(() => {
|
||
universitiesModal.style.display = 'none';
|
||
document.body.style.overflow = 'auto';
|
||
}, 300);
|
||
}
|
||
|
||
if (openUniversitiesBtn) openUniversitiesBtn.addEventListener('click', openUniversitiesModal);
|
||
if (closeUniversitiesBtn) closeUniversitiesBtn.addEventListener('click', closeUniversitiesModal);
|
||
if (universitiesModal) {
|
||
universitiesModal.addEventListener('click', (e) => {
|
||
if (e.target === universitiesModal) closeUniversitiesModal();
|
||
});
|
||
}
|
||
|
||
// Модалка с тестом
|
||
const testModal = document.getElementById('careerTestModal');
|
||
const openTestBtn = document.getElementById('showCareerTestBtn');
|
||
const closeTestBtn = document.getElementById('closeCareerTestBtn');
|
||
|
||
function openTestModal(e){
|
||
e.preventDefault();
|
||
document.body.style.overflow = 'hidden';
|
||
testModal.style.display = 'block';
|
||
setTimeout(() => testModal.classList.add('active'), 10);
|
||
}
|
||
|
||
function closeTestModal(){
|
||
testModal.classList.remove('active');
|
||
setTimeout(() => {
|
||
testModal.style.display = 'none';
|
||
document.body.style.overflow = 'auto';
|
||
}, 300);
|
||
}
|
||
|
||
if (openTestBtn) openTestBtn.addEventListener('click', openTestModal);
|
||
if (closeTestBtn) closeTestBtn.addEventListener('click', closeTestModal);
|
||
if (testModal) {
|
||
testModal.addEventListener('click', (e) => {
|
||
if (e.target === testModal) closeTestModal();
|
||
});
|
||
}
|
||
|
||
document.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Escape') {
|
||
if (testModal && testModal.style.display === 'block') closeTestModal();
|
||
if (universitiesModal && universitiesModal.style.display === 'block') closeUniversitiesModal();
|
||
}
|
||
});
|
||
|
||
// Аккордион для вузов
|
||
const accordionHeaders = document.querySelectorAll('.accordion-header');
|
||
accordionHeaders.forEach(header => {
|
||
header.addEventListener('click', function () {
|
||
const item = this.parentElement;
|
||
const content = this.nextElementSibling;
|
||
|
||
document.querySelectorAll('.accordion-content.active').forEach(activeContent => {
|
||
if (activeContent !== content) {
|
||
activeContent.classList.remove('active');
|
||
activeContent.style.maxHeight = null;
|
||
activeContent.previousElementSibling.classList.remove('active');
|
||
}
|
||
});
|
||
|
||
this.classList.toggle('active');
|
||
if (content.classList.contains('active')) {
|
||
content.classList.remove('active');
|
||
content.style.maxHeight = null;
|
||
} else {
|
||
content.classList.add('active');
|
||
content.style.maxHeight = content.scrollHeight + 'px';
|
||
}
|
||
});
|
||
});
|
||
|
||
// Открытие первого аккордиона по умолчанию
|
||
document.querySelectorAll('.university-card').forEach(card => {
|
||
const firstAccordion = card.querySelector('.accordion-item');
|
||
if (firstAccordion) {
|
||
const header = firstAccordion.querySelector('.accordion-header');
|
||
const content = firstAccordion.querySelector('.accordion-content');
|
||
header.classList.add('active');
|
||
content.classList.add('active');
|
||
content.style.maxHeight = content.scrollHeight + 'px';
|
||
}
|
||
});
|
||
});
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
// ---------- OPEN/CLOSE ----------
|
||
const modal = document.getElementById('ratingModal');
|
||
const openBtn = document.getElementById('showRatingBtn');
|
||
const closeBtn = document.getElementById('closeRatingBtn');
|
||
|
||
function openModal(e){
|
||
e.preventDefault();
|
||
document.body.style.overflow = 'hidden';
|
||
modal.style.display = 'block';
|
||
setTimeout(() => modal.classList.add('active'), 10);
|
||
|
||
if (typeof ym !== 'undefined') {
|
||
ym(105827527, 'reachGoal', 'rating_opened');
|
||
}
|
||
}
|
||
|
||
function closeModal(){
|
||
modal.classList.remove('active');
|
||
setTimeout(() => {
|
||
modal.style.display = 'none';
|
||
document.body.style.overflow = 'auto';
|
||
}, 300);
|
||
}
|
||
|
||
if (openBtn) openBtn.addEventListener('click', openModal);
|
||
if (closeBtn) closeBtn.addEventListener('click', closeModal);
|
||
if (modal) modal.addEventListener('click', (e) => { if (e.target === modal) closeModal(); });
|
||
document.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Escape' && modal && modal.style.display === 'block') closeModal();
|
||
});
|
||
|
||
// ---------- DATA (пока на фронте, потом можно заменить на API) ----------
|
||
// Оценки 0..100 (примерные заглушки). Замени на свои данные.
|
||
const universities = [
|
||
{ id:'ulgu', name:'УлГУ — Ульяновский государственный университет', type:'classic', acc:90, emp:75, rank:70, rev:78, url:'https://ulsu.ru' },
|
||
{ id:'ulstu', name:'УлГТУ — Ульяновский государственный технический университет', type:'technical', acc:88, emp:82, rank:72, rev:74, url:'https://ulstu.ru' },
|
||
{ id:'ulspu', name:'УлГПУ — Ульяновский государственный педагогический университет', type:'pedagogical', acc:86, emp:70, rank:60, rev:76, url:'https://ulspu.ru' },
|
||
{ id:'ulsau', name:'УлГАУ — Ульяновский государственный аграрный университет', type:'agro', acc:84, emp:68, rank:58, rev:72, url:'https://ulsau.ru' },
|
||
{ id:'uiga', name:'УИ ГА — Ульяновский институт гражданской авиации', type:'aviation', acc:85, emp:80, rank:65, rev:70, url:'https://uvauga.ru' },
|
||
{ id:'ranepa', name:'РАНХиГС (Ульяновский филиал)', type:'management', acc:83, emp:73, rank:62, rev:69, url:'https://ulyanovsk.ranepa.ru' },
|
||
];
|
||
|
||
// ---------- UI refs ----------
|
||
const listEl = document.getElementById('ratingList');
|
||
const countEl = document.getElementById('ratingCount');
|
||
const searchEl = document.getElementById('ratingSearch');
|
||
const sortEl = document.getElementById('ratingSort');
|
||
const minTotalEl = document.getElementById('ratingMinTotal');
|
||
const minTotalLabel = document.getElementById('ratingMinTotalLabel');
|
||
|
||
const typeEls = Array.from(document.querySelectorAll('.ratingType'));
|
||
|
||
const wAcc = document.getElementById('wAcc');
|
||
const wEmp = document.getElementById('wEmp');
|
||
const wRank = document.getElementById('wRank');
|
||
const wRev = document.getElementById('wRev');
|
||
|
||
const wAccL = document.getElementById('wAccL');
|
||
const wEmpL = document.getElementById('wEmpL');
|
||
const wRankL = document.getElementById('wRankL');
|
||
const wRevL = document.getElementById('wRevL');
|
||
|
||
const resetBtn = document.getElementById('ratingResetBtn');
|
||
|
||
function weights() {
|
||
return {
|
||
acc: Number(wAcc.value),
|
||
emp: Number(wEmp.value),
|
||
rank: Number(wRank.value),
|
||
rev: Number(wRev.value),
|
||
};
|
||
}
|
||
|
||
function calcTotal(u, w) {
|
||
const sumW = (w.acc + w.emp + w.rank + w.rev) || 1;
|
||
return Math.round(
|
||
(u.acc * w.acc + u.emp * w.emp + u.rank * w.rank + u.rev * w.rev) / sumW
|
||
);
|
||
}
|
||
|
||
function getSelectedTypes() {
|
||
return new Set(typeEls.filter(x => x.checked).map(x => x.value));
|
||
}
|
||
|
||
function render() {
|
||
const q = (searchEl.value || '').trim().toLowerCase();
|
||
const minTotal = Number(minTotalEl.value);
|
||
const selectedTypes = getSelectedTypes();
|
||
const w = weights();
|
||
|
||
// обновление лейблов
|
||
minTotalLabel.textContent = String(minTotal);
|
||
wAccL.textContent = w.acc; wEmpL.textContent = w.emp; wRankL.textContent = w.rank; wRevL.textContent = w.rev;
|
||
|
||
// фильтрация
|
||
let items = universities
|
||
.map(u => ({ ...u, total: calcTotal(u, w) }))
|
||
.filter(u => !q || u.name.toLowerCase().includes(q))
|
||
.filter(u => selectedTypes.has(u.type))
|
||
.filter(u => u.total >= minTotal);
|
||
|
||
// сортировка
|
||
const sort = sortEl.value;
|
||
const cmpNum = (k) => (a,b) => b[k] - a[k];
|
||
if (sort === 'total_desc') items.sort(cmpNum('total'));
|
||
if (sort === 'employment_desc') items.sort(cmpNum('emp'));
|
||
if (sort === 'reviews_desc') items.sort(cmpNum('rev'));
|
||
if (sort === 'accreditation_desc') items.sort(cmpNum('acc'));
|
||
if (sort === 'name_asc') items.sort((a,b) => a.name.localeCompare(b.name, 'ru'));
|
||
|
||
countEl.textContent = String(items.length);
|
||
|
||
// рендер
|
||
listEl.innerHTML = items.map((u, i) => `
|
||
<div class="university-card">
|
||
<div class="university-header">
|
||
<h3>${i+1}) ${u.name}</h3>
|
||
<div class="university-meta">
|
||
<div class="meta-item"><i class="fas fa-star"></i> Итог: <b>${u.total}</b>/100</div>
|
||
<div class="meta-item"><i class="fas fa-check-circle"></i> Аккредитация: ${u.acc}/100</div>
|
||
<div class="meta-item"><i class="fas fa-briefcase"></i> Трудоустройство: ${u.emp}/100</div>
|
||
<div class="meta-item"><i class="fas fa-trophy"></i> Рейтинги: ${u.rank}/100</div>
|
||
<div class="meta-item"><i class="fas fa-comment"></i> Отзывы: ${u.rev}/100</div>
|
||
</div>
|
||
</div>
|
||
<div class="university-body">
|
||
<div class="directions-list" style="margin-top:0;">
|
||
<div class="direction-item">Тип: ${u.type}</div>
|
||
<div class="direction-item">Весовая модель: A${w.acc}/E${w.emp}/R${w.rank}/O${w.rev}</div>
|
||
</div>
|
||
</div>
|
||
<div class="university-footer">
|
||
<a href="${u.url}" target="_blank" class="official-site">
|
||
Официальный сайт <i class="fas fa-external-link-alt"></i>
|
||
</a>
|
||
<a href="#" class="official-site ratingMoreBtn" data-id="${u.id}">
|
||
Подробнее <i class="fas fa-chevron-right"></i>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
|
||
// метрика по фильтрам (без спама: отправляем на изменение, но с лёгкой защитой)
|
||
if (typeof ym !== 'undefined') {
|
||
ym(105827527, 'reachGoal', 'rating_filtered', {
|
||
q: q ? '1' : '0',
|
||
min_total: String(minTotal),
|
||
types: Array.from(selectedTypes).join(','),
|
||
sort: sort
|
||
});
|
||
}
|
||
}
|
||
|
||
// события
|
||
[searchEl, sortEl, minTotalEl, wAcc, wEmp, wRank, wRev, ...typeEls].forEach(el => {
|
||
el.addEventListener('input', render);
|
||
el.addEventListener('change', render);
|
||
});
|
||
|
||
if (resetBtn) {
|
||
resetBtn.addEventListener('click', () => {
|
||
searchEl.value = '';
|
||
sortEl.value = 'total_desc';
|
||
minTotalEl.value = 0;
|
||
typeEls.forEach(x => x.checked = true);
|
||
wAcc.value = 20; wEmp.value = 35; wRank.value = 25; wRev.value = 20;
|
||
render();
|
||
});
|
||
}
|
||
|
||
// initial render
|
||
render();
|
||
});
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
// --- Логика фильтрации рейтинга вузов ---
|
||
const filterDirection = document.getElementById('filterDirection');
|
||
const filterDorm = document.getElementById('filterDorm');
|
||
const filterMil = document.getElementById('filterMil');
|
||
const universitiesList = document.getElementById('universitiesList');
|
||
const noResultsMsg = document.getElementById('noResultsMsg');
|
||
const ratingModal = document.getElementById('ratingModal');
|
||
const openRatingBtn = document.getElementById('showRatingModalBtn');
|
||
const closeRatingBtn = document.getElementById('closeRatingModalBtn');
|
||
|
||
// Функция фильтрации
|
||
function filterUniversities() {
|
||
if(!universitiesList) return;
|
||
|
||
const typeVal = filterDirection.value;
|
||
const needDorm = filterDorm.checked;
|
||
const needMil = filterMil.checked;
|
||
|
||
const cards = universitiesList.querySelectorAll('.university-card');
|
||
let visibleCount = 0;
|
||
|
||
cards.forEach(card => {
|
||
const types = (card.dataset.type || '').split(' ');
|
||
const hasDorm = card.dataset.dorm === 'true';
|
||
const hasMil = card.dataset.mil === 'true';
|
||
|
||
let match = true;
|
||
|
||
if (typeVal !== 'all' && !types.includes(typeVal)) {
|
||
match = false;
|
||
}
|
||
if (needDorm && !hasDorm) {
|
||
match = false;
|
||
}
|
||
if (needMil && !hasMil) {
|
||
match = false;
|
||
}
|
||
|
||
card.style.display = match ? 'block' : 'none';
|
||
if (match) visibleCount++;
|
||
});
|
||
|
||
noResultsMsg.style.display = visibleCount === 0 ? 'block' : 'none';
|
||
}
|
||
|
||
// Слушатели для фильтров
|
||
if (filterDirection) filterDirection.addEventListener('change', filterUniversities);
|
||
if (filterDorm) filterDorm.addEventListener('change', filterUniversities);
|
||
if (filterMil) filterMil.addEventListener('change', filterUniversities);
|
||
|
||
// Открытие модалки рейтинга
|
||
if (openRatingBtn) {
|
||
openRatingBtn.addEventListener('click', function(e) {
|
||
e.preventDefault();
|
||
if (typeof ym !== 'undefined') {
|
||
ym(105827527, 'reachGoal', 'rating_opened');
|
||
}
|
||
document.body.style.overflow = 'hidden';
|
||
ratingModal.style.display = 'block';
|
||
setTimeout(() => ratingModal.classList.add('active'), 10);
|
||
});
|
||
}
|
||
|
||
// Закрытие модалки
|
||
function closeRating() {
|
||
if (ratingModal) {
|
||
ratingModal.classList.remove('active');
|
||
setTimeout(() => {
|
||
ratingModal.style.display = 'none';
|
||
document.body.style.overflow = 'auto';
|
||
}, 300);
|
||
}
|
||
}
|
||
|
||
if (closeRatingBtn) closeRatingBtn.addEventListener('click', closeRating);
|
||
|
||
// Закрытие по клику на фон
|
||
if (ratingModal) {
|
||
ratingModal.addEventListener('click', (e) => {
|
||
if (e.target === ratingModal) closeRating();
|
||
});
|
||
}
|
||
|
||
// Закрытие по Escape
|
||
document.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Escape' && ratingModal && ratingModal.style.display === 'block') {
|
||
closeRating();
|
||
}
|
||
});
|
||
});
|
||
|
||
|
||
|