Adding simple delay to JavaScript code without using external libraries - javascript

A quick question, tell me please how to add delay to this code.
I guess it is super simple, but I am new to JavaScript.
I think the answer is somewhere in the beginning within the duration variable.
Here is JavaScript code:
var modern = requestAnimationFrame, duration = 400, initial, aim;
window.smoothScroll = function(target) {
var header = document.querySelectorAll('.aconmineli');
aim = -header[0].clientHeight;
initial = Date.now();
var scrollContainer = document.getElementById(target);
target = document.getElementById(target);
do {
scrollContainer = scrollContainer.parentNode;
if (!scrollContainer) return;
scrollContainer.scrollTop += 1;
}
while (scrollContainer.scrollTop == 0);
do {
if (target == scrollContainer) break;
aim += target.offsetTop;
}
while (target = target.offsetParent);
scroll = function(c, a, b, i) {
if (modern) {
var present = Date.now(),
elapsed = present-initial,
progress = Math.min(elapsed/duration, 1);
c.scrollTop = a + (b - a) * progress;
if (progress < 1) requestAnimationFrame(function() {
scroll(c, a, b, i);
});
}
else {
i++; if (i > 30) return;
c.scrollTop = a + (b - a) / 30 * i;
setTimeout(function() {scroll(c, a, b, i)}, 20);
}
}
scroll(scrollContainer, scrollContainer.scrollTop, aim, 0);
}
By the way it is a great pure JavaScript only code for scrolling on clicking.

var modern = requestAnimationFrame,
duration = 400,
initial,
aim,
delay = 1000;
window.smoothScroll = function(target) {
setTimeout(function() {
window.doSmoothScroll(target);
}, delay);
};
window.doSmoothScroll = function(target) {
var header = document.querySelectorAll('.navbar');
aim = -header[0].clientHeight;
initial = Date.now();
var scrollContainer = document.getElementById(target);
target = document.getElementById(target);
do {
scrollContainer = scrollContainer.parentNode;
if (!scrollContainer) return;
scrollContainer.scrollTop += 1;
}
while (scrollContainer.scrollTop === 0);
do {
if (target == scrollContainer) break;
aim += target.offsetTop;
}
while (target == target.offsetParent);
scroll = function(c, a, b, i) {
if (modern) {
var present = Date.now(),
elapsed = present - initial,
progress = Math.min(elapsed / duration, 1);
c.scrollTop = a + (b - a) * progress;
if (progress < 1) requestAnimationFrame(function() {
scroll(c, a, b, i);
});
} else {
i++;
if (i > 30) return;
c.scrollTop = a + (b - a) / 30 * i;
setTimeout(function() {
scroll(c, a, b, i);
}, 20);
}
};
scroll(scrollContainer, scrollContainer.scrollTop, aim, 0);
};

Related

Script tag unsuccessful

This works broken apart in js fiddle but when using a script tag the clock no longer works (no longer calls js). I have tried text/javascript , adding the javascript version in a script above and my latest attempt was adding language.
How do i determine how a line of javascript is suppose to be used in a script tag? Is there any way to figure out what phrase is suppose to be used in order for this to work.
It was originally made on code pen and it shows the javascript version is 1.7 there but i cannot get this to work if i use a script tag for the life of me.
<script language="JavaScript">/**[minimum JS only to set current time and sound the chimes]**/
(function () {
"use strict";
let seconds = document.getElementById("second_time"),
munutes = document.getElementById("minute_time"),
hours = document.getElementById("hour_time"),
s,
m,
h,
S,
M,
H,
time;
/*[set the clock to correct time and let CSS handle the rest]*/
function windup() {
(time = new Date()),
(s = time.getSeconds()),
(m = time.getMinutes()),
(h = time.getHours()),
(S = s * 6),
(M = m * 6 + s / 10),
(H = h * 30 + 0.5 * m);
seconds.style.transform = "rotate(" + S + "deg)";
munutes.style.transform = "rotate(" + M + "deg)";
hours.style.transform = "rotate(" + H + "deg)";
console.log("windup: " + h + ":" + m + ":" + s);
tick.volume = chime.volume = 1;
}
setTimeout(windup, 0);
/*[main visibility API function]*/
// use visibility API to check if current tab is active or not
let vis = (function () {
let stateKey,
eventKey,
keys = {
hidden: "visibilitychange",
webkitHidden: "webkitvisibilitychange",
mozHidden: "mozvisibilitychange",
msHidden: "msvisibilitychange"
};
for (stateKey in keys) {
if (stateKey in document) {
eventKey = keys[stateKey];
break;
}
}
return function (c) {
if (c) document.addEventListener(eventKey, c);
return !document[stateKey];
};
})();
/*[HTML5 Visibility API]****************************************/
// check if current tab is active or not
vis(function () {
if (vis()) {
setTimeout(function () {
// tween resume() code goes here
windup();
console.log("tab is visible - has focus");
}, 300);
} else {
// tween pause() code goes here
console.log("tab is invisible - has blur");
tick.volume = chime.volume = 0.1;
}
});
// check if browser window has focus
let notIE = document.documentMode === undefined,
isChromium = window.chrome;
if (notIE && !isChromium) {
// checks for Firefox and other NON IE Chrome versions
$(window)
.on("focusin", function () {
// tween resume() code goes here
setTimeout(function () {
windup();
console.log("focus");
}, 300);
})
.on("focusout", function () {
// tween pause() code goes here
console.log("blur");
tick.volume = chime.volume = 0.1;
});
} else {
// checks for IE and Chromium versions
if (window.addEventListener) {
// bind focus event
window.addEventListener(
"focus",
function (event) {
// tween resume() code goes here
setTimeout(function () {
windup();
console.log("focus");
}, 300);
},
false
);
// bind blur event
window.addEventListener(
"blur",
function (event) {
// tween pause() code goes here
console.log("blur");
tick.volume = chime.volume = 0.1;
},
false
);
} else {
// bind focus event
window.attachEvent("focus", function (event) {
// tween resume() code goes here
setTimeout(function () {
windup();
console.log("focus");
}, 300);
});
// bind focus event
window.attachEvent("blur", function (event) {
// tween pause() code goes here
console.log("blur");
tick.volume = chime.volume = 0.1;
});
}
}
/*[end HTML5 Visibility API]************************************/
/*[hourly and quarterly chimes]*/
const tick = document.getElementById("tick");
const chime = document.getElementById("chime");
const sound_dir = "http://www.gerasimenko.com/sandbox/codepen/sounds/";
let bell,
tock = "tock.wav";
tick.src = sound_dir + tock;
function hourly_chime(n) {
console.log("plays left: " + n);
if (n === 0) {
return;
} else {
chime.pause();
chime.currentTime = 0;
chime.play();
n--;
setTimeout(function () {
hourly_chime(n);
}, 3000);
}
}
setInterval(function () {
(time = new Date()),
(s = time.getSeconds()),
(m = time.getMinutes()),
(h = time.getHours());
console.log("watch: " + h + ":" + m + ":" + s);
tick.play();
if (s === 0 && (m === 15 || m === 30 || m === 45)) {
bell = "ding-tone.wav";
chime.src = sound_dir + bell;
hourly_chime(m / 15);
} else if (s === 0 && m === 0) {
bell = "bell-japanese.wav";
chime.src = sound_dir + bell;
h > 12 ? (h = h - 12) : h;
hourly_chime(h);
}
}, 1000);
})();
</script>

