@
feat(chemistry-8): Phase 2 — Глава 1 «Важнейшие классы неорг. соединений» (§10–23) Полная глава на движке (14 § + 2 лаб. опыта + 2 практические работы + финал-босс): - §10–12 оксиды (классификатор, свойства, получение) - §13–15 кислоты (классификатор, ряд активности, индикаторы, получение) - §16–18 основания (классификатор, фенолфталеин, Лаб.1 Cu(OH)₂↓, ПР2 нейтрализация) - §19–21 соли (таблица растворимости, РИО, соль+металл, Лаб.2, способы) - §22 генетическая связь классов + ПР3; §23 расчётный решатель; финал-босс (6 задач) - POOLS: ~45 задач (MCQ + числовые), шпаргалки и подсказки по каждому § chem8_svg.js: реализованы 5 хим-виджетов (были заглушки) — testTube (осадок/газ), indicatorScale (лакмус/фенолфталеин/метилоранж + pH), classifier (клик-DnD), solubilityTable (катион×анион), activitySeries (ряд активности металлов). chem8-textbook.css: стили виджетов. chem8_ch1_widgets.js: монтаж по §. Тесты: 24/24 (юнит + jsdom-виджеты + полностраничный SPA intro и ch1 — para-selector, активный §, монтаж флагманов, тренажёр, без ошибок). Ассеты 200. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> @
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
/*
|
||||
* Полностраничная jsdom-проверка chemistry_8_intro.html (SPA на chem8_engine.js):
|
||||
* выполняем реальный HTML + движок + виджеты, даём таймерам отработать, проверяем,
|
||||
* что para-selector построен, первый § активен и виджеты смонтированы — без ошибок.
|
||||
* Полностраничная jsdom-проверка глав «Химия 8» (SPA на chem8_engine.js):
|
||||
* выполняем реальный HTML + движок + виджеты, даём таймерам отработать, проверяем
|
||||
* para-selector, активный §, монтаж виджетов — без ошибок скриптов.
|
||||
*/
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert');
|
||||
@@ -14,70 +14,70 @@ const ROOT = path.join(__dirname, '..', '..');
|
||||
const readF = p => fs.readFileSync(path.join(ROOT, p), 'utf8');
|
||||
const wait = ms => new Promise(r => setTimeout(r, ms));
|
||||
|
||||
function buildPage() {
|
||||
let html = readF('frontend/textbooks/chemistry_8_intro.html');
|
||||
function buildPage(file, widgetsSrc) {
|
||||
let html = readF('frontend/textbooks/' + file);
|
||||
const inl = {
|
||||
'/js/biochem-core.js': readF('frontend/js/biochem-core.js'),
|
||||
'/js/chem8_svg.js': readF('frontend/js/chem8_svg.js'),
|
||||
'/js/chem8_intro_widgets.js': readF('frontend/js/chem8_intro_widgets.js'),
|
||||
[widgetsSrc]: readF('frontend/js' + widgetsSrc.replace('/js', '')),
|
||||
'/js/chem8_engine.js': readF('frontend/js/chem8_engine.js')
|
||||
};
|
||||
// CDN katex → удалить; api/xp → стабы (LS отсутствует, renderMathInElement — no-op)
|
||||
html = html
|
||||
.replace(/<script defer src="https:\/\/cdn[^"]*"[^>]*><\/script>/g, '')
|
||||
.replace(/<script src="\/js\/api\.js" defer><\/script>/, '<script>window.renderMathInElement=function(){};</script>')
|
||||
.replace(/<script src="\/js\/xp\.js" defer><\/script>/, '');
|
||||
Object.keys(inl).forEach(src => {
|
||||
// функция-замена: иначе $-последовательности в коде ломают вставку
|
||||
html = html.replace(new RegExp('<script src="' + src + '" defer><\\/script>'), () => '<script>\n' + inl[src] + '\n</script>');
|
||||
});
|
||||
return html;
|
||||
}
|
||||
|
||||
async function loadDom() {
|
||||
async function loadDom(file, widgetsSrc) {
|
||||
const errors = [];
|
||||
const vc = new VirtualConsole();
|
||||
vc.on('jsdomError', e => errors.push(e.message));
|
||||
const dom = new JSDOM(buildPage(), {
|
||||
const dom = new JSDOM(buildPage(file, widgetsSrc), {
|
||||
runScripts: 'dangerously', pretendToBeVisual: true, virtualConsole: vc, url: 'http://localhost/',
|
||||
beforeParse(w) { w.scrollTo = function () {}; } // jsdom не реализует scrollTo (в браузере есть)
|
||||
beforeParse(w) { w.scrollTo = function () {}; }
|
||||
});
|
||||
await wait(180); // дать отработать таймерам сборки § и монтажа виджетов (40–50 мс)
|
||||
await wait(180);
|
||||
return { dom, errors, doc: dom.window.document };
|
||||
}
|
||||
|
||||
test('страница SPA выполняется без ошибок скриптов', async () => {
|
||||
const { errors } = await loadDom();
|
||||
assert.deepEqual(errors, [], 'нет jsdomError: ' + errors.join(' | '));
|
||||
});
|
||||
|
||||
test('para-selector построен (11 карточек) и первый § активен', async () => {
|
||||
const { doc } = await loadDom();
|
||||
assert.equal(doc.querySelectorAll('#psel-grid .psel-card').length, 11, '11 карточек §');
|
||||
const active = doc.querySelector('.sec.active');
|
||||
assert.ok(active && active.id === 'sec-p1', 'активен §1');
|
||||
assert.ok(doc.querySelector('#p1-body .para-hero'), 'para-hero §1 построен');
|
||||
});
|
||||
|
||||
test('виджеты § смонтированы движком', async () => {
|
||||
const { doc } = await loadDom();
|
||||
assert.ok(doc.querySelectorAll('#p1-el .el-cell').length > 10, 'карта элементов §1');
|
||||
// перейдём на §6 и §8 через goTo, дождёмся монтажа флагманов
|
||||
/* ── Вводный раздел ── */
|
||||
test('intro: SPA без ошибок, 11 карточек, §1 активен, виджеты', async () => {
|
||||
const { doc, errors } = await loadDom('chemistry_8_intro.html', '/js/chem8_intro_widgets.js');
|
||||
assert.deepEqual(errors, [], 'нет ошибок: ' + errors.join(' | '));
|
||||
assert.equal(doc.querySelectorAll('#psel-grid .psel-card').length, 11, '11 карточек');
|
||||
assert.ok(doc.querySelector('.sec.active') && doc.querySelector('.sec.active').id === 'sec-p1', '§1 активен');
|
||||
assert.ok(doc.querySelectorAll('#p1-el .el-cell').length > 10, 'карта элементов');
|
||||
doc.defaultView.goTo('p6'); await wait(120);
|
||||
assert.ok(doc.querySelector('#p6-mount .mtri'), 'треугольник §6');
|
||||
doc.defaultView.goTo('p8'); await wait(120);
|
||||
assert.ok(doc.querySelector('#p8-mount .ceqb'), 'балансировщик §8');
|
||||
});
|
||||
|
||||
test('тренажёр задач отрисован для §2 (POOLS)', async () => {
|
||||
const { doc } = await loadDom();
|
||||
doc.defaultView.goTo('p2'); await wait(150);
|
||||
assert.ok(doc.querySelector('#taskArea p2, #taskAreap2'), 'область задач §2');
|
||||
assert.ok(doc.querySelectorAll('#navDotsp2 .nav-dot').length >= 4, 'навигация по задачам §2');
|
||||
/* ── Глава 1 ── */
|
||||
test('ch1: SPA без ошибок, 15 карточек, §10 активен', async () => {
|
||||
const { doc, errors } = await loadDom('chemistry_8_ch1.html', '/js/chem8_ch1_widgets.js');
|
||||
assert.deepEqual(errors, [], 'нет ошибок: ' + errors.join(' | '));
|
||||
assert.equal(doc.querySelectorAll('#psel-grid .psel-card').length, 15, '14 § + финал');
|
||||
assert.ok(doc.querySelector('.sec.active') && doc.querySelector('.sec.active').id === 'sec-p10', '§10 активен');
|
||||
assert.ok(doc.querySelector('#p10-body .para-hero'), 'para-hero §10');
|
||||
});
|
||||
|
||||
test('Chem8 доступен и считает Mr', async () => {
|
||||
const { dom } = await loadDom();
|
||||
assert.ok(dom.window.Chem8, 'window.Chem8 определён');
|
||||
assert.equal(dom.window.Chem8.molarMass('CaCO3'), 100);
|
||||
test('ch1: флагман-виджеты монтируются (классификатор, растворимость, ряд активности)', async () => {
|
||||
const { doc } = await loadDom('chemistry_8_ch1.html', '/js/chem8_ch1_widgets.js');
|
||||
doc.defaultView.goTo('p10'); await wait(120);
|
||||
assert.ok(doc.querySelector('#c-ox-cls .cls-chip'), 'классификатор оксидов §10');
|
||||
doc.defaultView.goTo('p13'); await wait(120);
|
||||
assert.ok(doc.querySelector('#c-acid-ind .ind-strip'), 'индикатор §13');
|
||||
doc.defaultView.goTo('p19'); await wait(120);
|
||||
assert.ok(doc.querySelector('#c-salt-sol .sol-tab'), 'таблица растворимости §19');
|
||||
doc.defaultView.goTo('p14'); await wait(120);
|
||||
assert.ok(doc.querySelector('#c-acid-act .act-cell'), 'ряд активности §14');
|
||||
});
|
||||
|
||||
test('ch1: тренажёр задач отрисован для §10', async () => {
|
||||
const { doc } = await loadDom('chemistry_8_ch1.html', '/js/chem8_ch1_widgets.js');
|
||||
await wait(150);
|
||||
assert.ok(doc.querySelectorAll('#navDotsp10 .nav-dot').length >= 4, 'навигация по задачам §10');
|
||||
});
|
||||
|
||||
@@ -64,13 +64,20 @@ test('Chem8.elementCounts — скобки и индексы', () => {
|
||||
assert.deepEqual(C.elementCounts('CO2'), { C: 1, O: 2 });
|
||||
});
|
||||
|
||||
test('Chem8 — заглушки возвращают null и не падают', () => {
|
||||
for (const fn of ['testTube', 'solubilityTable', 'oxStateCalc', 'geneticMap']) {
|
||||
test('Chem8 — оставшиеся заглушки возвращают null и не падают', () => {
|
||||
for (const fn of ['oxStateCalc', 'redoxBalancer', 'orbitalDiagram', 'miniPeriodic', 'dissociationAnim', 'geneticMap']) {
|
||||
assert.equal(typeof C[fn], 'function', fn + ' определён');
|
||||
assert.equal(C[fn]({}), null, fn + ' заглушка возвращает null');
|
||||
}
|
||||
});
|
||||
|
||||
test('Chem8 — Phase 2 виджеты экспортированы как функции', () => {
|
||||
for (const fn of ['testTube', 'indicatorScale', 'classifier', 'solubilityTable', 'activitySeries']) {
|
||||
assert.equal(typeof C[fn], 'function', fn + ' реализован');
|
||||
}
|
||||
assert.ok(C.testTube({ precipitate: '#88c' }).includes('<svg'), 'testTube → SVG');
|
||||
});
|
||||
|
||||
test('Chem8 — движки расчётов экспортированы как функции', () => {
|
||||
for (const fn of ['moleTriangle', 'equationBalancer']) {
|
||||
assert.equal(typeof C[fn], 'function', fn + ' определён');
|
||||
@@ -106,10 +113,10 @@ test('каждая глава существует, ссылается на ха
|
||||
const html = fs.readFileSync(path.join(TB, ch.file), 'utf8');
|
||||
assert.ok(html.includes('/textbook/chemistry-8"'), ch.file + ' ссылка назад в хаб');
|
||||
assert.ok(html.includes('/js/chem8_svg.js'), ch.file + ' подключает chem8_svg');
|
||||
if (ch.slug === 'chemistry-8-intro') {
|
||||
// intro перестроен на движок (SPA): slug задаётся через CHEM8_CFG
|
||||
assert.ok(html.includes("slug:'chemistry-8-intro'"), 'intro slug в CHEM8_CFG');
|
||||
assert.ok(html.includes('/js/chem8_engine.js'), 'intro подключает движок');
|
||||
if (ch.slug === 'chemistry-8-intro' || ch.slug === 'chemistry-8-ch1') {
|
||||
// перестроены на движок (SPA): slug задаётся через CHEM8_CFG
|
||||
assert.ok(html.includes("slug:'" + ch.slug + "'"), ch.file + ' slug в CHEM8_CFG');
|
||||
assert.ok(html.includes('/js/chem8_engine.js'), ch.file + ' подключает движок');
|
||||
} else {
|
||||
assert.ok(html.includes("const _TB_SLUG = '" + ch.slug + "'"), ch.file + ' slug (каркас)');
|
||||
}
|
||||
@@ -130,6 +137,19 @@ test('Phase 1 — раздел intro перестроен на движок (SPA
|
||||
assert.ok(!html.includes('Раздел в разработке'), 'баннер-заглушка убран');
|
||||
});
|
||||
|
||||
test('Phase 2 — Глава 1 построена на движке (§10–23 + лаб/ПР + финал)', () => {
|
||||
const html = fs.readFileSync(path.join(TB, 'chemistry_8_ch1.html'), 'utf8');
|
||||
assert.ok(html.includes('id="psel-grid"'), 'para-selector');
|
||||
for (let i = 10; i <= 23; i++) assert.ok(html.includes('id="sec-p' + i + '"'), '§' + i + ' секция');
|
||||
assert.ok(html.includes('id="sec-final1"'), 'финал');
|
||||
assert.ok(html.includes('id="c-ox-cls"'), 'классификатор оксидов');
|
||||
assert.ok(html.includes('id="c-salt-sol"'), 'таблица растворимости');
|
||||
assert.ok(html.includes('Лабораторный опыт 1'), 'Лаб.1');
|
||||
assert.ok(html.includes('Практическая работа 2'), 'ПР2');
|
||||
assert.ok(html.includes('/js/chem8_ch1_widgets.js'), 'виджеты главы');
|
||||
assert.ok(!html.includes('Раздел в разработке'), 'заглушка убрана');
|
||||
});
|
||||
|
||||
test('chem8_engine.js и виджеты — валидный синтаксис', () => {
|
||||
const eng = fs.readFileSync(path.join(ROOT, 'frontend', 'js', 'chem8_engine.js'), 'utf8');
|
||||
const wid = fs.readFileSync(path.join(ROOT, 'frontend', 'js', 'chem8_intro_widgets.js'), 'utf8');
|
||||
|
||||
@@ -297,6 +297,51 @@ html.dark .el-cell .s{color:var(--pri-l)}
|
||||
.drop-box h5{font-size:.8rem;font-weight:800;margin-bottom:8px;text-align:center;color:var(--pri-d)}
|
||||
html.dark .drop-box h5{color:var(--pri-l)}
|
||||
|
||||
/* testTube */
|
||||
.tt-svg{color:var(--pri);vertical-align:bottom}
|
||||
.tt-row{display:flex;gap:18px;flex-wrap:wrap;align-items:flex-end;margin:10px 0}
|
||||
.tt-cap{font-size:.84rem;color:var(--muted);text-align:center;max-width:120px}
|
||||
|
||||
/* indicatorScale */
|
||||
.ind-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:10px}
|
||||
.ind-row label{font-size:.85rem;font-weight:600;color:var(--muted)}
|
||||
.ind-strip{height:42px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:.92rem;border:1px solid var(--border);transition:background .25s}
|
||||
.ind-label{margin-top:8px;font-size:.9rem}
|
||||
.ind-label b{color:var(--pri-d)}html.dark .ind-label b{color:var(--pri-l)}
|
||||
|
||||
/* classifier */
|
||||
.cls-chip.on{border-color:var(--pri);box-shadow:0 0 0 3px var(--pri-soft)}
|
||||
.cls-chip.cls-ok{background:var(--ok-bg);border-color:var(--ok);color:var(--ok)}
|
||||
.cls-chip.cls-bad{background:var(--fail-bg);border-color:var(--fail);color:var(--fail)}
|
||||
.cls-items{display:flex;flex-wrap:wrap;gap:6px;min-height:24px}
|
||||
|
||||
/* solubilityTable */
|
||||
.sol-wrap{overflow-x:auto}
|
||||
.sol-tab{border-collapse:collapse;font-size:.78rem;font-family:var(--mono);min-width:520px}
|
||||
.sol-tab th,.sol-tab td{border:1px solid var(--border);padding:4px 6px;text-align:center;cursor:pointer}
|
||||
.sol-tab thead th{background:var(--card-soft);font-weight:800}
|
||||
.sol-tab th[data-an]{background:var(--card-soft);font-weight:800}
|
||||
.sol-tab td.sP{background:rgba(37,99,235,.12);color:#1d4ed8}
|
||||
.sol-tab td.sM{background:rgba(245,158,11,.18);color:#b45309}
|
||||
.sol-tab td.sH{background:rgba(220,38,38,.14);color:#b91c1c}
|
||||
.sol-tab td.sX{background:rgba(120,120,120,.12);color:var(--muted)}
|
||||
.sol-tab td.sol-dim,.sol-tab th.sol-dim{opacity:.3}
|
||||
.sol-tab td.sol-hot{outline:3px solid var(--pri);outline-offset:-3px;font-weight:900}
|
||||
.sol-out{margin-top:10px}
|
||||
|
||||
/* activitySeries */
|
||||
.act-row{display:flex;flex-wrap:wrap;gap:4px;align-items:center}
|
||||
.act-cell{font-family:var(--mono);font-weight:800;font-size:.82rem;padding:7px 9px;border:1.5px solid var(--border);border-radius:8px;background:var(--card);color:var(--text);cursor:pointer;transition:.12s}
|
||||
.act-cell:hover{border-color:var(--pri)}
|
||||
.act-cell.act-h{background:var(--card-soft);color:var(--muted);cursor:default;font-size:.74rem}
|
||||
.act-cell.act-on{background:var(--pri);border-color:var(--pri);color:#fff}
|
||||
.act-cell.act-disp{background:var(--ok-bg);border-color:var(--ok);color:var(--ok)}
|
||||
.act-axis{display:flex;justify-content:space-between;font-size:.72rem;color:var(--muted);margin:6px 2px}
|
||||
.act-out{margin-top:8px}
|
||||
|
||||
/* exa-step (разбор примеров) */
|
||||
.exa-step{font-family:var(--mono);font-size:.9rem;background:var(--card-soft);border-left:3px solid var(--pri);border-radius:0 8px 8px 0;padding:8px 12px;margin:6px 0}
|
||||
|
||||
/* FOOTER + popup */
|
||||
.foot{text-align:center;padding:24px 16px;color:var(--muted);font-size:.78rem;border-top:1px solid var(--border)}
|
||||
.ach-popup{position:fixed;bottom:22px;left:50%;transform:translateX(-50%) translateY(130px);background:var(--card);border:1.5px solid var(--pri);color:var(--text);padding:12px 20px;border-radius:13px;font-weight:700;box-shadow:var(--sh2);z-index:60;transition:transform .35s;display:flex;align-items:center;gap:10px;font-size:.9rem;max-width:90vw}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/* chem8_ch1_widgets.js — виджеты Главы 1 «Важнейшие классы неорганических соединений».
|
||||
* Монтируются движком: window.CHEM8_WIDGETS[id] / window.FLAG_MOUNTS[id].
|
||||
* Используют window.Chem8: classifier, indicatorScale, solubilityTable, activitySeries.
|
||||
*/
|
||||
(function (W) {
|
||||
'use strict';
|
||||
function C() { return W.Chem8 || {}; }
|
||||
function $(id) { return document.getElementById(id); }
|
||||
function xp(n, s) { try { if (W.addXp) W.addXp(n, s); } catch (e) {} }
|
||||
|
||||
/* §10 — классификатор оксидов */
|
||||
function mount_p10() {
|
||||
var el = $('c-ox-cls'); if (!el || el._b || !C().classifier) return; el._b = 1;
|
||||
C().classifier(el, {
|
||||
items: [
|
||||
{ id: 'Na2O', label: 'Na₂O', cat: 'осн' }, { id: 'CaO', label: 'CaO', cat: 'осн' },
|
||||
{ id: 'CO2', label: 'CO₂', cat: 'кисл' }, { id: 'SO3', label: 'SO₃', cat: 'кисл' }, { id: 'P2O5', label: 'P₂O₅', cat: 'кисл' },
|
||||
{ id: 'ZnO', label: 'ZnO', cat: 'амф' }, { id: 'Al2O3', label: 'Al₂O₃', cat: 'амф' },
|
||||
{ id: 'CO', label: 'CO', cat: 'несол' }, { id: 'N2O', label: 'N₂O', cat: 'несол' }
|
||||
],
|
||||
buckets: [{ cat: 'осн', label: 'Основные' }, { cat: 'кисл', label: 'Кислотные' }, { cat: 'амф', label: 'Амфотерные' }, { cat: 'несол', label: 'Несолеобразующие' }],
|
||||
onCheck: function (ok) { if (ok) xp(8, 'p10-cls'); }
|
||||
});
|
||||
}
|
||||
|
||||
/* §13 — классификатор кислот + индикатор */
|
||||
function mount_p13() {
|
||||
var cls = $('c-acid-cls');
|
||||
if (cls && !cls._b && C().classifier) { cls._b = 1; C().classifier(cls, {
|
||||
items: [
|
||||
{ id: 'HCl', label: 'HCl', cat: 'без' }, { id: 'H2S', label: 'H₂S', cat: 'без' }, { id: 'HBr', label: 'HBr', cat: 'без' },
|
||||
{ id: 'H2SO4', label: 'H₂SO₄', cat: 'кисл' }, { id: 'HNO3', label: 'HNO₃', cat: 'кисл' }, { id: 'H3PO4', label: 'H₃PO₄', cat: 'кисл' }
|
||||
],
|
||||
buckets: [{ cat: 'без', label: 'Бескислородные' }, { cat: 'кисл', label: 'Кислородсодержащие' }],
|
||||
onCheck: function (ok) { if (ok) xp(8, 'p13-cls'); }
|
||||
}); }
|
||||
var ind = $('c-acid-ind'); if (ind && !ind._b && C().indicatorScale) { ind._b = 1; C().indicatorScale(ind, { indicator: 'лакмус', ph: 2 }); }
|
||||
}
|
||||
|
||||
/* §14 — ряд активности + индикатор */
|
||||
function mount_p14() {
|
||||
var act = $('c-acid-act'); if (act && !act._b && C().activitySeries) { act._b = 1; C().activitySeries(act, {}); }
|
||||
var ind = $('c-acid-ind2'); if (ind && !ind._b && C().indicatorScale) { ind._b = 1; C().indicatorScale(ind, { indicator: 'метилоранж', ph: 2 }); }
|
||||
}
|
||||
|
||||
/* §16 — классификатор оснований + индикатор (фенолфталеин) */
|
||||
function mount_p16() {
|
||||
var cls = $('c-base-cls');
|
||||
if (cls && !cls._b && C().classifier) { cls._b = 1; C().classifier(cls, {
|
||||
items: [
|
||||
{ id: 'NaOH', label: 'NaOH', cat: 'щел' }, { id: 'KOH', label: 'KOH', cat: 'щел' }, { id: 'BaOH', label: 'Ba(OH)₂', cat: 'щел' },
|
||||
{ id: 'CuOH', label: 'Cu(OH)₂', cat: 'нер' }, { id: 'FeOH', label: 'Fe(OH)₃', cat: 'нер' }, { id: 'MgOH', label: 'Mg(OH)₂', cat: 'нер' }
|
||||
],
|
||||
buckets: [{ cat: 'щел', label: 'Щёлочи (растворимые)' }, { cat: 'нер', label: 'Нерастворимые' }],
|
||||
onCheck: function (ok) { if (ok) xp(8, 'p16-cls'); }
|
||||
}); }
|
||||
var ind = $('c-base-ind'); if (ind && !ind._b && C().indicatorScale) { ind._b = 1; C().indicatorScale(ind, { indicator: 'фенолфталеин', ph: 12 }); }
|
||||
}
|
||||
|
||||
/* §17 — индикатор нейтрализации */
|
||||
function mount_p17() { var ind = $('c-neutral-ind'); if (ind && !ind._b && C().indicatorScale) { ind._b = 1; C().indicatorScale(ind, { indicator: 'фенолфталеин', ph: 12 }); } }
|
||||
|
||||
/* §18 — индикатор (ПР2 нейтрализация) */
|
||||
function mount_p18() { var ind = $('c-pr2-ind'); if (ind && !ind._b && C().indicatorScale) { ind._b = 1; C().indicatorScale(ind, { indicator: 'лакмус', ph: 7 }); } }
|
||||
|
||||
/* §19 — таблица растворимости */
|
||||
function mount_p19() { var s = $('c-salt-sol'); if (s && !s._b && C().solubilityTable) { s._b = 1; C().solubilityTable(s, {}); } }
|
||||
|
||||
/* §20 — растворимость + ряд активности (соль + металл) */
|
||||
function mount_p20() {
|
||||
var s = $('c-salt-sol2'); if (s && !s._b && C().solubilityTable) { s._b = 1; C().solubilityTable(s, {}); }
|
||||
var a = $('c-salt-act'); if (a && !a._b && C().activitySeries) { a._b = 1; C().activitySeries(a, {}); }
|
||||
}
|
||||
|
||||
/* §23 — пошаговый решатель расчётных задач по классам */
|
||||
var ST = [
|
||||
{ eq: 'CaO + 2HCl → CaCl₂ + H₂O', given: 'Дано: m(CaO) = 28 г. Найти m(CaCl₂). M(CaO)=56, M(CaCl₂)=111.',
|
||||
steps: ['n(CaO) = m/M = 28/56 = 0,5 моль.', 'n(CaO):n(CaCl₂) = 1:1 → n(CaCl₂)=0,5 моль.', 'm(CaCl₂) = n·M = 0,5·111 = 55,5 г. Ответ: 55,5 г.'] },
|
||||
{ eq: 'Zn + H₂SO₄ → ZnSO₄ + H₂↑', given: 'Дано: n(Zn) = 2 моль. Найти V(H₂) при н.у.',
|
||||
steps: ['n(Zn):n(H₂) = 1:1 → n(H₂)=2 моль.', 'V(H₂) = n·Vm = 2·22,4 = 44,8 л. Ответ: 44,8 л.'] },
|
||||
{ eq: '2NaOH + H₂SO₄ → Na₂SO₄ + 2H₂O', given: 'Дано: n(H₂SO₄) = 0,5 моль. Найти n(NaOH).',
|
||||
steps: ['n(NaOH):n(H₂SO₄) = 2:1 → n(NaOH)=2·0,5=1 моль.', 'Ответ: 1 моль NaOH.'] }
|
||||
];
|
||||
function mount_p23() {
|
||||
var pick = $('c-calc-pick'), out = $('c-calc-out'), bStep = $('c-calc-step'), bAll = $('c-calc-all'); if (!pick || pick._b) return; pick._b = 1;
|
||||
ST.forEach(function (p, i) { var o = document.createElement('option'); o.value = i; o.textContent = p.eq; pick.appendChild(o); });
|
||||
var cur = 0, shown = 0;
|
||||
function render() {
|
||||
var p = ST[cur];
|
||||
var html = '<b>' + p.eq + '</b><br><span style="color:var(--muted)">' + p.given + '</span><div style="margin-top:8px">';
|
||||
for (var i = 0; i < shown; i++) html += '<div class="def-box" style="margin:6px 0">' + p.steps[i] + '</div>';
|
||||
if (shown === 0) html += '<span style="color:var(--muted)">Нажмите «Следующий шаг».</span>';
|
||||
html += '</div>'; out.className = shown >= p.steps.length ? 'out ok' : 'out'; out.innerHTML = html;
|
||||
}
|
||||
pick.addEventListener('change', function () { cur = +pick.value; shown = 0; render(); });
|
||||
bStep.addEventListener('click', function () { if (shown < ST[cur].steps.length) { shown++; render(); } });
|
||||
bAll.addEventListener('click', function () { shown = ST[cur].steps.length; render(); });
|
||||
render();
|
||||
}
|
||||
|
||||
W.CHEM8_WIDGETS = { p13: mount_p13, p16: mount_p16, p17: mount_p17, p18: mount_p18 };
|
||||
W.FLAG_MOUNTS = { p10: mount_p10, p14: mount_p14, p19: mount_p19, p20: mount_p20, p23: mount_p23 };
|
||||
})(window);
|
||||
+213
-7
@@ -350,6 +350,211 @@
|
||||
});
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────────────────────────────
|
||||
testTube(opts) -> SVG-строка пробирки. opts: {fill, color, precipitate, gas,
|
||||
label}. fill/color — цвет раствора; precipitate — цвет осадка на дне;
|
||||
gas:true — пузырьки; label — подпись под пробиркой.
|
||||
────────────────────────────────────────────────────────────────────────── */
|
||||
function testTube(opts) {
|
||||
opts = opts || {};
|
||||
var liq = opts.color || opts.fill || '#dbeafe';
|
||||
var prec = opts.precipitate || null;
|
||||
var gas = !!opts.gas;
|
||||
var bubbles = '';
|
||||
if (gas) for (var i = 0; i < 5; i++) {
|
||||
var cx = 26 + (i % 3) * 7, cy = 60 - i * 8;
|
||||
bubbles += '<circle cx="' + cx + '" cy="' + cy + '" r="' + (1.6 + (i % 2)) + '" fill="rgba(255,255,255,.75)"><animate attributeName="cy" from="78" to="20" dur="' + (1.4 + i * .2) + 's" repeatCount="indefinite"/></circle>';
|
||||
}
|
||||
var precSvg = prec ? '<path d="M20 78 q12 7 24 0 l-2 6 q-10 5 -20 0 z" fill="' + prec + '"/>' : '';
|
||||
return '<svg class="tt-svg" viewBox="0 0 64 110" width="56" height="96">'
|
||||
+ '<defs><clipPath id="ttclip"><path d="M20 14 v60 a12 12 0 0 0 24 0 v-60"/></clipPath></defs>'
|
||||
+ '<rect x="20" y="38" width="24" height="46" fill="' + liq + '" clip-path="url(#ttclip)" opacity=".85"/>'
|
||||
+ precSvg
|
||||
+ '<g clip-path="url(#ttclip)">' + bubbles + '</g>'
|
||||
+ '<path d="M20 12 v62 a12 12 0 0 0 24 0 v-62" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/>'
|
||||
+ '<line x1="17" y1="12" x2="47" y2="12" stroke="currentColor" stroke-width="3" stroke-linecap="round"/>'
|
||||
+ (opts.label ? '<text x="32" y="104" text-anchor="middle" font-size="10" font-weight="700" fill="currentColor">' + escapeHtml(opts.label) + '</text>' : '')
|
||||
+ '</svg>';
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────────────────────────────
|
||||
indicatorScale(mount, opts) — индикатор + шкала pH. Слайдер pH 0–14,
|
||||
выбор индикатора (лакмус/фенолфталеин/метилоранж), окраска полоски.
|
||||
────────────────────────────────────────────────────────────────────────── */
|
||||
var INDICATORS = {
|
||||
'лакмус': function (ph) { return ph < 5 ? ['#dc2626', 'красный (кислота)'] : ph > 8 ? ['#2563eb', 'синий (щёлочь)'] : ['#7c3aed', 'фиолетовый (нейтр.)']; },
|
||||
'фенолфталеин': function (ph) { return ph >= 8.2 ? ['#db2777', 'малиновый (щёлочь)'] : ['#f8fafc', 'бесцветный']; },
|
||||
'метилоранж': function (ph) { return ph < 3.1 ? ['#dc2626', 'красный (кислота)'] : ph > 4.4 ? ['#f59e0b', 'жёлтый'] : ['#fb923c', 'оранжевый']; }
|
||||
};
|
||||
function indicatorScale(mount, opts) {
|
||||
var host = typeof mount === 'string' ? global.document.querySelector(mount) : mount;
|
||||
if (!host) return null;
|
||||
opts = opts || {};
|
||||
var inds = Object.keys(INDICATORS);
|
||||
host.innerHTML =
|
||||
'<div class="ind-row"><label>Индикатор</label><select class="ind-sel">' +
|
||||
inds.map(function (n) { return '<option value="' + n + '"' + (n === opts.indicator ? ' selected' : '') + '>' + n + '</option>'; }).join('') +
|
||||
'</select><label>pH</label><input type="range" class="ind-ph" min="0" max="14" step="0.5" value="' + (opts.ph != null ? opts.ph : 7) + '"><span class="ind-phv bd"></span></div>' +
|
||||
'<div class="ind-strip"></div><div class="ind-label"></div>';
|
||||
var sel = host.querySelector('.ind-sel'), ph = host.querySelector('.ind-ph'),
|
||||
phv = host.querySelector('.ind-phv'), strip = host.querySelector('.ind-strip'), lab = host.querySelector('.ind-label');
|
||||
function upd() {
|
||||
var v = parseFloat(ph.value), pair = INDICATORS[sel.value](v);
|
||||
phv.textContent = 'pH ' + String(v).replace('.', ',');
|
||||
strip.style.background = pair[0];
|
||||
strip.style.color = (pair[0] === '#f8fafc' || pair[0] === '#f59e0b') ? '#1c1917' : '#fff';
|
||||
strip.textContent = pair[1];
|
||||
lab.innerHTML = 'Среда: <b>' + (v < 7 ? 'кислая' : v > 7 ? 'щелочная' : 'нейтральная') + '</b> · ' + sel.value + ' → ' + pair[1];
|
||||
}
|
||||
sel.addEventListener('change', upd); ph.addEventListener('input', upd); upd();
|
||||
return { el: host };
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────────────────────────────
|
||||
classifier(mount, {items, buckets, onCheck}) — клик-классификатор (DnD без drag).
|
||||
items: [{id,label,cat}]; buckets: [{cat,label}]. Клик по чипу → выбран; клик
|
||||
по корзине → положить. «Проверить» подсвечивает верно/неверно. +XP по onCheck.
|
||||
────────────────────────────────────────────────────────────────────────── */
|
||||
function classifier(mount, opts) {
|
||||
var host = typeof mount === 'string' ? global.document.querySelector(mount) : mount;
|
||||
if (!host) return null;
|
||||
opts = opts || {}; var items = opts.items || [], buckets = opts.buckets || [];
|
||||
var placed = {}; // id -> cat
|
||||
var sel = null;
|
||||
host.innerHTML =
|
||||
'<div class="cls-pool dnd-pool">' + items.map(function (it) {
|
||||
return '<button class="dnd-chip cls-chip" data-id="' + it.id + '">' + it.label + '</button>';
|
||||
}).join('') + '</div>' +
|
||||
'<div class="dnd-zones">' + buckets.map(function (b) {
|
||||
return '<div class="drop-box cls-zone" data-cat="' + b.cat + '"><h5>' + b.label + '</h5><div class="cls-items"></div></div>';
|
||||
}).join('') + '</div>' +
|
||||
'<div class="ceqb-actions" style="margin-top:10px"><button class="ceqb-btn primary cls-check">Проверить</button><button class="ceqb-btn cls-reset">Сброс</button></div>' +
|
||||
'<div class="out cls-out" style="display:none"></div>';
|
||||
var out = host.querySelector('.cls-out');
|
||||
function findItem(id) { return items.filter(function (x) { return x.id === id; })[0]; }
|
||||
function selectChip(chip) {
|
||||
if (sel) sel.classList.remove('on'); sel = chip; chip.classList.add('on');
|
||||
}
|
||||
host.querySelectorAll('.cls-chip').forEach(function (chip) {
|
||||
chip.addEventListener('click', function () { selectChip(chip); });
|
||||
});
|
||||
host.querySelectorAll('.cls-zone').forEach(function (zone) {
|
||||
zone.addEventListener('click', function () {
|
||||
if (!sel) return;
|
||||
var id = sel.getAttribute('data-id');
|
||||
placed[id] = zone.getAttribute('data-cat');
|
||||
zone.querySelector('.cls-items').appendChild(sel);
|
||||
sel.classList.remove('on'); sel.classList.add('placed'); sel = null;
|
||||
});
|
||||
});
|
||||
host.querySelector('.cls-check').addEventListener('click', function () {
|
||||
var ok = 0, total = items.length;
|
||||
items.forEach(function (it) {
|
||||
var chip = host.querySelector('.cls-chip[data-id="' + it.id + '"]');
|
||||
var correct = placed[it.id] === it.cat;
|
||||
chip.classList.remove('cls-ok', 'cls-bad');
|
||||
chip.classList.add(correct ? 'cls-ok' : 'cls-bad');
|
||||
if (correct) ok++;
|
||||
});
|
||||
out.style.display = 'block';
|
||||
out.className = 'out cls-out ' + (ok === total ? 'ok' : 'bad');
|
||||
out.textContent = 'Верно: ' + ok + ' из ' + total + (ok === total ? '. Отлично!' : '. Исправь выделенные.');
|
||||
if (typeof opts.onCheck === 'function') opts.onCheck(ok === total, ok, total);
|
||||
});
|
||||
host.querySelector('.cls-reset').addEventListener('click', function () {
|
||||
placed = {}; sel = null;
|
||||
var pool = host.querySelector('.cls-pool');
|
||||
host.querySelectorAll('.cls-chip').forEach(function (c) { c.classList.remove('placed', 'on', 'cls-ok', 'cls-bad'); pool.appendChild(c); });
|
||||
out.style.display = 'none';
|
||||
});
|
||||
return { el: host, result: function () { return placed; } };
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────────────────────────────
|
||||
solubilityTable(mount, opts) — таблица растворимости (катион×анион).
|
||||
Клик по катиону и аниону → подсветка ячейки + вердикт (Р/М/Н/—).
|
||||
────────────────────────────────────────────────────────────────────────── */
|
||||
var SOL_ANIONS = ['OH', 'Cl', 'NO3', 'SO4', 'CO3', 'PO4', 'S'];
|
||||
var SOL_CATIONS = ['Na', 'K', 'NH4', 'Ba', 'Ca', 'Mg', 'Al', 'Zn', 'Fe2', 'Fe3', 'Cu', 'Ag', 'Pb'];
|
||||
// P раств., M малораств., H нераств., '-' не существует/разлагается
|
||||
var SOL = {
|
||||
OH: {Na:'P',K:'P',NH4:'P',Ba:'P',Ca:'M',Mg:'H',Al:'H',Zn:'H',Fe2:'H',Fe3:'H',Cu:'H',Ag:'-',Pb:'H'},
|
||||
Cl: {Na:'P',K:'P',NH4:'P',Ba:'P',Ca:'P',Mg:'P',Al:'P',Zn:'P',Fe2:'P',Fe3:'P',Cu:'P',Ag:'H',Pb:'M'},
|
||||
NO3: {Na:'P',K:'P',NH4:'P',Ba:'P',Ca:'P',Mg:'P',Al:'P',Zn:'P',Fe2:'P',Fe3:'P',Cu:'P',Ag:'P',Pb:'P'},
|
||||
SO4: {Na:'P',K:'P',NH4:'P',Ba:'H',Ca:'M',Mg:'P',Al:'P',Zn:'P',Fe2:'P',Fe3:'P',Cu:'P',Ag:'M',Pb:'H'},
|
||||
CO3: {Na:'P',K:'P',NH4:'P',Ba:'H',Ca:'H',Mg:'H',Al:'-',Zn:'H',Fe2:'H',Fe3:'-',Cu:'H',Ag:'H',Pb:'H'},
|
||||
PO4: {Na:'P',K:'P',NH4:'P',Ba:'H',Ca:'H',Mg:'H',Al:'H',Zn:'H',Fe2:'H',Fe3:'H',Cu:'H',Ag:'H',Pb:'H'},
|
||||
S: {Na:'P',K:'P',NH4:'P',Ba:'P',Ca:'P',Mg:'P',Al:'-',Zn:'H',Fe2:'H',Fe3:'-',Cu:'H',Ag:'H',Pb:'H'}
|
||||
};
|
||||
var SOL_LABEL = { P: ['Р', 'растворимо'], M: ['М', 'малорастворимо'], H: ['Н', 'нерастворимо'], '-': ['—', 'не существует / разлагается'] };
|
||||
var CAT_HTML = { Na:'Na⁺', K:'K⁺', NH4:'NH₄⁺', Ba:'Ba²⁺', Ca:'Ca²⁺', Mg:'Mg²⁺', Al:'Al³⁺', Zn:'Zn²⁺', Fe2:'Fe²⁺', Fe3:'Fe³⁺', Cu:'Cu²⁺', Ag:'Ag⁺', Pb:'Pb²⁺' };
|
||||
var AN_HTML = { OH:'OH⁻', Cl:'Cl⁻', NO3:'NO₃⁻', SO4:'SO₄²⁻', CO3:'CO₃²⁻', PO4:'PO₄³⁻', S:'S²⁻' };
|
||||
function solubilityTable(mount, opts) {
|
||||
var host = typeof mount === 'string' ? global.document.querySelector(mount) : mount;
|
||||
if (!host) return null;
|
||||
opts = opts || {};
|
||||
var th = '<tr><th>ион</th>' + SOL_CATIONS.map(function (c) { return '<th data-cat="' + c + '">' + CAT_HTML[c] + '</th>'; }).join('') + '</tr>';
|
||||
var rows = SOL_ANIONS.map(function (an) {
|
||||
return '<tr><th data-an="' + an + '">' + AN_HTML[an] + '</th>' + SOL_CATIONS.map(function (c) {
|
||||
var v = SOL[an][c]; var cls = v === 'P' ? 'sP' : v === 'M' ? 'sM' : v === 'H' ? 'sH' : 'sX';
|
||||
return '<td class="' + cls + '" data-an="' + an + '" data-cat="' + c + '">' + SOL_LABEL[v][0] + '</td>';
|
||||
}).join('') + '</tr>';
|
||||
}).join('');
|
||||
host.innerHTML = '<div class="sol-wrap"><table class="sol-tab"><thead>' + th + '</thead><tbody>' + rows + '</tbody></table></div>'
|
||||
+ '<div class="out sol-out">Кликни по катиону и аниону — узнаешь растворимость соли/основания.</div>';
|
||||
var out = host.querySelector('.sol-out'), selCat = null, selAn = null;
|
||||
function upd() {
|
||||
host.querySelectorAll('.sol-tab td').forEach(function (td) {
|
||||
var on = (!selCat || td.getAttribute('data-cat') === selCat) && (!selAn || td.getAttribute('data-an') === selAn);
|
||||
td.classList.toggle('sol-dim', (selCat || selAn) && !on);
|
||||
td.classList.toggle('sol-hot', selCat && selAn && td.getAttribute('data-cat') === selCat && td.getAttribute('data-an') === selAn);
|
||||
});
|
||||
if (selCat && selAn) {
|
||||
var v = SOL[selAn][selCat];
|
||||
out.className = 'out sol-out ' + (v === 'H' ? 'ok' : '');
|
||||
out.innerHTML = CAT_HTML[selCat] + ' + ' + AN_HTML[selAn] + ' → <b>' + SOL_LABEL[v][1] + '</b>' +
|
||||
(v === 'H' ? ' (выпадает осадок ↓ — реакция идёт)' : v === 'P' ? ' (осадок не образуется)' : '');
|
||||
}
|
||||
}
|
||||
host.querySelectorAll('[data-cat]').forEach(function (el) {
|
||||
if (el.tagName === 'TH') el.addEventListener('click', function () { selCat = el.getAttribute('data-cat'); upd(); });
|
||||
});
|
||||
host.querySelectorAll('th[data-an]').forEach(function (el) { el.addEventListener('click', function () { selAn = el.getAttribute('data-an'); upd(); }); });
|
||||
host.querySelectorAll('.sol-tab td').forEach(function (td) {
|
||||
td.addEventListener('click', function () { selCat = td.getAttribute('data-cat'); selAn = td.getAttribute('data-an'); upd(); });
|
||||
});
|
||||
return { el: host };
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────────────────────────────
|
||||
activitySeries(mount, opts) — ряд активности металлов. Клик по металлу →
|
||||
подсветка; показывает, какие металлы он вытесняет и реакцию с кислотой.
|
||||
────────────────────────────────────────────────────────────────────────── */
|
||||
var ACT = ['K', 'Ca', 'Na', 'Mg', 'Al', 'Zn', 'Fe', 'Ni', 'Sn', 'Pb', 'H', 'Cu', 'Hg', 'Ag', 'Pt', 'Au'];
|
||||
function activitySeries(mount, opts) {
|
||||
var host = typeof mount === 'string' ? global.document.querySelector(mount) : mount;
|
||||
if (!host) return null;
|
||||
host.innerHTML = '<div class="act-row">' + ACT.map(function (m) {
|
||||
return '<button class="act-cell' + (m === 'H' ? ' act-h' : '') + '" data-m="' + m + '">' + (m === 'H' ? '(H₂)' : m) + '</button>';
|
||||
}).join('') + '</div><div class="act-axis"><span>← восстановит. свойства растут</span><span>активность падает →</span></div>'
|
||||
+ '<div class="out act-out">Кликни по металлу — узнаешь его активность и реакцию с кислотами.</div>';
|
||||
var out = host.querySelector('.act-out');
|
||||
host.querySelectorAll('.act-cell').forEach(function (c) {
|
||||
c.addEventListener('click', function () {
|
||||
var m = c.getAttribute('data-m'); if (m === 'H') return;
|
||||
var idx = ACT.indexOf(m), hIdx = ACT.indexOf('H');
|
||||
host.querySelectorAll('.act-cell').forEach(function (x) { x.classList.remove('act-on', 'act-disp'); });
|
||||
c.classList.add('act-on');
|
||||
ACT.forEach(function (mm, i) { if (i > idx && mm !== 'H') host.querySelector('.act-cell[data-m="' + mm + '"]').classList.add('act-disp'); });
|
||||
var withAcid = idx < hIdx ? 'вытесняет водород $\\text{H}_2$ из растворов кислот' : 'НЕ вытесняет водород из кислот (стоит после H)';
|
||||
out.className = 'out act-out';
|
||||
out.innerHTML = '<b>' + m + '</b>: ' + withAcid + '. Вытесняет из растворов солей все металлы, стоящие <b>правее</b> (подсвечены).';
|
||||
if (global.window && global.window.chem8RenderMath) try { global.window.chem8RenderMath(out); } catch (e) {}
|
||||
});
|
||||
});
|
||||
return { el: host };
|
||||
}
|
||||
|
||||
/* ---- Каркасы-заглушки интерактивных виджетов (реализуются по фазам) ---- */
|
||||
function notImplemented(name) {
|
||||
return function () {
|
||||
@@ -374,17 +579,18 @@
|
||||
fmt: fmt,
|
||||
moleTriangle: moleTriangle, // §6 — треугольник n–m–M
|
||||
equationBalancer: equationBalancer, // §8 — балансировщик уравнений
|
||||
// заглушки (см. план, разд. B) — наполняются в Phase 2–6
|
||||
testTube: notImplemented('testTube'), // §18,25 — пробирка: осадок/газ/окраска
|
||||
// готово (Phase 2 — классы неорганических соединений)
|
||||
testTube: testTube, // §18,25 — пробирка: осадок/газ/окраска
|
||||
indicatorScale: indicatorScale, // §13,14,16,17 — индикатор + шкала pH
|
||||
classifier: classifier, // §10,13,16,19 — клик-классификатор
|
||||
solubilityTable: solubilityTable, // §19,20 — таблица растворимости
|
||||
activitySeries: activitySeries, // §14,20 — ряд активности металлов
|
||||
// заглушки (см. план, разд. B) — наполняются в Phase 3–6
|
||||
oxStateCalc: notImplemented('oxStateCalc'), // §42 — калькулятор степени окисления
|
||||
redoxBalancer: notImplemented('redoxBalancer'), // §44 — e-баланс ОВР
|
||||
orbitalDiagram: notImplemented('orbitalDiagram'), // §33 — орбитальная диаграмма
|
||||
solubilityTable: notImplemented('solubilityTable'), // §19,20,48 — таблица растворимости
|
||||
activitySeries: notImplemented('activitySeries'), // §14,20 — ряд активности металлов
|
||||
miniPeriodic: notImplemented('miniPeriodic'), // §1,26,34 — мини-ПСХЭ с подсветкой
|
||||
indicatorScale: notImplemented('indicatorScale'), // §13,14,16,17 — индикатор + шкала pH
|
||||
miniPeriodic: notImplemented('miniPeriodic'), // §26,34 — мини-ПСХЭ с подсветкой
|
||||
dissociationAnim: notImplemented('dissociationAnim'),// §47 — анимация растворения
|
||||
classifier: notImplemented('classifier'), // §10,13,16,19,46 — DnD-классификатор
|
||||
geneticMap: notImplemented('geneticMap') // §22 — генетическая карта-граф классов
|
||||
};
|
||||
|
||||
|
||||
@@ -7,141 +7,344 @@
|
||||
<meta http-equiv="Expires" content="0">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>Химия 8 · Глава 1 · «Важнейшие классы неорганических соединений»</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800;900&family=Inter:wght@400;500;600;700&family=Unbounded:wght@700;800;900&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800;900&family=Inter:wght@400;500;600;700&family=Unbounded:wght@700;800;900&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
|
||||
<link rel="stylesheet" href="/css/chem8-textbook.css">
|
||||
<style>
|
||||
/* Глава 1 — teal-палитра */
|
||||
:root{ --pri:#0d9488; --pri-d:#0f766e; --pri-l:#2dd4bf; --pri-soft:#ccfbf1; --sec-acc:#0d9488; --sec-acc-d:#0f766e; --sec-acc-soft:#ccfbf1; }
|
||||
html.dark{ --bg:#0c1a18; --card:#102825; --card-soft:#13302c; --text:#ccfbf1; --muted:#7fd8c8; --border:#1d463f; --pri-soft:rgba(13,148,136,.2); --sec-acc-soft:rgba(13,148,136,.2); }
|
||||
.hdr{background:linear-gradient(110deg,#134e4a 0%,#0d9488 55%,#2dd4bf 100%)}
|
||||
.hdr::before{content:'ГЛАВА 1'}
|
||||
</style>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"></script>
|
||||
<script src="/js/api.js" defer></script>
|
||||
<script src="/js/xp.js" defer></script>
|
||||
<script src="/js/biochem-core.js" defer></script>
|
||||
<script src="/js/chem8_svg.js" defer></script>
|
||||
<style>
|
||||
:root{
|
||||
--bg:#fffbeb; --card:#fff; --text:#1c1917; --muted:#78716c; --border:#e7e5e4;
|
||||
--pri:#0d9488; --pri-d:#0f766e; --pri-l:#14b8a6; --pri-soft:#ccfbf1;
|
||||
--sh:0 4px 16px rgba(0,0,0,.06); --sh-h:0 12px 32px rgba(0,0,0,.12);
|
||||
}
|
||||
html.dark{ --bg:#0c1a18; --card:#102825; --text:#ccfbf1; --muted:#a8a29e; --border:#3a3026; --pri-soft:rgba(0,0,0,.2); }
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
html,body{min-height:100vh}
|
||||
body{font-family:'Inter',system-ui,sans-serif;background:var(--bg);color:var(--text);line-height:1.55;transition:background .25s,color .25s}
|
||||
.ic{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
|
||||
|
||||
.hdr{position:relative;background:linear-gradient(110deg,#0f766e 0%,#0d9488 55%,#14b8a6 100%);color:#fff;padding:34px 24px 30px;overflow:hidden;border-bottom:2px solid rgba(255,255,255,.18)}
|
||||
.hdr::before{content:'ГЛАВА 1';position:absolute;right:-12px;top:50%;transform:translateY(-50%);font-family:'Unbounded',sans-serif;font-size:clamp(4rem,13vw,10rem);font-weight:900;letter-spacing:-.04em;color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,.13);line-height:1;pointer-events:none;user-select:none;z-index:0}
|
||||
.hdr-inner{position:relative;z-index:1;max-width:1000px;margin:0 auto;display:flex;align-items:center;gap:16px;flex-wrap:wrap}
|
||||
.hdr-back{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;background:rgba(255,255,255,.16);border-radius:9px;color:#fff;text-decoration:none;font-size:.85rem;font-weight:600;transition:background .15s}
|
||||
.hdr-back:hover{background:rgba(255,255,255,.26)}
|
||||
.hdr-kicker{font-size:.72rem;font-weight:800;text-transform:uppercase;letter-spacing:.14em;opacity:.85}
|
||||
.hdr h1{font-family:'Outfit',sans-serif;font-size:1.55rem;font-weight:900;letter-spacing:-.01em;line-height:1.25;margin-top:3px}
|
||||
.hdr-side{margin-left:auto}
|
||||
.hdr-btn{padding:8px 12px;background:rgba(255,255,255,.16);border:none;color:#fff;border-radius:9px;cursor:pointer;font-weight:600;font-size:.82rem;display:inline-flex;align-items:center;gap:6px;transition:background .15s;font-family:inherit}
|
||||
.hdr-btn:hover{background:rgba(255,255,255,.26)}
|
||||
|
||||
main{max-width:1000px;margin:0 auto;padding:28px 24px 60px}
|
||||
|
||||
.wip{display:flex;gap:14px;align-items:flex-start;background:linear-gradient(135deg,var(--pri-soft),rgba(0,0,0,.02));border:1.5px dashed var(--pri);border-radius:16px;padding:18px 20px;margin-bottom:26px}
|
||||
.wip-ic{width:42px;height:42px;border-radius:11px;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;flex-shrink:0}
|
||||
.wip-ic svg{width:22px;height:22px;stroke:#fff;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
|
||||
.wip h2{font-family:'Outfit',sans-serif;font-size:1.05rem;color:var(--pri-d);margin-bottom:4px}
|
||||
html.dark .wip h2{color:var(--pri-l)}
|
||||
.wip p{font-size:.9rem;color:var(--muted);line-height:1.55}
|
||||
|
||||
.ol-title{font-family:'Outfit',sans-serif;font-size:1.15rem;font-weight:800;margin:6px 0 14px;display:flex;align-items:center;gap:9px}
|
||||
.ol-title svg{width:20px;height:20px;stroke:var(--pri);fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
|
||||
.ol-list{list-style:none;background:var(--card);border:1px solid var(--border);border-radius:14px;overflow:hidden;box-shadow:var(--sh)}
|
||||
.ol-para,.ol-note{display:flex;gap:12px;align-items:baseline;padding:12px 18px;border-bottom:1px solid var(--border)}
|
||||
.ol-list li:last-child{border-bottom:0}
|
||||
.ol-num{flex-shrink:0;min-width:46px;font-weight:800;color:var(--pri);font-size:.92rem}
|
||||
.ol-name{font-size:.94rem;color:var(--text)}
|
||||
.ol-note{background:var(--pri-soft);align-items:center;gap:10px}
|
||||
.ol-note-ic{display:inline-flex;color:var(--pri-d)}
|
||||
html.dark .ol-note-ic{color:var(--pri-l)}
|
||||
.ol-note-ic svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
|
||||
.ol-note span:last-child{font-size:.88rem;font-weight:600;color:var(--pri-d)}
|
||||
html.dark .ol-note span:last-child{color:var(--pri-l)}
|
||||
|
||||
.foot{text-align:center;padding:24px 16px;color:var(--muted);font-size:.78rem;border-top:1px solid var(--border);margin-top:30px}
|
||||
</style>
|
||||
<script src="/js/chem8_ch1_widgets.js" defer></script>
|
||||
<script src="/js/chem8_engine.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="hdr">
|
||||
<div class="hdr-inner">
|
||||
<a href="/textbook/chemistry-8" class="hdr-back">
|
||||
<svg class="ic" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg>
|
||||
К разделам
|
||||
</a>
|
||||
<div class="hdr-row">
|
||||
<div>
|
||||
<div class="hdr-kicker">Глава 1 · § 10–23</div>
|
||||
<h1>Важнейшие классы неорганических соединений</h1>
|
||||
<h1>Химия 8 · Глава 1</h1>
|
||||
<div class="hdr-sub">Оксиды, кислоты, основания и соли: состав, классификация, свойства, получение и генетическая связь</div>
|
||||
</div>
|
||||
<div class="hdr-side">
|
||||
<button id="theme-btn" class="hdr-btn" title="Сменить тему">
|
||||
<svg class="ic" viewBox="0 0 24 24"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>
|
||||
<span id="theme-lab">Тёмная</span>
|
||||
</button>
|
||||
<a href="/textbook/chemistry-8" class="hdr-btn"><svg class="ic" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg> К разделам</a>
|
||||
<button id="theme-btn" class="hdr-btn"><svg class="ic" viewBox="0 0 24 24"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg><span id="theme-lab">Тёмная</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="wip">
|
||||
<div class="wip-ic">
|
||||
<svg viewBox="0 0 24 24"><path d="M14.7 6.3a4 4 0 0 0-5.4 5.4l-6.3 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l6.3-6.3a4 4 0 0 0 5.4-5.4l-2.6 2.6-2-2 2.6-2.6z"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Раздел в разработке</h2>
|
||||
<p>Интерактивное наглядное наполнение этого раздела (теория, модели, симуляторы, тренажёры и боссы) добавляется поэтапно. Ниже — план параграфов раздела согласно учебнику.</p>
|
||||
</div>
|
||||
</section>
|
||||
<main class="main">
|
||||
<div class="col-main">
|
||||
<section class="hero">
|
||||
<h2>Четыре класса, из которых построена неорганическая химия</h2>
|
||||
<p>Оксиды, кислоты, основания и соли связаны между собой превращениями. Научившись узнавать класс вещества по формуле и предсказывать его реакции, ты сможешь «читать» химию как язык.</p>
|
||||
<div class="hero-row">
|
||||
<button class="btn-primary" onclick="goTo('p10')"><svg class="ic" viewBox="0 0 24 24"><polygon points="6 4 20 12 6 20 6 4" fill="currentColor" stroke="none"/></svg> Начать § 10</button>
|
||||
<div class="hero-progress"><span class="hp-label">Прогресс главы</span><div class="hp-bar"><div id="hero-hp-fill" class="hp-fill"></div></div><span id="hero-hp-text" class="hp-text">0%</span></div>
|
||||
<div id="hero-xp-badge" class="hero-xp-badge"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="ol-title">
|
||||
<svg viewBox="0 0 24 24"><path d="M4 6h16M4 12h16M4 18h10"/></svg>
|
||||
Содержание раздела
|
||||
<section class="psel"><div class="psel-title">Параграфы главы</div><div id="psel-grid" class="psel-grid"></div></section>
|
||||
|
||||
<section id="sec-p10" class="sec"><div class="sec-header"><span class="sec-num">§ 10</span><h2 class="sec-h">Оксиды. Состав и классификация</h2></div><div id="p10-body"></div></section>
|
||||
<section id="sec-p11" class="sec"><div class="sec-header"><span class="sec-num">§ 11</span><h2 class="sec-h">Химические свойства оксидов</h2></div><div id="p11-body"></div></section>
|
||||
<section id="sec-p12" class="sec"><div class="sec-header"><span class="sec-num">§ 12</span><h2 class="sec-h">Получение и применение оксидов</h2></div><div id="p12-body"></div></section>
|
||||
<section id="sec-p13" class="sec"><div class="sec-header"><span class="sec-num">§ 13</span><h2 class="sec-h">Кислоты. Состав и классификация</h2></div><div id="p13-body"></div></section>
|
||||
<section id="sec-p14" class="sec"><div class="sec-header"><span class="sec-num">§ 14</span><h2 class="sec-h">Химические свойства кислот</h2></div><div id="p14-body"></div></section>
|
||||
<section id="sec-p15" class="sec"><div class="sec-header"><span class="sec-num">§ 15</span><h2 class="sec-h">Получение и применение кислот</h2></div><div id="p15-body"></div></section>
|
||||
<section id="sec-p16" class="sec"><div class="sec-header"><span class="sec-num">§ 16</span><h2 class="sec-h">Основания</h2></div><div id="p16-body"></div></section>
|
||||
<section id="sec-p17" class="sec"><div class="sec-header"><span class="sec-num">§ 17</span><h2 class="sec-h">Химические свойства оснований</h2></div><div id="p17-body"></div></section>
|
||||
<section id="sec-p18" class="sec"><div class="sec-header"><span class="sec-num">§ 18</span><h2 class="sec-h">Получение оснований · Лаб. 1 · ПР 2</h2></div><div id="p18-body"></div></section>
|
||||
<section id="sec-p19" class="sec"><div class="sec-header"><span class="sec-num">§ 19</span><h2 class="sec-h">Соли. Состав и классификация</h2></div><div id="p19-body"></div></section>
|
||||
<section id="sec-p20" class="sec"><div class="sec-header"><span class="sec-num">§ 20</span><h2 class="sec-h">Химические свойства солей · Лаб. 2</h2></div><div id="p20-body"></div></section>
|
||||
<section id="sec-p21" class="sec"><div class="sec-header"><span class="sec-num">§ 21</span><h2 class="sec-h">Получение и применение солей</h2></div><div id="p21-body"></div></section>
|
||||
<section id="sec-p22" class="sec"><div class="sec-header"><span class="sec-num">§ 22</span><h2 class="sec-h">Взаимосвязь классов · ПР 3</h2></div><div id="p22-body"></div></section>
|
||||
<section id="sec-p23" class="sec"><div class="sec-header"><span class="sec-num">§ 23</span><h2 class="sec-h">Решение расчётных задач</h2></div><div id="p23-body"></div></section>
|
||||
<section id="sec-final1" class="sec"><div class="sec-header"><span class="sec-num">★</span><h2 class="sec-h">Финал главы</h2></div><div id="final1-body"></div></section>
|
||||
</div>
|
||||
<ul class="ol-list">
|
||||
<li class="ol-para"><span class="ol-num">§ 10</span><span class="ol-name">Оксиды. Состав и классификация оксидов</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 11</span><span class="ol-name">Химические свойства оксидов</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 12</span><span class="ol-name">Получение и применение оксидов</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 13</span><span class="ol-name">Кислоты. Состав и классификация кислот</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 14</span><span class="ol-name">Химические свойства кислот</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 15</span><span class="ol-name">Получение и применение кислот</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 16</span><span class="ol-name">Основания</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 17</span><span class="ol-name">Химические свойства оснований</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 18</span><span class="ol-name">Получение и применение оснований</span></li>
|
||||
<li class="ol-note"><span class="ol-note-ic"><svg viewBox="0 0 24 24"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg></span><span>Лабораторный опыт 1. Получение нерастворимого основания</span></li>
|
||||
<li class="ol-note"><span class="ol-note-ic"><svg viewBox="0 0 24 24"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg></span><span>Практическая работа 2. Изучение реакции нейтрализации</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 19</span><span class="ol-name">Соли. Состав и классификация солей</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 20</span><span class="ol-name">Химические свойства солей</span></li>
|
||||
<li class="ol-note"><span class="ol-note-ic"><svg viewBox="0 0 24 24"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg></span><span>Лабораторный опыт 2. Взаимодействие растворов солей с металлами</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 21</span><span class="ol-name">Получение и применение солей</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 22</span><span class="ol-name">Взаимосвязь между классами основных неорганических веществ</span></li>
|
||||
<li class="ol-note"><span class="ol-note-ic"><svg viewBox="0 0 24 24"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg></span><span>Практическая работа 3. Решение экспериментальных задач</span></li>
|
||||
<li class="ol-para"><span class="ol-num">§ 23</span><span class="ol-name">Решение расчётных задач по теме «Основные классы неорганических соединений»</span></li>
|
||||
</ul>
|
||||
<aside class="col-side"><div id="sidebar-content"></div></aside>
|
||||
</main>
|
||||
|
||||
<footer class="foot">
|
||||
Интерактивный учебник «Химия — 8 класс» · Глава 1 · LearnSpace
|
||||
</footer>
|
||||
<footer class="foot">Интерактивный учебник «Химия — 8 класс» · Глава 1 · «Важнейшие классы неорганических соединений» · LearnSpace</footer>
|
||||
<div id="ach-popup" class="ach-popup"><svg viewBox="0 0 24 24"><polygon points="12 2 22 20 2 20"/></svg><span id="ach-text">Достижение!</span></div>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
const _TB_SLUG = 'chemistry-8-ch1';
|
||||
(function(){
|
||||
var saved = localStorage.getItem('chemistry8_theme') || localStorage.getItem('theme') || 'light';
|
||||
if (saved === 'dark') document.documentElement.classList.add('dark');
|
||||
var lab = document.getElementById('theme-lab');
|
||||
if (lab) lab.textContent = saved === 'dark' ? 'Светлая' : 'Тёмная';
|
||||
document.getElementById('theme-btn').addEventListener('click', function(){
|
||||
document.documentElement.classList.toggle('dark');
|
||||
var dark = document.documentElement.classList.contains('dark');
|
||||
localStorage.setItem('chemistry8_theme', dark ? 'dark' : 'light');
|
||||
localStorage.setItem('theme', dark ? 'dark' : 'light');
|
||||
if (lab) lab.textContent = dark ? 'Светлая' : 'Тёмная';
|
||||
});
|
||||
})();
|
||||
window.CHEM8_CFG = { slug:'chemistry-8-ch1', themeKey:'chemistry8_theme', xpKey:'chemistry8_xp', progKey:'chemistry8_ch1_progress', achKey:'chemistry8_ch1_ach' };
|
||||
|
||||
window.PARAS = [
|
||||
{id:'p10',num:'§ 10',name:'Оксиды. Классификация',sub:'осн/кисл/амф'},
|
||||
{id:'p11',num:'§ 11',name:'Свойства оксидов',sub:'+ вода/кислота/щёлочь'},
|
||||
{id:'p12',num:'§ 12',name:'Получение оксидов',sub:'горение · разложение'},
|
||||
{id:'p13',num:'§ 13',name:'Кислоты. Классификация',sub:'основность'},
|
||||
{id:'p14',num:'§ 14',name:'Свойства кислот',sub:'+ Me · ряд активности'},
|
||||
{id:'p15',num:'§ 15',name:'Получение кислот',sub:'оксид + вода'},
|
||||
{id:'p16',num:'§ 16',name:'Основания',sub:'щёлочи/нераств.'},
|
||||
{id:'p17',num:'§ 17',name:'Свойства оснований',sub:'нейтрализация'},
|
||||
{id:'p18',num:'§ 18',name:'Получение · Лаб.1 · ПР2',sub:'Cu(OH)₂↓'},
|
||||
{id:'p19',num:'§ 19',name:'Соли. Классификация',sub:'растворимость'},
|
||||
{id:'p20',num:'§ 20',name:'Свойства солей · Лаб.2',sub:'РИО · соль+Me'},
|
||||
{id:'p21',num:'§ 21',name:'Получение солей',sub:'способы'},
|
||||
{id:'p22',num:'§ 22',name:'Связь классов · ПР3',sub:'генетика'},
|
||||
{id:'p23',num:'§ 23',name:'Расчётные задачи',sub:'по уравнениям'},
|
||||
{id:'final1',num:'★',name:'Финал главы',sub:'босс · ачивка',final:true}
|
||||
];
|
||||
|
||||
window.ACH_LABELS = { start:'Начало главы 1!', final1_tasks:'Классы веществ покорены!' };
|
||||
['p10','p11','p12','p13','p14','p15','p16','p17','p18','p19','p20','p21','p22','p23'].forEach(function(id){ window.ACH_LABELS[id+'_done']=id.toUpperCase()+' изучен!'; });
|
||||
|
||||
window.SIDEBARS = {
|
||||
p10:{title:'§10 Оксиды',rows:[['Оксид','ЭₓOᵧ, кислород −2'],['Основные','оксиды металлов'],['Кислотные','оксиды неметаллов'],['Амфотерные','ZnO, Al₂O₃']]},
|
||||
p11:{title:'§11 Свойства',rows:[['Осн. оксид','+ кислота, + вода'],['Кисл. оксид','+ щёлочь, + вода'],['Соль','продукт + H₂O']]},
|
||||
p12:{title:'§12 Получение',rows:[['Горение','S + O₂ → SO₂'],['Разложение','CaCO₃ → CaO + CO₂']]},
|
||||
p13:{title:'§13 Кислоты',rows:[['Кислота','HₓAc'],['Бескислородные','HCl, H₂S'],['Кислородсод.','H₂SO₄, HNO₃'],['Основность','число H']]},
|
||||
p14:{title:'§14 Свойства кислот',rows:[['+ Me','до H в ряду → H₂↑'],['+ осн. оксид','соль + вода'],['+ основание','нейтрализация'],['Индикатор','лакмус → красный']]},
|
||||
p15:{title:'§15 Получение',rows:[['Кисл. оксид + вода','SO₃+H₂O→H₂SO₄'],['Соль + кислота','']]},
|
||||
p16:{title:'§16 Основания',rows:[['Основание','Me(OH)ₙ'],['Щёлочи','NaOH, KOH, Ba(OH)₂'],['Нерастворимые','Cu(OH)₂, Fe(OH)₃'],['Фенолфталеин','малиновый в щёлочи']]},
|
||||
p17:{title:'§17 Свойства',rows:[['Нейтрализация','+ кислота → соль+H₂O'],['+ кисл. оксид','соль + вода'],['Разложение','Cu(OH)₂ → CuO+H₂O']]},
|
||||
p18:{title:'§18 Получение',rows:[['Щёлочь','Me + вода'],['Нераств.','щёлочь + соль'],['Лаб.1','Cu(OH)₂↓ голубой']]},
|
||||
p19:{title:'§19 Соли',rows:[['Соль','катион металла + анион'],['Средние','NaCl, CaCO₃'],['Растворимость','таблица']]},
|
||||
p20:{title:'§20 Свойства',rows:[['РИО','↓ ↑ H₂O'],['Соль + Me','активнее вытесняет'],['Лаб.2','соль + металл']]},
|
||||
p21:{title:'§21 Получение',rows:[['Кислота+основание',''],['Металл+кислота',''],['Оксид+кислота','']]},
|
||||
p22:{title:'§22 Связь',rows:[['Металл','→ оксид → основание → соль'],['Неметалл','→ оксид → кислота → соль']]},
|
||||
p23:{title:'§23 Расчёты',rows:[['Алгоритм','m→n→n→m'],['По уравнению','мольное отношение']]},
|
||||
final1:{title:'Финал главы 1',rows:[['§§10–23','все классы'],['Награда','ачивка + XP']]}
|
||||
};
|
||||
window.TIPS = [
|
||||
{sec:'p10',html:'Оксид — соединение элемента с кислородом (степень окисления −2). Оксиды металлов чаще основные, неметаллов — кислотные.'},
|
||||
{sec:'p11',html:'Основный оксид реагирует с кислотой, кислотный — со щёлочью. Оба могут давать соль.'},
|
||||
{sec:'p12',html:'Оксиды получают горением простых веществ и разложением солей/оснований.'},
|
||||
{sec:'p13',html:'Основность кислоты = число атомов H, способных замещаться металлом (HCl — одноосновная, H₂SO₄ — двухосновная).'},
|
||||
{sec:'p14',html:'Металлы ДО водорода в ряду активности вытесняют H₂ из растворов кислот; после — нет.'},
|
||||
{sec:'p15',html:'Кислородсодержащие кислоты получают: кислотный оксид + вода. Например, SO₃ + H₂O → H₂SO₄.'},
|
||||
{sec:'p16',html:'Растворимые основания — щёлочи (NaOH, KOH, Ba(OH)₂). Фенолфталеин в щёлочи становится малиновым.'},
|
||||
{sec:'p17',html:'Реакция нейтрализации: основание + кислота → соль + вода.'},
|
||||
{sec:'p18',html:'Нерастворимое основание получают: щёлочь + соль. Cu(OH)₂ — голубой осадок.'},
|
||||
{sec:'p19',html:'Растворимость соли определяют по таблице. Нерастворимая соль выпадает в осадок.'},
|
||||
{sec:'p20',html:'Реакции ионного обмена идут, если образуется осадок ↓, газ ↑ или вода. Металл вытесняет из соли менее активный металл.'},
|
||||
{sec:'p21',html:'Соли получают многими способами: кислота+основание, металл+кислота, оксид+кислота, соль+соль и др.'},
|
||||
{sec:'p22',html:'Генетическая связь: металл → основный оксид → основание → соль; неметалл → кислотный оксид → кислота → соль.'},
|
||||
{sec:'p23',html:'Расчёт по уравнению: найди n известного, по коэффициентам — n искомого, переведи в массу/объём.'},
|
||||
{sec:'final1',html:'Собери всё: классификация, свойства, растворимость, ряд активности, расчёты по уравнениям.'}
|
||||
];
|
||||
|
||||
window.POOLS = {
|
||||
p10:[
|
||||
{q:'Оксид — это…',opts:['Соединение двух неметаллов','Сложное вещество из двух элементов, один из которых кислород (с.о. −2)','Любое вещество с кислородом','Соль кислородной кислоты'],a:1,ex:'Оксид — бинарное соединение элемента с кислородом.'},
|
||||
{q:'Какой из оксидов основный?',opts:['CO₂','SO₃','Na₂O','P₂O₅'],a:2,ex:'Na₂O — оксид активного металла, основный.'},
|
||||
{q:'Амфотерный оксид — это…',opts:['Na₂O','CaO','ZnO','CO'],a:2,ex:'ZnO проявляет и основные, и кислотные свойства.'},
|
||||
{q:'Несолеобразующий оксид:',opts:['CO','SO₂','CaO','Al₂O₃'],a:0,ex:'CO не образует солей — несолеобразующий.'}
|
||||
],
|
||||
p11:[
|
||||
{q:'Основный оксид реагирует с…',opts:['Основанием','Кислотой','Другим основным оксидом','Инертным газом'],a:1,ex:'Основный оксид + кислота → соль + вода.'},
|
||||
{q:'Кислотный оксид реагирует с…',opts:['Кислотой','Щёлочью','Кислотным оксидом','Металлом'],a:1,ex:'Кислотный оксид + щёлочь → соль + вода.'},
|
||||
{q:'Продукт реакции CaO + H₂O:',opts:['CaCO₃','Ca(OH)₂','CaCl₂','CaO₂'],a:1,ex:'Основный оксид активного металла + вода → щёлочь.'}
|
||||
],
|
||||
p12:[
|
||||
{q:'Каким способом получают оксиды?',opts:['Только электролизом','Горением простых веществ и разложением солей','Только из кислот','Только из щелочей'],a:1,ex:'Горение (S+O₂→SO₂) и разложение (CaCO₃→CaO+CO₂).'},
|
||||
{q:'При разложении 1 моль CaCO₃ образуется … моль CO₂',hint:'1:1',unit:'моль',a:1,ex:'CaCO₃ → CaO + CO₂, отношение 1:1.'}
|
||||
],
|
||||
p13:[
|
||||
{q:'Бескислородная кислота — это…',opts:['H₂SO₄','HNO₃','HCl','H₃PO₄'],a:2,ex:'HCl не содержит кислорода.'},
|
||||
{q:'Основность серной кислоты H₂SO₄ равна…',hint:'число атомов H',unit:'',a:2,ex:'Два атома водорода → двухосновная.'},
|
||||
{q:'Какого цвета лакмус в растворе кислоты?',opts:['Синий','Красный','Жёлтый','Бесцветный'],a:1,ex:'Лакмус в кислоте — красный.'}
|
||||
],
|
||||
p14:[
|
||||
{q:'Какой металл вытесняет водород из соляной кислоты?',opts:['Cu','Ag','Zn','Au'],a:2,ex:'Zn стоит до H в ряду активности.'},
|
||||
{q:'Реакция кислоты с основанием называется…',opts:['Разложения','Нейтрализации','Замещения','Горения'],a:1,ex:'Кислота + основание → соль + вода — нейтрализация.'},
|
||||
{q:'Медь (Cu) с разбавленной HCl…',opts:['Бурно реагирует','Не реагирует (стоит после H)','Образует H₂','Растворяется с осадком'],a:1,ex:'Cu после водорода — H₂ не вытесняет.'}
|
||||
],
|
||||
p15:[
|
||||
{q:'H₂SO₄ можно получить реакцией…',opts:['SO₃ + H₂O','SO₂ + H₂','S + H₂O','Na₂SO₄ + H₂O'],a:0,ex:'Кислотный оксид SO₃ + вода → серная кислота.'},
|
||||
{q:'Какой оксид при растворении в воде даёт кислоту?',opts:['CaO','Na₂O','CO₂','MgO'],a:2,ex:'CO₂ + H₂O → H₂CO₃ (кислотный оксид).'}
|
||||
],
|
||||
p16:[
|
||||
{q:'Щёлочь — это…',opts:['Любое основание','Растворимое в воде основание','Нерастворимое основание','Кислота'],a:1,ex:'Щёлочи — растворимые основания (NaOH, KOH...).'},
|
||||
{q:'Нерастворимое основание:',opts:['NaOH','KOH','Cu(OH)₂','Ba(OH)₂'],a:2,ex:'Cu(OH)₂ нерастворим.'},
|
||||
{q:'Фенолфталеин в растворе щёлочи становится…',opts:['Красным','Малиновым','Жёлтым','Синим'],a:1,ex:'В щёлочи фенолфталеин малиновый.'}
|
||||
],
|
||||
p17:[
|
||||
{q:'Продукты реакции NaOH + HCl:',opts:['NaCl + H₂','NaCl + H₂O','Na₂O + HCl','NaH + ClOH'],a:1,ex:'Нейтрализация: NaCl + H₂O.'},
|
||||
{q:'При нагревании Cu(OH)₂ разлагается на…',opts:['Cu + H₂O','CuO + H₂O','CuO + H₂','Cu + O₂'],a:1,ex:'Cu(OH)₂ → CuO + H₂O.'}
|
||||
],
|
||||
p18:[
|
||||
{q:'Cu(OH)₂ в лаборатории получают реакцией…',opts:['Cu + H₂O','CuSO₄ + NaOH','CuO + H₂O','Cu + NaOH'],a:1,ex:'Соль + щёлочь → нерастворимое основание Cu(OH)₂↓.'},
|
||||
{q:'Какого цвета осадок Cu(OH)₂?',opts:['Белый','Голубой','Бурый','Чёрный'],a:1,ex:'Гидроксид меди(II) — голубой осадок.'}
|
||||
],
|
||||
p19:[
|
||||
{q:'Соль — это…',opts:['Оксид металла','Продукт замещения H кислоты на металл','Гидроксид','Простое вещество'],a:1,ex:'В соли водород кислоты замещён металлом.'},
|
||||
{q:'Какая соль нерастворима в воде?',opts:['NaCl','KNO₃','BaSO₄','CaCl₂'],a:2,ex:'BaSO₄ — нерастворим (см. таблицу).'},
|
||||
{q:'Все нитраты (NO₃⁻)…',opts:['Нерастворимы','Растворимы','Малорастворимы','Разлагаются водой'],a:1,ex:'Нитраты растворимы все.'}
|
||||
],
|
||||
p20:[
|
||||
{q:'Реакция ионного обмена идёт, если образуется…',opts:['Только газ','Осадок ↓, газ ↑ или вода','Только осадок','Новая кислота'],a:1,ex:'Условие необратимости РИО.'},
|
||||
{q:'Какой металл вытеснит медь из раствора CuSO₄?',opts:['Ag','Au','Fe','Hg'],a:2,ex:'Fe активнее Cu → вытесняет медь.'},
|
||||
{q:'Реакция AgNO₃ + NaCl даёт осадок…',opts:['AgNO₃','NaCl','AgCl↓','NaNO₃'],a:2,ex:'AgCl — белый осадок ↓.'}
|
||||
],
|
||||
p21:[
|
||||
{q:'Какой способ НЕ даёт соль?',opts:['Кислота + основание','Металл + кислота','Оксид + кислота','Два инертных газа'],a:3,ex:'Инертные газы не реагируют.'},
|
||||
{q:'Zn + 2HCl даёт соль…',opts:['ZnO','ZnCl₂','Zn(OH)₂','ZnSO₄'],a:1,ex:'ZnCl₂ + H₂↑.'}
|
||||
],
|
||||
p22:[
|
||||
{q:'Генетический ряд металла:',opts:['Me → кислота → соль','Me → основный оксид → основание → соль','Me → кислотный оксид → кислота','Me → соль → оксид'],a:1,ex:'Металл → осн. оксид → основание → соль.'},
|
||||
{q:'Из чего можно получить кислоту в ряду неметалла?',opts:['Из основного оксида','Из кислотного оксида + вода','Из металла','Из щёлочи'],a:1,ex:'Кислотный оксид + вода → кислота.'}
|
||||
],
|
||||
p23:[
|
||||
{q:'CaO + 2HCl → CaCl₂ + H₂O. Дано n(CaO)=0,5 моль. Найди n(CaCl₂).',hint:'1:1',unit:'моль',a:0.5,ex:'Отношение 1:1 → 0,5 моль.'},
|
||||
{q:'Zn + H₂SO₄ → ZnSO₄ + H₂↑. Дано n(Zn)=2 моль. Найди V(H₂) при н.у.',hint:'n(H₂)=2; V=n·22,4',unit:'л',a:44.8,ex:'2·22,4=44,8 л.'},
|
||||
{q:'2NaOH + H₂SO₄ → Na₂SO₄ + 2H₂O. Дано n(H₂SO₄)=0,5 моль. Найди n(NaOH).',hint:'2:1',unit:'моль',a:1,ex:'2·0,5=1 моль.'}
|
||||
],
|
||||
final1:[
|
||||
{q:'Какой оксид кислотный?',opts:['CaO','Na₂O','SO₃','MgO'],a:2,ex:'SO₃ — оксид неметалла, кислотный.'},
|
||||
{q:'Основность H₃PO₄ равна…',hint:'число H',unit:'',a:3,ex:'Три атома H — трёхосновная.'},
|
||||
{q:'Какой металл НЕ вытесняет H₂ из кислоты?',opts:['Mg','Zn','Fe','Cu'],a:3,ex:'Cu стоит после H.'},
|
||||
{q:'Реакция CuSO₄ + 2NaOH даёт осадок…',opts:['CuO','Cu(OH)₂↓','Na₂SO₄','Cu'],a:1,ex:'Cu(OH)₂ — голубой осадок ↓.'},
|
||||
{q:'Дано: m(CaCO₃)=50 г, M=100. Найди n.',hint:'n=m/M',unit:'моль',a:0.5,ex:'50/100=0,5 моль.'},
|
||||
{q:'Zn + 2HCl → ZnCl₂ + H₂↑. n(Zn)=1 моль. Найди V(H₂) н.у.',hint:'V=n·22,4',unit:'л',a:22.4,ex:'1·22,4=22,4 л.'}
|
||||
]
|
||||
};
|
||||
|
||||
/* конструкторы */
|
||||
function rememberBox(items){ return '<div class="remember-box"><div class="remember-box-title"><svg class="ic" viewBox="0 0 24 24" style="width:15px;height:15px"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg> Запомни!</div><ul>'+items.map(function(t){return '<li>'+t+'</li>';}).join('')+'</ul></div>'; }
|
||||
function qList(items){ return '<div class="section-title">Вопросы и задания</div><ol class="q-list">'+items.map(function(t){return '<li>'+t+'</li>';}).join('')+'</ol>'; }
|
||||
function wgt(title, inner){ return '<div class="wgt"><div class="wgt-h"><svg class="ic" viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h10"/></svg> '+title+'</div>'+inner+'</div>'; }
|
||||
function flag(title, help, inner){ return '<div class="flag-card"><div class="flag-title">'+title+'</div><div class="flag-help">'+help+'</div>'+inner+'</div>'; }
|
||||
function hero(ph,label,title,formula,desc,tags){ return '<div class="para-hero ph-'+ph+'"><div class="ph-label">'+label+'</div><h2>'+title+'</h2>'+(formula?'<div class="ph-formula">'+formula+'</div>':'')+'<div class="ph-desc">'+desc+'</div>'+(tags?'<div class="ph-tags">'+tags.map(function(t){return '<span class="ph-tag">'+t+'</span>';}).join('')+'</div>':'')+'</div>'; }
|
||||
function tube(o){ return (window.Chem8&&window.Chem8.testTube)?window.Chem8.testTube(o):''; }
|
||||
|
||||
window.BUILDERS = {
|
||||
p10:bp10,p11:bp11,p12:bp12,p13:bp13,p14:bp14,p15:bp15,p16:bp16,p17:bp17,p18:bp18,p19:bp19,p20:bp20,p21:bp21,p22:bp22,p23:bp23,final1:bfinal
|
||||
};
|
||||
|
||||
function bp10(){ document.getElementById('p10-body').innerHTML =
|
||||
hero(1,'§ 10 · Глава 1','Оксиды. Состав и классификация','ЭₓOᵧ','Самый распространённый класс: соединения элементов с кислородом — от песка и воды до углекислого газа.',['оксид','классификация','амфотерность'])
|
||||
+makeCard('theory','Что такое оксид','§10','<p><b>Оксид</b> — сложное вещество из двух элементов, один из которых — кислород в степени окисления −2 (Na₂O, CaO, CO₂, SO₃, H₂O).</p><p>Оксиды делят на <b>солеобразующие</b> (дают соли) и <b>несолеобразующие</b> (CO, N₂O, NO). Солеобразующие — на <b>основные</b> (оксиды металлов: Na₂O, CaO), <b>кислотные</b> (оксиды неметаллов: CO₂, SO₃, P₂O₅) и <b>амфотерные</b> (ZnO, Al₂O₃).</p>')
|
||||
+flag('Классификатор оксидов','Перетащи (кликни чип, затем корзину) каждый оксид в свой класс и нажми «Проверить».','<div id="c-ox-cls"></div>')
|
||||
+rememberBox(['Оксиды металлов чаще основные, неметаллов — кислотные.','Амфотерные: ZnO, Al₂O₃, Cr₂O₃ — ведут себя двойственно.','CO, NO, N₂O — несолеобразующие.'])
|
||||
+qList(['Чем основный оксид отличается от кислотного?','Приведи по два примера оксидов каждого класса.'])
|
||||
+secNav(null,'p11')+readButton('p10'); wireReadBtn('p10'); }
|
||||
|
||||
function bp11(){ document.getElementById('p11-body').innerHTML =
|
||||
hero(2,'§ 11 · Глава 1','Химические свойства оксидов','оксид + … → соль','Как основные и кислотные оксиды реагируют с водой, кислотами и щелочами, образуя соли.',['+ вода','+ кислота','+ щёлочь'])
|
||||
+makeCard('theory','Свойства оксидов','§11','<p><b>Основные оксиды:</b><br>• + вода (только активные металлы) → щёлочь: CaO + H₂O → Ca(OH)₂<br>• + кислота → соль + вода: CuO + 2HCl → CuCl₂ + H₂O</p><p><b>Кислотные оксиды:</b><br>• + вода → кислота: SO₃ + H₂O → H₂SO₄<br>• + щёлочь → соль + вода: CO₂ + 2NaOH → Na₂CO₃ + H₂O</p>')
|
||||
+makeCard('example','Признак реакции',null,'<div class="tt-row"><div><div style="text-align:center">'+tube({color:'#dbeafe'})+'</div><div class="tt-cap">CuO + кислота → голубой раствор соли</div></div></div>')
|
||||
+rememberBox(['Основный + кислотный оксид → соль (CaO + CO₂ → CaCO₃).','Не все оксиды реагируют с водой (CuO, Fe₂O₃ — нет).'])
|
||||
+qList(['Допиши: SO₂ + NaOH → ?','С чем реагирует основный оксид CaO?'])
|
||||
+secNav('p10','p12')+readButton('p11'); wireReadBtn('p11'); }
|
||||
|
||||
function bp12(){ document.getElementById('p12-body').innerHTML =
|
||||
hero(3,'§ 12 · Глава 1','Получение и применение оксидов','S + O₂ → SO₂','Откуда берут оксиды и где их применяют — от извести до кремнезёма.',['горение','разложение','применение'])
|
||||
+makeCard('theory','Способы получения','§12','<p>• <b>Горение</b> простых веществ: S + O₂ → SO₂; 2Cu + O₂ → 2CuO.<br>• <b>Разложение</b> солей и оснований: CaCO₃ →(t) CaO + CO₂↑; Cu(OH)₂ →(t) CuO + H₂O.</p><p><b>Применение:</b> CaO (негашёная известь) — в строительстве, SiO₂ — стекло, CO₂ — газировка и огнетушители.</p>')
|
||||
+rememberBox(['Горение неметалла даёт кислотный оксид, металла — основный.','Карбонаты при нагревании разлагаются на оксид и CO₂.'])
|
||||
+qList(['Напиши уравнение горения углерода.','Где применяют негашёную известь CaO?'])
|
||||
+secNav('p11','p13')+readButton('p12'); wireReadBtn('p12'); }
|
||||
|
||||
function bp13(){ document.getElementById('p13-body').innerHTML =
|
||||
hero(4,'§ 13 · Глава 1','Кислоты. Состав и классификация','HₓAc','Вещества с кислым вкусом и подвижными атомами водорода: как их различают и классифицируют.',['основность','индикатор'])
|
||||
+makeCard('theory','Кислоты и их классификация','§13','<p><b>Кислота</b> — сложное вещество, в составе которого есть атомы водорода, способные замещаться металлом, и кислотный остаток.</p><p>По наличию кислорода: <b>бескислородные</b> (HCl, H₂S, HBr) и <b>кислородсодержащие</b> (H₂SO₄, HNO₃, H₃PO₄). По числу атомов H — <b>основность</b>: одноосновные (HCl), двухосновные (H₂SO₄), трёхосновные (H₃PO₄).</p>')
|
||||
+flag('Классификатор кислот','Распредели кислоты по наличию кислорода.','<div id="c-acid-cls"></div>')
|
||||
+wgt('Индикатор: кислая среда','<div id="c-acid-ind"></div>')
|
||||
+rememberBox(['Основность = число замещаемых атомов H.','Лакмус в кислоте красный, метилоранж — розово-красный.'])
|
||||
+qList(['Определи основность H₃PO₄.','Какие кислоты бескислородные?'])
|
||||
+secNav('p12','p14')+readButton('p13'); wireReadBtn('p13'); }
|
||||
|
||||
function bp14(){ document.getElementById('p14-body').innerHTML =
|
||||
hero(5,'§ 14 · Глава 1','Химические свойства кислот','+ Me · + оксид · + основание','Четыре главные реакции кислот и роль ряда активности металлов.',['ряд активности','нейтрализация'])
|
||||
+makeCard('theory','Свойства кислот','§14','<p>Кислоты реагируют:<br>• с <b>металлами</b> (до H в ряду активности) → соль + H₂↑: Zn + 2HCl → ZnCl₂ + H₂↑<br>• с <b>основными оксидами</b> → соль + вода: CuO + H₂SO₄ → CuSO₄ + H₂O<br>• с <b>основаниями</b> (нейтрализация) → соль + вода<br>• с <b>солями</b> → новая соль + новая кислота (если ↓↑).</p>')
|
||||
+flag('Ряд активности металлов','Кликни металл — узнаешь, вытесняет ли он водород из кислот и какие металлы вытесняет из солей.','<div id="c-acid-act"></div>')
|
||||
+wgt('Индикатор: метилоранж','<div id="c-acid-ind2"></div>')
|
||||
+rememberBox(['Металлы после H (Cu, Ag, Au) водород из кислот НЕ вытесняют.','Признак реакции с металлом — выделение пузырьков H₂↑.'])
|
||||
+qList(['Будет ли реагировать Ag с HCl? Почему?','Допиши: Fe + HCl → ?'])
|
||||
+secNav('p13','p15')+readButton('p14'); wireReadBtn('p14'); }
|
||||
|
||||
function bp15(){ document.getElementById('p15-body').innerHTML =
|
||||
hero(6,'§ 15 · Глава 1','Получение и применение кислот','SO₃ + H₂O → H₂SO₄','Как получают кислоты и где их используют — от аккумуляторов до пищевой промышленности.',['получение','применение'])
|
||||
+makeCard('theory','Получение кислот','§15','<p>• <b>Кислотный оксид + вода</b> → кислота: SO₃ + H₂O → H₂SO₄; CO₂ + H₂O → H₂CO₃.<br>• <b>Соль + сильная кислота</b> → новая кислота: BaCl₂ + H₂SO₄ → BaSO₄↓ + 2HCl.</p><p><b>Применение:</b> H₂SO₄ — «хлеб химии» (аккумуляторы, удобрения), HCl — в металлургии, H₃PO₄ — пищевая.</p>')
|
||||
+rememberBox(['Бескислородные кислоты не получить «оксид + вода» — у них нет кислорода.','H₂SO₄ — одно из важнейших веществ промышленности.'])
|
||||
+qList(['Из какого оксида получают угольную кислоту?','Где применяют серную кислоту?'])
|
||||
+secNav('p14','p16')+readButton('p15'); wireReadBtn('p15'); }
|
||||
|
||||
function bp16(){ document.getElementById('p16-body').innerHTML =
|
||||
hero(7,'§ 16 · Глава 1','Основания','Me(OH)ₙ','Гидроксиды металлов: растворимые щёлочи и нерастворимые основания.',['щёлочи','индикатор'])
|
||||
+makeCard('theory','Основания','§16','<p><b>Основание</b> — сложное вещество из атома металла и гидроксогрупп OH. По растворимости: <b>щёлочи</b> (растворимые: NaOH, KOH, Ca(OH)₂, Ba(OH)₂) и <b>нерастворимые</b> (Cu(OH)₂, Fe(OH)₃, Mg(OH)₂).</p><p>Щёлочи изменяют окраску индикаторов: лакмус → синий, фенолфталеин → малиновый, метилоранж → жёлтый.</p>')
|
||||
+flag('Классификатор оснований','Раздели основания на щёлочи и нерастворимые.','<div id="c-base-cls"></div>')
|
||||
+wgt('Индикатор: фенолфталеин в щёлочи','<div id="c-base-ind"></div>')
|
||||
+rememberBox(['Щёлочи — растворимые основания активных металлов (I–II групп).','Фенолфталеин — главный индикатор на щёлочь (малиновый).'])
|
||||
+qList(['Назови три щёлочи.','Почему Cu(OH)₂ не относят к щелочам?'])
|
||||
+secNav('p15','p17')+readButton('p16'); wireReadBtn('p16'); }
|
||||
|
||||
function bp17(){ document.getElementById('p17-body').innerHTML =
|
||||
hero(8,'§ 17 · Глава 1','Химические свойства оснований','нейтрализация','Реакции щелочей и нерастворимых оснований: соль, вода и разложение при нагревании.',['+ кислота','+ оксид','разложение'])
|
||||
+makeCard('theory','Свойства оснований','§17','<p>• <b>Нейтрализация:</b> основание + кислота → соль + вода: NaOH + HCl → NaCl + H₂O.<br>• Щёлочь + <b>кислотный оксид</b> → соль + вода: 2NaOH + CO₂ → Na₂CO₃ + H₂O.<br>• <b>Разложение</b> нерастворимых оснований при нагревании: Cu(OH)₂ →(t) CuO + H₂O.</p>')
|
||||
+wgt('Индикатор: нейтрализация (двигай pH)','<div id="c-neutral-ind"></div>')
|
||||
+rememberBox(['Реакция нейтрализации идёт всегда (образуется вода).','Щёлочи термически устойчивы, нерастворимые основания — разлагаются.'])
|
||||
+qList(['Допиши: KOH + H₂SO₄ → ?','Что образуется при нагревании Fe(OH)₃?'])
|
||||
+secNav('p16','p18')+readButton('p17'); wireReadBtn('p17'); }
|
||||
|
||||
function bp18(){ document.getElementById('p18-body').innerHTML =
|
||||
hero(9,'§ 18 · Глава 1','Получение оснований · Лаб. 1 · ПР 2','CuSO₄ + 2NaOH → Cu(OH)₂↓','Как получают щёлочи и нерастворимые основания; лабораторный опыт и реакция нейтрализации.',['Лаб.1','ПР.2','осадок'])
|
||||
+makeCard('theory','Получение оснований','§18','<p>• <b>Щёлочи:</b> активный металл + вода (2Na + 2H₂O → 2NaOH + H₂↑) или основный оксид + вода.<br>• <b>Нерастворимые основания:</b> щёлочь + соль → основание↓ + соль: CuSO₄ + 2NaOH → Cu(OH)₂↓ + Na₂SO₄.</p>')
|
||||
+makeCard('lab','Лабораторный опыт 1 · Получение нерастворимого основания',null,'<p>К раствору соли меди(II) добавь раствор щёлочи — выпадает <b>голубой осадок</b> Cu(OH)₂.</p><div class="tt-row"><div><div style="text-align:center;color:#0891b2">'+tube({color:'#a5f3fc',precipitate:'#22d3ee',label:'Cu(OH)₂'})+'</div><div class="tt-cap">Голубой осадок Cu(OH)₂↓</div></div></div><p>CuSO₄ + 2NaOH → Cu(OH)₂↓ + Na₂SO₄</p>')
|
||||
+makeCard('lab','Практическая работа 2 · Реакция нейтрализации',null,'<p>К щёлочи с фенолфталеином (малиновый) приливай кислоту — окраска исчезает в точке нейтрализации.</p>'+wgt('Двигай pH: исчезновение малиновой окраски','<div id="c-pr2-ind"></div>'))
|
||||
+rememberBox(['Cu(OH)₂ — голубой, Fe(OH)₃ — бурый, Fe(OH)₂ — зеленоватый.','Нерастворимое основание получают только из щёлочи + соль.'])
|
||||
+qList(['Как получить Fe(OH)₃ из соли железа(III)?','Что наблюдают в точке нейтрализации с фенолфталеином?'])
|
||||
+secNav('p17','p19')+readButton('p18'); wireReadBtn('p18'); }
|
||||
|
||||
function bp19(){ document.getElementById('p19-body').innerHTML =
|
||||
hero(1,'§ 19 · Глава 1','Соли. Состав и классификация','катион + анион','Соли — продукт встречи кислоты и основания; растворимость определяют по таблице.',['растворимость','классификация'])
|
||||
+makeCard('theory','Соли','§19','<p><b>Соль</b> — сложное вещество из катионов металла (или NH₄⁺) и анионов кислотного остатка: NaCl, CaCO₃, CuSO₄. Это продукт замещения атомов H в кислоте на металл.</p><p>По составу: <b>средние</b> (NaCl, Na₂SO₄), <b>кислые</b> (NaHCO₃), <b>основные</b> (CuOHCl). Растворимость определяют по <b>таблице растворимости</b>.</p>')
|
||||
+flag('Таблица растворимости','Кликни катион и анион — узнаешь, растворима ли соль и выпадет ли осадок.','<div id="c-salt-sol"></div>')
|
||||
+rememberBox(['Все нитраты и соли натрия/калия растворимы.','Нерастворимая соль выпадает в осадок ↓.'])
|
||||
+qList(['Растворим ли BaSO₄? А CaCO₃?','Из какой кислоты и основания получают Na₂SO₄?'])
|
||||
+secNav('p18','p20')+readButton('p19'); wireReadBtn('p19'); }
|
||||
|
||||
function bp20(){ document.getElementById('p20-body').innerHTML =
|
||||
hero(2,'§ 20 · Глава 1','Химические свойства солей · Лаб. 2','↓ ↑ H₂O','Реакции ионного обмена и вытеснение металлов из растворов солей.',['РИО','соль + Me','Лаб.2'])
|
||||
+makeCard('theory','Свойства солей','§20','<p>• <b>Соль + соль</b> → две новые соли (если ↓): AgNO₃ + NaCl → AgCl↓ + NaNO₃.<br>• <b>Соль + щёлочь</b> → новое основание↓ + соль.<br>• <b>Соль + кислота</b> → новая соль + кислота (если ↓↑).<br>• <b>Соль + металл</b>: более активный металл вытесняет менее активный: Fe + CuSO₄ → FeSO₄ + Cu.</p>')
|
||||
+flag('Таблица растворимости (предскажи осадок)','Проверь, образуется ли осадок в реакции обмена.','<div id="c-salt-sol2"></div>')
|
||||
+flag('Ряд активности (соль + металл)','Кликни металл — увидишь, какие металлы он вытесняет из растворов солей.','<div id="c-salt-act"></div>')
|
||||
+makeCard('lab','Лабораторный опыт 2 · Соль + металл',null,'<p>Опусти железный гвоздь в раствор CuSO₄ — он покрывается <b>красным налётом меди</b>, раствор бледнеет. Fe + CuSO₄ → FeSO₄ + Cu.</p>')
|
||||
+rememberBox(['РИО идёт, если образуется осадок, газ или вода.','Металл вытесняет из соли только менее активный металл.'])
|
||||
+qList(['Вытеснит ли серебро медь из CuSO₄?','Допиши: BaCl₂ + Na₂SO₄ → ?'])
|
||||
+secNav('p19','p21')+readButton('p20'); wireReadBtn('p20'); }
|
||||
|
||||
function bp21(){ document.getElementById('p21-body').innerHTML =
|
||||
hero(3,'§ 21 · Глава 1','Получение и применение солей','много способов','Соли получают десятком способов — это перекрёсток всех классов.',['способы','применение'])
|
||||
+makeCard('theory','Способы получения солей','§21','<p>• кислота + основание (нейтрализация)<br>• кислота + основный оксид<br>• кислота + металл<br>• кислота + соль<br>• щёлочь + кислотный оксид<br>• соль + соль<br>• соль + металл<br>• металл + неметалл (2Na + Cl₂ → 2NaCl)</p><p><b>Применение:</b> NaCl — пища, Na₂CO₃ — стекло и мыло, CaCO₃ — строительство, KNO₃ — удобрения.</p>')
|
||||
+rememberBox(['Соль — продукт реакции кислоты и основания (или их «родственников»).','Один и тот же продукт можно получить разными способами.'])
|
||||
+qList(['Назови три способа получить CuSO₄.','Где применяют поваренную соль NaCl?'])
|
||||
+secNav('p20','p22')+readButton('p21'); wireReadBtn('p21'); }
|
||||
|
||||
function bp22(){ document.getElementById('p22-body').innerHTML =
|
||||
hero(4,'§ 22 · Глава 1','Взаимосвязь классов · ПР 3','генетическая связь','Все классы связаны цепочками превращений — от простого вещества до соли.',['генетика','ПР.3'])
|
||||
+makeCard('theory','Генетическая связь','§22','<p><b>Ряд металла:</b> металл → основный оксид → основание → соль<br>Na → Na₂O → NaOH → NaCl</p><p><b>Ряд неметалла:</b> неметалл → кислотный оксид → кислота → соль<br>S → SO₃ → H₂SO₄ → Na₂SO₄</p><p>Эти ряды «встречаются» в солях — продукте реакции кислоты и основания.</p>')
|
||||
+'<div class="insight-box"><div class="insight-title">Цепочка превращений</div><p>Ca → CaO → Ca(OH)₂ → CaCl₂. Попробуй записать уравнение каждого перехода!</p></div>'
|
||||
+makeCard('lab','Практическая работа 3 · Экспериментальные задачи',null,'<p>По выданным реактивам осуществи цепочку превращений и докажи получение каждого вещества (например, получи из меди — оксид меди, затем соль).</p>')
|
||||
+rememberBox(['Металл и неметалл — начала двух генетических рядов.','Соль — точка встречи кислотного и основного «миров».'])
|
||||
+qList(['Запиши цепочку S → SO₂ → … → Na₂SO₃.','Какой класс стоит между оксидом металла и солью?'])
|
||||
+secNav('p21','p23')+readButton('p22'); wireReadBtn('p22'); }
|
||||
|
||||
function bp23(){ document.getElementById('p23-body').innerHTML =
|
||||
hero(5,'§ 23 · Глава 1','Решение расчётных задач','по уравнениям','Расчёты массы и объёма по уравнениям реакций классов неорганических веществ.',['расчёты','мольные отношения'])
|
||||
+makeCard('rule','Алгоритм','§23','<ol><li>Записать и уравнять уравнение.</li><li>Найти n известного: n=m/M (или V/Vm).</li><li>По коэффициентам — n искомого.</li><li>Перейти к m=n·M (или V=n·Vm).</li></ol>')
|
||||
+flag('Пошаговый решатель по уравнению','Выбери задачу и раскрывай решение по шагам.','<div class="fld"><label>Задача</label><select id="c-calc-pick"></select></div><div class="out" id="c-calc-out"></div><div class="fld"><button class="btn" id="c-calc-step">Следующий шаг ▸</button><button class="btn" id="c-calc-all">Показать всё</button></div>')
|
||||
+rememberBox(['Мольное отношение берут из коэффициентов.','Для газов используют Vm=22,4 л/моль.'])
|
||||
+secNav('p22','final1')+readButton('p23'); wireReadBtn('p23'); }
|
||||
|
||||
function bfinal(){ document.getElementById('final1-body').innerHTML =
|
||||
hero('final','Финал главы 1','Босс: классы неорганических соединений','оксиды · кислоты · основания · соли','Шесть интегрированных задач на всю главу. Победи босса — получи ачивку «Классы веществ покорены».')
|
||||
+makeCard('rule','Шпаргалка главы',null,'<div class="formula-grid"><div class="fcard"><h3>Оксиды</h3><div class="main-f">осн · кисл · амф</div></div><div class="fcard"><h3>Кислоты</h3><div class="main-f">HₓAc, основность</div></div><div class="fcard"><h3>Основания</h3><div class="main-f">Me(OH)ₙ</div></div><div class="fcard highlight"><h3>Соли</h3><div class="main-f">катион + анион</div></div></div>')
|
||||
+'<p style="margin:10px 0;color:var(--muted);font-size:.9rem">Реши все задачи ниже — за каждую +5 XP, за полную победу — ачивка и бонус.</p>'
|
||||
+secNav('p23',null); }
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user