Files
Learn_System/frontend/js/chem7_ch4_widgets.js
T
Maxim Dolgolyov 7574d16678 feat(chemistry7): Phase 4 — Глава 4 «Вода» завершена (§§23–26 + ЛО5 + ПР4 + финал)
§23 Состав и свойства воды (разложение 2:1 + реакции воды),
§24 Основания (конструктор Me(OH)n + индикаторы щёлочи),
ЛО5 Действие щелочей на индикаторы,
§25 Реакция нейтрализации (анимация фенолфталеин малиновый → бесцветный),
ПР4 Реакция нейтрализации, §26 Охрана окружающей среды (экология-инфографика),
финал главы (6 боссов). chem7_ch4_widgets.js.

ВСЕ 26 параграфов курса «Химия 7» наполнены. Тесты chem7: 15/15 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:04:49 +03:00

146 lines
10 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.
/* chem7_ch4_widgets.js — интерактивы главы 4 «Вода» (Химия 7).
* Монтируются движком chem8_engine.js: window.CHEM8_WIDGETS[id].
* Используют window.Chem8 (chem8_svg.js): chemEq, formula.
* Без эмоджи; KaTeX — через window.chem8RenderMath.
*/
(function (W) {
'use strict';
function C() { return W.Chem8 || {}; }
function $(id) { return document.getElementById(id); }
function esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }
function gcd(a, b) { return b ? gcd(b, a % b) : a; }
function ceq(src, opts){ return C().chemEq ? C().chemEq(src, opts || {}) : esc(src); }
function fml(s){ return C().formula ? C().formula(s) : s; }
function strip(color){ return '<div style="width:120px;height:32px;border-radius:8px;border:1.5px solid var(--border);background:'+color+';display:inline-block;vertical-align:middle"></div>'; }
/* §23 — разложение воды (2:1) + реакции воды */
var WRX = [
{ name:'Разложение электрическим током', eq:'2H2O = 2H2^ + O2^', cond:'эл. ток', note:'Вода разлагается на простые вещества: водорода получается вдвое больше по объёму, чем кислорода (2 : 1).' },
{ name:'Реакция с натрием', eq:'2Na + 2H2O = 2NaOH + H2^', note:'Активные металлы реагируют с водой, образуя щёлочь и водород.' },
{ name:'Реакция с оксидом кальция', eq:'CaO + H2O = Ca(OH)2', note:'Оксиды активных металлов с водой дают основания.' },
{ name:'Реакция с углекислым газом', eq:'CO2 + H2O = H2CO3', note:'Оксиды неметаллов с водой дают кислоты.' }
];
function decompSvg(){
// две перевёрнутые пробирки: H2 (заполнена на 2/2), O2 (на 1/2)
return '<svg viewBox="0 0 220 140" width="100%" style="max-width:240px">'
+ '<rect x="40" y="20" width="34" height="90" rx="6" fill="#dbeafe" stroke="#93c5fd"/>'
+ '<rect x="40" y="20" width="34" height="74" rx="6" fill="#bfdbfe"/>'
+ '<text x="57" y="125" text-anchor="middle" font-size="13" font-weight="700" fill="#1d4ed8">H₂</text>'
+ '<text x="57" y="58" text-anchor="middle" font-size="11" fill="#1e3a8a">2 V</text>'
+ '<rect x="146" y="20" width="34" height="90" rx="6" fill="#fee2e2" stroke="#fca5a5"/>'
+ '<rect x="146" y="65" width="34" height="45" rx="6" fill="#fecaca"/>'
+ '<text x="163" y="125" text-anchor="middle" font-size="13" font-weight="700" fill="#b91c1c">O₂</text>'
+ '<text x="163" y="90" text-anchor="middle" font-size="11" fill="#7f1d1d">1 V</text>'
+ '<rect x="20" y="110" width="180" height="12" rx="4" fill="#60a5fa"/>'
+ '</svg>';
}
function mount_p23() {
var m = $('p23-water'); if (!m || m._built) return; m._built = 1;
var idx = 0;
function render(){
var r = WRX[idx];
m.innerHTML = (idx===0 ? decompSvg() : '')
+ '<div class="fld"><label>Реакция воды</label><select id="p23-pick">'
+ WRX.map(function(x,i){ return '<option value="'+i+'"'+(i===idx?' selected':'')+'>'+esc(x.name)+'</option>'; }).join('') + '</select></div>'
+ '<div class="out ok" style="margin-top:8px"><div style="font-size:1.05rem">'+ceq(r.eq,{cond:r.cond})+'</div>'
+ '<div style="font-size:.86rem;color:var(--muted);margin-top:6px">'+esc(r.note)+'</div></div>';
$('p23-pick').addEventListener('change', function(e){ idx=+e.target.value; m._built=0; render(); });
}
render();
}
/* индикаторы в щёлочи */
var ALK_IND = {
'Лакмус': { neutral:['#7c3aed','фиолетовый'], alk:['#2563eb','синий'] },
'Фенолфталеин': { neutral:['#f3f4f6','бесцветный'], alk:['#db2777','малиновый'] },
'Метилоранж': { neutral:['#f59e0b','оранжевый'], alk:['#eab308','жёлтый'] }
};
function alkIndicator(mountId) {
var m = $(mountId); if (!m || m._built) return; m._built = 1;
var ind = 'Фенолфталеин';
function render(){
var c = ALK_IND[ind];
m.innerHTML = '<div class="fld"><label>Индикатор</label><select id="'+mountId+'-sel">'
+ Object.keys(ALK_IND).map(function(k){ return '<option'+(k===ind?' selected':'')+'>'+k+'</option>'; }).join('') + '</select></div>'
+ '<div class="out ok" style="margin-top:8px">В нейтральной среде: ' + strip(c.neutral[0]) + ' <b>'+c.neutral[1]+'</b><br>'
+ 'В щёлочи: ' + strip(c.alk[0]) + ' <b>'+c.alk[1]+'</b></div>';
$(mountId+'-sel').addEventListener('change', function(e){ ind=e.target.value; m._built=0; render(); });
}
render();
}
/* §24 — конструктор оснований Me(OH)n + индикаторы */
var BM = [ ['Na',1], ['K',1], ['Ca',2], ['Mg',2], ['Cu',2], ['Al',3], ['Fe',3] ];
var SOLUBLE = { Na:1, K:1, Ca:1 };
function mount_p24() {
var b = $('p24-bld');
if (b && !b._built) { b._built = 1;
function rom(n){ return ['','I','II','III'][n]; }
b.innerHTML = '<div class="fld"><label>Металл</label><select id="p24-m">'
+ BM.map(function(e,i){ return '<option value="'+i+'"'+(e[0]==='Na'?' selected':'')+'>'+e[0]+' ('+rom(e[1])+')</option>'; }).join('') + '</select> + гидроксогруппа OH (I)</div><div class="out" id="p24-out"></div>';
function upd(){
var e=BM[+$('p24-m').value], n=e[1];
var raw = e[0] + (n>1 ? '(OH)'+n : 'OH');
var sol = SOLUBLE[e[0]] ? 'щёлочь (растворимое основание)' : 'нерастворимое основание';
var out=$('p24-out'); out.className='out ok';
out.innerHTML='<span class="bd">Валентность '+e[0]+' = '+rom(n)+', OH = I → '+n+' группы OH<br>Формула основания: <b style="font-size:1.15rem">'+fml(raw)+'</b><br>Это '+sol+'.</span>';
}
$('p24-m').addEventListener('change',upd); upd();
}
alkIndicator('p24-ind');
}
function mount_lo5() { alkIndicator('lo5-ind'); }
/* §25 / ПР4 — нейтрализация (фенолфталеин малиновый → бесцветный) */
function mount_neutral(mountId) {
var m = $(mountId); if (!m || m._built) return; m._built = 1;
var done = false;
function beaker(color){ return '<svg viewBox="0 0 80 90" width="70" style="vertical-align:middle"><path d="M20 10 h40 v30 l14 38 a6 6 0 0 1-6 8 H12 a6 6 0 0 1-6-8 l14-38 Z" fill="none" stroke="var(--muted)" stroke-width="2"/><path d="M16 52 h48 l8 22 a4 4 0 0 1-4 5 H12 a4 4 0 0 1-4-5 Z" fill="'+color+'"/></svg>'; }
function render(){
m.innerHTML = '<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap">' + beaker(done?'#f8fafc':'#db2777')
+ '<div>'+(done
? 'Раствор стал <b>бесцветным</b> — кислота нейтрализовала щёлочь. Реакция завершена.'
: 'В щёлочи с фенолфталеином раствор <b>малиновый</b>. Добавляй кислоту по каплям.')+'</div></div>'
+ '<div class="fld" style="margin-top:8px"><button class="btn primary" id="'+mountId+'-go">'+(done?'Сбросить':'Добавить кислоту')+'</button></div>'
+ (done ? '<div class="out ok" style="margin-top:8px"><div style="font-size:1.05rem">'+ceq('HCl + NaOH = NaCl + H2O')+'</div><div style="font-size:.84rem;color:var(--muted);margin-top:4px">Кислота + основание → соль + вода. Это реакция <b>нейтрализации</b>.</div></div>' : '');
$(mountId+'-go').addEventListener('click', function(){ done=!done; m._built=0; render(); });
}
render();
}
function mount_p25() { mount_neutral('p25-neu'); }
function mount_pr4() { mount_neutral('pr4-neu'); }
/* §26 — охрана воды и воздуха: источники загрязнения и способы охраны */
var ECO = {
'Источники загрязнения': [
['Промышленные выбросы','Газы и пыль из труб заводов загрязняют воздух.'],
['Сточные воды','Неочищенные стоки отравляют реки и озёра.'],
['Нефть','Разливы нефти губят водные организмы.'],
['Кислотные дожди','Оксиды серы и азота в воздухе образуют кислоты, выпадающие с дождём.']
],
'Способы охраны и очистки': [
['Очистные сооружения','Сточные воды очищают перед сбросом.'],
['Фильтрование','На водопроводных станциях удаляют твёрдые частицы.'],
['Хлорирование и озонирование','Обеззараживают питьевую воду.'],
['Бережное отношение','Экономить воду и не загрязнять водоёмы.']
]
};
function mount_p26() {
var m = $('p26-eco'); if (!m || m._built) return; m._built = 1;
var cols = Object.keys(ECO).map(function(title){
var items = ECO[title].map(function(it,i){ return '<button class="eco-it btn" data-t="'+esc(title)+'" data-i="'+i+'" style="display:block;width:100%;text-align:left;margin:4px 0">'+esc(it[0])+'</button>'; }).join('');
return '<div style="flex:1;min-width:200px"><div style="font-weight:700;margin-bottom:6px">'+esc(title)+'</div>'+items+'</div>';
}).join('');
m.innerHTML = '<div style="display:flex;gap:14px;flex-wrap:wrap">'+cols+'</div><div class="out" id="p26-eco-out" style="margin-top:8px">Кликни по пункту, чтобы узнать подробнее.</div>';
var out=$('p26-eco-out');
m.querySelectorAll('.eco-it').forEach(function(b){
b.addEventListener('click', function(){ var it=ECO[b.dataset.t][+b.dataset.i]; out.className='out ok'; out.innerHTML='<b>'+esc(it[0])+'.</b> '+esc(it[1]); });
});
}
W.CHEM8_WIDGETS = Object.assign(W.CHEM8_WIDGETS || {}, {
p23: mount_p23, p24: mount_p24, lo5: mount_lo5, p25: mount_p25, pr4: mount_pr4, p26: mount_p26
});
W.FLAG_MOUNTS = Object.assign(W.FLAG_MOUNTS || {}, {});
})(window);