Variable is returning null in console

When I click on an anchor I pass the attribute ' data-target ' to my target var. In the scroll function I pass the target in the parameters and everything works well. My problem is that the console logs an error showing the target returning a null in this line:
var targetPosition = target.offsetTop;
Can anyone explain why this is happening?
var anchors = document.querySelectorAll('a[href^="#"]');
var headerHeight = document.querySelector('header').offsetHeight;
for (var i = 0; i < anchors.length; i++) {
anchors[i].addEventListener('click', function(event) {
event.preventDefault();
var anchor_location = this.getAttribute('data-target');
// Find the element with ID that matches data-target value.
var target = document.querySelector(anchor_location);
scroll(target, headerHeight);
})
}
function scroll(target, headerHeight) {
var start = null;
var duration = 1100; //d
var targetPosition = target.offsetTop;
var startPosition = window.pageYOffset; //b
var distance = targetPosition - startPosition - headerHeight; //c
console.log(distance);
window.requestAnimationFrame(step);
function step(timestamp) {
if (!start) start = timestamp;
var progress = timestamp - start; //t
// window.scrollTo(0, distance*(progress/duration) + startPosition);
window.scrollTo(0, quintic(progress, startPosition, distance, duration));
if (progress < duration) {
window.requestAnimationFrame(step);
}
}
}
// http://www.gizma.com/easing/ [easing equations]
function quintic (t, b, c, d) {
t /= d/2;
if (t < 1) return c/2*t*t*t*t*t + b;
t -= 2;
return c/2*(t*t*t*t*t + 2) + b;
};

How to Change 2 Math.floor random numbers if they are equal

