PageSourceSearch

https://forsakuwait.com/public/website/assets/js/jquery.smoothscroll.js

js forsakuwait.com collected 2026-09-24 10:59:37 UTC 11,275 bytes, 469 lines download raw bytes

1// SmoothScroll v1.2.1
2// Licensed under the terms of the MIT license.
3
4// People involved
5//  - Balazs Galambosi (maintainer)  
6//  - Patrick Brunner  (original idea)
7//  - Michael Herf     (Pulse Algorithm)
8//  - Justin Force     (Resurect)
9
10// Scroll Variables (tweakable)
11var framerate = 150; // [Hz]
12var animtime  = 700; // [px]
13var stepsize  = 90; // [px]
14
15// Pulse (less tweakable)
16// ratio of "tail" to "acceleration"
17var pulseAlgorithm = true;
18var pulseScale     = 8;
19var pulseNormalize = 1;
20
21// Acceleration
22var acceleration   = true;
23var accelDelta     = 10;  // 20
24var accelMax       = 1;   // 1
25
26// Keyboard Settings
27var keyboardsupport = true;  // option
28var disableKeyboard = false; // other reasons
29var arrowscroll     = 50;    // [px]
30
31// Excluded pages
32var exclude = "";
33var disabled = false;
34
35// Other Variables
36var frame = false;
37var direction = { x: 0, y: 0 };
38var initdone  = false;
39var fixedback = true;
40var root = document.documentElement;
41var activeElement;
42
43var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36 };
44
45/**
46 * Sets up scrolls array, determines if frames are involved.
47 */
48function init() {
49
50  if (!document.body) return;
51
52  var body = document.body;
53  var html = document.documentElement;
54  var windowHeight = window.innerHeight;
55  var scrollHeight = body.scrollHeight;
56
57  // check compat mode for root element
58  root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
59  activeElement = body;
60
61  initdone = true;
62
63  // Checks if this script is running in a frame
64  if (top != self) {
65    frame = true;
66  }
67
68  /**
69   * This fixes a bug where the areas left and right to
70   * the content does not trigger the onmousewheel event
71   * on some pages. e.g.: html, body { height: 100% }
72   */
73  else if (scrollHeight > windowHeight &&
74           (body.offsetHeight <= windowHeight ||
75            html.offsetHeight <= windowHeight)) {
76
77    // DOMChange (throttle): fix height
78    var pending = false;
79    var refresh = function() {
80      if (!pending && html.scrollHeight != document.height) {
81        pending = true; // add a new pending action
82        setTimeout(function(){
83          html.style.height = document.height + 'px';
84          pending = false;
85        }, 500); // act rarely to stay fast
86      }
87    };
88    html.style.height = '';
89    setTimeout(refresh, 10);
90    addEvent("DOMNodeInserted", refresh);
91    addEvent("DOMNodeRemoved",  refresh);
92
93    // clearfix
94    if (root.offsetHeight <= windowHeight) {
95      var underlay = document.createElement("div");
96      underlay.style.clear = "both";
97      body.appendChild(underlay);
98    }
99  }
100
101  // gmail performance fix
102  if (document.URL.indexOf("mail.google.com") > -1) {
103    var s = document.createElement("style");
104    s.innerHTML = ".iu { visibility: hidden }";
105    (document.getElementsByTagName("head")[0] || html).appendChild(s);
106  }
107  // disable fixed background
108  if (!fixedback && !disabled) {
109    body.style.backgroundAttachment = "scroll";
110    html.style.backgroundAttachment = "scroll";
111  }
112}
113
114
115/************************************************
116 * SCROLLING
117 ************************************************/
118
119var que = [];
120var pending = false;
121var lastScroll = +new Date;
122
123/**
124 * Pushes scroll actions to the scrolling queue.
125 */
126function scrollArray(elem, left, top, delay) {
127
128  delay || (delay = 1000);
129  directionCheck(left, top);
130
131  if (acceleration) {
132    var now = +new Date;
133    var elapsed = now - lastScroll;
134    if (elapsed < accelDelta) {
135      var factor = (1 + (30 / elapsed)) / 2;
136      if (factor > 1) {
137        factor = Math.min(factor, accelMax);
138        left *= factor;
139        top  *= factor;
140      }
141    }
142    lastScroll = +new Date;
143  }
144
145  // push a scroll command
146  que.push({
147    x: left,
148    y: top,
149    lastX: (left < 0) ? 0.99 : -0.99,
150    lastY: (top  < 0) ? 0.99 : -0.99,
151    start: +new Date
152  });
153
154  // don't act if there's a pending queue
155  if (pending) {
156    return;
157  }
158
159  var scrollWindow = (elem === document.body);
160
161  var step = function() {
162
163    var now = +new Date;
164    var scrollX = 0;
165    var scrollY = 0;
166
167    for (var i = 0; i < que.length; i++) {
168
169      var item = que[i];
170      var elapsed  = now - item.start;
171      var finished = (elapsed >= animtime);
172
173      // scroll position: [0, 1]
174      var position = (finished) ? 1 : elapsed / animtime;
175
176      // easing [optional]
177      if (pulseAlgorithm) {
178        position = pulse(position);
179      }
180
181      // only need the difference
182      var x = (item.x * position - item.lastX) >> 0;
183      var y = (item.y * position - item.lastY) >> 0;
184
185      // add this to the total scrolling
186      scrollX += x;
187      scrollY += y;
188
189      // update last values
190      item.lastX += x;
191      item.lastY += y;
192
193      // delete and step back if it's over
194      if (finished) {
195        que.splice(i, 1); i--;
196      }
197    }
198
199    // scroll left and top
200    if (scrollWindow) {
201      window.scrollBy(scrollX, scrollY)
202    }
203    else {
204      if (scrollX) elem.scrollLeft += scrollX;
205      if (scrollY) elem.scrollTop  += scrollY;
206    }
207
208    // clean up if there's nothing left to do
209    if (!left && !top) {
210      que = [];
211    }
212
213    if (que.length) {
214      requestFrame(step, elem, (delay / framerate + 1));
215    } else {
216      pending = false;
217    }
218  }
219
220  // start a new queue of actions
221  requestFrame(step, elem, 0);
222  pending = true;
223}
224
225
226/***********************************************
227 * EVENTS
228 ***********************************************/
229
230/**
231 * Mouse wheel handler.
232 * @param {Object} event
233 */
234function wheel(event) {
235
236  if (!initdone) {
237    init();
238  }
239
240  var target = event.target;
241  var overflowing = overflowingAncestor(target);
242
243  // use default if there's no overflowing
244  // element or default action is prevented
245  if (!overflowing || event.defaultPrevented ||
246      isNodeName(activeElement, "embed") ||
247        (isNodeName(target, "embed") && /\.pdf/i.test(target.src))) {
248    return true;
249  }
250
251  var deltaX = event.wheelDeltaX || 0;
252  var deltaY = event.wheelDeltaY || 0;
253
254  // use wheelDelta if deltaX/Y is not available
255  if (!deltaX && !deltaY) {
256    deltaY = event.wheelDelta || 0;
257  }
258
259  // scale by step size
260  // delta is 120 most of the time
261  // synaptics seems to send 1 sometimes
262  if (Math.abs(deltaX) > 1.2) {
263    deltaX *= stepsize / 120;
264  }
265  if (Math.abs(deltaY) > 1.2) {
266    deltaY *= stepsize / 120;
267  }
268
269  scrollArray(overflowing, -deltaX, -deltaY);
270  event.preventDefault();
271}
272
273/**
274 * Keydown event handler.
275 * @param {Object} event
276 */
277function keydown(event) {
278
279  var target   = event.target;
280  var modifier = event.ctrlKey || event.altKey || event.metaKey ||
281    (event.shiftKey && event.keyCode !== key.spacebar);
282
283  // do nothing if user is editing text
284  // or using a modifier key (except shift)
285  // or in a dropdown
286  if ( /input|textarea|select|embed/i.test(target.nodeName) ||
287      target.isContentEditable ||
288        event.defaultPrevented   ||
289          modifier ) {
290    return true;
291  }
292  // spacebar should trigger button press
293  if (isNodeName(target, "button") &&
294      event.keyCode === key.spacebar) {
295    return true;
296  }
297
298  var shift, x = 0, y = 0;
299  var elem = overflowingAncestor(activeElement);
300  var clientHeight = elem.clientHeight;
301
302  if (elem == document.body) {
303    clientHeight = window.innerHeight;
304  }
305
306  switch (event.keyCode) {
307    case key.up:
308      y = -arrowscroll;
309    break;
310    case key.down:
311      y = arrowscroll;
312    break;
313    case key.spacebar: // (+ shift)
314      shift = event.shiftKey ? 1 : -1;
315    y = -shift * clientHeight * 0.9;
316    break;
317    case key.pageup:
318      y = -clientHeight * 0.9;
319    break;
320    case key.pagedown:
321      y = clientHeight * 0.9;
322    break;
323    case key.home:
324      y = -elem.scrollTop;
325    break;
326    case key.end:
327      var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
328    y = (damt > 0) ? damt+10 : 0;
329    break;
330    case key.left:
331      x = -arrowscroll;
332    break;
333    case key.right:
334      x = arrowscroll;
335    break;
336    default:
337      return true; // a key we don't care about
338  }
339
340  scrollArray(elem, x, y);
341  event.preventDefault();
342}
343
344/**
345 * Mousedown event only for updating activeElement
346 */
347function mousedown(event) {
348  activeElement = event.target;
349}
350
351
352/***********************************************
353 * OVERFLOW
354 ***********************************************/
355
356var cache = {}; // cleared out every once in while
357setInterval(function(){ cache = {}; }, 10 * 1000);
358
359var uniqueID = (function() {
360  var i = 0;
361  return function (el) {
362    return el.uniqueID || (el.uniqueID = i++);
363  };
364})();
365
366function setCache(elems, overflowing) {
367  for (var i = elems.length; i--;)
368  cache[uniqueID(elems[i])] = overflowing;
369  return overflowing;
370}
371
372function overflowingAncestor(el) {
373  var elems = [];
374  var rootScrollHeight = root.scrollHeight;
375  do {
376    var cached = cache[uniqueID(el)];
377    if (cached) {
378      return setCache(elems, cached);
379    }
380    elems.push(el);
381    if (rootScrollHeight === el.scrollHeight) {
382      if (!frame || root.clientHeight + 10 < rootScrollHeight) {
383        return setCache(elems, document.body); // scrolling root in WebKit
384      }
385    } else if (el.clientHeight + 10 < el.scrollHeight) {
386      overflow = getComputedStyle(el, "").getPropertyValue("overflow-y");
387      if (overflow === "scroll" || overflow === "auto") {
388        return setCache(elems, el);
389      }
390    }
391  } while (el = el.parentNode);
392}
393
394
395/***********************************************
396 * HELPERS
397 ***********************************************/
398
399function addEvent(type, fn, bubble) {
400  window.addEventListener(type, fn, (bubble||false));
401}
402
403function removeEvent(type, fn, bubble) {
404  window.removeEventListener(type, fn, (bubble||false));
405}
406
407function isNodeName(el, tag) {
408  return (el.nodeName||"").toLowerCase() === tag.toLowerCase();
409}
410
411function directionCheck(x, y) {
412  x = (x > 0) ? 1 : -1;
413  y = (y > 0) ? 1 : -1;
414  if (direction.x !== x || direction.y !== y) {
415    direction.x = x;
416    direction.y = y;
417    que = [];
418    lastScroll = 0;
419  }
420}
421
422var requestFrame = (function(){
423  return  window.requestAnimationFrame       ||
424    window.webkitRequestAnimationFrame ||
425    function(callback, element, delay){
426    window.setTimeout(callback, delay || (1000/60));
427  };
428})();
429
430/***********************************************
431 * PULSE
432 ***********************************************/
433
434/**
435 * Viscous fluid with a pulse for part and decay for the rest.
436 * - Applies a fixed force over an interval (a damped acceleration), and
437 * - Lets the exponential bleed away the velocity over a longer interval
438 * - Michael Herf, http://stereopsis.com/stopping/
439 */
440function pulse_(x) {
441  var val, start, expx;
442  // test
443  x = x * pulseScale;
444  if (x < 1) { // acceleartion
445    val = x - (1 - Math.exp(-x));
446  } else {     // tail
447    // the previous animation ended here:
448    start = Math.exp(-1);
449    // simple viscous drag
450    x -= 1;
451    expx = 1 - Math.exp(-x);
452    val = start + (expx * (1 - start));
453  }
454  return val * pulseNormalize;
455}
456
457function pulse(x) {
458  if (x >= 1) return 1;
459  if (x <= 0) return 0;
460
461  if (pulseNormalize == 1) {
462    pulseNormalize /= pulse_(1);
463  }
464  return pulse_(x);
465}
466
467addEvent("mousedown", mousedown);
468addEvent("mousewheel", wheel);
469addEvent("load", init);

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.