Enhance bands management UI and interactivity
Improved the bands configuration page with info and controls cards, search/filter functionality, statistics, and visual feedback for checkbox actions. Updated bands.js to add animations, keyboard shortcuts, bulk award toggling, and dynamic statistics updates for a more user-friendly experience.
这个提交包含在:
		
							父节点
							
								
									bfbd104d49
								
							
						
					
					
						当前提交
						9a5f825d10
					
				
					共有  2 个文件被更改,包括 375 次插入 和 53 次删除
				
			
		|  | @ -23,39 +23,210 @@ $wwff = 0; | ||||||
| 
 | 
 | ||||||
| <h2><?php echo lang('options_bands'); ?></h2>
 | <h2><?php echo lang('options_bands'); ?></h2>
 | ||||||
| 
 | 
 | ||||||
| <div class="card"> | <!-- Info Card --> | ||||||
|  | <div class="card mb-3"> | ||||||
| 	<div class="card-header"> | 	<div class="card-header"> | ||||||
| 	<?php echo lang('options_bands'); ?>
 | 		<i class="fas fa-info-circle"></i> <?php echo lang('options_bands'); ?> Information
 | ||||||
| 	</div> | 	</div> | ||||||
| 	<div class="card-body"> | 	<div class="card-body"> | ||||||
|     <p class="card-text"> | 		<div class="alert alert-primary alert-dismissible fade show" role="alert"> | ||||||
|  | 			<strong><i class="fas fa-lightbulb"></i> Quick Guide:</strong>  | ||||||
|  | 			The <strong>first column</strong> controls if a band appears in QSO entry. The <strong>award columns</strong> (CQ, DOK, DXCC, etc.) control which awards are tracked for that band. Use the <strong>master checkboxes</strong> at the bottom to toggle all bands for a specific award. | ||||||
|  | 			<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> | ||||||
|  | 		</div> | ||||||
|  | 		 | ||||||
|  | 		<p class="card-text mb-2"> | ||||||
| 			<?php echo lang('options_bands_text_ln1'); ?>
 | 			<?php echo lang('options_bands_text_ln1'); ?>
 | ||||||
| 		</p> | 		</p> | ||||||
|     <p class="card-text"> | 		<p class="card-text mb-0"> | ||||||
| 			<?php echo lang('options_bands_text_ln2'); ?>
 | 			<?php echo lang('options_bands_text_ln2'); ?>
 | ||||||
| 		</p> | 		</p> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|  | <!-- Controls Card --> | ||||||
|  | <div class="card mb-3"> | ||||||
|  | 	<div class="card-header"> | ||||||
|  | 		<i class="fas fa-sliders-h"></i> Band Management Controls | ||||||
|  | 	</div> | ||||||
|  | 	<div class="card-body"> | ||||||
|  | 		<!-- Statistics --> | ||||||
|  | 		<div class="row mb-3"> | ||||||
|  | 			<div class="col-md-8"> | ||||||
|  | 				<div class="alert alert-info py-2 mb-0"> | ||||||
|  | 					<div class="row text-center"> | ||||||
|  | 						<div class="col-md-6 col-6"> | ||||||
|  | 							<strong id="activeBandsCount">0</strong><br> | ||||||
|  | 							<small>Active for QSO Entry</small> | ||||||
|  | 						</div> | ||||||
|  | 						<div class="col-md-6 col-6"> | ||||||
|  | 							<strong><?php echo count($bands); ?></strong><br>
 | ||||||
