Files
Learn_System/frontend/js/textbook-clip.js
T
Maxim Dolgolyov 43fe90d601 feat(materials): Фаза 3 (часть 2) — источник «Учебник»
Сервер инжектит в /textbook/<slug> плавающую кнопку «В мои материалы» (js/textbook-clip.js +
material-save.js рядом с deep-link). Сохраняет текущий § как ссылку /textbook/<slug>#sec-<id>
(заголовок = название §, источник = глава). Скрыта в classroom-embed и для неавторизованных.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 12:17:08 +03:00

50 lines
2.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
/* textbook-clip.js — floating «В мои материалы» button on textbook pages.
* Injected by the server into /textbook/<slug>. Saves the currently open
* paragraph as a link (/textbook/<slug>#sec-<id>) into the student's
* personal materials. Reuses MaterialSave (material-save.js) + LS (api.js).
* Hidden inside the classroom embed (iframe) to avoid clutter. */
(function () {
if (window.parent !== window) return; // skip in classroom embed
if (!window.LS || !LS.getToken || !LS.getToken()) return; // only for logged-in users
function chapterTitle() {
return (document.title || 'Учебник').replace(/\s*[—|].*$/, '').replace(/\s*·\s*LearnSpace.*$/i, '').trim() || 'Учебник';
}
function sectionTitle() {
const h = document.querySelector('.sec.active .sec-h');
if (h && h.textContent.trim()) return h.textContent.trim();
const n = document.querySelector('.psel-card.active .psel-name');
if (n && n.textContent.trim()) return n.textContent.trim();
return (document.title || 'Тема').split('·').pop().trim() || 'Тема';
}
function activeId() {
const c = document.querySelector('.psel-card.active');
return c && c.dataset ? c.dataset.id : null;
}
function save(btn) {
if (!window.MaterialSave) { if (LS.toast) LS.toast('Модуль не загружен', 'error'); return; }
const slug = location.pathname.replace(/^\/textbook\//, '').replace(/\/+$/, '');
if (!slug) return;
const id = activeId();
const hash = id ? '#sec-' + id : (location.hash || '');
MaterialSave.link({ title: sectionTitle(), url: '/textbook/' + slug + hash, sourceTitle: chapterTitle() }, btn);
}
function build() {
if (document.getElementById('__ls_clip') || !document.body) return;
const btn = document.createElement('button');
btn.id = '__ls_clip';
btn.type = 'button';
btn.title = 'Сохранить эту тему в «Мои материалы»';
btn.innerHTML = '<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/></svg><span>В мои материалы</span>';
btn.style.cssText = 'position:fixed;right:18px;bottom:18px;z-index:9000;display:inline-flex;align-items:center;gap:7px;padding:10px 14px;border-radius:99px;border:none;background:#8b5cf6;color:#fff;font:600 13px/1 Inter,system-ui,sans-serif;cursor:pointer;box-shadow:0 6px 20px rgba(139,92,246,.4)';
btn.addEventListener('click', function () { save(btn); });
document.body.appendChild(btn);
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', function () { setTimeout(build, 300); });
else setTimeout(build, 300);
})();