I'm trying to replicate the Monty Hall Problem, if you've heard of it, and I need to add in a system that will change one of two Math.floor random numbers when they are equal. My question is how do I change a variable that is random into another if it is equal to a second random variable. If you look into the Monty Hall Problem, the wrong variable would be an incorrect choice and door is correct, I set both to be random, but obviously, they cannot both be equal. This is what I have so far.
setInterval(gr, 1000)
function gr() {
if (wrong === door) {
door = Math.floor((Math.random() * 3) + 1);
}
}
var door1 = 0;
var door2 = 0;
var door3 = 0;
var door;
var wrong;
var attempt = 0;
var d1 = document.getElementById('door1');
var d2 = document.getElementById('door2');
var d3 = document.getElementById('door3');
setInterval(gr, 1000)
function gr() {
if (wrong === door) {
door = Math.floor((Math.random() * 3) + 1);
}
}
function dr1() {
document.getElementById('door1').style.pointerEvents = 'none';
document.getElementById('door2').style.pointerEvents = 'none';
document.getElementById('door3').style.pointerEvents = 'none';
document.getElementById('door1').style.backgroundColor = "green";
door1 = 1;
if (door2 === 1) {
document.getElementById('door2').style.backgroundColor = "black";
door2 = 0;
} else if (door3 === 1) {
document.getElementById('door3').style.backgroundColor = "black";
door3 = 0;
}
if (attempt === 0) {
wrong = Math.floor((Math.random() * 2) + 1);
door = Math.floor((Math.random() * 3) + 1);
if (wrong === 1) {
document.getElementById('door2').style.backgroundColor = "white";
change1a();
} else if (wrong === 2) {
document.getElementById('door3').style.backgroundColor = "white";
change1b();
}
}
attempt = 1;
}
function dr2() {
document.getElementById('door1').style.pointerEvents = 'none';
document.getElementById('door3').style.pointerEvents = 'none';
document.getElementById('door2').style.backgroundColor = "green";
door2 = 1;
if (door1 === 1) {
document.getElementById('door1').style.backgroundColor = "black";
door1 = 0;
} else if (door3 === 1) {
document.getElementById('door3').style.backgroundColor = "black";
door3 = 0;
}
if (attempt === 0) {
wrong = Math.floor((Math.random() * 2) + 1);
door = Math.floor((Math.random() * 3) + 1);
if (wrong === 1) {
document.getElementById('door1').style.backgroundColor = "white";
change2a();
} else if (wrong === 2) {
document.getElementById('door3').style.backgroundColor = "white";
change2b();
}
}
attempt = 1;
}
function dr3() {
document.getElementById('door1').style.pointerEvents = 'none';
document.getElementById('door2').style.pointerEvents = 'none';
document.getElementById('door3').style.backgroundColor = "green";
door3 = 1;
if (door1 === 1) {
document.getElementById('door1').style.backgroundColor = "black";
door1 = 0;
} else if (door2 === 1) {
document.getElementById('door2').style.backgroundColor = "black";
door2 = 0;
}
if (attempt === 0) {
wrong = Math.floor((Math.random() * 2) + 1);
door = Math.floor((Math.random() * 3) + 1);
if (wrong === 1) {
document.getElementById('door1').style.backgroundColor = "white";
change3a();
} else if (wrong === 2) {
document.getElementById('door2').style.backgroundColor = "white";
change3b();
}
}
attempt = 1;
}
function change1a() {
document.getElementById('door3').style.pointerEvents = "all";
}
function change1b() {
document.getElementById('door2').style.pointerEvents = "all";
}
function change2a() {
document.getElementById('door3').style.pointerEvents = "all";
}
function change2b() {
document.getElementById('door1').style.pointerEvents = "all";
}
}
I tried adapting your code, but it looked too messy for me to understand everything you wanted to do. So, instead, I decided to create my own, just for fun. You can get some inspiration in there.
To answer your specific question, this is the way I choose the door:
var selectedDoor = 1,
correctDoor = 2,
losingDoor = getLosingDoor();
function getLosingDoor() {
var losingDoor;
do {
losingDoor = Math.floor((Math.random() * 3) + 1);
} while ([correctDoor, selectedDoor].indexOf(losingDoor) > -1);
return losingDoor;
}
Full demo
// Create a MontyHall instance in the #app div
var myMontyHall = MontyHall(document.getElementById('app'));
function MontyHall(container) {
var self = {
// Will hold DOM references
refs: null,
// Will hold the MontyHall instance's state
state: null,
/*
* Creates the doors in the DOM and in the state
*/
init: function() {
self.state = {
attempts: 0,
doorCount: 3,
correctDoor: self.getRandomInt(0, 3)
};
self.refs = {
container: container,
instructions: document.createElement('p'),
doorsWrapper: document.createElement('div'),
doors: []
};
// Reset container
self.refs.container.innerHTML = '';
// Setup a container for the doors
self.refs.doorsWrapper.className = 'doors-wrapper';
self.refs.container.appendChild(self.refs.doorsWrapper);
// Setup a container for instructions
self.say('Please select a door.');
self.refs.container.appendChild(self.refs.instructions);
// For each door
for (var i=0; i<self.state.doorCount; i++) {
// Create a div
var el = document.createElement('div');
// Give it a class
el.className = 'door';
// Add click event listener
(function(index) {
el.addEventListener('click', function(){
self.clickOnDoor(index);
});
})(i);
// Append it to the doors container
self.refs.doorsWrapper.append(el);
// Store a reference to it
self.refs.doors.push(el);
}
return self;
},
/*
* Called when a door is clicked
*/
clickOnDoor: function(index) {
self.state.selectedDoor = index;
// If this is the first attempt
if (self.state.attempts === 0) {
// Show it is selected
self.refs.doors[self.state.selectedDoor].classList.add('selected');
// Find a non selected losing door
self.state.losingDoor = self.getLosingDoor();
// Open it
self.refs.doors[self.state.losingDoor].classList.add('disabled', 'loser');
// Update instructions
self.say(
'You selected door #' + (index + 1) + '.<br>'
+ 'I opened door #' + (self.state.losingDoor + 1) + ', '
+ 'it contains a sheep.<br>'
+ 'You can now keep your choice, or change your mind.'
);
self.state.attempts++;
} else {
// For each door
self.refs.doors.forEach(function(el, i) {
// Disable it
el.classList.add('disabled');
// Show it as a winner or a loser
el.classList.add(i === self.state.correctDoor ? 'winner' : 'loser');
// Show it as selected or not
el.classList.toggle('selected', i === index);
});
// Update instructions
self.say(
(
self.state.correctDoor === index ?
'<span class="green">Congratulations, you won!</span>' :
'<span class="red">Sorry, you lost...</span>'
)
+ '<br>'
+ 'The gold was behind door #' + (self.state.correctDoor + 1) + '.<br>'
+ '<button class="restart">Play again</button>'
);
// Enable restart button
self.refs.instructions.querySelector('.restart')
.addEventListener('click', self.init);
}
},
/*
* Returns the index of a losing door, which is not selected
*/
getLosingDoor: function() {
var losingDoor;
do {
losingDoor = self.getRandomInt(0, self.state.doorCount);
} while ([
self.state.correctDoor,
self.state.selectedDoor
].indexOf(losingDoor) > -1);
return losingDoor;
},
/*
* Sets the instructions innerHTML
*/
say: function(html) {
self.refs.instructions.innerHTML = html;
},
/*
* Returns an integer between min and max
*/
getRandomInt: function(min, max) {
return Math.floor((Math.random() * (max-min)) + min);
}
};
return self.init();
}
/* I minified the CSS to avoid cluttering my answer. Full version in link below */body{font-family:Arial,Helvetica,sans-serif;text-align:center}p{margin-top:.2em}button{margin-top:.5em}.door{display:inline-block;width:3em;height:5em;border:1px solid #000;margin:.5em;background-image:url(https://image.ibb.co/c7mssS/doors.jpg);background-size:300% 100%;background-position:center;cursor:pointer;box-shadow:0 0 5px 1px #1070ff;transition:all .3s ease}.door:not(.disabled):hover{opacity:.9}.door.selected{box-shadow:0 0 5px 3px #b910ff}.door.loser{background-position:right}.door.winner{background-position:left}.door.disabled{pointer-events:none}.door.disabled:not(.selected){box-shadow:none}span{font-weight:700}.green{color:#42e25d}.red{color:#ff2f00}
<div id="app"></div>
JSFiddle demo

is it possible keydown event will affect setInterval?

I made a simple snake game by javascript, I try to add a feature that when the
var trail = [];
var tail = 5;
var normal_speed = 1000 / 10
var speed = 1000 / 10;
var game_status = 0;
var my_game;
button.addEventListener("click", function () {
clearInterval(my_game);
my_game = setInterval(game, speed);
});
window.onload = function () {
canv = document.getElementById("gc");
context = canv.getContext("2d");
document.addEventListener("keydown", keyPush);
document.addEventListener("keyup", keyRelease);
}
function game() {
for (var i = 0; i < trail.length; i++) {
context.fillRect(trail[i].x * grid_size, trail[i].y * grid_size, grid_size - 2, grid_size - 2);
if (trail[i].x == player_x && trail[i].y == player_y) {
if (game_status == 0) {
tail = 5;
} else {
endGame();
return;
}
}
}
trail.push({
x: player_x,
y: player_y
});
while (trail.length > tail) {
trail.shift();
}
}
function keyPush(keyEvent) {
switch (keyEvent.keyCode) {
case 16:
clearInterval(my_game);
speed = normal_speed * 0.5;
my_game = setInterval(game, speed);
break;
}
}
function keyRelease(keyEvent) {
switch (keyEvent.keyCode) {
case 16:
clearInterval(my_game);
speed = normal_speed;
my_game = setInterval(game, speed);
break;
}
}
user holds the shift key, the snake will speed up. But right now when I hold shift for a short time it works fine, but if I hold it for a long time the game will pause (snake stop moving). Here is my code, please help me fix it.
Your question is not clear, hence I had some fun, enjoy :-D
onload = function () {
var ZOOM = 10;
var FPS = 24;
var LENGTH = 5;
var started = false;
var orientation = {
N: 1, S: 2, E: 3, W: 4
};
var frame = {
width: 20,
height: 15,
el: document.getElementById("frame")
};
var snake = function () {
var body = new Array(LENGTH);
for (let i = 0; i < LENGTH; i++) {
body[i] = { x: i + 1, y: 1 };
}
return {
orientation: orientation.E,
updated: null,
dead: false,
speed: 5, // steps/s
tail: 0,
head: LENGTH - 1,
body: body
};
}();
window.start = start;
frame.el.style.width = frame.width * ZOOM + "px";
frame.el.style.height = frame.height * ZOOM + "px";
refreshSnake();
function start () {
if (!started) {
started = true;
document.addEventListener("click", rotateSnake);
snake.updated = new Date().getTime();
setInterval(loop, 1000 / FPS);
}
}
function loop () {
var now = new Date().getTime();
var t = now - snake.updated;
var d = snake.speed * t / 1000;
if (d >= 1) {
updateSnake(Math.round(d));
snake.updated = now;
refreshSnake();
}
}
function rotateSnake () {
switch (snake.orientation) {
case orientation.N:
snake.orientation = orientation.E; break;
case orientation.E:
snake.orientation = orientation.S; break;
case orientation.S:
snake.orientation = orientation.W; break;
case orientation.W:
snake.orientation = orientation.N; break;
}
}
function updateSnake (steps) {
var tail, head;
var dead = snake.dead;
var length = snake.body.length;
for (let i = 0; !dead && i < steps; i++) {
tail = snake.body[snake.tail];
head = snake.body[snake.head];
snake.tail = (snake.tail + 1) % length;
snake.head = (snake.head + 1) % length;
tail.x = head.x;
tail.y = head.y;
head = tail;
switch (snake.orientation) {
case orientation.N: head.y -= 1; break;
case orientation.S: head.y += 1; break;
case orientation.E: head.x += 1; break;
case orientation.W: head.x -= 1; break;
}
if (snake.dead = (
head.y + 1 > frame.height
|| head.x + 1 > frame.width
|| head.y < 0
|| head.x < 0
)) break;
}
}
function refreshSnake (now) {
var bg = snake.dead ? "red" : "white";
frame.el.innerHTML = snake.body.map(function (bit) {
return "<div style=\""
+ "width:" + ZOOM + "px;"
+ "height:" + ZOOM + "px;"
+ "top:" + (bit.y * ZOOM) + "px;"
+ "left:" + (bit.x * ZOOM) + "px;"
+ "position:absolute;"
+ "background:" + bg + ";"
+ "\"></div>";
}).join("");
}
};
<p>Tap or click in the snippet viewer to turn right ! <button onclick="start(); event.stopPropagation();">Start</button></p>
<div id="frame" style="background:black;position:relative;"></div>
I'd suggest that there is some handling of 'Shift' somewhere else
try event.preventDefault()
http://api.jquery.com/event.preventDefault/

JQuery and JS NoConflict() Not Working

I have a website that uses smooth scroll which works great.. But once I added the following code:
var $ = jQuery.noConflict();
$(document).ready(function() {
$(function() {
var $ticker = $('#news-ticker'),
$first = $('.news-ticket-class li:first-child', $ticker);
// put an empty space between each letter so we can
// use break word
$('.news-ticket-class li', $ticker).each(function() {
var $this = $(this),
text = $this.text();
$this.html(text.split('').join('​'));
});
// begin the animation
function tick($el) {
$el.addClass('tick')
.one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function() {
$el.removeClass('tick');
var $next = $el.next('li');
$next = $next.length > 0 ? $next : $first;
tick($next);
});
}
tick($first);
});
});
It breaks the smooth scroll. I have tried using the noconflict and that doesn't help as you can see.
The template I use is here that has the smooth scrolling option.
I am stuck with either the above code or my menus working. If you have any other suggestions that mimic someone typing, like this website, please send over my way.
EDIT: This is the smooth scroll script:
//
// SmoothScroll for websites v1.4.0 (Balazs Galambosi)
// http://www.smoothscroll.net/
//
// Licensed under the terms of the MIT license.
//
// You may use it in your theme if you credit me.
// It is also free to use on any individual website.
//
// Exception:
// The only restriction is to not publish any
// extension for browsers or native application
// without getting a written permission first.
//
(function () {
// Scroll Variables (tweakable)
var defaultOptions = {
// Scrolling Core
frameRate : 150, // [Hz]
animationTime : 500, // [ms]
stepSize : 100, // [px]
// Pulse (less tweakable)
// ratio of "tail" to "acceleration"
pulseAlgorithm : true,
pulseScale : 4,
pulseNormalize : 1,
// Acceleration
accelerationDelta : 50, // 50
accelerationMax : 3, // 3
// Keyboard Settings
keyboardSupport : true, // option
arrowScroll : 50, // [px]
// Other
touchpadSupport : false, // ignore touchpad by default
fixedBackground : true,
excluded : ''
};
var options = defaultOptions;
// Other Variables
var isExcluded = false;
var isFrame = false;
var direction = { x: 0, y: 0 };
var initDone = false;
var root = document.documentElement;
var activeElement;
var observer;
var refreshSize;
var deltaBuffer = [];
var isMac = /^Mac/.test(navigator.platform);
var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32,
pageup: 33, pagedown: 34, end: 35, home: 36 };
/***********************************************
* INITIALIZE
***********************************************/
/**
* Tests if smooth scrolling is allowed. Shuts down everything if not.
*/
function initTest() {
if (options.keyboardSupport) {
addEvent('keydown', keydown);
}
}
/**
* Sets up scrolls array, determines if frames are involved.
*/
function init() {
if (initDone || !document.body) return;
initDone = true;
var body = document.body;
var html = document.documentElement;
var windowHeight = window.innerHeight;
var scrollHeight = body.scrollHeight;
// check compat mode for root element
root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
activeElement = body;
initTest();
// Checks if this script is running in a frame
if (top != self) {
isFrame = true;
}
/**
* Please duplicate this radar for a Safari fix!
* rdar://22376037
* https://openradar.appspot.com/radar?id=4965070979203072
*
* Only applies to Safari now, Chrome fixed it in v45:
* This fixes a bug where the areas left and right to
* the content does not trigger the onmousewheel event
* on some pages. e.g.: html, body { height: 100% }
*/
else if (scrollHeight > windowHeight &&
(body.offsetHeight <= windowHeight ||
html.offsetHeight <= windowHeight)) {
var fullPageElem = document.createElement('div');
fullPageElem.style.cssText = 'position:absolute; z-index:-10000; ' +
'top:0; left:0; right:0; height:' +
root.scrollHeight + 'px';
document.body.appendChild(fullPageElem);
// DOM changed (throttled) to fix height
var pendingRefresh;
refreshSize = function () {
if (pendingRefresh) return; // could also be: clearTimeout(pendingRefresh);
pendingRefresh = setTimeout(function () {
if (isExcluded) return; // could be running after cleanup
fullPageElem.style.height = '0';
fullPageElem.style.height = root.scrollHeight + 'px';
pendingRefresh = null;
}, 500); // act rarely to stay fast
};
setTimeout(refreshSize, 10);
addEvent('resize', refreshSize);
// TODO: attributeFilter?
var config = {
attributes: true,
childList: true,
characterData: false
// subtree: true
};
observer = new MutationObserver(refreshSize);
observer.observe(body, config);
if (root.offsetHeight <= windowHeight) {
var clearfix = document.createElement('div');
clearfix.style.clear = 'both';
body.appendChild(clearfix);
}
}
// disable fixed background
if (!options.fixedBackground && !isExcluded) {
body.style.backgroundAttachment = 'scroll';
html.style.backgroundAttachment = 'scroll';
}
}
/**
* Removes event listeners and other traces left on the page.
*/
function cleanup() {
observer && observer.disconnect();
removeEvent(wheelEvent, wheel);
removeEvent('mousedown', mousedown);
removeEvent('keydown', keydown);
removeEvent('resize', refreshSize);
removeEvent('load', init);
}
/************************************************
* SCROLLING
************************************************/
var que = [];
var pending = false;
var lastScroll = Date.now();
/**
* Pushes scroll actions to the scrolling queue.
*/
function scrollArray(elem, left, top) {
directionCheck(left, top);
if (options.accelerationMax != 1) {
var now = Date.now();
var elapsed = now - lastScroll;
if (elapsed < options.accelerationDelta) {
var factor = (1 + (50 / elapsed)) / 2;
if (factor > 1) {
factor = Math.min(factor, options.accelerationMax);
left *= factor;
top *= factor;
}
}
lastScroll = Date.now();
}
// push a scroll command
que.push({
x: left,
y: top,
lastX: (left < 0) ? 0.99 : -0.99,
lastY: (top < 0) ? 0.99 : -0.99,
start: Date.now()
});
// don't act if there's a pending queue
if (pending) {
return;
}
var scrollWindow = (elem === document.body);
var step = function (time) {
var now = Date.now();
var scrollX = 0;
var scrollY = 0;
for (var i = 0; i < que.length; i++) {
var item = que[i];
var elapsed = now - item.start;
var finished = (elapsed >= options.animationTime);
// scroll position: [0, 1]
var position = (finished) ? 1 : elapsed / options.animationTime;
// easing [optional]
if (options.pulseAlgorithm) {
position = pulse(position);
}
// only need the difference
var x = (item.x * position - item.lastX) >> 0;
var y = (item.y * position - item.lastY) >> 0;
// add this to the total scrolling
scrollX += x;
scrollY += y;
// update last values
item.lastX += x;
item.lastY += y;
// delete and step back if it's over
if (finished) {
que.splice(i, 1); i--;
}
}
// scroll left and top
if (scrollWindow) {
window.scrollBy(scrollX, scrollY);
}
else {
if (scrollX) elem.scrollLeft += scrollX;
if (scrollY) elem.scrollTop += scrollY;
}
// clean up if there's nothing left to do
if (!left && !top) {
que = [];
}
if (que.length) {
requestFrame(step, elem, (1000 / options.frameRate + 1));
} else {
pending = false;
}
};
// start a new queue of actions
requestFrame(step, elem, 0);
pending = true;
}
/***********************************************
* EVENTS
***********************************************/
/**
* Mouse wheel handler.
* #param {Object} event
*/
function wheel(event) {
if (!initDone) {
init();
}
var target = event.target;
var overflowing = overflowingAncestor(target);
// use default if there's no overflowing
// element or default action is prevented
// or it's a zooming event with CTRL
if (!overflowing || event.defaultPrevented || event.ctrlKey) {
return true;
}
// leave embedded content alone (flash & pdf)
if (isNodeName(activeElement, 'embed') ||
(isNodeName(target, 'embed') && /\.pdf/i.test(target.src)) ||
isNodeName(activeElement, 'object')) {
return true;
}
var deltaX = -event.wheelDeltaX || event.deltaX || 0;
var deltaY = -event.wheelDeltaY || event.deltaY || 0;
if (isMac) {
if (event.wheelDeltaX && isDivisible(event.wheelDeltaX, 120)) {
deltaX = -120 * (event.wheelDeltaX / Math.abs(event.wheelDeltaX));
}
if (event.wheelDeltaY && isDivisible(event.wheelDeltaY, 120)) {
deltaY = -120 * (event.wheelDeltaY / Math.abs(event.wheelDeltaY));
}
}
// use wheelDelta if deltaX/Y is not available
if (!deltaX && !deltaY) {
deltaY = -event.wheelDelta || 0;
}
// line based scrolling (Firefox mostly)
if (event.deltaMode === 1) {
deltaX *= 40;
deltaY *= 40;
}
// check if it's a touchpad scroll that should be ignored
if (!options.touchpadSupport && isTouchpad(deltaY)) {
return true;
}
// scale by step size
// delta is 120 most of the time
// synaptics seems to send 1 sometimes
if (Math.abs(deltaX) > 1.2) {
deltaX *= options.stepSize / 120;
}
if (Math.abs(deltaY) > 1.2) {
deltaY *= options.stepSize / 120;
}
scrollArray(overflowing, deltaX, deltaY);
event.preventDefault();
scheduleClearCache();
}
/**
* Keydown event handler.
* #param {Object} event
*/
function keydown(event) {
var target = event.target;
var modifier = event.ctrlKey || event.altKey || event.metaKey ||
(event.shiftKey && event.keyCode !== key.spacebar);
// our own tracked active element could've been removed from the DOM
if (!document.body.contains(activeElement)) {
activeElement = document.activeElement;
}
// do nothing if user is editing text
// or using a modifier key (except shift)
// or in a dropdown
// or inside interactive elements
var inputNodeNames = /^(textarea|select|embed|object)$/i;
var buttonTypes = /^(button|submit|radio|checkbox|file|color|image)$/i;
if ( inputNodeNames.test(target.nodeName) ||
isNodeName(target, 'input') && !buttonTypes.test(target.type) ||
isNodeName(activeElement, 'video') ||
isInsideYoutubeVideo(event) ||
target.isContentEditable ||
event.defaultPrevented ||
modifier ) {
return true;
}
// spacebar should trigger button press
if ((isNodeName(target, 'button') ||
isNodeName(target, 'input') && buttonTypes.test(target.type)) &&
event.keyCode === key.spacebar) {
return true;
}
var shift, x = 0, y = 0;
var elem = overflowingAncestor(activeElement);
var clientHeight = elem.clientHeight;
if (elem == document.body) {
clientHeight = window.innerHeight;
}
switch (event.keyCode) {
case key.up:
y = -options.arrowScroll;
break;
case key.down:
y = options.arrowScroll;
break;
case key.spacebar: // (+ shift)
shift = event.shiftKey ? 1 : -1;
y = -shift * clientHeight * 0.9;
break;
case key.pageup:
y = -clientHeight * 0.9;
break;
case key.pagedown:
y = clientHeight * 0.9;
break;
case key.home:
y = -elem.scrollTop;
break;
case key.end:
var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
y = (damt > 0) ? damt+10 : 0;
break;
case key.left:
x = -options.arrowScroll;
break;
case key.right:
x = options.arrowScroll;
break;
default:
return true; // a key we don't care about
}
scrollArray(elem, x, y);
event.preventDefault();
scheduleClearCache();
}
/**
* Mousedown event only for updating activeElement
*/
function mousedown(event) {
activeElement = event.target;
}
/***********************************************
* OVERFLOW
***********************************************/
var uniqueID = (function () {
var i = 0;
return function (el) {
return el.uniqueID || (el.uniqueID = i++);
};
})();
var cache = {}; // cleared out after a scrolling session
var clearCacheTimer;
//setInterval(function () { cache = {}; }, 10 * 1000);
function scheduleClearCache() {
clearTimeout(clearCacheTimer);
clearCacheTimer = setInterval(function () { cache = {}; }, 1*1000);
}
function setCache(elems, overflowing) {
for (var i = elems.length; i--;)
cache[uniqueID(elems[i])] = overflowing;
return overflowing;
}
// (body) (root)
// | hidden | visible | scroll | auto |
// hidden | no | no | YES | YES |
// visible | no | YES | YES | YES |
// scroll | no | YES | YES | YES |
// auto | no | YES | YES | YES |
function overflowingAncestor(el) {
var elems = [];
var body = document.body;
var rootScrollHeight = root.scrollHeight;
do {
var cached = cache[uniqueID(el)];
if (cached) {
return setCache(elems, cached);
}
elems.push(el);
if (rootScrollHeight === el.scrollHeight) {
var topOverflowsNotHidden = overflowNotHidden(root) && overflowNotHidden(body);
var isOverflowCSS = topOverflowsNotHidden || overflowAutoOrScroll(root);
if (isFrame && isContentOverflowing(root) ||
!isFrame && isOverflowCSS) {
return setCache(elems, getScrollRoot());
}
} else if (isContentOverflowing(el) && overflowAutoOrScroll(el)) {
return setCache(elems, el);
}
} while (el = el.parentElement);
}
function isContentOverflowing(el) {
return (el.clientHeight + 10 < el.scrollHeight);
}
// typically for <body> and <html>
function overflowNotHidden(el) {
var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
return (overflow !== 'hidden');
}
// for all other elements
function overflowAutoOrScroll(el) {
var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
return (overflow === 'scroll' || overflow === 'auto');
}
/***********************************************
* HELPERS
***********************************************/
function addEvent(type, fn) {
window.addEventListener(type, fn, false);
}
function removeEvent(type, fn) {
window.removeEventListener(type, fn, false);
}
function isNodeName(el, tag) {
return (el.nodeName||'').toLowerCase() === tag.toLowerCase();
}
function directionCheck(x, y) {
x = (x > 0) ? 1 : -1;
y = (y > 0) ? 1 : -1;
if (direction.x !== x || direction.y !== y) {
direction.x = x;
direction.y = y;
que = [];
lastScroll = 0;
}
}
var deltaBufferTimer;
if (window.localStorage && localStorage.SS_deltaBuffer) {
deltaBuffer = localStorage.SS_deltaBuffer.split(',');
}
function isTouchpad(deltaY) {
if (!deltaY) return;
if (!deltaBuffer.length) {
deltaBuffer = [deltaY, deltaY, deltaY];
}
deltaY = Math.abs(deltaY)
deltaBuffer.push(deltaY);
deltaBuffer.shift();
clearTimeout(deltaBufferTimer);
deltaBufferTimer = setTimeout(function () {
if (window.localStorage) {
localStorage.SS_deltaBuffer = deltaBuffer.join(',');
}
}, 1000);
return !allDeltasDivisableBy(120) && !allDeltasDivisableBy(100);
}
function isDivisible(n, divisor) {
return (Math.floor(n / divisor) == n / divisor);
}
function allDeltasDivisableBy(divisor) {
return (isDivisible(deltaBuffer[0], divisor) &&
isDivisible(deltaBuffer[1], divisor) &&
isDivisible(deltaBuffer[2], divisor));
}
function isInsideYoutubeVideo(event) {
var elem = event.target;
var isControl = false;
if (document.URL.indexOf ('www.youtube.com/watch') != -1) {
do {
isControl = (elem.classList &&
elem.classList.contains('html5-video-controls'));
if (isControl) break;
} while (elem = elem.parentNode);
}
return isControl;
}
var requestFrame = (function () {
return (window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback, element, delay) {
window.setTimeout(callback, delay || (1000/60));
});
})();
var MutationObserver = (window.MutationObserver ||
window.WebKitMutationObserver ||
window.MozMutationObserver);
var getScrollRoot = (function() {
var SCROLL_ROOT;
return function() {
if (!SCROLL_ROOT) {
var dummy = document.createElement('div');
dummy.style.cssText = 'height:10000px;width:1px;';
document.body.appendChild(dummy);
var bodyScrollTop = document.body.scrollTop;
var docElScrollTop = document.documentElement.scrollTop;
window.scrollBy(0, 3);
if (document.body.scrollTop != bodyScrollTop)
(SCROLL_ROOT = document.body);
else
(SCROLL_ROOT = document.documentElement);
window.scrollBy(0, -3);
document.body.removeChild(dummy);
}
return SCROLL_ROOT;
};
})();
/***********************************************
* PULSE (by Michael Herf)
***********************************************/
/**
* Viscous fluid with a pulse for part and decay for the rest.
* - Applies a fixed force over an interval (a damped acceleration), and
* - Lets the exponential bleed away the velocity over a longer interval
* - Michael Herf, http://stereopsis.com/stopping/
*/
function pulse_(x) {
var val, start, expx;
// test
x = x * options.pulseScale;
if (x < 1) { // acceleartion
val = x - (1 - Math.exp(-x));
} else { // tail
// the previous animation ended here:
start = Math.exp(-1);
// simple viscous drag
x -= 1;
expx = 1 - Math.exp(-x);
val = start + (expx * (1 - start));
}
return val * options.pulseNormalize;
}
function pulse(x) {
if (x >= 1) return 1;
if (x <= 0) return 0;
if (options.pulseNormalize == 1) {
options.pulseNormalize /= pulse_(1);
}
return pulse_(x);
}
/***********************************************
* FIRST RUN
***********************************************/
var userAgent = window.navigator.userAgent;
var isEdge = /Edge/.test(userAgent); // thank you MS
var isChrome = /chrome/i.test(userAgent) && !isEdge;
var isSafari = /safari/i.test(userAgent) && !isEdge;
var isMobile = /mobile/i.test(userAgent);
var isIEWin7 = /Windows NT 6.1/i.test(userAgent) && /rv:11/i.test(userAgent);
var isEnabledForBrowser = (isChrome || isSafari || isIEWin7) && !isMobile;
var wheelEvent;
if ('onwheel' in document.createElement('div'))
wheelEvent = 'wheel';
else if ('onmousewheel' in document.createElement('div'))
wheelEvent = 'mousewheel';
if (wheelEvent && isEnabledForBrowser) {
addEvent(wheelEvent, wheel);
addEvent('mousedown', mousedown);
addEvent('load', init);
}
/***********************************************
* PUBLIC INTERFACE
***********************************************/
function SmoothScroll(optionsToSet) {
for (var key in optionsToSet)
if (defaultOptions.hasOwnProperty(key))
options[key] = optionsToSet[key];
}
SmoothScroll.destroy = cleanup;
if (window.SmoothScrollOptions) // async API
SmoothScroll(window.SmoothScrollOptions)
if (typeof define === 'function' && define.amd)
define(function() {
return SmoothScroll;
});
else if ('object' == typeof exports)
module.exports = SmoothScroll;
else
window.SmoothScroll = SmoothScroll;
})();
I believe the purpose of noConflict is to relinquish control of the $ global variable for external libraries, so doing var $ = jQuery.noConflict(); just sets the global $ to what noConflict returns, which is the jQuery object. In other words, it doesn't buy you anything - it's simply setting $ to what $ would be, even without the noConflict() method.
Change the $ to $j like the following:
var $j = jQuery.noConflict();
$j(document).ready(function() {
$j(function() {
var $ticker = $j('#news-ticker'),
$first = $j('.news-ticket-class li:first-child', $ticker);
// put an empty space between each letter so we can
// use break word
$j('.news-ticket-class li', $ticker).each(function() {
var $this = $j(this),
text = $this.text();
$this.html(text.split('').join('​'));
});
// begin the animation
function tick($el) {
$el.addClass('tick')
.one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function() {
$el.removeClass('tick');
var $next = $el.next('li');
$next = $next.length > 0 ? $next : $first;
tick($next);
});
}
tick($first);
});
});

Categories

Resources