1var VIETNAMESE_N_ASCII_MAP = { 2 "à ": "a", "ả": "a", "ã": "a", "á": "a", "ạ": "a", "Ä": "a", "ằ": "a", "ẳ": "a", "ẵ": "a", 3 "ắ": "a", "ặ": "a", "â": "a", "ầ": "a", "ẩ": "a", "ẫ": "a", "ấ": "a", "áº": "a", "Ä": "d", 4 "è": "e", "ẻ": "e", "ẽ": "e", "é": "e", "ẹ": "e", "ê": "e", "á»": "e", "á»": "e", "á» ": "e", 5 "ế": "e", "á»": "e", "ì": 'i', "á»": 'i', "Ä©": 'i', "Ã": 'i', "á»": 'i', "ò": 'o', "á»": 'o', 6 "õ": "o", "ó": "o", "á»": "o", "ô": "o", "á»": "o", "á»": "o", "á»": "o", "á»": "o", "á»": "o", 7 "Æ¡": "o", "á»": "o", "á»": "o", "ỡ": "o", "á»": "o", "ợ": "o", "ù": "u", "á»§": "u", "Å©": "u", 8 "ú": "u", "ụ": "u", "ư": "u", "ừ": "u", "á»": "u", "ữ": "u", "ứ": "u", "á»±": "u", "ỳ": "y", 9 "á»·": "y", "ỹ": "y", "ý": "y", "ỵ": "y", "Ã": "A", "Ả": "A", "Ã": "A", "Ã": "A", "Ạ": "A", 10 "Ä": "A", "Ằ": "A", "Ẳ": "A", "Ẵ": "A", "Ắ": "A", "Ặ": "A", "Ã": "A", "Ầ": "A", "Ẩ": "A", 11 "Ẫ": "A", "Ấ": "A", "Ậ": "A", "Ä": "D", "Ã": "E", "Ẻ": "E", "Ẽ": "E", "Ã": "E", "Ẹ": "E", 12 "Ã": "E", "á»": "E", "á»": "E", "á»": "E", "Ế": "E", "á»": "E", "Ã": "I", "á»": "I", "Ĩ": "I", 13 "Ã": "I", "á»": "I", "Ã": "O", "á»": "O", "Ã": "O", "Ã": "O", "á»": "O", "Ã": "O", "á»": "O", 14 "á»": "O", "á»": "O", "á»": "O", "á»": "O", "Æ ": "O", "á»": "O", "á»": "O", "á» ": "O", "á»": "O", 15 "Ợ": "O", "Ã": "U", "Ủ": "U", "Ũ": "U", "Ã": "U", "Ụ": "U", "Ư": "U", "Ừ": "U", "Ử": "U", 16 "á»®": "U", "Ứ": "U", "á»°": "U", "Ỳ": "Y", "á»¶": "Y", "Ỹ": "Y", "Ã": "Y", "á»´": "Y" 17}; 18 19function formatNumber(price, desSep = ',', groupSep = '.', number = 0) { 20 if (price != parseFloat(price)) { 21 price = 0; 22 } 23 var newstr = ''; 24 price = parseFloat(price); 25 var p = price.toFixed(number).split("."); 26 var chars = p[0].split("").reverse(); 27 var count = 0; 28 for (let x = 0; x < chars.length; x++) { 29 count++; 30 if (count % 3 == 1 && count != 1) { 31 newstr = chars[x] + groupSep + newstr; 32 } else { 33 newstr = chars[x] + newstr; 34 } 35 } 36 37 if (p.length > 1) { 38 newstr += desSep + p[1]; 39 } else if (number > 0) { 40 newstr += desSep; 41 for (let i = 0; i < number; i++) { 42 newstr += '0'; 43 } 44 } 45 46 return newstr; 47} 48 49function formatPrice(price, template = null) { 50 if (!template) { 51 return formatNumber(price, ',', '.') + ' ââ«'; 52 } else { 53 let retval = formatNumber(price, ',', '.') + ' ââ«'; 54 let matches = template.match(/{money}{([^a-zA-z0-9]+)}{([0-9]+)}/); 55 if (matches.length > 2) { 56 let separate = matches[1]; 57 let number = parseInt(matches[2]); 58 template = template.replace(/{([^a-zA-z0-9]+)}/, ''); 59 template = template.replace(/{([0-9]+)}/, ''); 60 let decimal = separate == '.' ? ',' : '.'; 61 retval = template.replace('{money}', formatNumber(price, separate, decimal, number)); 62 } 63 64 return retval; 65 } 66} 67 68function decimalAdjust(type, value) { 69 let matches = priceTemplate.match(/{money}{([^a-zA-z0-9]+)}{([0-9]+)}/); 70 let exp = -2; 71 if (matches.length == 3) { 72 exp = parseInt(matches[2] * (matches[2] ? -1 : 1)); 73 } 74 // If the exp is undefined or zero... 75 if (typeof exp === 'undefined' || +exp === 0) { 76 return Math[type](value); 77 } 78 value = +value; 79 exp = +exp; 80 // If the value is not a number or the exp is not an integer... 81 if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) { 82 return NaN; 83 } 84 // Shift 85 value = value.toString().split('e'); 86 value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp))); 87 // Shift back 88 value = value.toString().split('e'); 89 return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)); 90} 91 92function permute(array) { 93 Array.prototype.swap = function (index, otherIndex) { 94 var valueAtIndex = this[index];; 95 this[index] = this[otherIndex]; 96 this[otherIndex] = valueAtIndex; 97 } 98 var result = [array.slice()], length = array.length; 99 for (var i = 1, heap = new Array(length).fill(0); i < length;) 100 if (heap[i] < i) { 101 array.swap(i, i % 2 && heap[i]); 102 result.push(array.slice()); 103 heap[i]++; 104 i = 1; 105 } else { 106 heap[i] = 0; 107 i++; 108 } 109 return result; 110} 111 112function getParameterByName(name, url) { 113 if (!url) url = window.location.href; 114 name = name.replace(/[\[\]]/g, '\\$&'); 115 var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), 116 results = regex.exec(url); 117 if (!results) return null; 118 if (!results[2]) return ''; 119 return decodeURIComponent(results[2].replace(/\+/g, ' ')); 120} 121 122function isIos() { 123 var ua = navigator.userAgent || ''; 124 125 if (/(iPhone|iPad|iPod)/i.test(ua)) { 126 return true; 127 } 128 129 // iPadOS 13+ requests desktop sites by default and then reports a macOS 130 // Safari UA with no iPad token. A real Mac reports 0 touch points, an iPad
131 // reports 5, so this separates them. 132 return navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1; 133} 134 135function canUseWebP() { 136 var elem = document.createElement('canvas'); 137 138 if (!!(elem.getContext && elem.getContext('2d'))) { 139 // was able or not to get WebP representation 140 return elem.toDataURL('image/webp').indexOf('data:image/webp') == 0; 141 } 142 143 // very old browser like IE 8, canvas not supported 144 return false; 145} 146 147webpSupport = canUseWebP(); 148 149function getImageCdn($url, $width = 0, $height = 0, $fitIn = false, $webp = false, filters) { 150 $fitIn = false; 151 if ($url && !$url.match(/\.(jpg|jpeg|png|gif|jfif|webp)$/i)) { 152 return $url; 153 } 154 var zoomIn = ''; 155 if (!$url) { 156 return $url; 157 } 158 159 if ($url.indexOf('http') != 0) { 160 if ($url.indexOf('//') != 0) { 161 if ($url.indexOf('/') != 0) { 162 $url = 'https://' + $url; 163 } else { 164 $url = window.location.origin + $url; 165 } 166 } else { 167 $url = 'http:' + $url; 168 } 169 } 170 171 const sizePattern = new RegExp(/(image|blank|sticker|unsafe)\/\d+x\d+/); 172 if (sizePattern.test($url)) { 173 return $url; 174 } 175 176 const regex = /^https?:\/\/[^/]+(\/[^?#]*)/; 177 const match = regex.exec($url); 178 const path = match && match[1]; 179 if (path && (path.startsWith("/image/") || path.startsWith("/blank/") || path.startsWith("/sticker/"))) { 180 if (!$width) $width = $height; 181 $url = $url.replace('/blank/', '/blank/' + $width + 'x' + $width + '/'); 182 $url = $url.replace('/image/', '/image/' + $width + 'x' + $width + '/'); 183 $url = $url.replace('/sticker/', '/sticker/' + $width + 'x' + $width + '/'); 184 $url = replaceImageUrl($url); 185 return $url; 186 } 187 $url = replaceImageUrl($url); 188 if (($width == 1260 && $height == 0) || ($width == 0 && $height == 0)) { 189 return $url; 190 } 191 let tempCdnIgnoreUrl = cdnIgnoreUrl.map((url) => { 192 return decrypt('megaads', url); 193 }) 194 195 let tempCdnAllowUrl = cdnAllowUrl.map((url) => { 196 return decrypt('megaads', url); 197 }) 198 199 if (typeof tempCdnIgnoreUrl !== 'undefined') { 200 for (let item of tempCdnIgnoreUrl) { 201 if ($url.includes(item)) { 202 return $url; 203 } 204 } 205 } 206 if (typeof tempCdnAllowUrl !== 'undefined') { 207 let check = false; 208 for (let item of tempCdnAllowUrl) { 209 if ($url.includes(item)) { 210 check = true; 211 break; 212 } 213 } 214 if (!check) { 215 return $url; 216 } 217 } 218 if (typeof filters !== 'undefined' && typeof filters.zoomIn !== 'undefined') { 219 zoomIn = filters.zoomIn; 220 } 221 $originUrl = $url; 222 if ($url.substr(0, 4) == 'http') { 223 $url = $url.replace('https://', ''); 224 $url = $url.replace('http://', ''); 225 } 226 if ($url.includes('redbubble.net')) { 227 $url = 'asset/' + crypt('megaads', $url); 228 } 229 if ($url.includes('i.etsystatic.com') || $url.includes('res.cloudinary.com')) { 230 $url = 'asset/' + crypt('megaads', $url); 231 } 232 if ($url.includes('?')) { 233 $url = encodeURIComponent($url); 234 } 235 236 // else { 237 // $url = document.domain + $url; 238 // } 239 $webp = false; 240 // if ($webp) { 241 // if( webpSupport ) { 242 // $webp = true; 243 // } else { 244 // $webp = false; 245 // } 246 // } 247 248 $baseCdnUrl = baseCdnUrl + "/"; 249 if (zoomIn !== '') { 250 $baseCdnUrl = baseCdnUrl + "" + zoomIn + "/"; 251 } 252 $fitIn = ($fitIn && $width && $height); 253 // $fitIn = false; 254 if ($fitIn) { 255 $baseCdnUrl += "fit-in/"; 256 } 257 if ($width || $height) { 258 $baseCdnUrl += $width + "x" + $height + "/"; 259 } 260 // if ($fitIn || $webp) { 261 // $baseCdnUrl += "filters"; 262 // } 263 // if ($fitIn) { 264 // $baseCdnUrl += ":fill(fff)"; 265 // } 266 // if ($webp) { 267 // $baseCdnUrl += ":format(webp)"; 268 // } 269 // if ($fitIn || $webp) { 270 // $baseCdnUrl += "/"; 271 // } 272 $baseCdnUrl += $url; 273 return $baseCdnUrl; 274} 275 276const replaceImageUrl = (url) => { 277 for (const [key, value] of Object.entries(cdnReplaceUrl)) { 278 url = url.replace(key, value); 279 } 280 return url; 281} 282const crypt = (salt, text) => { 283 const textToChars = (text) => text.split("").map((c) =>
283 c.charCodeAt(0)); 284 const byteHex = (n) => ("0" + Number(n).toString(16)).substr(-2); 285 const applySaltToChar = (code) => textToChars(salt).reduce((a, b) => a ^ b, code); 286 287 return text 288 .split("") 289 .map(textToChars) 290 .map(applySaltToChar) 291 .map(byteHex) 292 .join(""); 293 }; 294 295const decrypt = (salt, encoded) => { 296 const textToChars = (text) => text.split("").map((c) => c.charCodeAt(0)); 297 const applySaltToChar = (code) => textToChars(salt).reduce((a, b) => a ^ b, code); 298 return encoded 299 .match(/.{1,2}/g) 300 .map((hex) => parseInt(hex, 16)) 301 .map(applySaltToChar) 302 .map((charCode) => String.fromCharCode(charCode)) 303 .join(""); 304 }; 305function getEtsyStatic(url, w, h) 306{ 307 let parts = url.split('/'); 308 let endPath = parts.pop(); 309 310 if (!w) w = 'N'; 311 if (!h) h = 'N'; 312 313 endPath = endPath.replace(/il_([\dN]+)x([\dN]+)/, 'il_' + w + 'x' + h); 314 parts.push(endPath); 315 316 return parts.join('/'); 317} 318 319function getRedBubbleStatic(url, w, h) 320{ 321 let parts = url.split('/'); 322 let endPath = parts.pop(); 323 324 if (!w) w = 0; 325 if (!h) h = 0; 326 327 if (w > 0 && h > 0) { 328 endPath = endPath.replace(/(\d+)x(\d+)/, w + 'x' + h); 329 /*endPath = endPath.replace(/(\d+)x/, w + 'x'); 330 endPath = endPath.replace(/x(\d+)/, 'x' + h);*/ 331 } 332 333 parts.push(endPath); 334 335 return parts.join('/'); 336} 337 338function toFriendlyString(originalString) { 339 if (originalString == null || originalString.length == 0) { 340 return originalString; 341 } 342 //ELSE: 343 var removedDuplicatedSpacesString = originalString.replace(/\s+/g, " "); 344 var removedVietnameseCharsString = ""; 345 for (var idx = 0; idx < removedDuplicatedSpacesString.length; idx++) { 346 var ch = removedDuplicatedSpacesString[idx]; 347 var alternativeChar = VIETNAMESE_N_ASCII_MAP[ch]; 348 if (alternativeChar != null) { 349 removedVietnameseCharsString += alternativeChar; 350 } else { 351 removedVietnameseCharsString += ch; 352 } 353 } 354 return removedVietnameseCharsString.toLowerCase() 355 .replace(/[^0-9a-zA-Z]/g, "-") 356 .replace(/\-+/g, "-"); 357} 358 359function isNaturalNumber(n) { 360 n = n.toString(); // force the value incase it is not 361 var n1 = Math.abs(n), 362 n2 = parseInt(n, 10); 363 return !isNaN(n1) && n2 === n1 && n1.toString() === n; 364} 365function getCookie(name) { 366 // Create a regular expression to search for the cookie by name 367 const value = document.cookie 368 .split('; ') 369 .find(row => row.startsWith(name + '=')); 370 371 // If the cookie exists, return its value; otherwise, return null 372 return value ? value.split('=')[1] : null; 373} 374// Auto-append prx query param from cookie to URL 375(function () { 376 var prx = getCookie('prx'); 377 if (prx && !getParameterByName('prx')) { 378 var separator = window.location.search ? '&' : '?'; 379 var newUrl = window.location.href + separator + 'prx=' + encodeURIComponent(prx); 380 window.history.replaceState(null, '', newUrl); 381 } 382})();
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.