1 2(function($) { 3 4 var useWindow = window; 5 6 if (!Object.keys) { 7 Object.keys = (function() { 8 'use strict'; 9 var hasOwnProperty = Object.prototype.hasOwnProperty, 10 hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), 11 dontEnums = [ 12 'toString', 13 'toLocaleString', 14 'valueOf', 15 'hasOwnProperty', 16 'isPrototypeOf', 17 'propertyIsEnumerable', 18 'constructor' 19 ], 20 dontEnumsLength = dontEnums.length; 21 22 return function(obj) { 23 if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { 24 throw new TypeError('Object.keys called on non-object'); 25 } 26 27 var result = [], prop, i; 28 29 for (prop in obj) { 30 if (hasOwnProperty.call(obj, prop)) { 31 result.push(prop); 32 } 33 } 34 35 if (hasDontEnumBug) { 36 for (i = 0; i < dontEnumsLength; i++) { 37 if (hasOwnProperty.call(obj, dontEnums[i])) { 38 result.push(dontEnums[i]); 39 } 40 } 41 } 42 return result; 43 }; 44 }()); 45 } 46 47 // Used to disable some features on IE8 48 var limited_mode = false;
49 var tick_duration = 200; // in ms 50 51 var debug = (location.hash === "#debug"); 52 function debug_log(msg) { 53 if (debug) { 54 console.log(msg); 55 } 56 } 57 58 var allUnits = ["Days", "Hours", "Minutes", "Seconds"]; 59 var nextUnits = { 60 Seconds: "Minutes", 61 Minutes: "Hours", 62 Hours: "Days", 63 Days: "Years" 64 }; 65 var secondsIn = { 66 Seconds: 1, 67 Minutes: 60, 68 Hours: 3600, 69 Days: 86400, 70 Months: 2678400, 71 Years: 31536000 72 }; 73 74 /** 75 * Converts hex color code into object containing integer values for the r,g,b use 76 * This function (hexToRgb) originates from: 77 * http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb 78 * @param {string} hex color code 79 */ 80 function hexToRgb(hex) { 81 82 // Verify already RGB (e.g. "rgb(0,0,0)") or RGBA (e.g. "rgba(0,0,0,0.5)") 83 var rgba = /^rgba?\(([\d]+),([\d]+),([\d]+)(,([\d\.]+))?\)$/; 84 if(rgba.test(hex)) { 85 var result = rgba.exec(hex); 86 return { 87 r: parseInt(result[1]), 88 g: parseInt(result[2]), 89 b: parseInt(result[3]), 90 a: parseInt(result[5] ? result[5] : 1) 91 }; 92 } 93 94 // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") 95 var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 96 hex = hex.replace(shorthandRegex, function(m, r, g, b) { 97 return r + r + g + g + b + b; 98 }); 99 100 var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 101 return result ? { 102 r: parseInt(result[1], 16), 103 g: parseInt(result[2], 16), 104 b: parseInt(result[3], 16) 105 } : null; 106 } 107 108 function isCanvasSupported() { 109 var elem = document.createElement('canvas'); 110 return !!(elem.getContext && elem.getContext('2d')); 111 } 112 113 /** 114 * Function s4() and guid() originate from: 115 * http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript 116 */ 117 function s4() { 118 return Math.floor((1 + Math.random()) * 0x10000) 119 .toString(16) 120 .substring(1); 121 } 122 123 /** 124 * Creates a unique id 125 * @returns {String} 126 */ 127 function guid() { 128 return s4() + s4() + '-' + s4() + '-' + s4() + '-' + 129 s4() + '-' + s4() + s4() + s4(); 130 } 131 132 /** 133 * Array.prototype.indexOf fallback for IE8 134 * @param {Mixed} mixed 135 * @returns {Number} 136 */ 137 if (!Array.prototype.indexOf) { 138 Array.prototype.indexOf = function(elt /*, from*/) 139 { 140 var len = this.length >>> 0; 141 142 var from = Number(arguments[1]) || 0; 143 from = (from < 0) 144 ? Math.ceil(from) 145 : Math.floor(from); 146 if (from < 0) 147 from += len; 148 149 for (; from < len; from++) 150 { 151 if (from in this && 152 this[from] === elt) 153 return from; 154 } 155 return -1; 156 }; 157 } 158 159 function parse_date(str) { 160 var match = str.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}\s[0-9]{1,2}:[0-9]{2}:[0-9]{2}$/); 161 if (match !== null && match.length > 0) { 162 var parts = str.split(" "); 163 var date = parts[0].split("-"); 164 var time = parts[1].split(":"); 165 return new Date(date[0], date[1] - 1, date[2], time[0], time[1], time[2]); 166 } 167 // Fallback for different date formats 168 var d = Date.parse(str); 169 if (!isNaN(d)) 170 return d; 171 d = Date.parse(str.replace(/-/g, '/').replace('T', ' ')); 172 if (!isNaN(d)) 173 return d; 174 // Cant find anything 175 return new Date(); 176 } 177 178 function parse_times(diff, old_diff, total_duration, units, floor) { 179 var raw_time = {}; 180 var raw_old_time = {}; 181 var time = {}; 182 var pct = {}; 183 var old_pct = {}; 184 var old_time = {}; 185 186 var greater_unit = null; 187 for(var i = 0; i < units.length; i++) { 188 var unit = units[i]; 189 var maxUnits; 190 191 if (greater_unit === null) { 192 maxUnits = total_duration / secondsIn[unit]; 193 } 194 else { 195 maxUnits = secondsIn[greater_unit] / secondsIn[unit]; 196 } 197 198 var curUnits = (diff / secondsIn[unit]); 199 var oldUnits = (old_diff / secondsIn[unit]); 200 201 if(floor) { 202 if(curUnits > 0) curUnits = Math.floor(curUnits); 203 else curUnits = Math.ceil(curUnits); 204 if(oldUnits > 0) oldUnits = Math.floor(oldUnits); 205 else oldUnits = Math.ceil(oldUnits); 206 } 207 208 if (unit !== "Days") { 209 curUnits = curUnits % maxUnits; 210 oldUnits = oldUnits % maxUnits; 211 } 212 213 raw_time[unit] = curUnits; 214 time[unit] = Math.abs(curUnits); 215 raw_old_time[unit] = oldUnits; 216 old_time[unit] = Math.abs(oldUnits); 217 pct[unit] = Math.abs(curUnits) / maxUnits; 218 old_pct[unit] = Math.abs(oldUnits) / maxUnits; 219 220 greater_unit = unit; 221 } 222 223 return { 224 raw_time: raw_time, 225 raw_old_time: raw_old_time, 226 time: time, 227 old_time: old_time, 228 pct: pct, 229 old_pct: old_pct 230 }; 231 } 232 233 var TC_Instance_List = {}; 234 function updateUsedWindow() { 235 if(typeof useWindow.TC_Instance_List !== "undefined") {
236 TC_Instance_List = useWindow.TC_Instance_List; 237 } 238 else { 239 useWindow.TC_Instance_List = TC_Instance_List; 240 } 241 initializeAnimationFrameHandler(useWindow); 242 }; 243 244 function initializeAnimationFrameHandler(w) { 245 var vendors = ['webkit', 'moz']; 246 for (var x = 0; x < vendors.length && !w.requestAnimationFrame; ++x) { 247 w.requestAnimationFrame = w[vendors[x] + 'RequestAnimationFrame']; 248 w.cancelAnimationFrame = w[vendors[x] + 'CancelAnimationFrame']; 249 } 250 251 if (!w.requestAnimationFrame || !w.cancelAnimationFrame) { 252 w.requestAnimationFrame = function(callback, element, instance) { 253 if (typeof instance === "undefined") 254 instance = {data: {last_frame: 0}}; 255 var currTime = new Date().getTime(); 256 var timeToCall = Math.max(0, 16 - (currTime - instance.data.last_frame)); 257 var id = w.setTimeout(function() { 258 callback(currTime + timeToCall); 259 }, timeToCall); 260 instance.data.last_frame = currTime + timeToCall; 261 return id; 262 }; 263 w.cancelAnimationFrame = function(id) { 264 clearTimeout(id); 265 }; 266 } 267 }; 268 269 270 var TC_Instance = function(element, options) { 271 this.element = element; 272 this.container; 273 this.listeners = null; 274 this.data = { 275 paused: false, 276 last_frame: 0, 277 animation_frame: null, 278 interval_fallback: null, 279 timer: false, 280 total_duration: null, 281 prev_time: null, 282 drawn_units: [], 283 text_elements: { 284 Days: null, 285 Hours: null, 286 Minutes: null, 287 Seconds: null 288 }, 289 attributes: { 290 canvas: null, 291 context: null, 292 item_size: null, 293 line_width: null, 294 radius: null, 295 outer_radius: null 296 }, 297 state: { 298 fading: { 299 Days: false, 300 Hours: false, 301 Minutes: false, 302 Seconds: false 303 } 304 } 305 }; 306 307 this.config = null; 308 this.setOptions(options); 309 this.initialize(); 310 }; 311 312 TC_Instance.prototype.clearListeners = function() { 313 this.listeners = { all: [], visible: [] }; 314 }; 315 316 TC_Instance.prototype.addTime = function(seconds_to_add) { 317 if(this.data.attributes.ref_date instanceof Date) { 318 var d = this.data.attributes.ref_date; 319 d.setSeconds(d.getSeconds() + seconds_to_add); 320 } 321 else if(!isNaN(this.data.attributes.ref_date)) { 322 this.data.attributes.ref_date += (seconds_to_add * 1000); 323 } 324 }; 325 326 TC_Instance.prototype.initialize = function(clear_listeners) { 327 // Initialize drawn units 328 this.data.drawn_units = []; 329 for(var i = 0; i < Object.keys(this.config.time).length; i++) { 330 var unit = Object.keys(this.config.time)[i]; 331 if (this.config.time[unit].show) { 332 this.data.drawn_units.push(unit); 333 } 334 } 335 336 // Avoid stacking 337 $(this.element).children('div.time_circles').remove(); 338 339 if (typeof clear_listeners === "undefined") 340 clear_listeners = true; 341 if (clear_listeners || this.listeners === null) { 342 this.clearListeners(); 343 } 344 this.container = $("<div>"); 345 this.container.addClass('time_circles'); 346 this.container.appendTo(this.element); 347 348 // Determine the needed width and height of TimeCircles 349 var height = this.element.offsetHeight; 350 var width = this.element.offsetWidth; 351 if (height === 0) 352 height = $(this.element).height(); 353 if (width === 0) 354 width = $(this.element).width(); 355 356 if (height === 0 && width > 0) 357 height = width / this.data.drawn_units.length; 358 else if (width === 0 && height > 0) 359 width = height * this.data.drawn_units.length; 360 361 // Create our canvas and set it to the appropriate size 362 var canvasElement = document.createElement('canvas'); 363 canvasElement.width = width; 364 canvasElement.height = height; 365 366 // Add canvas elements 367 this.data.attributes.canvas = $(canvasElement); 368 this.data.attributes.canvas.appendTo(this.container); 369 370 // Check if the browser has browser support 371 var canvasSupported = isCanvasSupported(); 372 // If the browser doesn't have browser support, check if explorer canvas is loaded 373 // (A javascript library that adds canvas support to browsers that don't have it) 374 if(!canvasSupported && typeof G_vmlCanvasManager !== "undefined") { 375 G_vmlCanvasManager.initElement(canvasElement); 376 limited_mode = true; 377 canvasSupported = true; 378 } 379 if(canvasSupported) { 380 this.data.attributes.context = canvasElement.getContext('2d'); 381 } 382 383 this.data.attributes.item_size = Math.min(width / this.data.drawn_units.length, height); 384 this.data.attributes.line_width = this.data.attributes.item_size * this.config.fg_width; 385 this.data.attributes.radius = ((this.data.attributes.item_size * 0.8) - this.data.attributes.line_width) / 2; 386 this.data.attributes.outer_radius = this.data.attributes.radius + 0.5 * Math.max(this.data.attributes.line_width, this.data.attributes.line_width * this.config.bg_width); 387 388 // Prepare Time Elements 389 var i = 0; 390 for (var key in this.data.text_elements) { 391 if (!this.config.time[key].show) 392 continue; 393 394 var textElement = $("<div>"); 395 textElement.addClass('textDiv_' + key); 396 textElement.css("top", Math.round(0.35 * this.data.attributes.item_size)); 397 textElement.css("left", Math.round(i++ * this.data.attributes.item_size)); 398 textElement.css("width", this.data.attributes.item_size); 399 textElement.appendTo(this.container); 400 401 var headerElement = $("<h4>"); 402 headerElement.text(this.config.time[key].text); // Options 403 headerElement.css("font-size", Math.round(this.config.text_size * this.data.attributes.item_size)); 404 headerElement.css("line-height", Math.round(this.config.text_size * this.data.attributes.item_size) + "px"); 405 headerElement.appendTo(textElement); 406 407 var numberElement = $("<span>"); 408 numberElement.css("font-size", Math.round(3 * this.config.text_size * this.data.attributes.item_size)); 409 numberElement.css("line-height", Math.round(this.config.text_size * this.data.attributes.item_size) + "px"); 410 numberElement.appendTo(textElement); 411 412 this.data.text_elements[key] = numberElement; 413 } 414 415 this.start(); 416 if (!this.config.start) { 417 this.data.paused = true; 418 } 419 420 // Set up interval fallback 421 var _this = this; 422 this.data.interval_fallback = useWindow.setInterval(function(){ 423 _this.update.call(_this, true); 424 }, 100); 425 }; 426 427 TC_Instance.prototype.update = function(nodraw) { 428 if(typeof nodraw === "undefined") { 429 nodraw = false;
430 } 431 else if(nodraw && this.data.paused) { 432 return; 433 } 434 435 if(limited_mode) { 436 //Per unit clearing doesn't work in IE8 using explorer canvas, so do it in one time. The downside is that radial fade cant be used 437 this.data.attributes.context.clearRect(0, 0, this.data.attributes.canvas[0].width, this.data.attributes.canvas[0].hright); 438 } 439 var diff, old_diff; 440 441 var prevDate = this.data.prev_time; 442 var curDate = new Date(); 443 this.data.prev_time = curDate; 444 445 if (prevDate === null) 446 prevDate = curDate; 447 448 // If not counting past zero, and time < 0, then simply draw the zero point once, and call stop 449 if (!this.config.count_past_zero) { 450 if (curDate > this.data.attributes.ref_date) { 451 for(var i = 0; i < this.data.drawn_units.length; i++) { 452 var key = this.data.drawn_units[i]; 453 454 // Set the text value 455 this.data.text_elements[key].text("0"); 456 var x = (i * this.data.attributes.item_size) + (this.data.attributes.item_size / 2); 457 var y = this.data.attributes.item_size / 2; 458 var color = this.config.time[key].color; 459 this.drawArc(x, y, color, 0); 460 } 461 this.stop(); 462 return; 463 } 464 } 465 466 // Compare current time with reference 467 diff = (this.data.attributes.ref_date - curDate) / 1000; 468 old_diff = (this.data.attributes.ref_date - prevDate) / 1000; 469 470 var floor = this.config.animation !== "smooth"; 471 472 var visible_times = parse_times(diff, old_diff, this.data.total_duration, this.data.drawn_units, floor); 473 var all_times = parse_times(diff, old_diff, secondsIn["Years"], allUnits, floor); 474 475 var i = 0; 476 var j = 0; 477 var lastKey = null; 478 479 var cur_shown = this.data.drawn_units.slice(); 480 for (var i in allUnits) { 481 var key = allUnits[i]; 482 483 // Notify (all) listeners 484 if (Math.floor(all_times.raw_time[key]) !== Math.floor(all_times.raw_old_time[key])) { 485 this.notifyListeners(key, Math.floor(all_times.time[key]), Math.floor(diff), "all"); 486 } 487 488 if (cur_shown.indexOf(key) < 0) 489 continue; 490 491 // Notify (visible) listeners 492 if (Math.floor(visible_times.raw_time[key]) !== Math.floor(visible_times.raw_old_time[key])) { 493 this.notifyListeners(key, Math.floor(visible_times.time[key]), Math.floor(diff), "visible"); 494 } 495 496 if(!nodraw) { 497 // Set the text value 498 this.data.text_elements[key].text(Math.floor(Math.abs(visible_times.time[key]))); 499 500 var x = (j * this.data.attributes.item_size) + (this.data.attributes.item_size / 2); 501 var y = this.data.attributes.item_size / 2; 502 var color = this.config.time[key].color; 503 504 if (this.config.animation === "smooth") { 505 if (lastKey !== null && !limited_mode) { 506 if (Math.floor(visible_times.time[lastKey]) > Math.floor(visible_times.old_time[lastKey])) { 507 this.radialFade(x, y, color, 1, key); 508 this.data.state.fading[key] = true; 509 } 510 else if (Math.floor(visible_times.time[lastKey]) < Math.floor(visible_times.old_time[lastKey])) { 511 this.radialFade(x, y, color, 0, key); 512 this.data.state.fading[key] = true; 513 } 514 } 515 if (!this.data.state.fading[key]) { 516 this.drawArc(x, y, color, visible_times.pct[key]); 517 } 518 } 519 else { 520 this.animateArc(x, y, color, visible_times.pct[key], visible_times.old_pct[key], (new Date()).getTime() + tick_duration); 521 } 522 } 523 lastKey = key; 524 j++; 525 } 526 527 // Dont request another update if we should be paused 528 if(this.data.paused || nodraw) { 529 return; 530 } 531 532 // We need this for our next frame either way 533 var _this = this; 534 var update = function() { 535 _this.update.call(_this); 536 }; 537 538 // Either call next update immediately, or in a second 539 if (this.config.animation === "smooth") { 540 // Smooth animation, Queue up the next frame
541 this.data.animation_frame = useWindow.requestAnimationFrame(update, _this.element, _this); 542 } 543 else { 544 // Tick animation, Don't queue until very slightly after the next second happens 545 var delay = (diff % 1) * 1000; 546 if (delay < 0) 547 delay = 1000 + delay; 548 delay += 50; 549 550 _this.data.animation_frame = useWindow.setTimeout(function() { 551 _this.data.animation_frame = useWindow.requestAnimationFrame(update, _this.element, _this); 552 }, delay); 553 } 554 }; 555 556 TC_Instance.prototype.animateArc = function(x, y, color, target_pct, cur_pct, animation_end) { 557 if (this.data.attributes.context === null) 558 return; 559 560 var diff = cur_pct - target_pct; 561 if (Math.abs(diff) > 0.5) { 562 if (target_pct === 0) { 563 this.radialFade(x, y, color, 1); 564 } 565 else { 566 this.radialFade(x, y, color, 0); 567 } 568 } 569 else { 570 var progress = (tick_duration - (animation_end - (new Date()).getTime())) / tick_duration; 571 if (progress > 1) 572 progress = 1; 573 574 var pct = (cur_pct * (1 - progress)) + (target_pct * progress); 575 this.drawArc(x, y, color, pct); 576 577 //var show_pct = 578 if (progress >= 1) 579 return; 580 var _this = this; 581 useWindow.requestAnimationFrame(function() { 582 _this.animateArc(x, y, color, target_pct, cur_pct, animation_end); 583 }, this.element); 584 } 585 }; 586 587 TC_Instance.prototype.drawArc = function(x, y, color, pct) { 588 if (this.data.attributes.context === null) 589 return; 590 591 var clear_radius = Math.max(this.data.attributes.outer_radius, this.data.attributes.item_size / 2); 592 if(!limited_mode) { 593 this.data.attributes.context.clearRect( 594 x - clear_radius, 595 y - clear_radius, 596 clear_radius * 2, 597 clear_radius * 2 598 ); 599 } 600 601 if (this.config.use_background) { 602 this.data.attributes.context.beginPath(); 603 this.data.attributes.context.arc(x, y, this.data.attributes.radius, 0, 2 * Math.PI, false); 604 this.data.attributes.context.lineWidth = this.data.attributes.line_width * this.config.bg_width; 605 606 // line color 607 this.data.attributes.context.strokeStyle = this.config.circle_bg_color; 608 this.data.attributes.context.stroke(); 609 } 610 611 // Direction 612 var startAngle, endAngle, counterClockwise; 613 var defaultOffset = (-0.5 * Math.PI); 614 var fullCircle = 2 * Math.PI; 615 startAngle = defaultOffset + (this.config.start_angle / 360 * fullCircle); 616 var offset = (2 * pct * Math.PI); 617 618 if (this.config.direction === "Both") { 619 counterClockwise = false; 620 startAngle -= (offset / 2); 621 endAngle = startAngle + offset; 622 } 623 else { 624 if (this.config.direction === "Clockwise") { 625 counterClockwise = false; 626 endAngle = startAngle + offset; 627 } 628 else { 629 counterClockwise = true; 630 endAngle = startAngle - offset; 631 } 632 } 633 634 this.data.attributes.context.beginPath(); 635 this.data.attributes.context.arc(x, y, this.data.attributes.radius, startAngle, endAngle, counterClockwise); 636 this.data.attributes.context.lineWidth = this.data.attributes.line_width; 637 638 // line color 639 this.data.attributes.context.strokeStyle = color; 640 this.data.attributes.context.stroke(); 641 }; 642 643 TC_Instance.prototype.radialFade = function(x, y, color, from, key) { 644 // TODO: Make fade_time option 645 var rgb = hexToRgb(color); 646 var _this = this; // We have a few inner scopes here that will need access to our instance 647 648 var step = 0.2 * ((from === 1) ? -1 : 1); 649 var i; 650 for (i = 0; from <= 1 && from >= 0; i++) { 651 // Create inner scope so our variables are not changed by the time the Timeout triggers 652 (function() {
653 var delay = 50 * i; 654 var rgba = "rgba(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ", " + (Math.round(from * 10) / 10) + ")"; 655 useWindow.setTimeout(function() { 656 _this.drawArc(x, y, rgba, 1); 657 }, delay); 658 }()); 659 from += step; 660 } 661 if (typeof key !== undefined) { 662 useWindow.setTimeout(function() { 663 _this.data.state.fading[key] = false; 664 }, 50 * i); 665 } 666 }; 667 668 TC_Instance.prototype.timeLeft = function() { 669 if (this.data.paused && typeof this.data.timer === "number") { 670 return this.data.timer; 671 } 672 var now = new Date(); 673 return ((this.data.attributes.ref_date - now) / 1000); 674 }; 675 676 TC_Instance.prototype.start = function() { 677 useWindow.cancelAnimationFrame(this.data.animation_frame); 678 useWindow.clearTimeout(this.data.animation_frame) 679 680 // Check if a date was passed in html attribute or jquery data 681 var attr_data_date = $(this.element).data('date'); 682 if (typeof attr_data_date === "undefined") { 683 attr_data_date = $(this.element).attr('data-date'); 684 } 685 if (typeof attr_data_date === "string") { 686 this.data.attributes.ref_date = parse_date(attr_data_date); 687 } 688 // Check if this is an unpause of a timer 689 else if (typeof this.data.timer === "number") { 690 if (this.data.paused) { 691 this.data.attributes.ref_date = (new Date()).getTime() + (this.data.timer * 1000); 692 } 693 } 694 else { 695 // Try to get data-timer 696 var attr_data_timer = $(this.element).data('timer'); 697 if (typeof attr_data_timer === "undefined") { 698 attr_data_timer = $(this.element).attr('data-timer'); 699 } 700 if (typeof attr_data_timer === "string") { 701 attr_data_timer = parseFloat(attr_data_timer); 702 } 703 if (typeof attr_data_timer === "number") { 704 this.data.timer = attr_data_timer; 705 this.data.attributes.ref_date = (new Date()).getTime() + (attr_data_timer * 1000); 706 } 707 else { 708 // data-timer and data-date were both not set 709 // use config date 710 this.data.attributes.ref_date = this.config.ref_date; 711 } 712 } 713 714 // Start running 715 this.data.paused = false; 716 this.update.call(this); 717 }; 718 719 TC_Instance.prototype.restart = function() { 720 this.data.timer = false; 721 this.start(); 722 }; 723 724 TC_Instance.prototype.stop = function() { 725 if (typeof this.data.timer === "number") { 726 this.data.timer = this.timeLeft(this); 727 } 728 // Stop running 729 this.data.paused = true; 730 useWindow.cancelAnimationFrame(this.data.animation_frame); 731 }; 732 733 TC_Instance.prototype.destroy = function() { 734 this.clearListeners(); 735 this.stop(); 736 useWindow.clearInterval(this.data.interval_fallback); 737 this.data.interval_fallback = null; 738 739 this.container.remove(); 740 $(this.element).removeAttr('data-tc-id'); 741 $(this.element).removeData('tc-id'); 742 }; 743 744 TC_Instance.prototype.setOptions = function(options) { 745 if (this.config === null) { 746 this.default_options.ref_date = new Date(); 747 this.config = $.extend(true, {}, this.default_options); 748 } 749 $.extend(true, this.config, options); 750 751 // Use window.top if use_top_frame is true 752 if(this.config.use_top_frame) { 753 useWindow = window.top; 754 } 755 else { 756 useWindow = window; 757 } 758 updateUsedWindow(); 759 760 this.data.total_duration = this.config.total_duration; 761 if (typeof this.data.total_duration === "string") { 762 if (typeof secondsIn[this.data.total_duration] !== "undefined") { 763 // If set to Years, Months, Days, Hours or Minutes, fetch the secondsIn value for that 764 this.data.total_duration = secondsIn[this.data.total_duration]; 765 } 766 else if (this.data.total_duration === "Auto") { 767 // If set to auto, total_duration is the size of 1 unit, of the unit type bigger than the largest shown 768 for(var i = 0; i < Object.keys(this.config.time).length; i++) { 769 var unit = Object.keys(this.config.time)[i]; 770 if (this.config.time[unit].show) { 771 this.data.total_duration = secondsIn[nextUnits[unit]]; 772 break; 773 } 774 } 775 } 776 else { 777 // If it's a string, but neither of the above, user screwed up. 778 this.data.total_duration = secondsIn["Years"]; 779 console.error("Valid values for TimeCircles config.total_duration are either numeric, or (string) Years, Months, Days, Hours, Minutes, Auto"); 780 } 781 } 782 }; 783 784 TC_Instance.prototype.addListener = function(f, context, type) { 785 if (typeof f !== "function") 786 return; 787 if (typeof type === "undefined") 788 type = "visible"; 789 this.listeners[type].push({func: f, scope: context}); 790 }; 791 792 TC_Instance.prototype.notifyListeners = function(unit, value, total, type) { 793 for (var i = 0; i < this.listeners[type].length; i++) { 794 var listener = this.listeners[type][i]; 795 listener.func.apply(listener.scope, [unit, value, total]); 796 } 797 }; 798 799 TC_Instance.prototype.default_options = { 800 ref_date: new Date(), 801 start: true, 802 animation: "smooth", 803 count_past_zero: true, 804 circle_bg_color: "#60686F", 805 use_background: true, 806 fg_width: 0.1, 807 bg_width: 1.2, 808 text_size: 0.07, 809 total_duration: "Auto", 810 direction: "Clockwise", 811 use_top_frame: false, 812 start_angle: 0, 813 time: { 814 Days: { 815 show: true, 816 text: "Days", 817 color: "#FC6" 818 }, 819 Hours: { 820 show: true, 821 text: "Hours", 822 color: "#9CF" 823 }, 824 Minutes: { 825 show: true, 826 text: "Minutes", 827 color: "#BFB" 828 }, 829 Seconds: { 830 show: true, 831 text: "Seconds", 832 color: "#F99" 833 } 834 } 835 }; 836 837 // Time circle class 838 var TC_Class = function(elements, options) { 839 this.elements = elements; 840 this.options = options; 841 this.foreach(); 842 }; 843 844 TC_Class.prototype.getInstance = function(element) { 845 var instance; 846 847 var cur_id = $(element).data("tc-id"); 848 if (typeof cur_id === "undefined") { 849 cur_id = guid(); 850 $(element).attr("data-tc-id", cur_id); 851 } 852 if (typeof TC_Instance_List[cur_id] === "undefined") { 853 var options = this.options; 854 var element_options = $(element).data('options'); 855 if (typeof element_options === "string") { 856 element_options = JSON.parse(element_options); 857 } 858 if (typeof element_options === "object") { 859 options = $.extend(true, {}, this.options, element_options); 860 } 861 instance = new TC_Instance(element, options); 862 TC_Instance_List[cur_id] = instance; 863 } 864 else { 865 instance = TC_Instance_List[cur_id]; 866 if (typeof this.options !== "undefined") { 867 instance.setOptions(this.options); 868 } 869 } 870 return instance; 871 }; 872 873 TC_Class.prototype.addTime = function(seconds_to_add) { 874 this.foreach(function(instance) { 875 instance.addTime(seconds_to_add); 876 }); 877 }; 878 879 TC_Class.prototype.foreach = function(callback) { 880 var _this = this; 881 this.elements.each(function() { 882 var instance = _this.getInstance(this); 883 if (typeof callback === "function") { 884 callback(instance); 885 } 886 }); 887 return this; 888 }; 889 890 TC_Class.prototype.start = function() { 891 this.foreach(function(instance) { 892 instance.start(); 893 }); 894 return this; 895 }; 896 897 TC_Class.prototype.stop = function() { 898 this.foreach(function(instance) { 899 instance.stop(); 900 }); 901 return this; 902 }; 903 904 TC_Class.prototype.restart = function() { 905 this.foreach(function(instance) { 906 instance.restart(); 907 }); 908 return this; 909 }; 910 911 TC_Class.prototype.rebuild = function() { 912 this.foreach(function(instance) { 913 instance.initialize(false); 914 }); 915 return this; 916 }; 917 918 TC_Class.prototype.getTime = function() { 919 return this.getInstance(this.elements[0]).timeLeft(); 920 }; 921 922 TC_Class.prototype.addListener = function(f, type) { 923 if (typeof type === "undefined") 924 type = "visible"; 925 var _this = this; 926 this.foreach(function(instance) { 927 instance.addListener(f, _this.elements, type); 928 }); 929 return this; 930 }; 931 932 TC_Class.prototype.destroy = function() { 933 this.foreach(function(instance) { 934 instance.destroy(); 935 }); 936 return this; 937 }; 938 939 TC_Class.prototype.end = function() { 940 return this.elements; 941 }; 942 943 $.fn.TimeCircles = function(options) { 944 return new TC_Class(this, options); 945 }; 946}(jQuery)); 947 948 949 950 951 952 953 $(function(){ 954 $("#CountDownTimer").TimeCircles({ time: { Days: { show: false }, Hours: { show: true } } 955 }); 956 }); 957 958 959 960$(document).ready(function() { 961 962 963var newsletter_p = setInterval(function(){ 964$("#ouibounce-modal").css("display","block") 965$("body").addClass('fixed'); 966clearInterval(newsletter_p); 967},5000); 968 969$('.cus-overlay').click(function(){
970 $('#ouibounce-modal2').attr('id' , 'ouibounce-modal' ); 971 setTimeout(function(){ $('#ouibounce-modal').css('display' , 'block' )}, 5000); 972 973}); 974$('.popup-form .close').click(function(){ 975 $('#ouibounce-modal2').attr('id' , 'ouibounce-modal' ); 976 977 setTimeout(function(){ $('#ouibounce-modal').css('display' , 'block' )}, 5000); 978 979}); 980 981 982$('div#btmsticky a.various, .various, a.view-pricing-txt.various, img.bn-2').click(function(){ 983 $('#ouibounce-modal').attr('id' , 'ouibounce-modal2' ); 984 985}); 986 987 988 $('.modal-footer a, .underlay').click( function(){ 989 $("body").removeClass('fixed'); 990 991 }); 992 993 994$(window).scroll(function(){ 995 996 997 var headerHeight = 300-140; 998 if ( ( $(window).scrollTop() >= headerHeight ) ){ 999 $('.floating-form-wrap, .side-bars').fadeIn( 300 ); 1000 $('.floating-banner').fadeIn(300); 1001 $('.btm-sticky').fadeIn(300); 1002 } 1003 else { 1004 $('.floating-form-wrap, .side-bars').fadeOut( 300 ); 1005 $('.floating-banner').fadeOut(300); 1006 $('.btm-sticky').fadeOut(300); 1007 } 1008 1009 });//window scroll end 1010 1011 1012$('.lead_price').click(function(){ 1013 $('<input>').attr({ 1014 type: 'hidden', 1015 value: '-', 1016 id: 'lead_p', 1017 name: 'lead_p' 1018}).appendTo('#popupform form'); 1019 }); 1020 1021$('.lead_price2').click(function(){ 1022 $('<input>').attr({ 1023 type: 'hidden', 1024 value: 'New-', 1025 id: 'lead_p', 1026 name: 'lead_p' 1027}).appendTo('#popupform form'); 1028 }); 1029 1030 $('.close, .cus-overlay').click(function(){ 1031 $("#popupform form").find("#lead_p").remove(); 1032 1033 1034}); 1035 1036 $(".view-pricing-txt").click(function(){ 1037 var pkgname2=$(this).attr('title'); 1038 1039 if ( $(this).attr('title') !== undefined) 1040 { 1041 $('.popupform h3, .popupform h2').html(pkgname2); 1042 $('#textC').html(pkgname2); 1043 1044 return; 1045 } 1046 else { 1047 var pkgname2=$(this).attr('title'); 1048 $('#lead_pkg_name').html("REQUEST FREE CONSULTATION"); 1049 $('#textC').html("REQUEST FREE CONSULTATION"); 1050 1051 1052 } 1053 }); 1054 1055 1056 1057 1058 1059$('[data-fancybox]').fancybox(); 1060$(".validate-footer").validate(); 1061$(".validate-popup").validate(); 1062$(".validate-contact").validate(); 1063$(".validate-opt").validate(); 1064$(".validate-lpform").validate(); 1065 1066 1067 1068 1069$('.various, div#btmsticky a.various, img.bn-2').click( function(){ 1070 $("body").addClass('fixed'); 1071 $('.popupform').show(300).addClass('visibleit'); 1072 $('.cus-overlay').fadeIn(300); 1073}); 1074 1075$('a.various2').click( function(){ 1076 $("body").addClass('fixed'); 1077 $('.popfrm').show(300).addClass('visibleit'); 1078 $('.cus-overlay').fadeIn(300); 1079}); 1080 1081 1082 1083 1084 1085$('.cus-overlay, .close').click( function(){ 1086 $("body").removeClass('fixed'); 1087 $('.popupform').css({'overflow':'hidden'}) 1088 $('.popupform').hide(300); 1089 $('.cus-overlay').fadeOut(300) 1090 $(this).fadeOut(300); 1091 }); 1092 1093 1094 1095 1096 1097 1098 1099 1100window.__lc = window.__lc || {}; 1101window.__lc.license = 19777042; 1102window.__lc.integration_name = "manual_channels"; 1103window.__lc.product_name = "livechat"; 1104;(function(n,t,c){function i(n){return e._h?e._h.apply(null,n):e._q.push(n)}var e={_q:[],_h:null,_v:"2.0",on:function(){i(["on",c.call(arguments)])},once:function(){i(["once",c.call(arguments)])},off:function(){i(["off",c.call(arguments)])},get:function(){if(!e._h)throw new Error("[LiveChatWidget] You can't use getters before load.");return i(["get",c.call(arguments)])},call:function(){i(["call",c.call(arguments)])},init:function(){var n=t.createElement("script");n.async=!0,n.type="text/javascript",n.src="https://cdn.livechatinc.com/tracking.js",t.head.appendChild(n)}};!n.__lc.asyncInit&&e.init(),n.LiveChatWidget=n.LiveChatWidget||e}(window,document,[].slice)) 1105 1106 1107 1108 1109$('.chat').click( function(){ 1110LiveChatWidget.call('maximize'); return false; 1111}); 1112 1113 1114 1115 $zopim(function() { 1116 $zopim.livechat.theme.setColors({badge: '#fd7c07', primary: '#fd7c07'}); 1117 $zopim.livechat.theme.reload(); // apply new theme settings 1118 }); 1119 1120 /* $zopim(function() { 1121 $zopim.livechat.setGreetings({ 1122 'online': 'Chat with us', 1123 'offline': 'Leave us a message' 1124 }); 1125 }); */ 1126 1127$("li:first-child").addClass("first"); 1128$("li:last-child").addClass("last"); 1129$("tr:nth-child(odd)").addClass("alter"); 1130$('[href="#"]').attr("href", "javascript:;"); 1131 1132}); 1133 1134 1135$( document ).ready(function() { 1136 var currentIP = $("meta[name=ip2loc]").attr('content'); 1137 var key = '5XpThOAEkfgOvEJ'; 1138 $.ajax({ 1139 method: 'get', 1140 url: 'https://pro.ip-api.com/json/' + currentIP, 1141 data: {key: key}, 1142 success: function (data) { 1143 if (data) { 1144 $('input[name=ip2loc_ip]').val(data.query); 1145 $('input[name=ip2loc_isp]').val(data.isp); 1146 $('input[name=ip2loc_org]').val(data.org); 1147 $('input[name=ip2loc_country]').val(data.country); 1148 $('input[name=ip2loc_region]').val(data.regionName); 1149 $('input[name=ip2loc_city]').val(data.city); 1150 $('input[name=ip2loc_countryCode]').val(data.countryCode); 1151 } 1152 } 1153 }); 1154 1155 1156 var currentIP = $("meta[name=ip2loc]").attr('content'); 1157 var iplocactionKey = '5XpThOAEkfgOvEJ'; 1158 1159 1160 $(".ftpn").intlTelInput({ 1161 autoPlaceholder: true, 1162 defaultCountry: "auto", 1163 initialCountry: "auto", 1164 nationalMode: false, 1165 numberType: "MOBILE", 1166 preventInvalidNumbers: true, 1167 geoIpLookup: function(callback) { 1168 $.get('https://pro.ip-api.com/json/' + currentIP + '?key=' + iplocactionKey, function() {}, 'jsonp').always(function(resp) { 1169 var countryCode = (resp && resp.countryCode) ? resp.countryCode : ""; 1170 callback(resp.countryCode); 1171 }); 1172 } 1173 }).done(function() {}); 1174 1175 1176 $('.test-slider').owlCarousel({ 1177 loop:true, 1178 margin: 10, 1179 items:1, 1180 nav:false, 1181 autoplay: true, 1182 autoplayTimeout: 2000, 1183 autoplayHoverPause: true 1184 }); 1185 1186}); 1187 1188 1189 1190/* Book Cover Design â jQuery interactions */ 1191 1192(function ($) { 1193 "use strict"; 1194 1195 function pad(n) { 1196 return n < 10 ? "0" + n : String(n); 1197 } 1198 1199 function setRing($circle, value, max) { 1200 var circumference = 264; 1201 var offset = circumference - (value / max) * circumference; 1202 $circle.css("stroke-dashoffset", offset); 1203 } 1204 1205 function startCountdown() { 1206 var totalSeconds = 5600; 1207 1208 function tick() { 1209 if (totalSeconds < 0) totalSeconds = 5600; 1210 1211 var h = Math.floor(totalSeconds / 3600); 1212 var m = Math.floor((totalSeconds % 3600) / 60); 1213 var s = totalSeconds % 60; 1214 1215 $("#cd-hours").text(pad(h)); 1216 $("#cd-minutes").text(pad(m)); 1217 $("#cd-seconds").text(pad(s)); 1218 1219 setRing($(".progress.hours"), h, 24); 1220 setRing($(".progress.minutes"), m, 60); 1221 setRing($(".progress.seconds"), s, 60); 1222 1223 totalSeconds -= 1; 1224 } 1225 1226 tick(); 1227 setInterval(tick, 1000); 1228 } 1229 1230 function revealOnScroll() { 1231 var winBottom = $(window).scrollTop() + $(window).height() * 0.88; 1232 1233 $(".reveal").each(function () { 1234 var $el = $(this); 1235 if (!$el.hasClass("visible") && $el.offset().top < winBottom) { 1236 $el.addClass("visible"); 1237 1238 // stagger children inside section 1239 $el.find(".genre-tile, .why-card, .flow-card, .process-step, .icon-pill, .craft-item") 1240 .each(function (i) { 1241 var $child = $(this); 1242 $child.css({ 1243 opacity: 0, 1244 transform: "translateY(18px)" 1245 }); 1246 setTimeout(function () { 1247 $child.css({ 1248 transition: "opacity 0.5s ease, transform 0.5s ease", 1249 opacity: 1, 1250 transform: "translateY(0)" 1251 }); 1252 }, 80 + i * 70); 1253 }); 1254 } 1255 }); 1256 } 1257 1258 function revealBanner() { 1259 $(".reveal-banner").each(function (i) { 1260 var $el = $(this); 1261 setTimeout(function () { 1262 $el.addClass("visible"); 1263 }, 80 + i * 90); 1264 }); 1265 } 1266 1267 function initFaq() { 1268 $(".faq-item.active .faq-a").show(); 1269 1270 $(".faq-q").on("click", function () { 1271 var $item = $(this).closest(".faq-item"); 1272 var $answer = $item.find(".faq-a"); 1273 var isOpen = $item.hasClass("active"); 1274 1275 $(".faq-item").not($item).removeClass("active").find(".faq-a").slide
1275Up(280); 1276 $(".faq-item").not($item).find(".faq-q").attr("aria-expanded", "false"); 1277 1278 if (isOpen) { 1279 $item.removeClass("active"); 1280 $answer.slideUp(280); 1281 $(this).attr("aria-expanded", "false"); 1282 } else { 1283 $item.addClass("active"); 1284 $answer.slideDown(280); 1285 $(this).attr("aria-expanded", "true"); 1286 } 1287 }); 1288 } 1289 1290 function bannerParallax() { 1291 var $banner = $(".n-inner-banner"); 1292 if (!$banner.length) return; 1293 1294 $(window).on("scroll", function () { 1295 var scrolled = $(window).scrollTop(); 1296 if (scrolled < $banner.outerHeight()) { 1297 $banner.css("background-position", "center " + scrolled * 0.25 + "px"); 1298 } 1299 }); 1300 } 1301 1302 function initForm() { 1303 $("#bannerForm").on("submit", function (e) { 1304 e.preventDefault(); 1305 var $btn = $(this).find(".btn-submit"); 1306 var original = $btn.html(); 1307 $btn.html('<i class="fa fa-check"></i> Thank You!').prop("disabled", true); 1308 setTimeout(function () { 1309 $btn.html(original).prop("disabled", false); 1310 $("#bannerForm")[0].reset(); 1311 }, 2200); 1312 }); 1313 } 1314 1315 function imageTilt() { 1316 $(".media-frame, .polaroid, .magazine__art").on("mousemove", function (e) { 1317 var $el = $(this); 1318 var off = $el.offset(); 1319 var x = (e.pageX - off.left) / $el.outerWidth(); 1320 var y = (e.pageY - off.top) / $el.outerHeight(); 1321 var rx = (0.5 - y) * 8; 1322 var ry = (x - 0.5) * 8; 1323 $el.css("transform", "perspective(800px) rotateX(" + rx + "deg) rotateY(" + ry + "deg)"); 1324 }).on("mouseleave", function () { 1325 $(this).css("transform", ""); 1326 }); 1327 } 1328 1329 $(function () { 1330 startCountdown(); 1331 revealBanner(); 1332 revealOnScroll(); 1333 initFaq(); 1334 bannerParallax(); 1335 initForm(); 1336 imageTilt(); 1337 1338 $(window).on("scroll resize", revealOnScroll); 1339 }); 1340})(jQuery); 1341 1342 1343 1344 1345 1346 1347/* BWI Premium Navigation â unique prefix: bwi-pn- */ 1348(function ($) { 1349 "use strict"; 1350 1351 var $header = $("#bwiPnHeader"); 1352 if (!$header.length) return; 1353 1354 var $wrap = $("#bwiPnWrap"); 1355 var $top = $("#bwiPnTop"); 1356 var $toggle = $("#bwiPnToggle"); 1357 var $scrim = $("#bwiPnScrim"); 1358 var $nav = $header.find(".bwi-pn__nav"); 1359 var $items = $header.find(".bwi-pn__item--drop"); 1360 var mq = window.matchMedia("(max-width: 1024px)"); 1361 1362 function isMobile() { 1363 return mq.matches; 1364 } 1365 1366 function closeAllDrops() { 1367 $items.removeClass("is-open"); 1368 $items.find(".bwi-pn__drop-btn").attr("aria-expanded", "false"); 1369 } 1370 1371 function syncDrawerTop() { 1372 var target = $wrap.length ? $wrap[0] : document.documentElement; 1373 if (!isMobile()) { 1374 target.style.removeProperty("--bwi-pn-drawer-top"); 1375 $nav.css({ top: "", bottom: "", maxHeight: "", height: "" }); 1376 return; 1377 } 1378 var rect = $header[0].getBoundingClientRect(); 1379 var top = Math.max(0, Math.round(rect.bottom)); 1380 target.style.setProperty("--bwi-pn-drawer-top", top + "px"); 1381 } 1382 1383 function closeDrawer() { 1384 $header.removeClass("is-drawer-open"); 1385 $wrap.removeClass("is-drawer-open"); 1386 $toggle.attr("aria-expanded", "false").attr("aria-label", "Open menu"); 1387 $scrim.attr("hidden", true); 1388 $("body").removeClass("bwi-pn-no-scroll"); 1389 closeAllDrops(); 1390 } 1391 1392 function openDrawer() { 1393 $header.addClass("is-drawer-open"); 1394 $wrap.addClass("is-drawer-open"); 1395 // topbar hide ke baad measure â overlay header se start ho 1396 window.requestAnimationFrame(function () { 1397 syncDrawerTop(); 1398 }); 1399 $toggle.attr("aria-expanded", "true").attr("aria-label", "Close menu"); 1400 $scrim.removeAttr("hidden"); 1401 $("body").addClass("bwi-pn-no-scroll"); 1402 } 1403 1404 $items.each(function () { 1405 var $item = $(this); 1406 var $btn = $item.find("> .bwi-pn__drop-btn"); 1407 var hoverTimer; 1408 1409 $item.on("mouseenter", function () { 1410 if (isMobile()) return; 1411 clearTimeout(hoverTimer); 1412 closeAllDrops(); 1413 $item.addClass("is-open"); 1414 $btn.attr("aria-expanded", "true"); 1415 }); 1416 1417 $item.on("mouseleave", function () { 1418 if (isMobile()) return; 1419 hoverTimer = setTimeout(function () { 1420 $item.removeClass("is-open"); 1421 $btn.attr("aria-expanded", "false"); 1422 }, 140); 1423 }); 1424 1425 $btn.on("click", function (e) { 1426 e.preventDefault(); 1427 e.stopPropagation(); 1428 var open = $item.hasClass("is-open"); 1429 if (isMobile()) { 1430 $items.not($item).removeClass("is-open")
1431 .find(".bwi-pn__drop-btn").attr("aria-expanded", "false"); 1432 $item.toggleClass("is-open", !open); 1433 $btn.attr("aria-expanded", open ? "false" : "true"); 1434 } else { 1435 closeAllDrops(); 1436 if (!open) { 1437 $item.addClass("is-open"); 1438 $btn.attr("aria-expanded", "true"); 1439 } 1440 } 1441 }); 1442 }); 1443 1444 $toggle.on("click", function (e) { 1445 e.preventDefault(); 1446 if ($header.hasClass("is-drawer-open")) closeDrawer(); 1447 else openDrawer(); 1448 }); 1449 1450 $scrim.on("click", closeDrawer); 1451 1452 $(document).on("keydown", function (e) { 1453 if (e.key === "Escape") closeDrawer(); 1454 }); 1455 1456 $(document).on("click", function (e) { 1457 if (!$(e.target).closest(".bwi-pn").length) closeAllDrops(); 1458 }); 1459 1460 $header.on("click", ".bwi-pn__cols a, .bwi-pn__item:not(.bwi-pn__item--drop) > .bwi-pn__link", function () { 1461 if (isMobile()) closeDrawer(); 1462 }); 1463 1464 function onBreakpointChange() { 1465 closeDrawer(); 1466 syncDrawerTop(); 1467 } 1468 1469 if (mq.addEventListener) mq.addEventListener("change", onBreakpointChange); 1470 else if (mq.addListener) mq.addListener(onBreakpointChange); 1471 1472 if ("IntersectionObserver" in window && $top.length) { 1473 var io = new IntersectionObserver( 1474 function (entries) { 1475 $header.toggleClass("bwi-pn--scrolled", !entries[0].isIntersecting); 1476 }, 1477 { root: null, threshold: 0 } 1478 ); 1479 io.observe($top[0]); 1480 } else { 1481 var ticking = false; 1482 $(window).on("scroll", function () { 1483 if (ticking) return; 1484 ticking = true; 1485 window.requestAnimationFrame(function () { 1486 var past = $top.length 1487 ? $top[0].getBoundingClientRect().bottom <= 0 1488 : $(window).scrollTop() > 8; 1489 $header.toggleClass("bwi-pn--scrolled", past); 1490 ticking = false; 1491 }); 1492 }); 1493 } 1494 1495 $(window).on("resize orientationchange", function () { 1496 if ($header.hasClass("is-drawer-open")) syncDrawerTop(); 1497 }); 1498})(jQuery); 1499
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.