Files
Learn_System/frontend/js/chem7_ch3_widgets.js
T
Maxim Dolgolyov 0af08bcc55 feat(chemistry7): Phase 3 Волна 1 — Глава 3, §18 + §19 + §20 + ЛО3
§18 Водород — элемент и простое вещество (паспорт + модель H2),
§19 Химические свойства водорода (горение → вода, восстановление CuO → Cu),
§20 Понятие о кислотах (индикаторы лакмус/метилоранж + таблица кислот),
ЛО3 Действие кислот на индикаторы. chem7_ch3_widgets.js. Тест: 13/13 pass.

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

173 lines
14 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_ch3_widgets.js — интерактивы главы 3 «Водород» (Химия 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; }
var COL = { H:'#cbd5e1', O:'#ef4444' };
function molSvg(atoms){
var list=[]; atoms.forEach(function(p){ for(var i=0;i<p[1];i++) list.push(p[0]); });
var x=22, svg=''; list.forEach(function(el){ x+=16; svg+='<circle cx="'+x+'" cy="30" r="15" fill="'+(COL[el]||'#94a3b8')+'" stroke="rgba(0,0,0,.25)"/><text x="'+x+'" y="35" text-anchor="middle" font-size="12" font-weight="700" fill="#fff">'+el+'</text>'; x+=24; });
return '<svg viewBox="0 0 '+(x+10)+' 60" width="100%" style="max-width:'+(x+10)+'px;height:auto">'+svg+'</svg>';
}
/* §18 — модель H₂ + паспорт водорода */
function mount_p18() {
var m = $('p18-card'); if (!m || m._built) return; m._built = 1;
m.innerHTML = molSvg([['H',2]])
+ '<div class="out ok"><b>Водород</b><br>Элемент: символ H, $Z=1$, $A_r=1$ — самый лёгкий элемент.<br>'
+ 'Простое вещество: молекула $H_2$ — самый лёгкий газ, без цвета и запаха, легче воздуха, мало растворим в воде.<br>'
+ 'В природе: в составе воды, многих веществ; во Вселенной — самый распространённый элемент.</div>';
if (W.chem8RenderMath) try { W.chem8RenderMath(m); } catch(e){}
}
/* §19 — реакции водорода: горение и восстановление */
var RX = [
{ name:'Горение водорода в кислороде', eq:'2H2 + O2 = 2H2O', note:'Водород горит, образуя воду. Смесь водорода с воздухом — «гремучий газ», взрывается!' },
{ name:'Восстановление оксида меди(II)', eq:'H2 + CuO = Cu + H2O', note:'Водород отнимает кислород у оксида: чёрный CuO превращается в красную медь. Водород здесь — восстановитель.' }
];
function mount_p19() {
var m = $('p19-rx'); if (!m || m._built) return; m._built = 1;
var idx = 0;
function render(){
var r = RX[idx];
var swatch = idx===1 ? '<div style="margin-top:6px"><span style="display:inline-block;width:46px;height:20px;background:#1f2937;border-radius:4px;vertical-align:middle"></span> CuO (чёрный) &rarr; <span style="display:inline-block;width:46px;height:20px;background:#b45309;border-radius:4px;vertical-align:middle"></span> Cu (красный)</div>' : '';
m.innerHTML = '<div class="fld"><label>Реакция</label><select id="p19-pick">'
+ RX.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) + '</div><div style="font-size:.86rem;color:var(--muted);margin-top:6px">' + esc(r.note) + '</div>' + swatch + '</div>';
$('p19-pick').addEventListener('change', function(e){ idx=+e.target.value; m._built=0; render(); });
}
render();
}
/* индикаторы */
var ACIDS = [
{ f:'HCl', name:'соляная', res:'Cl', resName:'хлорид', resVal:1 },
{ f:'H2SO4', name:'серная', res:'SO4', resName:'сульфат', resVal:2 },
{ f:'HNO3', name:'азотная', res:'NO3', resName:'нитрат', resVal:1 },
{ f:'H2CO3', name:'угольная', res:'CO3', resName:'карбонат',resVal:2 }
];
var INDIC = {
'Лакмус': { neutral:['#7c3aed','фиолетовый'], acid:['#dc2626','красный'] },
'Метилоранж': { neutral:['#f59e0b','оранжевый'], acid:['#e11d48','розово-красный'] }
};
function indicatorWidget(mountId, withAcidPick) {
var m = $(mountId); if (!m || m._built) return; m._built = 1;
var ind = 'Лакмус', acid = 0;
function strip(color){ return '<div style="width:120px;height:34px;border-radius:8px;border:1.5px solid var(--border);background:'+color+';display:inline-block;vertical-align:middle"></div>'; }
function render(){
var a = ACIDS[acid], col = INDIC[ind];
m.innerHTML = '<div class="fld"><label>Индикатор</label><select id="'+mountId+'-ind">'
+ Object.keys(INDIC).map(function(k){ return '<option'+(k===ind?' selected':'')+'>'+k+'</option>'; }).join('') + '</select>'
+ (withAcidPick ? '<label>Кислота</label><select id="'+mountId+'-acid">' + ACIDS.map(function(x,i){ return '<option value="'+i+'"'+(i===acid?' selected':'')+'>'+fml(x.f)+' ('+x.name+')</option>'; }).join('') + '</select>' : '') + '</div>'
+ '<div class="out ok" style="margin-top:8px">В нейтральной среде: ' + strip(col.neutral[0]) + ' <b>'+col.neutral[1]+'</b><br>'
+ 'В кислоте' + (withAcidPick?(' ('+fml(a.f)+')'):'') + ': ' + strip(col.acid[0]) + ' <b>'+col.acid[1]+'</b></div>';
$(mountId+'-ind').addEventListener('change', function(e){ ind=e.target.value; m._built=0; render(); });
if (withAcidPick) $(mountId+'-acid').addEventListener('change', function(e){ acid=+e.target.value; m._built=0; render(); });
}
render();
}
function mount_p20() {
indicatorWidget('p20-ind', true);
var t = $('p20-acids'); if (t && !t._built) { t._built = 1;
t.innerHTML = '<table style="width:100%;border-collapse:collapse;font-size:.9rem"><tr style="background:var(--pri-soft)"><th style="padding:6px;text-align:left">Кислота</th><th style="padding:6px;text-align:left">Название</th><th style="padding:6px;text-align:left">Остаток</th></tr>'
+ ACIDS.map(function(a){ return '<tr><td style="padding:6px;border-top:1px solid var(--border)">'+fml(a.f)+'</td><td style="padding:6px;border-top:1px solid var(--border)">'+a.name+'</td><td style="padding:6px;border-top:1px solid var(--border)">'+fml(a.res)+' ('+a.resName+')</td></tr>'; }).join('') + '</table>';
}
}
function mount_lo3() { indicatorWidget('lo3-ind', false); }
/* §21 — ряд активности металлов */
var ROW = ['K','Ca','Na','Mg','Al','Zn','Fe','Ni','Sn','Pb','H','Cu','Hg','Ag','Pt','Au'];
function mount_p21() {
var m = $('p21-act'); if (!m || m._built) return; m._built = 1;
var hIdx = ROW.indexOf('H');
m.innerHTML = '<div style="display:flex;flex-wrap:wrap;gap:4px">'
+ ROW.map(function(el,i){ var isH=el==='H'; return '<button class="act-cell" data-i="'+i+'" style="padding:6px 9px;border-radius:7px;border:1.5px solid '+(isH?'#dc2626':'var(--border)')+';background:'+(isH?'#fee2e2':'var(--card)')+';color:var(--text);font-weight:700;cursor:'+(isH?'default':'pointer')+'">'+(isH?'H₂':el)+'</button>'; }).join('') + '</div>'
+ '<div style="font-size:.8rem;color:var(--muted);margin-top:4px">Слева активность убывает вправо. Граница — водород H₂.</div>'
+ '<div class="out" id="p21-act-out" style="margin-top:8px">Кликни по металлу — узнаешь, вытесняет ли он водород из кислоты.</div>';
var out = $('p21-act-out');
m.querySelectorAll('.act-cell').forEach(function(b){
b.addEventListener('click', function(){
var i=+b.dataset.i, el=ROW[i]; if(el==='H'){ out.className='out'; out.innerHTML='<b>Водород H₂</b> — граница ряда активности.'; return; }
out.className='out ok';
if(i<hIdx){
var extra = (i<=2) ? ' <span style="color:#dc2626">Внимание: очень активный металл — с кислотами реагирует бурно (для получения водорода используют Zn, Fe).</span>' : '';
out.innerHTML = '<b>'+el+'</b> стоит левее H₂ → <b>вытесняет водород</b> из соляной и серной кислот: образуются соль и $H_2\\uparrow$.'+extra;
} else {
out.innerHTML = '<b>'+el+'</b> стоит правее H₂ → водород из кислот <b>не вытесняет</b> (например, медь и серебро с этими кислотами не реагируют).';
}
if (W.chem8RenderMath) try { W.chem8RenderMath(out); } catch(e){}
});
});
}
/* ЛО4 — взаимодействие кислот с металлами */
var L4M = [ ['Zn','цинк',1], ['Fe','железо',1], ['Mg','магний',1], ['Cu','медь',0] ];
var L4A = [ ['HCl','соляная'], ['H2SO4','серная'] ];
function mount_lo4() {
var m = $('lo4-rx'); if (!m || m._built) return; m._built = 1;
var mi=0, ai=0;
var EQ = { 'Zn|HCl':'Zn + 2HCl = ZnCl2 + H2^', 'Zn|H2SO4':'Zn + H2SO4 = ZnSO4 + H2^',
'Fe|HCl':'Fe + 2HCl = FeCl2 + H2^', 'Fe|H2SO4':'Fe + H2SO4 = FeSO4 + H2^',
'Mg|HCl':'Mg + 2HCl = MgCl2 + H2^', 'Mg|H2SO4':'Mg + H2SO4 = MgSO4 + H2^' };
function render(){
m.innerHTML = '<div class="fld"><label>Металл</label><select id="lo4-m">'+L4M.map(function(x,i){return '<option value="'+i+'"'+(i===mi?' selected':'')+'>'+x[1]+' ('+x[0]+')</option>';}).join('')+'</select>'
+ '<label>Кислота</label><select id="lo4-a">'+L4A.map(function(x,i){return '<option value="'+i+'"'+(i===ai?' selected':'')+'>'+fml(x[0])+'</option>';}).join('')+'</select>'
+ '<button class="btn primary" id="lo4-go">Провести опыт</button></div><div class="out" id="lo4-out" style="margin-top:8px">Выбери металл и кислоту.</div>';
$('lo4-m').addEventListener('change',function(e){mi=+e.target.value;m._built=0;render();});
$('lo4-a').addEventListener('change',function(e){ai=+e.target.value;m._built=0;render();});
$('lo4-go').addEventListener('click',function(){
var met=L4M[mi], ac=L4A[ai], out=$('lo4-out');
if(!met[2]){ out.className='out bad'; out.innerHTML='<b>'+met[1]+'</b> стоит правее H₂ в ряду активности — реакция <b>не идёт</b>, пузырьки не выделяются.'; return; }
out.className='out ok';
out.innerHTML='Наблюдаем <b>выделение пузырьков газа</b> (водород $H_2\\uparrow$). Металл вытесняет водород из кислоты:<div style="font-size:1.05rem;margin-top:6px">'+ceq(EQ[met[0]+'|'+ac[0]])+'</div>';
if (W.chem8RenderMath) try { W.chem8RenderMath(out); } catch(e){}
});
}
render();
}
/* §22 — конструктор солей (металл + кислотный остаток) */
var SM = [ ['Na',1], ['K',1], ['Ca',2], ['Mg',2], ['Zn',2], ['Al',3] ];
var SR = [ ['Cl',1,'хлорид'], ['NO3',1,'нитрат'], ['SO4',2,'сульфат'], ['CO3',2,'карбонат'] ];
function mount_p22() {
var m = $('p22-salt'); if (!m || m._built) return; m._built = 1;
function render(){
m.innerHTML = '<div class="fld"><label>Металл</label><select id="p22-m">'+SM.map(function(x,i){return '<option value="'+i+'"'+(x[0]==='Ca'?' selected':'')+'>'+x[0]+' ('+rom(x[1])+')</option>';}).join('')+'</select>'
+ '<label>Остаток</label><select id="p22-r">'+SR.map(function(x,i){return '<option value="'+i+'">'+fml(x[0])+' ('+x[2]+', '+rom(x[1])+')</option>';}).join('')+'</select></div><div class="out" id="p22-out"></div>';
$('p22-m').addEventListener('change',upd); $('p22-r').addEventListener('change',upd); upd();
}
function rom(n){ return ['','I','II','III'][n]; }
function upd(){
var me=SM[+$('p22-m').value], re=SR[+$('p22-r').value];
var lcm=me[1]*re[1]/gcd(me[1],re[1]), x=lcm/me[1], y=lcm/re[1];
var poly=/[0-9]/.test(re[0]);
var raw = me[0] + (x>1?x:'') + (poly && y>1 ? '('+re[0]+')'+y : re[0] + (y>1?y:''));
var out=$('p22-out'); out.className='out ok';
out.innerHTML='<span class="bd">Валентности: '+me[0]+' = '+rom(me[1])+', остаток '+fml(re[0])+' = '+rom(re[1])+'<br>Формула соли ('+re[2]+'а): <b style="font-size:1.15rem">'+fml(raw)+'</b></span>';
}
render();
}
/* ПР3 — чистота водорода («гремучий газ») */
function mount_pr3() {
var m = $('pr3-test'); if (!m || m._built) return; m._built = 1;
m.innerHTML = '<div class="fld"><button class="btn primary" id="pr3-mix">Поджечь смесь H₂ с воздухом</button><button class="btn" id="pr3-pure">Поджечь чистый H₂</button></div><div class="out" id="pr3-out" style="margin-top:8px">Чтобы проверить чистоту водорода, его поджигают.</div>';
$('pr3-mix').addEventListener('click',function(){ var o=$('pr3-out'); o.className='out bad'; o.innerHTML='Смесь водорода с воздухом — «<b>гремучий газ</b>» — взрывается с резким <b>хлопком</b>. Значит, водород собран нечисто.'; });
$('pr3-pure').addEventListener('click',function(){ var o=$('pr3-out'); o.className='out ok'; o.innerHTML='Чистый водород горит <b>спокойно</b>, почти без звука. Значит, газ собран чисто.'; });
}
W.CHEM8_WIDGETS = Object.assign(W.CHEM8_WIDGETS || {}, {
p18: mount_p18, p19: mount_p19, p20: mount_p20, lo3: mount_lo3,
p21: mount_p21, lo4: mount_lo4, p22: mount_p22, pr3: mount_pr3
});
W.FLAG_MOUNTS = Object.assign(W.FLAG_MOUNTS || {}, {});
})(window);