(function(){'use strict'; if(window.fiChampRunningOrder)return; var pending=0; function mount(body){ if(!body||body.fiOrderController)return; var table=body.closest('table'),comp=Number(body.dataset.compId||table.dataset.compId),text={}; try{text=JSON.parse(body.dataset.stageLabels||'{}');}catch(e){} function t(key){return text['stage_'+key]||key;} var data=null,loading=false,saving=false,dragging=false,sortable=false,before=[],disposed=false; var note=document.createElement('p');note.className='fi-champ-order-status';note.setAttribute('role','status');note.setAttribute('aria-live','polite');note.style.cssText='font:11px/1.4 system-ui,sans-serif;color:#70889b;margin:4px 12px 8px'; var wrap=table.closest('.champ-table-wrap')||table;wrap.parentNode.insertBefore(note,wrap); function status(value,error){note.textContent=value;note.style.color=error?'#b03d4b':'#70889b';} function rows(){return Array.from(body.querySelectorAll(':scope>tr[data-row-id]:not(.ui-sortable-helper):not(.ui-sortable-placeholder)'));} function id(row){return Number(row.dataset.rowId.replace(/^dancer_/,''));} function segment(){return data&&data.segments[comp+':1'];} function focused(){return body.contains(document.activeElement)&&document.activeElement.matches('input,textarea,select');} function disable(){if(sortable)jQuery(body).sortable('option','disabled',loading||saving||!data);} async function request(write,ids){ var controller=new AbortController(),timer=setTimeout(function(){controller.abort();},30000); try{var url='/organizer/stage_order.php',options={credentials:'same-origin',cache:'no-store',signal:controller.signal}; if(write){var form=new URLSearchParams();form.set('token',data.token);form.set('payload',JSON.stringify({op:'reorder_champ',comp:comp,round:1,hall:data.hall,stage:data.stage,roster_only:true,version:data.version,order_version:segment().order_version,ids:ids}));options.method='POST';options.body=form;} else url+='?'+new URLSearchParams({comp:comp,roster_only:'1'}); var response=await fetch(url,options),result;try{result=await response.json();}catch(e){throw new Error(t('error'));} if(!response.ok||!result.ok)throw new Error(result.error||t('error'));return result; }finally{clearTimeout(timer);} } function apply(result){ var first=result.segments[comp+':1'];if(!first||first.category!==4)throw new Error(t('changed')); var signatures={},map={};rows().forEach(function(row){map[id(row)]=row;}); [1,2].forEach(function(round){var s=result.segments[comp+':'+round];if(!s)return;s.groups.forEach(function(group){group.rows.forEach(function(person){(signatures[person.id]||(signatures[person.id]=[])).push(round+':'+group.key);});});}); first.base_order.forEach(function(dancer){if(map[dancer]){map[dancer].dataset.runningGroup=(signatures[dancer]||['unknown:'+dancer]).join('|');body.appendChild(map[dancer]);delete map[dancer];}}); Object.keys(map).forEach(function(dancer){map[dancer].dataset.runningGroup='unknown:'+dancer;body.appendChild(map[dancer]);}); data=result;initSort();disable(); } function sameMembers(ids){var expected=segment().base_order.slice().sort(function(a,b){return a-b;}),actual=ids.slice().sort(function(a,b){return a-b;});return expected.length===actual.length&&expected.every(function(v,i){return v===actual[i];});} async function load(){ if(disposed||loading||saving||dragging||focused()||!body.isConnected)return; loading=true;disable();if(!data)status(t('loading')); try{var result=await request(false);if(!body.isConnected)return;if(focused())return;apply(result);status(t('tabulation_order_hint'));} catch(e){status(e.message||t('error'),true);}finally{loading=false;disable();} } async function save(){ var ids=rows().map(id);if(!sameMembers(ids)){before.forEach(function(row){body.appendChild(row);});status(t('changed'),true);return;} if(ids.every(function(v,i){return v===id(before[i]);}))return; saving=true;pending++;disable();status(t('saving')); try{var result=await request(true,ids);if(body.isConnected){apply(result);status(t('saved'));}} catch(e){if(body.isConnected){before.forEach(function(row){body.appendChild(row);});status(e.message||t('error'),true);}} finally{saving=false;pending--;disable();} } function initSort(){ if(sortable||!window.jQuery||!jQuery.fn.sortable)return;sortable=true; jQuery(body).sortable({items:'>tr[data-row-id]',handle:'td.col-num,td.col-name',cancel:'input,textarea,select,button,a,label',axis:'y',scroll:true,scrollSensitivity:50,scrollSpeed:15,placeholder:'champ-row-ghost', helper:function(event,row){var helper=row.clone().removeAttr('data-row-id');helper.find('[id]').removeAttr('id');row.children().each(function(i){helper.children().eq(i).width(jQuery(this).width());});return helper;}, start:function(){if(loading||saving)return false;dragging=true;before=rows();}, update:function(){var current=rows(),valid=current.length===before.length&¤t.every(function(row,i){return row.dataset.runningGroup===before[i].dataset.runningGroup;});if(!valid){jQuery(body).sortable('cancel');status(t('same_dance'),true);return;}save();}, stop:function(){dragging=false;} }); } body.fiOrderController={load:load,pending:function(){return saving;}}; var interval=setInterval(function(){if(!body.isConnected){disposed=true;clearInterval(interval);note.remove();return;}load();},10000); load();return body.fiOrderController; } window.fiChampRunningOrder={mount:mount,pending:function(){return pending>0;}}; window.addEventListener('beforeunload',function(event){if(pending){event.preventDefault();event.returnValue='';}}); })();