1import {scenarios,actions,counters,reviewChoices,reviewDate,makePlan,defaultChoices} from './planner.mjs?v=20261003-select1'; 2export function initPlanner({root=document,lang,onGoal=()=>{},onChange=()=>{}}){ 3 const $=id=>root.querySelector('#'+id),t=(en,zh)=>lang==='zh'?zh:en; 4 let legacy={},fixedReview='',goal='work'; 5 function options(id,rows,value,retained){ 6 const select=$(id);select.replaceChildren(); 7 for(const r of rows){const o=document.createElement('option');o.value=r.id;o.textContent=r.label[lang];select.append(o);} 8 if(retained!==undefined){const o=document.createElement('option');o.value='saved';o.textContent=retained;select.prepend(o);} 9 select.value=value; 10 } 11 function populate(note={}){ 12 legacy={};const base=defaultChoices(goal); 13 for(const [field,rows]of [['task',scenarios[goal]],['action',actions[goal]],['counter',counters[goal]]]){ 14 const retained=typeof note[field]==='string';if(retained)legacy[field]=note[field]; 15 const label=note[field]===''?t('Not chosen yet','å°æªéæ©'):field==='task'?t('Saved: ','å·²åï¼')+note[field]:field==='action'?t('Keep my saved action','ä¿çå·²ä¿åçè¡å¨'):t('Keep my saved condition','ä¿çå·²ä¿åçè°æ´æ¡ä»¶'); 16 options('note-'+field,rows,retained?'saved':base[field],retained?label:undefined); 17 } 18 // Resolve relative choices once, using the visitor's local calendar. Restoring 19 // an absolute date never silently moves a review into the future. 20 const dated=typeof note.review==='string'&¬e.review.length>0,restored=Object.hasOwn(note,'review'); 21 options('note-review',reviewChoices.map(([id,en,zh])=>({id,label:{en,zh}})),dated?'saved':restored?'none':'7',dated?t('Saved: ','å·²åï¼')+note.review:undefined); 22 fixedReview=dated?note.review:reviewDate(restored?'none':'7');$('note-done').value=note.done?'tried':'planned';preview(); 23 } 24 function read(){ 25 const defaults=defaultChoices(goal),choice={goal,done:$('note-done').value==='tried',review:'none'}; 26 for(const k of ['task','action','counter'])choice[k]=$('note-'+k).value==='saved'?defaults[k]:$('note-'+k).value; 27 const note=makePlan(choice,lang);for(const k of ['task','action','counter'])if($('note-'+k).value==='saved')note[k]=legacy[k]; 28 if($('note-task').value==='saved'&&legacy.task&&$('note-action').value!=='saved'){ 29 const scenario=scenarios[goal].find(s=>s.label.en===legacy.task||s.label.zh===legacy.task)||{input:{en:legacy.task,zh:legacy.task},output:{en:'a result you can check',zh:'ä¸ä»½å¯æ ¸å¯¹çç»æ'}}; 30 note.action=actions[goal].find(a=>a.id===choice.action).make(scenario)[lang]; 31 } 32 note.review=fixedReview;return note; 33 } 34 function preview(){const note=read();for(const k of ['task','action','counter','review'])root.querySelector('[data-plan-output='+k+']').textContent=note[k]||(k==='review'?t('No review date set','ææªå®æå¤æ¥'):t('Not chosen yet','å°æªéæ©'));} 35 function changed(){preview();onChange();} 36 $('plan-goal').addEventListener('change',()=>{goal=$('plan-goal').value;populate();onGoal(goal);changed();}); 37 $('note-task').addEventListener('change',()=>{ 38 // A new scenario gets a matching action; a saved action is retained until the 39 // reader actively chooses another scenario or direction. 40 if($('note-task').value!=='saved'){const id=$('note-action').value;options('note-action',actions[goal],actions[goal].some(a=>a.id===id)?id:actions[goal][0].id);delete legacy.action;}$('note-done').value='planned';changed(); 41 }); 42 $('note-action').addEventListener('change',()=>{if($('note-action').value!=='saved'&&$('note-task').value==='saved'&&!legacy.task)$('note-task').value=defaultChoices(goal).task;$('note-done').value='planned';changed();}); 43 for(const k of ['counter','done'])$('note-'+k).addEventListener('change',changed); 44 $('note-review').addEventListener('change',()=>{fixedReview=$('note-review').value==='saved'?legacy.review:reviewDate($('note-review').value);changed();}); 45 return {read,load(nextGoal,note){goal=nextGoal;$('plan-goal').value=goal;populate(note);legacy.review=note?.review||'';}}; 46}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.