1class NomadClient { 2 static SortByQuerystring(value) { 3 const SORT_NAME = "sortColumn"; 4 const ASCENDING_NAME = "sortAscending"; 5 6 let searchParams = new URLSearchParams(window.location.search); 7 let currentSort = searchParams.get(SORT_NAME); 8 let isAscending = searchParams.get(ASCENDING_NAME); 9 10 if (value == currentSort) { 11 if (isAscending == 'true') { 12 searchParams.set(ASCENDING_NAME, false); 13 } else { 14 searchParams.set(ASCENDING_NAME, true); 15 } 16 } else if (value != "") { 17 searchParams.set(SORT_NAME, value); 18 searchParams.set(ASCENDING_NAME, true); 19 } else { 20 searchParams.delete(SORT_NAME); 21 searchParams.delete(ASCENDING_NAME); 22 } 23 24 window.location.search = searchParams.toString(); 25 } 26 27 static AltSortByQuerystring(value, sortPrefix) { 28 const sortName = sortPrefix + "Sort"; 29 const sortDirection = sortPrefix + "Direction"; 30 31 let searchParams = new URLSearchParams(window.location.search); 32 let currentSort = searchParams.get(sortName); 33 let isAscending = searchParams.get(sortDirection); 34 35 if (value == currentSort) { 36 if (isAscending == 'true') { 37 searchParams.set(sortDirection, false); 38 } else { 39 searchParams.set(sortDirection, true); 40 } 41 } else if (value != "") { 42 searchParams.set(sortName, value); 43 searchParams.set(sortDirection, true); 44 } else { 45 searchParams.delete(sortName); 46 searchParams.delete(sortDirection); 47 } 48 49 window.location.search = searchParams.toString(); 50 } 51 52 static SetQueryParam(name, value) { 53 var searchParams = new URLSearchParams(window.location.search); 54 if (value != "") { 55 searchParams.set(name, value); 56 } else { 57 searchParams.delete(name); 58 } 59 window.location.search = searchParams.toString(); 60 } 61 62 static ToggleClick(selector) { 63 var list = selector; 64 65 if (typeof selector === 'string' || selector instanceof String) { 66 list = document.getElementById(selector); 67 if (list == null) return; 68 } 69 const ACTIVE_NAME = "active"; 70 71 var isActive = list.classList.contains(ACTIVE_NAME); 72 if (isActive) { 73 list.classList.remove(ACTIVE_NAME); 74 } else { 75 list.classList.add(ACTIVE_NAME); 76 } 77 } 78 79 static ToggleGroup(selector, group) { 80 var items = document.getElementsByClassName(group); 81 if (items == null) return; 82 83 const ACTIVE_NAME = "active"; 84 for (var i = 0; i < items.length; i++) { 85 var item = items[i]; 86 var isActive = item.classList.contains(ACTIVE_NAME); 87 var isSelected = item.id == selector; 88 if (isSelected) { 89 if (!isActive) { 90 item.classList.add(ACTIVE_NAME); 91 } 92 } else { 93 if (isActive) { 94 item.classList.remove(ACTIVE_NAME); 95 } 96 } 97 } 98 } 99 100 static ToggleGroups(pairs) { 101 for (var i = 0; i < pairs.length; i++) { 102 var pair = pairs[i]; 103 NomadClient.ToggleGroup(pair.id, pair.group); 104 } 105 } 106 107 static Ready(callback) { 108 // in case the document is already rendered 109 if (document.readyState != 'loading') callback(); 110 // modern browsers 111 else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback); 112 // IE <= 8 113 else document.attachEvent('onreadystatechange', function () { 114 if (document.readyState == 'complete') callback(); 115 }); 116 } 117 118 static FormatDate(value) { 119 if (value == null) return ""; 120 var dateString = value.substr(6); 121 var currentTime = new Date(parseInt(dateString)); 122 var month = currentTime.getMonth() + 1; 123 var day = currentTime.getDate(); 124 var year = currentTime.getFullYear(); 125 return this.FormatDateWithSlashes(month, day, year); 126 } 127 128 static FormatDate2(value) { 129 let month = value.getMonth() + 1; 130 let day = value.getDate(); 131 let year = value.getFullYear(); 132 return this.FormatDateWithDashes(month, day, year); 133 } 134 135 static FormatDateWithSlashes(month, day, year) { 136 var result = month + "/" + day + "/" + year; 137 return result; 138 } 139 140 static FormatDateWithDashes(month, day, year) {
141 if (month < 10) { month = '0' + month.toString(); } 142 if (day < 10) { day = '0' + day.toString(); } 143 let result = year + '-' + month + '-' + day; 144 return result; 145 } 146 147 static NowDate() { 148 let now = new Date(); 149 let result = NomadClient.FormatDate2(now); 150 return result; 151 } 152 153 static FormatUTCDate(value) { 154 if (value == null) return ""; 155 var dateString = value.substr(6); 156 var currentTime = new Date(parseInt(dateString)); 157 var month = currentTime.getUTCMonth() + 1; 158 var day = currentTime.getUTCDate(); 159 var year = currentTime.getUTCFullYear(); 160 return this.FormatDateWithSlashes(month, day, year); 161 } 162 163 static FormatTZDate(value) { 164 if (value == null) return ""; 165 var currentTime = new Date(value); 166 var month = currentTime.getUTCMonth() + 1; 167 var day = currentTime.getUTCDate(); 168 var year = currentTime.getUTCFullYear(); 169 return this.FormatDateWithSlashes(month, day, year); 170 } 171 172 static FormatItemsList(value) { 173 var result = ""; 174 if (value !== null && Array.isArray(value)) { 175 for (var i = 0; i < value.length; i++) { 176 result += value[i] + "<br/>" 177 } 178 } 179 180 return result; 181 } 182 183 static FormatCurrency(value) { 184 try { 185 var formatter = new Intl.NumberFormat(NomadSettings.CurrencyLocale, { style: 'currency', currency: NomadSettings.CurrencyType }); 186 var result = formatter.format(value); 187 return result; 188 } 189 catch { 190 return value; 191 } 192 } 193 194 static IsTrackingUrl(text) { 195 return NomadClient.TrackingUrl(text).includes('http'); 196 } 197 198 static TrackingUrl(text) { 199 var ups = /\b(1Z ?[0-9A-Z]{3} ?[0-9A-Z]{3} ?[0-9A-Z]{2} ?[0-9A-Z]{4} ?[0-9A-Z]{3} ?[0-9A-Z]|[\dT]\d\d\d ?\d\d\d\d ?\d\d\d)\b/i; 200 201 var fedex1 = /(\b96\d{20}\b)|(\b\d{15}\b)|(\b\d{12}\b)/i; 202 var fedex2 = /\b((98\d\d\d\d\d?\d\d\d\d|98\d\d) ?\d\d\d\d ?\d\d\d\d( ?\d\d\d)?)\b/i; 203 var fedex3 = /^[0-9]{15}$/i; 204 205 var usps1 = /(\b\d{30}\b)|(\b91\d+\b)|(\b\d{20}\b)/i; 206 var usps2 = /^E\D{1}\d{9}\D{2}$|^9\d{15,21}$/i; 207 var usps3 = /^91[0-9]+$/i; 208 var usps4 = /^[A-Za-z]{2}[0-9]+US$/i; 209 210 var result = ''; 211 212 if (ups.test(text)) { 213 result = 'http://wwwapps.ups.com/etracking/tracking.cgi?tracknum='; 214 } else if (fedex1.test(text) || fedex2.test(text) || fedex3.test(text)) { 215 result = 'https://www.fedex.com/fedextrack/?action=track&tracknumbers='; 216 } else if (usps1.test(text) || usps2.test(text) || usps3.test(text) || usps4.test(text)) { 217 result = 'https://tools.usps.com/go/TrackConfirmAction.action?tLabels='; 218 } 219 220 if (result === '') { 221 return ''; 222 } 223 224 return result + text; 225 } 226 227 static parseBool(value) { 228 return value == null ? null : (value === 'true'); 229 } 230 231 static rangeText(minimumOptions, maximumOptions) { 232 if (minimumOptions == 1 && maximumOptions == null) return minimumOptions; 233 if (minimumOptions == 0 && maximumOptions == null) return "1 or more"; 234 if (maximumOptions == null) return minimumOptions + " or more"; 235 if (minimumOptions == 0 && maximumOptions == 1) return "1"; 236 if (minimumOptions == 0 && maximumOptions > 1) return "up to " + maximumOptions; 237 if (minimumOptions == maximumOptions) return minimumOptions; 238 return minimumOptions + " to " + maximumOptions; 239 } 240 241 static CommaDelimited(items, selector) { 242 let result = ""; 243 if (items == null || selector == null) return result; 244 245 const length = items.length; 246 for (let i = 0; i < length; i++) { 247 let item = items[i]; 248 result += selector(item); 249 if (i < length - 1) { 250 result += ", "; 251 } 252 } 253 254 return result; 255 } 256 257 static IsString(value) { 258 return (typeof value === 'string' || value instanceof String); 259 } 260 261 static NewGuid() { 262 // TODO: This should be replaced by a server endpoint call - guids should not be generated in javascript. 263 return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => 264 (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) 265 ); 266 } 267 268 static get EmptyGuid() { 269 return '00000000-0000-0000-0000-000000000000'; 270 } 271 272 static IsValidGuid(value) { 273 const regexGuid = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/; 274 if (!value) return false;
275 if (value[0] === "{") { 276 value = value.substring(1, value.length - 1); 277 } 278 return regexGuid.test(value); 279 } 280 281 static async ApiGet(url) { 282 const response = await fetch(url); 283 const result = await response.json(); 284 return result; 285 } 286 287 static async ApiGetWithThrow(url) { 288 const response = await NomadClient.ApiGet(url); 289 NomadClient.CheckAndThrow(response); 290 return response; 291 } 292 293 static async ApiPost(url, data) { 294 const response = await fetch(url, { 295 method: 'POST', 296 headers: { 297 'Accept': 'application/json', 298 'Content-Type': 'application/json' 299 }, 300 body: JSON.stringify(data) 301 }); 302 const result = await response.json(); 303 return result; 304 } 305 306 static async ApiPostWithThrow(url, data) { 307 const response = await NomadClient.ApiPost(url, data); 308 NomadClient.CheckAndThrow(response); 309 return response; 310 } 311 312 static CheckAndThrow(response) { 313 if (response.exceptionMessage != null) { 314 console.log(response.exceptionMessage); 315 throw response.exceptionMessage; 316 } 317 if (response.StackTraceString != null) { 318 console.log(response.Message); 319 throw response.Message; 320 } 321 } 322 323 static SetFocus(input) { 324 const $el = document.getElementById(input); 325 if ($el == null) { 326 return; 327 } 328 $el.focus(); 329 if ($el.setSelectionRange) { 330 $el.setSelectionRange(0, $el.value.length); 331 } else if ($el.select) { 332 $el.select(); 333 } 334 } 335 336 static InsertAndExecuteHTML(targetElement, htmlString) { 337 // targetElement is a DOM element, not a JQuery or string. 338 339 const parser = new DOMParser(); 340 const doc = parser.parseFromString(htmlString, 'text/html'); 341 342 const scripts = doc.querySelectorAll('script.dynamic'); 343 scripts.forEach(oldScript => { 344 oldScript.remove(); 345 }); 346 347 targetElement.innerHTML = doc.body.innerHTML; 348 349 scripts.forEach(oldScript => { 350 const newScript = document.createElement('script'); 351 352 Array.from(oldScript.attributes).forEach(attr => { 353 newScript.setAttribute(attr.name, attr.value); 354 }); 355 356 newScript.textContent = oldScript.textContent; 357 358 document.body.appendChild(newScript); 359 360 if (!newScript.src) { 361 newScript.remove(); 362 } 363 }); 364 } 365}
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.