|  | 							<small>Total Bands Configured</small> | ||||||
|  | 						</div> | ||||||
|  | 					</div> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="col-md-4"> | ||||||
|  | 				<div class="btn-group btn-group-sm w-100" role="group"> | ||||||
|  | 					<button type="button" class="btn btn-outline-success" id="enableAllAwards" title="Enable all award tracking for all bands"> | ||||||
|  | 						<i class="fas fa-check-double"></i> Enable All Awards | ||||||
|  | 					</button> | ||||||
|  | 					<button type="button" class="btn btn-outline-warning" id="resetAllAwards" title="Disable all award tracking"> | ||||||
|  | 						<i class="fas fa-times"></i> Reset Awards | ||||||
|  | 					</button> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 		 | ||||||
|  | 		<!-- Search and Filter --> | ||||||
|  | 		<div class="row"> | ||||||
|  | 			<div class="col-md-8"> | ||||||
|  | 				<div class="input-group"> | ||||||
|  | 					<div class="input-group-prepend"> | ||||||
|  | 						<span class="input-group-text"><i class="fas fa-search"></i></span> | ||||||
|  | 					</div> | ||||||
|  | 					<input type="text" id="bandSearch" class="form-control" placeholder="Search bands, frequencies, or band groups... (Press / to focus)"> | ||||||
|  | 					<div class="input-group-append"> | ||||||
|  | 						<button class="btn btn-outline-secondary" type="button" id="clearSearch" title="Clear search"> | ||||||
|  | 							<i class="fas fa-times"></i> | ||||||
|  | 						</button> | ||||||
|  | 					</div> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="col-md-4"> | ||||||
|  | 				<div class="btn-group btn-group-sm w-100" role="group"> | ||||||
|  | 					<button type="button" class="btn btn-outline-secondary" id="showActiveOnly"> | ||||||
|  | 						<i class="fas fa-eye"></i> Active Only | ||||||
|  | 					</button> | ||||||
|  | 					<button type="button" class="btn btn-outline-secondary" id="showAll"> | ||||||
|  | 						<i class="fas fa-list"></i> Show All | ||||||
|  | 					</button> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|  | <!-- Bands Table Card --> | ||||||
|  | <div class="card"> | ||||||
|  | <div class="card-header d-flex justify-content-between align-items-center"> | ||||||
|  | 	<span><i class="fas fa-table"></i> Bands Configuration</span> | ||||||
|  | 	<span class="badge badge-secondary" id="visibleRowsCount">Loading...</span> | ||||||
|  | </div> | ||||||
|  |   <div class="card-body"> | ||||||
|  | 	 | ||||||
|     <div class="table-responsive"> |     <div class="table-responsive"> | ||||||
|  | 		<style> | ||||||
|  | 		.card { | ||||||
|  | 			box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); | ||||||
|  | 			border: 1px solid rgba(0,0,0,.125); | ||||||
|  | 		} | ||||||
|  | 		.card-header { | ||||||
|  | 			background-color: #f8f9fa;
 | ||||||
|  | 			border-bottom: 1px solid rgba(0,0,0,.125); | ||||||
|  | 			font-weight: 500; | ||||||
|  | 		} | ||||||
|  | 		.card-header i { | ||||||
|  | 			color: #6c757d;
 | ||||||
|  | 			margin-right: 0.5rem; | ||||||
|  | 		} | ||||||
|  | 		.bandtable th, .bandtable td { | ||||||
|  | 			text-align: center; | ||||||
|  | 			vertical-align: middle; | ||||||
|  | 			white-space: nowrap; | ||||||
|  | 			padding: 8px 4px; | ||||||
|  | 		} | ||||||
|  | 		.bandtable th { | ||||||
|  | 			background-color: #f8f9fa;
 | ||||||
|  | 			border-top: 2px solid #dee2e6;
 | ||||||
|  | 		} | ||||||
|  | 		.bandtable tfoot th { | ||||||
|  | 			background-color: #e9ecef;
 | ||||||
|  | 			border-top: 2px solid #adb5bd;
 | ||||||
|  | 		} | ||||||
|  | 		.bandtable th:first-child, | ||||||
|  | 		.bandtable td:first-child { | ||||||
|  | 			position: sticky; | ||||||
|  | 			left: 0; | ||||||
|  | 			background-color: #fff;
 | ||||||
|  | 			z-index: 2; | ||||||
|  | 			box-shadow: 2px 0 2px rgba(0,0,0,0.1); | ||||||
|  | 		} | ||||||
|  | 		.bandtable th:nth-child(2), | ||||||
|  | 		.bandtable td:nth-child(2) { | ||||||
|  | 			position: sticky; | ||||||
|  | 			left: 40px; | ||||||
|  | 			background-color: #fff;
 | ||||||
|  | 			z-index: 2; | ||||||
|  | 			box-shadow: 2px 0 2px rgba(0,0,0,0.1); | ||||||
|  | 			font-weight: bold; | ||||||
|  | 		} | ||||||
|  | 		.bandtable thead th:first-child, | ||||||
|  | 		.bandtable thead th:nth-child(2) { | ||||||
|  | 			z-index: 3; | ||||||
|  | 			background-color: #f8f9fa;
 | ||||||
|  | 		} | ||||||
|  | 		.bandtable input[type="checkbox"] { | ||||||
|  | 			transform: scale(1.2); | ||||||
|  | 			cursor: pointer; | ||||||
|  | 		} | ||||||
|  | 		.band-checkbox-cell { | ||||||
|  | 			background-color: #f8f9fa;
 | ||||||
|  | 		} | ||||||
|  | 		.frequency-cell { | ||||||
|  | 			font-family: monospace; | ||||||
|  | 			font-size: 0.9em; | ||||||
|  | 		} | ||||||
|  | 		.saving { | ||||||
|  | 			background-color: #fff3cd !important;
 | ||||||
|  | 			transition: background-color 0.3s ease; | ||||||
|  | 		} | ||||||
|  | 		.saved { | ||||||
|  | 			background-color: #d4edda !important;
 | ||||||
|  | 			transition: background-color 0.3s ease; | ||||||
|  | 		} | ||||||
|  | 		.updating { | ||||||
|  | 			background-color: #e2e3e5 !important;
 | ||||||
|  | 			transition: background-color 0.2s ease; | ||||||
|  | 		} | ||||||
|  | 		.updated { | ||||||
|  | 			background-color: #d1ecf1 !important;
 | ||||||
|  | 			transition: background-color 0.3s ease; | ||||||
|  | 		} | ||||||
|  | 		.band-actions { | ||||||
|  | 			white-space: nowrap; | ||||||
|  | 		} | ||||||
|  | 		.band-actions .btn { | ||||||
|  | 			margin: 0 2px; | ||||||
|  | 		} | ||||||
|  | 		@media (max-width: 768px) { | ||||||
|  | 			.bandtable th, .bandtable td { | ||||||
|  | 				padding: 4px 2px; | ||||||
|  | 				font-size: 0.85em; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		</style> | ||||||
| 		 | 		 | ||||||
|     <table style="width:100%" class="bandtable table table-sm table-striped"> |     <table style="width:100%" class="bandtable table table-sm table-striped"> | ||||||
| 			<thead> | 			<thead> | ||||||
| 				<tr> | 				<tr> | ||||||
| 					<th></th> | 					<th title="Enable/disable band for QSO entry">Active</th> | ||||||
| 					<th><?php echo lang('gen_hamradio_band'); ?></th>
 | 					<th><?php echo lang('gen_hamradio_band'); ?></th>
 | ||||||
| 					<th><?php echo lang('gen_hamradio_cq'); ?></th>
 | 					<th title="CQ Magazine DX Awards">CQ</th> | ||||||
|                     <th><?php echo lang('gen_hamradio_dok'); ?></th>
 |                     <th title="Diplom Ortsverbände Kennung">DOK</th> | ||||||
|                     <th><?php echo lang('gen_hamradio_dxcc'); ?></th>
 |                     <th title="DX Century Club">DXCC</th> | ||||||
|                     <th><?php echo lang('gen_hamradio_iota'); ?></th>
 |                     <th title="Islands On The Air">IOTA</th> | ||||||
| 					<th><?php echo lang('gen_hamradio_pota'); ?></th>
 | 					<th title="Parks on the Air">POTA</th> | ||||||
| 					<th><?php echo lang('gen_hamradio_sig'); ?></th>
 | 					<th title="Special Interest Group">SIG</th> | ||||||
|                     <th><?php echo lang('gen_hamradio_sota'); ?></th>
 |                     <th title="Summits on the Air">SOTA</th> | ||||||
|                     <th><?php echo lang('gen_hamradio_county_reference'); ?></th>
 |                     <th title="US Counties">Counties</th> | ||||||
|                     <th><?php echo lang('menu_vucc'); ?></th>
 |                     <th title="VHF/UHF Century Club">VUCC</th> | ||||||
|                     <th><?php echo lang('menu_was'); ?></th>
 |                     <th title="Worked All States">WAS</th> | ||||||
| 					<th><?php echo lang('gen_hamradio_wwff'); ?></th>
 | 					<th title="World Wide Flora and Fauna">WWFF</th> | ||||||
| 					<th><?php echo lang('gen_hamradio_bandgroup'); ?></th>
 | 					<th title="Band group classification">Group</th> | ||||||
| 					<th><?php echo lang('options_bands_ssb_qrg'); ?></th> 
 | 					<th title="SSB Operating Frequency">SSB</th>  | ||||||
| 					<th><?php echo lang('options_bands_data_qrg'); ?></th>
 | 					<th title="Data Operating Frequency">Data</th> | ||||||
| 					<th><?php echo lang('options_bands_cw_qrg'); ?></th>
 | 					<th title="CW Operating Frequency">CW</th> | ||||||
| 					<?php if($this->session->userdata('user_type') == '99') { ?>
 | 					<?php if($this->session->userdata('user_type') == '99') { ?>
 | ||||||
|                     <th></th> |                     <th></th> | ||||||
|                     <th></th> |                     <th></th> | ||||||
|  | @ -65,28 +236,28 @@ $wwff = 0; | ||||||
| 			<tbody> | 			<tbody> | ||||||
| 				<?php foreach ($bands as $band) { ?>
 | 				<?php foreach ($bands as $band) { ?>
 | ||||||
| 				<tr> | 				<tr> | ||||||
|                     <td style="text-align: center; vertical-align: middle;" class='band_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->active == 1) {echo 'checked';}?>></td>
 |                     <td class='band_<?php echo $band->id ?> band-checkbox-cell'><input type="checkbox" <?php if ($band->active == 1) {echo 'checked';}?>></td>
 | ||||||
| 					<td style="text-align: center; vertical-align: middle;" ><?php echo $band->band;?></td>
 | 					<td class="band-name"><?php echo $band->band;?></td>
 | ||||||
| 					<td style="text-align: center; vertical-align: middle;" class='cq_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->cq == 1) {echo 'checked'; $cq++;}?>></td>
 | 					<td class='cq_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->cq == 1) {echo 'checked'; $cq++;}?>></td>
 | ||||||
|                     <td style="text-align: center; vertical-align: middle;" class='dok_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->dok == 1) {echo 'checked'; $dok++;}?>></td>
 |                     <td class='dok_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->dok == 1) {echo 'checked'; $dok++;}?>></td>
 | ||||||
|                     <td style="text-align: center; vertical-align: middle;" class='dxcc_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->dxcc == 1) {echo 'checked'; $dxcc++;}?>></td>
 |                     <td class='dxcc_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->dxcc == 1) {echo 'checked'; $dxcc++;}?>></td>
 | ||||||
|                     <td style="text-align: center; vertical-align: middle;" class='iota_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->iota == 1) {echo 'checked'; $iota++;}?>></td>
 |                     <td class='iota_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->iota == 1) {echo 'checked'; $iota++;}?>></td>
 | ||||||
|                     <td style="text-align: center; vertical-align: middle;" class='pota_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->iota == 1) {echo 'checked'; $pota++;}?>></td>
 |                     <td class='pota_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->pota == 1) {echo 'checked'; $pota++;}?>></td>
 | ||||||
|                     <td style="text-align: center; vertical-align: middle;" class='sig_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->sig == 1) {echo 'checked'; $sig++;}?>></td>
 |                     <td class='sig_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->sig == 1) {echo 'checked'; $sig++;}?>></td>
 | ||||||
|                     <td style="text-align: center; vertical-align: middle;" class='sota_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->sota == 1) {echo 'checked'; $sota++;}?>></td>
 |                     <td class='sota_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->sota == 1) {echo 'checked'; $sota++;}?>></td>
 | ||||||
|                     <td style="text-align: center; vertical-align: middle;" class='uscounties_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->uscounties == 1) {echo 'checked'; $uscounties++;}?>></td>
 |                     <td class='uscounties_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->uscounties == 1) {echo 'checked'; $uscounties++;}?>></td>
 | ||||||
|                     <td style="text-align: center; vertical-align: middle;" class='vucc_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->vucc == 1) {echo 'checked'; $vucc++;}?>></td>
 |                     <td class='vucc_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->vucc == 1) {echo 'checked'; $vucc++;}?>></td>
 | ||||||
|                     <td style="text-align: center; vertical-align: middle;" class='was_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->was == 1) {echo 'checked'; $was++;}?>></td>
 |                     <td class='was_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->was == 1) {echo 'checked'; $was++;}?>></td>
 | ||||||
| 					<td style="text-align: center; vertical-align: middle;" class='wwff_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->wwff == 1) {echo 'checked'; $wwff++;}?>></td>
 | 					<td class='wwff_<?php echo $band->id ?>'><input type="checkbox" <?php if ($band->wwff == 1) {echo 'checked'; $wwff++;}?>></td>
 | ||||||
| 					<td style="text-align: center; vertical-align: middle;" ><?php echo $band->bandgroup;?></td>
 | 					<td><?php echo $band->bandgroup;?></td>
 | ||||||
| 					<td style="text-align: center; vertical-align: middle;" ><?php echo $band->ssb;?></td>
 | 					<td class="frequency-cell"><?php echo $band->ssb;?></td>
 | ||||||
| 					<td style="text-align: center; vertical-align: middle;" ><?php echo $band->data;?></td>
 | 					<td class="frequency-cell"><?php echo $band->data;?></td>
 | ||||||
| 					<td style="text-align: center; vertical-align: middle;" ><?php echo $band->cw;?></td>
 | 					<td class="frequency-cell"><?php echo $band->cw;?></td>
 | ||||||
| 					<?php if($this->session->userdata('user_type') == '99') { ?>
 | 					<?php if($this->session->userdata('user_type') == '99') { ?>
 | ||||||
| 					<td style="text-align: center; vertical-align: middle;" > | 					<td> | ||||||
| 						<a href="javascript:editBandDialog('<?php echo $band->bandid ?>');" class="btn btn-outline-primary btn-sm" title="Edit"><i class="fas fa-edit"></i></a> | 						<a href="javascript:editBandDialog('<?php echo $band->bandid ?>');" class="btn btn-outline-primary btn-sm" title="Edit"><i class="fas fa-edit"></i></a> | ||||||
| 					</td> | 					</td> | ||||||
| 					<td style="text-align: center; vertical-align: middle;" > | 					<td> | ||||||
| 						<a href="javascript:deleteBand('<?php echo $band->id . '\',\'' . $band->band ?>');" class="btn btn-danger btn-sm" title="Delete"><i class="fas fa-trash-alt"></i></a> | 						<a href="javascript:deleteBand('<?php echo $band->id . '\',\'' . $band->band ?>');" class="btn btn-danger btn-sm" title="Delete"><i class="fas fa-trash-alt"></i></a> | ||||||
|                     </td> |                     </td> | ||||||
| 					<?php } ?>
 | 					<?php } ?>
 | ||||||
|  | @ -95,7 +266,7 @@ $wwff = 0; | ||||||
| 				<?php } ?>
 | 				<?php } ?>
 | ||||||
| 			</tbody> | 			</tbody> | ||||||
| 			<tfoot> | 			<tfoot> | ||||||
| 					<th><?php echo lang('general_word_all'); ?></th>
 | 					<th>Toggle All</th> | ||||||
| 					<th></th> | 					<th></th> | ||||||
| 					<th class="master_cq"><input type="checkbox" <?php if ($cq > 0) echo 'checked';?>></th>
 | 					<th class="master_cq"><input type="checkbox" <?php if ($cq > 0) echo 'checked';?>></th>
 | ||||||
| 					<th class="master_dok"><input type="checkbox" <?php if ($dok > 0) echo 'checked';?>></th>
 | 					<th class="master_dok"><input type="checkbox" <?php if ($dok > 0) echo 'checked';?>></th>
 | ||||||
|  | @ -115,7 +286,7 @@ $wwff = 0; | ||||||
|                     <th></th> |                     <th></th> | ||||||
| 					<th></th> | 					<th></th> | ||||||
| 			</tfoot> | 			</tfoot> | ||||||
| 		<table> | 		</table> | ||||||
| 	</div> | 	</div> | ||||||
|   <br/> |   <br/> | ||||||
|   <p> |   <p> | ||||||
|  |  | ||||||
|  | @ -1,16 +1,48 @@ | ||||||
| $('.bandtable').on('click', 'input[type="checkbox"]', function() { | $('.bandtable').on('click', 'input[type="checkbox"]', function() { | ||||||
| 	var clickedbandid = $(this).closest('td').attr("class"); | 	var $checkbox = $(this); | ||||||
|  | 	var $cell = $checkbox.closest('td'); | ||||||
|  | 	 | ||||||
|  | 	// Add visual feedback
 | ||||||
|  | 	$cell.addClass('saving'); | ||||||
|  | 	$checkbox.prop('disabled', true); | ||||||
|  | 	 | ||||||
|  | 	var clickedbandid = $cell.attr("class"); | ||||||
| 	clickedbandid = clickedbandid.match(/\d+/)[0]; | 	clickedbandid = clickedbandid.match(/\d+/)[0]; | ||||||
| 	saveBand(clickedbandid); | 	 | ||||||
|  | 	saveBand(clickedbandid, function() { | ||||||
|  | 		// Remove visual feedback on success
 | ||||||
|  | 		$cell.removeClass('saving'); | ||||||
|  | 		$checkbox.prop('disabled', false); | ||||||
|  | 		 | ||||||
|  | 		// Add success flash
 | ||||||
|  | 		$cell.addClass('saved'); | ||||||
|  | 		setTimeout(function() { | ||||||
|  | 			$cell.removeClass('saved'); | ||||||
|  | 		}, 1000); | ||||||
|  | 	}); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| $('.bandtable tfoot').on('click', 'input[type="checkbox"]', function() { | $('.bandtable tfoot').on('click', 'input[type="checkbox"]', function() { | ||||||
| 	var clickedaward = $(this).closest('th').attr("class"); | 	var $masterCheckbox = $(this); | ||||||
| 	var status = $(this).is(":checked"); | 	var clickedaward = $masterCheckbox.closest('th').attr("class"); | ||||||
|  | 	var status = $masterCheckbox.is(":checked"); | ||||||
| 	clickedaward = clickedaward.replace('master_', ''); | 	clickedaward = clickedaward.replace('master_', ''); | ||||||
| 	$('[class^='+clickedaward+'_] input[type="checkbox').each(function() { | 	 | ||||||
| 		$(this).prop( "checked", status ); | 	// Update all related checkboxes with animation
 | ||||||
|  | 	$('[class^='+clickedaward+'_] input[type="checkbox"]').each(function() { | ||||||
|  | 		var $checkbox = $(this); | ||||||
|  | 		var $cell = $checkbox.closest('td'); | ||||||
|  | 		 | ||||||
|  | 		$cell.addClass('updating'); | ||||||
|  | 		setTimeout(function() { | ||||||
|  | 			$checkbox.prop("checked", status); | ||||||
|  | 			$cell.removeClass('updating').addClass('updated'); | ||||||
|  | 			setTimeout(function() { | ||||||
|  | 				$cell.removeClass('updated'); | ||||||
|  | 			}, 500); | ||||||
|  | 		}, Math.random() * 200); // Stagger the updates
 | ||||||
| 	}); | 	}); | ||||||
|  | 	 | ||||||
| 	saveBandAward(clickedaward, status); | 	saveBandAward(clickedaward, status); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | @ -34,8 +66,122 @@ $('.bandtable').DataTable({ | ||||||
| 	"scrollCollapse": true, | 	"scrollCollapse": true, | ||||||
| 	"paging": false, | 	"paging": false, | ||||||
| 	"scrollX": true, | 	"scrollX": true, | ||||||
|  | 	"searching": true, | ||||||
| 	"language": { | 	"language": { | ||||||
| 		url: getDataTablesLanguageUrl(), | 		url: getDataTablesLanguageUrl(), | ||||||
|  | 	}, | ||||||
|  | 	"columnDefs": [ | ||||||
|  | 		{ | ||||||
|  | 			"targets": [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // Checkbox columns
 | ||||||
|  | 			"orderable": false, | ||||||
|  | 			"className": "text-center" | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"targets": [14, 15, 16], // Frequency columns
 | ||||||
|  | 			"className": "text-center frequency-cell" | ||||||
|  | 		} | ||||||
|  | 	], | ||||||
|  | 	"drawCallback": function() { | ||||||
|  | 		updateStatistics(); | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // Custom search functionality
 | ||||||
|  | $('#bandSearch').on('keyup', function() { | ||||||
|  | 	$('.bandtable').DataTable().search(this.value).draw(); | ||||||
|  | 	updateStatistics(); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // Clear search button
 | ||||||
|  | $('#clearSearch').on('click', function() { | ||||||
|  | 	$('#bandSearch').val(''); | ||||||
|  | 	$('.bandtable').DataTable().search('').draw(); | ||||||
|  | 	updateStatistics(); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // Keyboard shortcut to focus search (like GitHub)
 | ||||||
|  | $(document).on('keydown', function(e) { | ||||||
|  | 	if (e.key === '/' && !$(e.target).is('input, textarea')) { | ||||||
|  | 		e.preventDefault(); | ||||||
|  | 		$('#bandSearch').focus(); | ||||||
|  | 	} | ||||||
|  | 	if (e.key === 'Escape' && $(e.target).is('#bandSearch')) { | ||||||
|  | 		$('#bandSearch').blur().val(''); | ||||||
|  | 		$('.bandtable').DataTable().search('').draw(); | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // Filter buttons
 | ||||||
|  | $('#showActiveOnly').on('click', function() { | ||||||
|  | 	$('.bandtable tbody tr').each(function() { | ||||||
|  | 		var $row = $(this); | ||||||
|  | 		var isActive = $row.find('.band-checkbox-cell input[type="checkbox"]').is(':checked'); | ||||||
|  | 		if (!isActive) { | ||||||
|  | 			$row.hide(); | ||||||
|  | 		} else { | ||||||
|  | 			$row.show(); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 	$(this).addClass('active').siblings().removeClass('active'); | ||||||
|  | 	updateStatistics(); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | $('#showAll').on('click', function() { | ||||||
|  | 	$('.bandtable tbody tr').show(); | ||||||
|  | 	$(this).addClass('active').siblings().removeClass('active'); | ||||||
|  | 	updateStatistics(); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // Initialize with "Show All" active
 | ||||||
|  | $('#showAll').addClass('active'); | ||||||
|  | 
 | ||||||
|  | // Update statistics
 | ||||||
|  | function updateStatistics() { | ||||||
|  | 	var activeBands = $('.band-checkbox-cell input[type="checkbox"]:checked').length; | ||||||
|  | 	$('#activeBandsCount').text(activeBands); | ||||||
|  | 	 | ||||||
|  | 	// Update visible rows count
 | ||||||
|  | 	var visibleRows = $('.bandtable tbody tr:visible').length; | ||||||
|  | 	var totalRows = $('.bandtable tbody tr').length; | ||||||
|  | 	$('#visibleRowsCount').text(visibleRows + ' of ' + totalRows + ' bands'); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Update statistics on page load
 | ||||||
|  | $(document).ready(function() { | ||||||
|  | 	updateStatistics(); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // Update statistics when band status changes
 | ||||||
|  | $('.bandtable').on('change', '.band-checkbox-cell input[type="checkbox"]', function() { | ||||||
|  | 	updateStatistics(); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // Bulk action buttons
 | ||||||
|  | $('#enableAllAwards').on('click', function() { | ||||||
|  | 	if (confirm('This will enable ALL award tracking (DXCC, IOTA, SOTA, WWFF, POTA, etc.) for ALL bands. Continue?')) { | ||||||
|  | 		$('.bandtable tbody tr').each(function() { | ||||||
|  | 			var $row = $(this); | ||||||
|  | 			// Check all award checkboxes except the first (active) column
 | ||||||
|  | 			$row.find('input[type="checkbox"]').not('.band-checkbox-cell input').each(function() { | ||||||
|  | 				if (!$(this).is(':checked')) { | ||||||
|  | 					$(this).prop('checked', true).trigger('change'); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | $('#resetAllAwards').on('click', function() { | ||||||
|  | 	if (confirm('This will disable ALL award tracking for ALL bands (bands will remain active for QSO entry). Continue?')) { | ||||||
|  | 		$('.bandtable tbody tr').each(function() { | ||||||
|  | 			var $row = $(this); | ||||||
|  | 			// Uncheck all award checkboxes except the first (active) column
 | ||||||
|  | 			$row.find('input[type="checkbox"]').not('.band-checkbox-cell input').each(function() { | ||||||
|  | 				if ($(this).is(':checked')) { | ||||||
|  | 					$(this).prop('checked', false).trigger('change'); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
| 	} | 	} | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | @ -201,7 +347,7 @@ function deactivateAllBands() { | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function saveBand(id) { | function saveBand(id, callback) { | ||||||
| 	$.ajax({ | 	$.ajax({ | ||||||
| 		url: base_url + 'index.php/band/saveBand', | 		url: base_url + 'index.php/band/saveBand', | ||||||
| 		type: 'post', | 		type: 'post', | ||||||
|  | @ -220,6 +366,11 @@ function saveBand(id) { | ||||||
| 			'vucc': $(".vucc_"+id+" input[type='checkbox']").is(":checked") | 			'vucc': $(".vucc_"+id+" input[type='checkbox']").is(":checked") | ||||||
| 		}, | 		}, | ||||||
| 		success: function (html) { | 		success: function (html) { | ||||||
|  | 			if (callback) callback(); | ||||||
|  | 		}, | ||||||
|  | 		error: function() { | ||||||
|  | 			// Show error state
 | ||||||
|  | 			if (callback) callback(); | ||||||
| 		} | 		} | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
|  |  | ||||||
		正在加载…
	
		在新工单中引用