1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2// Summer - Common JavaScript functions. 3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4// Program Updates 5// 6// 07.12.2011 3.0.0 DJV V3 mods for showLargePic. 7// 23.01.2012 3.0.1 DJV Fixed error in doClrLargePic when no large picture on screen. 8// 12.07.2013 3.2.0 DJV Geolocation coding added. 9// 25.07.2013 3.2.1 DJV Rename getLocation to geoLocation to avoid clash with Google Shopping PHP function. 10// 28.04.2014 3.2.2 DJV Added Postcode Reminder code. 11// 09.09.2014 3.4.0 DJV Added check screen size for Postcode reminder. 12// 27.09.2014 3.4.1 DJV gID mods. 13// 20.11.2014 3.4.2 DJV Added various bits of mobile-only coding (including 3rd party swipe code). 14// 22.01.2015 3.4.3 DJV Added Info Bar code. 15// 16.03.2015 3.4.4 DJV Added carousel code. 16// 27.06.2016 4.0.0 DJV Simplified dec. Moved the PC reminder code to v4topmenu.js. 17// 16.08.2016 4.0.1 DJV Removed scrollToProd and dec (now done in numerical.js). 18// 25.08.2016 4.0.2 DJV Added toggleBasket (). 19// 02.10.2016 4.0.3 DJV Removed lots of redundant code! 20// 03.10.2016 4.0.4 DJV Added global wh setting and handleResize. 21// 23.10.2018 4.3.0 DJV Mods to do with new product menu. 22// 30.10.2018 4.3.1 DJV Added resizeTopBars so that it could be called from elsewhere (v4productbar.js). 23// 09.05.2019 4.3.2 DJV Added video popup overlay. 24// 24.01.2020 4.5.0 DJV Renamed from v4utils.js. 25// 21.10.2020 4.6.0 DJV Added gh(). 26// 18.02.2021 4.6.1 DJV Added setCTBox as having it in commands.php doesn't always work. 27// 14.03.2023 4.8.0 DJV Removed redundant resize and panel functions. 28// 22.03.2023 4.8.1 DJV Now uses winWH. 29// 29.03.2023 4.8.2 DJV Added resizePanelBlocks to the resizehandler. 30// 30.03.2023 4.8.3 DJV Fixed remaining wh => winWH issues. 31// 18.04.2023 4.8.4 DJV Removed setProdlisteners function as no longer needed. 32// 33//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 35var pbInit = true, 36 sdMax, 37 sdStep = 25, 38 sdDone = 0, 39 sdTm = null; 40 41addResizeHandler ("handleResize"); 42handleResize (); 43 44window.onscroll = sdCheck2; 45sdTm = setTimeout ("sdCheck1()", 2000); 46 47//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 49function isTouchDevice () 50{ 51 return 'ontouchstart' in window // works on most browsers 52 || navigator.maxTouchPoints; // works on IE11 and Surface 53} 54 55//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 56// Summer main resize handler - anything that needs to be updated on a screen resize needs to be added here 57//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 58 59function handleResize () 60{ 61 if (typeof pbCapacityCheck == 'function') 62 pbCapacityCheck (); 63 64 if (typeof doResizeProdBoxes == 'function') 65 doResizeProdBoxes (); 66 67 if (typeof resizePanelBlocks == 'function') 68 resizePanelBlocks (); 69 70 setProdBoxTitleSize (); 71} 72 73//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 74 75function setProdBoxTitleSize () 76{ 77 var nms = document.getElementsByClassName ("nproductNames"), 78 maxSz = 9999; 79 80 for (var i in nms) 81 { 82 var w = nms[i].clientWidth; 83 84 if (w > 0 && w < maxSz) 85 maxSz = w; 86 } 87 88 nms = document.getElementsByClassName ("nproductName"); 89 90 for (var i in nms) 91 { 92 var nm = nms[i]; 93 nmfs = 20; 94 95 while (nm.clientWidth != nm.scrollWidth && nmfs > 15) 96 nm.style.fontSize = --nmfs + "px"; 97 98 if (nm.clientWidth != nm.scrollWidth) 99 { 100 nm.style.fontSize = "20px"; 101 nm.style.height = "auto"; 102 nm.style.whiteSpace = "normal"; 103 } 104 } 105 106 nms = document.getElementsByClassName ("nproductInfo"); 107 108 for (var i in nms) 109 { 110 var nm = nms[i]; 111 nmfs = 16; 112 113 while (nm.clientWidth != nm.scrollWidth && nmfs > 13) 114 nm.style.fontSize = --nmfs + "px"; 115 116 if (nm.clientWidth != nm.scrollWidth) 117 { 118 nm.style.fontSize = "16px"; 119 nm.style.height = "auto"; 120 nm.style.whiteSpace = "normal"; 121 } 122 } 123} 124
125//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 126 127function sdec (num, dp) 128{ 129 if (dp == 0) 130 return num; 131 132 var p = Math.pow (10, dp); 133 num = Math.round (num * p) / p; 134 var n = "" + num; 135 136 var dp1 = n.indexOf ("."); 137 var l = n.length; 138 139 if (dp1 == -1) 140 { 141 n += "."; 142 dp1 = n.indexOf ("."); 143 l = n.length; 144 } 145 146 while (l - dp1 < dp + 1) 147 { 148 n += "0"; 149 l = n.length; 150 } 151 152 while (l - dp1 > dp + 1) 153 { 154 n = n.substring (0, n.length - 1); 155 l = n.length; 156 } 157 158 return n; 159} 160 161//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 162// Touch/swipe events - http://padilicious.com/code/touchevents/ 163//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 164 165var triggerElementID = null, // this variable is used to identity the triggering element 166 fingerCount = 0, 167 startX = 0, 168 startY = 0, 169 curX = 0, 170 curY = 0, 171 deltaX = 0, 172 deltaY = 0, 173 horzDiff = 0, 174 vertDiff = 0, 175 minLength = 10, // the shortest distance the user may swipe 176 swipeLength = 0, 177 swipeAngle = null, 178 swipeDirection = null; 179 180//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 181 182function touchStart (event, passedName) 183{ 184 fingerCount = event.touches.length; 185 186 if (fingerCount == 1) 187 { 188 startX = event.touches[0].clientX; 189 startY = event.touches[0].clientY; 190 triggerElementID = passedName; 191 } 192 else 193 touchCancel (event); 194} 195 196//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 197 198function touchMove (event) 199{ 200 if (event.touches.length == 1) 201 { 202 curX = event.touches[0].clientX; 203 curY = event.touches[0].clientY; 204 205 var swipeLength = Math.abs (startX - curX); 206 207 if (swipeLength >= minLength) 208 { 209 if (triggerElementID == "productbar") 210 { 211 swipePBar (startX - curX); 212 startX = curX; 213 touchCancel (event); 214 return true; 215 } 216 else 217 if (triggerElementID == "prodpics") 218 { 219 swipeProdPics (startX - curX); 220 touchCancel (event); 221 } 222 } 223 } 224 else 225 touchCancel (event); 226} 227 228//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 229 230function touchEnd (event) 231{ 232 if (fingerCount == 1 && curX != 0) 233 { 234 swipeLength = Math.round (Math.sqrt (Math.pow (curX - startX, 2) + Math.pow (curY - startY, 2))); 235 236 if (swipeLength >= minLength) 237 { 238 var X = startX - curX; 239 var Y = curY - startY; 240 var Z = Math.round (Math.sqrt (Math.pow (X, 2) + Math.pow (Y,2))); 241 var r = Math.atan2 (Y, X); 242 swipeAngle = Math.round (r * 180 / Math.PI); 243 244 if (swipeAngle < 0) 245 swipeAngle = 360 - Math.abs (swipeAngle); 246 247 if ((swipeAngle >= 0 && swipeAngle <= 20) || (swipeAngle >= 340 && swipeAngle <= 360)) 248 { 249 } 250 else 251 if (swipeAngle >= 160 && swipeAngle <= 200) 252 { 253 } 254 } 255 } 256 257 touchCancel (event); 258} 259 260//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 261 262function touchCancel (event) 263{ 264 // reset the variables back to default values 265 266 fingerCount = startX = startY = curX = curY = deltaX = deltaY = horzDiff = vertDiff = swipeLength = 0; 267 swipeAngle = swipeDirection = triggerElementID = null; 268} 269
270//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 271// Promo bar 272//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 273 274var promoInd = 0, 275 promoTm = null, 276 promoOpac = 100, 277 promoDir = -1, 278 promoTxt = [], 279 promoSpeed = 13; 280 281//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 282 283function fixPromo (n) 284{ 285 promoInd = n; 286 clearTimeout (promoTm); 287 288 gID ("promocontent").style.opacity = 1; 289 gID ("promocontent").innerHTML = promoTxt [promoInd]; 290 291 for (var i = 0; i < promoTxt.length; i++) 292 gID ("prdot" + i).style.backgroundColor = (promoInd == i ? "#040" : "white"); 293 294 //promoTm = setTimeout ("nextPromo()", 30000); // Start again after 30 seconds 295} 296 297//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 298 299function rotatePromo () 300{ 301 if (gID ("promocontent")) 302 { 303 promoTm = setTimeout ("nextPromo()", promoSpeed * 1000); 304 gID ("prdot0").style.backgroundColor = "#040"; 305 } 306} 307 308//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 309 310function nextPromo () 311{ 312 clearTimeout (promoTm); 313 314 if (promoTxt.length < 2) 315 return; 316 317 var tm = 20; 318 319 if (promoDir == -1) 320 { 321 promoOpac -= 2; 322 323 if (promoOpac > 0) 324 gID ("promocontent").style.opacity = (promoOpac / 100); 325 else 326 { 327 if (++promoInd >= promoTxt.length) 328 promoInd = 0; 329 330 gID ("promocontent").style.opacity = 0; 331 gID ("promocontent").innerHTML = promoTxt [promoInd]; 332 333 for (var i = 0; i < promoTxt.length; i++) 334 gID ("prdot" + i).style.backgroundColor = (promoInd == i ? "#040" : "white"); 335 336 promoDir = 1; 337 } 338 } 339 else 340 { 341 promoOpac += 2; 342 343 if (promoOpac < 100) 344 gID ("promocontent").style.opacity = (promoOpac / 100); 345 else 346 { 347 promoDir = -1; 348 tm = promoSpeed * 1000; 349 } 350 } 351 352 promoTm = setTimeout ("nextPromo()", tm); 353} 354 355//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 356 357var _showBasket = false; 358 359function toggleBasket () 360{ 361 _showBasket = !_showBasket; 362 gID ("chkbasket").style.display = (_showBasket ? "block" : "none"); 363 gID ("showbskbtn").value = (_showBasket ? "Hide Basket" : "Show Basket"); 364} 365 366//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 367 368function showIntroVid (vidKey, vidTitle) 369{ 370 var lnk = "https://www.youtube.com/watch?v=" + vidKey, 371 vm = gID ("dlibgallerypopup"), 372 wmx = parseFloat (winWH[0]) * 0.9, 373 hmx = parseFloat (winWH[1]) * 0.9, 374 vw = parseInt (wmx), 375 vh = parseInt (wmx * 0.75), 376 gm = gID ("gallerypagemask"); 377 378 if (vh > hmx) 379 { 380 vh = hmx; 381 vw = parseInt (vh * 1.333); 382 } 383 384 vm.innerHTML = div ("dlibgalleryclose.dlibgallerynav", "✕", {onclick: "closeIntroVid()", title: "Close"}) + 385 iframe ("https://www.youtube.com/embed/" + vidKey + "?rel=0&autoplay=1&enablejsapi=1", "@border-width: 0", 386 vw, vh, {title: vidTitle, id: "sumIntro"}); 387 388 gm.style.display = vm.style.display = "block"; 389 vm.style.position = "absolute"; 390 vm.style.top = parseInt ((winWH[1] - vh) / 2) + "px"; 391 vm.style.left = parseInt ((winWH[0] - vw) / 2) + "px"; 392 393 var v = gID ("sumIntro"); 394 395 v.width = vw; 396 v.height = vh; 397} 398 399//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 400 401function closeIntroVid () 402{ 403 gID ("gallerypagemask").style.display = gID ("dlibgallerypopup").style.display = "none"; 404 gID ("dlibgallerypopup").innerHTML = ""; 405} 406 407//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 408 409function sdCheck1 () 410{ 411 var chk = false; 412 clearTimeout (sdTm); 413 414 chk = (document.body.offsetHeight > window.innerHeight); 415 416 if (chk && gID ("scrolldown")) 417 { 418 var doIt = true; 419 420 // See if the content is off the bottom of the viewable page 421 422 var cCol = gID ("contentcol"); 423 424 if (cCol) 425 { 426 var xy = DLibUtilities.findPos (cCol), 427 ht = cCol.clientHeight; 428 429 if (xy [1] + ht < winWH [1]) 430 doIt = false;
431 } 432 433 if (doIt) 434 gID ("scrolldown").style.visibility = "visible"; 435 } 436 437 if (typeof pbCapacityCheck == 'function') 438 pbCapacityCheck (); 439 440 setProdBoxTitleSize (); 441} 442 443//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 444 445function sdCheck2 () 446{ 447 var st = document.documentElement.scrollTop; 448 449 if (gID ("scrolldown")) 450 { 451 if (st > 150 && st < 450) 452 { 453 var op = parseInt ((st - 150) / 3); 454 gID ("scrolldown").style.opacity = 1 - op / 100; 455 } 456 else 457 if (st > 450) 458 gID ("scrolldown").style.visibility = "hidden"; // Turn off until next screen 459 } 460 461 if (gID ("badgebar")) 462 { 463 if (st > 250) 464 gID ("badgebar").style.display = "none"; 465 else 466 { 467 gID ("badgebar").style.display = "flex"; 468 gID ("badgebar").style.opacity = (st > 100 ? 1 - parseInt ((st - 100) / 0.6667) / 100 : 1); 469 } 470 } 471} 472 473//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 474 475function startScrollDown () 476{ 477 sdMax = winWH[1] * 0.9; 478 sdDone = 0; 479 sdStep = 25; 480 doScTm = setTimeout ("doScrollDown()", 25); 481} 482 483//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 484 485function doScrollDown () 486{ 487 clearTimeout (doScTm); 488 sdDone += sdStep; 489 window.scrollBy (0, sdStep); 490 491 if ((sdStep > 0 && sdDone < sdMax) || (sdStep < 0 && sdDone > 0)) 492 doScTm = setTimeout ("doScrollDown()", 25); 493 494 sdCheck2 (); 495} 496 497//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 498 499function gh (s) 500{ 501 var h = 0; 502 503 if (s.length == 0) 504 return h; 505 506 for (var i = 0; i < s.length; i++) 507 { 508 h = ((h << 7) - h) + s.charCodeAt (i); 509 h = h & 0x7FFFFFFF; 510 } 511 512 return "0x" + h.toString (16) + "c923"; 513} 514 515//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 516// CTEXT Box more code when height specified 517//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 518 519function setCTBox (i, ht) 520{ 521 var ct = gID ("ctb" + i).style, 522 rm = gID ("ctrm" + i).style; 523 524 if (ct.maxHeight == "") 525 { 526 ct.maxHeight = ht + "px"; 527 rm.display = "flex"; 528 } 529 else 530 { 531 ct.maxHeight = ""; 532 rm.display = "none"; 533 } 534} 535 536////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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.