1function getAppDirectory() { 2 var path = window.location.pathname; 3 var segments = path.split("/").filter(Boolean); 4 5 // If running on localhost with no virtual directory 6 if (window.location.hostname === "localhost" && !path.includes("webapp")) { 7 return ""; 8 } 9 10 // The virtual directory is ONLY "webapp" (or whatever your app root is) 11 // Never use a controller name as the base check explicitly 12 var knownAppRoots = ["webapp"]; // add your actual virtual directory name here 13 14 if (segments.length > 0 && knownAppRoots.includes(segments[0].toLowerCase())) { 15 return segments[0]; 16 } 17 18 // No virtual directory app is at root 19 return ""; 20} 21 22 23// Razor runs here, so it resolves correctly to "/" or "/webapp/" 24function getAppBaseUrl() { 25 // Use the Razor-resolved base URL if available most reliable approach 26 if (window.__appBaseUrl) { 27 return window.location.origin + window.__appBaseUrl; 28 } 29 // Fallback to the path-parsing approach 30 var dir = getAppDirectory(); 31 return window.location.origin + (dir ? "/" + dir : "") + "/"; 32} 33 34function formatUKAmount(value) { 35 const formatter = new Intl.NumberFormat('en-GB', { 36 style: 'currency', 37 currency: 'GBP' 38 }).format(value); 39 40 return formatter; 41} 42 43function formatAmount(amount) { 44 let formatted = new Intl.NumberFormat('en-NG', { 45 style: 'currency', 46 currency: 'NGN' 47 }).format(amount); 48 return formatted; 49} 50 51function formatAmountGeneric(amount, currency, locale = navigator.language) { 52 try { 53 return new Intl.NumberFormat(locale, { 54 style: 'currency', 55 currency: currency 56 }).format(amount); 57 } catch (error) { 58 console.warn(`Invalid currency or locale: ${currency}, ${locale}`, error); 59 // Fallback: just return the number with currency code appended 60 return `${currency} ${amount.toFixed(2)}`; 61 } 62} 63 64function escapeHtml(unsafe) { 65 if (!unsafe) return ''; 66 return unsafe.toString() 67 .replace(/&/g, "&") 68 .replace(/</g, "<") 69 .replace(/>/g, ">") 70 .replace(/"/g, """) 71 .replace(/'/g, "'"); 72} 73 74function truncateText(text, maxLength = 150) { 75 if (!text) return ''; 76 77 return text.length > maxLength 78 ? text.substring(0, maxLength) + '...' 79 : text; 80} 81 82 83function parseDate(resumptionDate) { 84 // Extract the number inside 85 let timestamp = parseInt(resumptionDate.replace(/\/Date\((\d+)\)\//, "$1"), 10); 86 87 // Convert to JavaScript Date 88 let date = new Date(timestamp); 89 90 return date; 91} 92 93function formatDate(msDate) { 94 if (!msDate) return ''; 95 96 // Handle Microsoft JSON date e.g. "/Date(1234567890)/" 97 const match = /\/Date\((\d+)\)\//.exec(msDate); 98 if (match) { 99 const date = new Date(parseInt(match[1])); 100 return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`; 101 } 102 103 // Handle ISO string e.g. "2026-04-02T00:00:00" or "2026-04-02" 104 // Extract date parts directly from the string avoids timezone conversion entirely 105 if (typeof msDate === 'string') { 106 const parts = msDate.match(/^(\d{4})-(\d{2})-(\d{2})/); 107 if (parts) { 108 return `${parts[1]}-${parts[2]}-${parts[3]}`; 109 } 110 } 111 112 // Fallback parse as date object 113 const date = new Date(msDate); 114 if (!isNaN(date.getTime())) { 115 // Use UTC methods to avoid local timezone shift 116 return `${date.getUTCFullYear()}-${(date.getUTCMonth() + 1).toString().padStart(2, '0')}-${date.getUTCDate().toString().padStart(2, '0')}`; 117 } 118 119 return ''; 120} 121 122function getTaxYearConfigurations() { 123 const taxYearConfigurations = document.getElementById('taxYearConfigurations'); 124 125 if (taxYearConfigurations) { 126 127 taxYearConfigurations.innerHTML = '<option value="" selected disabled> Select </option>'; // Reset fourth level category options 128 129 fetch(getAppBaseUrl() + `Payslip/GetTaxYearConfigurations`) 130 .then(response => response.json()) 131 .then(data => { 132 if (data && data.IsSuccess && data.Data.length > 0) { 133 data.Data.forEach((item, index) => { 134 const option = document.createElement('option'); 135 option.value = item.ConfigId; // Adjust based on your API response 136 option.textContent = item.TaxYear; // Adjust based on your API response 137 138 // Select the first (most recent) record by default 139 if (index === 0) { 140 option.selected = true; 141 } 142 143 taxYearConfigurations.appendChild(option); 144 //open_designation.appendChild(option); 145 }); 146 } else { 147 console.warn('No tax year configurations foun
147d.'); 148 } 149 }) 150 .catch(error => { 151 console.error('Error fetching tax year configurations:', error); 152 }); 153 } 154}
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.