'Edit or archive club','member'=>'Add member','invite'=>'Invite members', 'season'=>'Add season','charge'=>'Record season dues','payment'=>'Record payment', 'adjust'=>'Correct dues','reverse'=>'Reverse incorrect payment','revokeInvitation'=>'Revoke invitation', 'note_add'=>'Add note','note_edit'=>'Edit note','note_delete'=>'Delete note']; $doc=new DOMDocument('1.0','UTF-8');$previous=libxml_use_internal_errors(true); try{$loaded=$doc->loadHTML(''.$html,LIBXML_NONET);} finally{libxml_clear_errors();libxml_use_internal_errors($previous);} if(!$loaded)throw new RuntimeException('Cannot render club dialogs.'); $main=$doc->getElementsByTagName('main')->item(0); if(!$main)throw new LogicException('Club summary container is missing.'); $dialogs=[];$index=0; foreach(iterator_to_array($main->getElementsByTagName('form')) as $form){ $values=[];foreach($form->getElementsByTagName('input') as $input)$values[$input->getAttribute('name')]=$input->getAttribute('value'); $step=$values['step']??''; if(!in_array($values['action']??'',['Roster.workspace','Roster.memberSummary'],true)||!isset($titles[$step]))continue; $title=$step==='member'&&!empty($values['membership_serial'])?'Edit membership':$titles[$step]; $id='club-action-'.(++$index);$parent=$form->parentNode; $trigger=$doc->createElement('button');$trigger->appendChild($doc->createTextNode($title)); foreach(['type'=>'button','class'=>'btn '.($step==='note_delete'?'btn-outline-danger':'btn-outline-primary').' me-2 mb-2','data-bs-toggle'=>'modal','data-bs-target'=>'#'.$id,'data-club-step'=>$step] as $key=>$value)$trigger->setAttribute($key,$value); $dialog=$doc->createElement('div'); foreach(['class'=>'modal fade club-action-modal','id'=>$id,'tabindex'=>'-1','aria-labelledby'=>$id.'-title','aria-hidden'=>'true'] as $key=>$value)$dialog->setAttribute($key,$value); $layout=$dialog->appendChild($doc->createElement('div'));$layout->setAttribute('class','modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable'); $content=$layout->appendChild($doc->createElement('div'));$content->setAttribute('class','modal-content'); $header=$content->appendChild($doc->createElement('div'));$header->setAttribute('class','modal-header'); $heading=$header->appendChild($doc->createElement('h2'));$heading->setAttribute('class','modal-title fs-5');$heading->setAttribute('id',$id.'-title');$heading->appendChild($doc->createTextNode($title)); $close=$header->appendChild($doc->createElement('button'));$close->setAttribute('type','button');$close->setAttribute('class','btn-close');$close->setAttribute('data-bs-dismiss','modal');$close->setAttribute('aria-label','Close'); $body=$content->appendChild($doc->createElement('div'));$body->setAttribute('class','modal-body'); // Keep the selected row visible in the dialog so financial/member actions are unambiguous. $row=$parent;while($row&&$row!==$main&&!in_array($row->nodeName,['tr','li'],true))$row=$row->parentNode; if($row&&$row!==$main&&!in_array($step,['note_edit','note_delete'],true)){ $text=$row->textContent; if($row->nodeName==='tr')$text=implode(' ยท ',array_map(static fn($cell)=>trim($cell->textContent),array_slice(iterator_to_array($row->getElementsByTagName('td')),0,-1))); $context=$body->appendChild($doc->createElement('p'));$context->setAttribute('class','text-secondary');$context->appendChild($doc->createTextNode(trim(preg_replace('/\s+/u',' ',$text)))); } if($parent->nodeName==='details'){ $parent->parentNode->replaceChild($trigger,$parent); foreach(iterator_to_array($parent->childNodes) as $child)if($child->nodeName!=='summary')$body->appendChild($child); }else{ $previous=$form->previousSibling; if($previous&&$previous->nodeName==='h4')$previous->parentNode->removeChild($previous); $following=$form->nextSibling; $parent->replaceChild($trigger,$form);$body->appendChild($form); if($following&&$following->nodeName==='p')$body->appendChild($following); } $error=$doc->createElement('p');$error->setAttribute('class','alert alert-danger club-modal-error');$error->setAttribute('role','alert');$error->setAttribute('tabindex','-1');$error->setAttribute('hidden','hidden');$body->insertBefore($error,$body->firstChild); $footer=$content->appendChild($doc->createElement('div'));$footer->setAttribute('class','modal-footer'); $cancel=$footer->appendChild($doc->createElement('button'));$cancel->setAttribute('type','button');$cancel->setAttribute('class','btn btn-outline-secondary');$cancel->setAttribute('data-bs-dismiss','modal');$cancel->appendChild($doc->createTextNode('Cancel')); $dialogs[]=$dialog; if($step==='invite')foreach(iterator_to_array($main->getElementsByTagName('a')) as $link)if($link->getAttribute('href')==='#club-invitations'){$link->parentNode->replaceChild($trigger,$link);break;} } foreach($dialogs as $dialog)$main->appendChild($dialog); $script=$main->appendChild($doc->createElement('script'));$script->setAttribute('src','js/club-modals.js?version='.Base::VERSION); return $doc->saveHTML($main); } }