I have just developed a new parallax scrolling script. I have it working just the way I want however there is just 1 issue with it currently.
I want the script to start scrolling the background image at the y coord that is specified in the css stylesheet by default. Instead my script seems to be resetting the CSS y coord to 0 before scrolling the image. This is obviously undesired behavior.
// Parallax scripting starts here
$.prototype.jpayParallax = function(userOptions){
var _api = {};
_api.utils = {};
_api.utils.isElementInViewport = function(el){
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
);
}
_api.utils.debounceScrollWheel = (function(){
$(function(){
var $window = $(window); //Window object
var scrollTime = 0.3; //Scroll time
var scrollDistance = 50; //Distance. Use smaller value for shorter scroll and greater value for longer scroll
$window.on("mousewheel DOMMouseScroll", function(event){
event.preventDefault();
var delta = event.originalEvent.wheelDelta/120 || -event.originalEvent.detail/3;
var scrollTop = $window.scrollTop();
var finalScroll = scrollTop - parseInt(delta*scrollDistance);
TweenMax.to($window, scrollTime, {
scrollTo : { y: finalScroll, autoKill:true },
ease: Power1.easeOut, //For more easing functions see http://api.greensock.com/js/com/greensock/easing/package-detail.html
autoKill: true,
overwrite: 5
});
});
});
})();
_api.selector = 'data-jpay-parallax';
_api.methods = {};
_api.methods.checkForVisibleParallaxEls = function(){
$('['+_api.selector+']').each(function(){
var instanceObject = $(this);
var origBgPos = $(this).css('backgroundPosition').split(' ');
var options = $(this).data('jpay-parallax');
console.log(origBgPos)
if (_api.utils.isElementInViewport(instanceObject)){
_api.methods.doParallax(instanceObject, options);
}
});
}
_api.methods.doParallax = function(instanceToManip, userOptions){
var direction = userOptions.settings.direction;
var orientation = userOptions.settings.orientation;
var speed = userOptions.settings.speed;
var type = userOptions.settings.type;
var speedInt;
var getSpeed = (function(){
if (speed){
switch(speed){
case 'slow':
speedInt = 10;
break;
case 'fast':
speedInt = 5;
break;
case 'faster':
speedInt = 1;
break;
default:
throw new TypeError('Unknown speed parameter added to module instructions');
}
}
})();
var distToTopInt = function(){
if (typeof speedInt === 'number'){
return $(window).scrollTop()/speedInt;
}
else {
return $(window).scrollTop();
}
}
var origPos = instanceToManip.css('backgroundPosition').split(' ');
var origPosX = parseInt(origPos[0]);
var origPosY = parseInt(origPos[1]);
var newPosY = origPosY += distToTopInt();
var newPosX = origPosX += distToTopInt();
if (orientation === 'vertical' && direction !== 'reverse'){
instanceToManip.css('backgroundPositionY', newPosX+'px');
}
else if (orientation === 'vertical' && direction === 'reverse'){
instanceToManip.css('backgroundPositionY', -newPosX+'px');
}
else if (orientation == 'horizontal' && direction !== 'reverse'){
instanceToManip.css('backgroundPositionX', newPosX+'px');
}
else if (orientation == 'horizontal' && direction === 'reverse'){
instanceToManip.css('backgroundPositionX', -newPosY+'px');
}
}
$(window).on('scroll', _api.methods.checkForVisibleParallaxEls)
};
$.fn.jpayParallax();
Here is the pen:
http://codepen.io/nicholasabrams/pen/OPxKXm/?editors=001
BONUS: Why does this script also mess with the css set backgroundSize property when the script never accesses it?
I am looking for advice in where in the script to cache the original CSS background image y coord value so that it becomes incremented from there instead of starting at 0px /0 for each instance. Thanks again for the help!
Related
Let's say I have a white-space: nowrap; div with overflow: hidden;. Its content is, of course, much longer than the div is, and needs to be scrolled to get revealed.
I was using this library, but it does not work for mobile devices with touch input. Do you know any alternative or ways to implement this feature?
Finally, my wish is fullfilled. Here I modified dragscroll.js library to enable touch support.
/* Modified dragscroll.js by Undust4able */
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
factory((root.dragscroll = {}));
}
}(this, function (exports) {
var _window = window;
var _document = document;
var mousemove = 'mousemove';
var mouseup = 'mouseup';
var mousedown = 'mousedown';
var touchmove = 'touchmove';
var touchup = 'touchend';
var touchdown = 'touchstart';
var EventListener = 'EventListener';
var addEventListener = 'add'+EventListener;
var removeEventListener = 'remove'+EventListener;
var dragged = [];
var reset = function(i, el) {
for (i = 0; i < dragged.length;) {
el = dragged[i++];
el = el.container || el;
el[removeEventListener](mousedown, el.md, 0);
_window[removeEventListener](mouseup, el.mu, 0);
_window[removeEventListener](mousemove, el.mm, 0);
el[removeEventListener](touchdown, el.td, 0);
_window[removeEventListener](touchup, el.tu, 0);
_window[removeEventListener](touchmove, el.tm, 0);
}
// cloning into array since HTMLCollection is updated dynamically
dragged = [].slice.call(_document.getElementsByClassName('dragscroll'));
for (i = 0; i < dragged.length;) {
(function(el, lastClientX, lastClientY, pushed, scroller, cont){
(cont = el.container || el)[addEventListener](
mousedown,
cont.md = function(e) {
if (!el.hasAttribute('nochilddrag') ||
_document.elementFromPoint(
e.pageX, e.pageY
) == cont
) {
pushed = 1;
lastClientX = e.clientX;
lastClientY = e.clientY;
e.preventDefault();
}
}, 0
);
(cont = el.container || el)[addEventListener](
touchdown,
cont.td = function(e) {
if (!el.hasAttribute('nochilddrag') ||
_document.elementFromPoint(
e.pageX, e.pageY
) == cont
) {
pushed = 1;
e.preventDefault();
e = e.targetTouches[0];
lastClientX = e.clientX;
lastClientY = e.clientY;
}
}, 0
);
_window[addEventListener](
mouseup, cont.mu = function() {pushed = 0;}, 0
);
_window[addEventListener](
touchup, cont.tu = function() {pushed = 0;}, 0
);
_window[addEventListener](
mousemove,
cont.mm = function(e) {
if (pushed) {
(scroller = el.scroller||el).scrollLeft -=
(- lastClientX + (lastClientX=e.clientX));
scroller.scrollTop -=
(- lastClientY + (lastClientY=e.clientY));
}
}, 0
);
_window[addEventListener](
touchmove,
cont.tm = function(e) {
if (pushed) {
e = e.targetTouches[0];
(scroller = el.scroller||el).scrollLeft -=
(- lastClientX + (lastClientX=e.clientX));
scroller.scrollTop -=
(- lastClientY + (lastClientY=e.clientY));
}
}, 0
);
})(dragged[i++]);
}
}
if (_document.readyState == 'complete') {
reset();
} else {
_window[addEventListener]('load', reset, 0);
}
exports.reset = reset;
}));
Make a container div with overflow-y: hidden;overflow-x: scroll; and set it to whatever pre-determined height you want.
Then have your inner div that will house the content set to position:absolute; and set its width to whatever size you need the accommodate your content.
The content will scroll with the mouse and by touch.
Sounds kinda like you're going for a netflix style side scroller - check out this codepen I've done up that shows what I was just talking about.
http://codepen.io/hoonin_hooligan/pen/aZBxRG
I have implemented a javascript smooth scroll in a one page site and works perfectly. However, because I have a fixed nav at the top of the page, when the page scrolls to the anchor, the top of the page disappears behind the nav. How can I offset the scroll of 90px?
Here is the code:
var ss = {
fixAllLinks: function() {
// Get a list of all links in the page
var allLinks = document.getElementsByTagName('a');
// Walk through the list
for (var i=0;i<allLinks.length;i++) {
var lnk = allLinks[i];
if ((lnk.href && lnk.href.indexOf('#') != -1) &&
( (lnk.pathname == location.pathname) ||
('/'+lnk.pathname == location.pathname) ) &&
(lnk.search == location.search)) {
// If the link is internal to the page (begins in #)
// then attach the smoothScroll function as an onclick
// event handler
ss.addEvent(lnk,'click',ss.smoothScroll);
}
}
},
smoothScroll: function(e) {
// This is an event handler; get the clicked on element,
// in a cross-browser fashion
if (window.event) {
target = window.event.srcElement;
} else if (e) {
target = e.target;
} else return;
// Make sure that the target is an element, not a text node
// within an element
if (target.nodeName.toLowerCase() != 'a') {
target = target.parentNode;
}
// Paranoia; check this is an A tag
if (target.nodeName.toLowerCase() != 'a') return;
// Find the <a name> tag corresponding to this href
// First strip off the hash (first character)
anchor = target.hash.substr(1);
// Now loop all A tags until we find one with that name
var allLinks = document.getElementsByTagName('a');
var destinationLink = null;
for (var i=0;i<allLinks.length;i++) {
var lnk = allLinks[i];
if (lnk.name && (lnk.name == anchor)) {
destinationLink = lnk;
break;
}
}
if (!destinationLink) destinationLink = document.getElementById(anchor);
// If we didn't find a destination, give up and let the browser do
// its thing
if (!destinationLink) return true;
// Find the destination's position
var destx = destinationLink.offsetLeft;
var desty = destinationLink.offsetTop;
var thisNode = destinationLink;
while (thisNode.offsetParent &&
(thisNode.offsetParent != document.body)) {
thisNode = thisNode.offsetParent;
destx += thisNode.offsetLeft;
desty += thisNode.offsetTop;
}
// Stop any current scrolling
clearInterval(ss.INTERVAL);
cypos = ss.getCurrentYPos();
ss_stepsize = parseInt((desty-cypos)/ss.STEPS);
ss.INTERVAL =
setInterval('ss.scrollWindow('+ss_stepsize+','+desty+',"'+anchor+'")',20);
// And stop the actual click happening
if (window.event) {
window.event.cancelBubble = true;
window.event.returnValue = false;
}
if (e && e.preventDefault && e.stopPropagation) {
e.preventDefault();
e.stopPropagation();
}
},
scrollWindow: function(scramount,dest,anchor) {
wascypos = ss.getCurrentYPos();
isAbove = (wascypos < dest);
window.scrollTo(0,wascypos + scramount);
iscypos = ss.getCurrentYPos();
isAboveNow = (iscypos < dest);
if ((isAbove != isAboveNow) || (wascypos == iscypos)) {
// if we've just scrolled past the destination, or
// we haven't moved from the last scroll (i.e., we're at the
// bottom of the page) then scroll exactly to the link
window.scrollTo(0,dest);
// cancel the repeating timer
clearInterval(ss.INTERVAL);
// and jump to the link directly so the URL's right
location.hash = anchor;
}
},
getCurrentYPos: function() {
if (document.body && document.body.scrollTop)
return document.body.scrollTop;
if (document.documentElement && document.documentElement.scrollTop)
return document.documentElement.scrollTop;
if (window.pageYOffset)
return window.pageYOffset;
return 0;
},
addEvent: function(elm, evType, fn, useCapture) {
// addEvent and removeEvent
// cross-browser event handling for IE5+, NS6 and Mozilla
// By Scott Andrew
if (elm.addEventListener){
elm.addEventListener(evType, fn, useCapture);
return true;
} else if (elm.attachEvent){
var r = elm.attachEvent("on"+evType, fn);
return r;
} else {
alert("Handler could not be removed");
}
}
}
ss.STEPS = 25;
ss.addEvent(window,"load",ss.fixAllLinks);
Thanks in advance for your help!
You can do a calculation when setting the destination coordinates:
// Find the destination's position
var destx = destinationLink.offsetLeft;
var desty = destinationLink.offsetTop;
var thisNode = destinationLink;
while (thisNode.offsetParent &&
(thisNode.offsetParent != document.body)) {
thisNode = thisNode.offsetParent;
destx += thisNode.offsetLeft;
desty += thisNode.offsetTop;
}
//subtract nav from offset position
desty = desty - 90;
if(desty < 0){ desty = 0; }
That being said, using a static number is dangerous business. Might make more sense to calculate minus the header's actual height instead.
Simply make changes in the CSS:
html{
scroll-behavior: smooth;
scroll-padding-top: 50px;
}
This will handle your fixed header issue.
i want to make a message which will be always on the top however scrolling the page using java script.
i tried the below code, but when i scroll it still on its static place
var message = '<b><font color=000000 size=5>mona link to us! </font></b>'
//enter a color name or hex to be used as the background color of the message
var backgroundcolor = "#FFFF8A"
//enter 1 for always display, 2 for ONCE per browser session
var displaymode = 1
//Set duration message should appear on screen, in seconds (10000=10 sec, 0=perpetual)
var displayduration = 0
//enter 0 for non-flashing message, 1 for flashing
var flashmode = 1
//if above is set to flashing, enter the flash-to color below
var flashtocolor = "lightyellow"
var ie = document.all
var ieNOTopera = document.all && navigator.userAgent.indexOf("Opera") == -1
function regenerate() {
window.location.reload()
}
function regenerate2() {
if (document.layers)
setTimeout("window.onresize=regenerate", 400)
}
var which = 0
function flash() {
if (which == 0) {
if (document.layers)
topmsg_obj.bgColor = flashtocolor
else
topmsg_obj.style.backgroundColor = flashtocolor
which = 1
}
else {
if (document.layers)
topmsg_obj.bgColor = backgroundcolor
else
topmsg_obj.style.backgroundColor = backgroundcolor
which = 0
}
}
if (ie || document.getElementById)
document.write('<div id="topmsg" style="position:absolute;visibility:hidden">' + message + '</div>')
var topmsg_obj = ie ? document.all.topmsg : document.getElementById ? document.getElementById("topmsg") : document.topmsg
function positionit() {
var dsocleft = ie ? document.body.scrollLeft : pageXOffset
var dsoctop = ie ? document.body.scrollTop : pageYOffset
var window_width = ieNOTopera ? document.body.clientWidth : window.innerWidth - 20
var window_height = ieNOTopera ? document.body.clientHeight : window.innerHeight
if (ie || document.getElementById) {
topmsg_obj.style.left = parseInt(dsocleft) + window_width / 2 - topmsg_obj.offsetWidth / 2
topmsg_obj.style.top = parseInt(dsoctop) + parseInt(window_height) - topmsg_obj.offsetHeight - 4
}
else if (document.layers) {
topmsg_obj.left = dsocleft + window_width / 2 - topmsg_obj.document.width / 2
topmsg_obj.top = dsoctop + window_height - topmsg_obj.document.height - 5
}
}
function setmessage() {
if (displaymode == 2 && (!display_msg_or_not()))
return
if (document.layers) {
topmsg_obj = new Layer(window.innerWidth)
topmsg_obj.bgColor = backgroundcolor
regenerate2()
topmsg_obj.document.write(message)
topmsg_obj.document.close()
positionit()
topmsg_obj.visibility = "show"
if (displayduration != 0)
setTimeout("topmsg_obj.visibility='hide'", displayduration)
}
else {
positionit()
topmsg_obj.style.backgroundColor = backgroundcolor
topmsg_obj.style.visibility = "visible"
if (displayduration != 0)
setTimeout("topmsg_obj.style.visibility='hidden'", displayduration)
}
setInterval("positionit()", 100)
if (flashmode == 1)
setInterval("flash()", 1000)
}
function get_cookie(Name) {
var search = Name + "="
var returnvalue = ""
if (document.cookie.length > 0) {
offset = document.cookie.indexOf(search)
if (offset != -1) {
offset += search.length
end = document.cookie.indexOf(";", offset)
if (end == -1)
end = document.cookie.length;
returnvalue = unescape(document.cookie.substring(offset, end))
}
}
return returnvalue;
}
function display_msg_or_not() {
if (get_cookie("displaymsg") == "") {
document.cookie = "displaymsg=yes"
return true
}
else
return false
}
if (document.layers || ie || document.getElementById)
window.onload = setmessage
any help. or any new code please
If I'm understanding what you want, I think you're totally over thinking it. You can use CSS to keep your message fixed at the top of the page. just add position: fixed. It's how I make my header stay at the top of the page on this site: http://www.recipegraze.com
So use javascript to make the message appear/disappear, but use some simple CSS to make it stick to the top of the page.
edit: you'll also want to up the z-index of the message to make sure it appears on top of your other content, not under it.
I am trying to center a DIV in screen using below code but it is not working for me. Someone please suggest me to make it work
var hnw = {};
hnw.w = 0;
hnw.h = 0;
if (!window.innerWidth) {
if (!(document.documentElement.clientWidth == 0)) {
hnw.w = document.documentElement.clientWidth;
hnw.h = document.documentElement.clientHeight;
}
else {
hnw.w = document.body.clientWidth;
hnw.h = document.body.clientHeight;
}
}
else {
hnw.w = window.innerWidth;
hnw.h = window.innerHeight;
}
var midEle = document.createElement('div');
var _x = 0;
var _y = 0;
var offsetX = 0;
var offsetY = 0;
if (!window.pageYOffset) {
if (!(document.documentElement.scrollTop == 0)) {
offsetY = document.documentElement.scrollTop;
offsetX = document.documentElement.scrollLeft;
}
else {
offsetY = document.body.scrollTop;
offsetX = document.body.scrollLeft;
}
}
else {
offsetX = window.pageXOffset;
offsetY = window.pageYOffset;
}
midEle.style.width = "300px";
midEle.style.height = "300px";
midEle.innerHTML = "Some Text";
midEle.style.display = "block";
var _x_w = parseInt(midEle.style.width, 10), _y_h = parseInt(midEle.style.height, 10);
_x = ((hnw.w - _x_w) / 2) + offsetX;
_y = ((hnw.h - _y_h) / 2) + offsetY;
console.log(_x, " ", _y);
midEle.style.position = "absolute";
midEle.style.left = _x;
midEle.style.top = _y;
document.body.appendChild(midEle);
Can't this be done with CSS instead?
Javascript:
var midEle = document.createElement('div');
midEle.className = 'centered';
document.body.appendChild(midEle);
CSS:
.centered{
background-color: red;
height: 300px;
width: 300px;
margin: -150px 0 0 -150px;
top: 50%;
left: 50%;
position: fixed;
}
http://jsfiddle.net/FkEyy/3/
By setting the margins to the negative half of the elements height and width, and setting top and left values to 50%, you'll center the element. This is a common way of centering content with CSS :)
For left and top style properties px was missing. Values must be either px or %
Change
midEle.style.left = _x;
midEle.style.top = _y;
To
midEle.style.left = _x+"px";
midEle.style.top = _y+"px";
Demo: http://jsfiddle.net/muthkum/AFkKt/
Here is a demo if you want to center something in the browser viewport using vanilla JavaScript.
http://jsfiddle.net/CDtGR/5/
<html>
<!--measure size of elements,
get absolute position of elements,
get viewport size and scrollposition-->
<script>
var mesr =
{
Metrics: {
px: 1,
measureUnits: function(target) {
if(typeof(target) == 'undefined')
target = document.getElementsByTagName('body')[0];
mesr.Metrics.measureUnit("em", target);
mesr.Metrics.measureUnit("pt", target);
mesr.Metrics.measureUnit("%", target);
},
measureUnit: function(unit, target) {
if(typeof(target.Metrics) == 'undefined')
target.Metrics = {};
var measureTarget = target;
if(target.tagName == 'IMG' && typeof(target.parentNode) != 'undefined')
measureTarget = target.parentNode;
var measureElement = document.createElement("div");
measureElement.style.width = "1"+unit;
measureElement.style.cssFloat = "left";
measureElement.style.styleFloat = "left";
measureElement.style.margin = "0px";
measureElement.style.padding = "0px";
measureTarget.appendChild(measureElement);
target.Metrics[unit] = measureElement.offsetWidth;
measureElement.parentNode.removeChild(measureElement);
return target.Metrics[unit];
},
getUnitPixels: function(unitString, target) {
if(typeof(target) == 'undefined')
target = document.getElementsByTagName('body')[0];
if(typeof(target.Metrics) == 'undefined')
mesr.Metrics.measureUnits(target);
var unit = unitString.replace(/[0-9\s]+/ig,'').toLowerCase();
var size = Number(unitString.replace(/[^0-9]+/ig,''));
if(typeof(target.Metrics[unit]) == 'undefined')
return 0;
var metricSize = target.Metrics[unit];
var pixels = Math.floor(Number(metricSize * size));
return pixels;
}
},
getElementOffset: function(target) {
var pos = [target.offsetLeft,target.offsetTop];
if(target.offsetParent != null) {
var offsetPos = mesr.getElementOffset(target.offsetParent);
pos = [
pos[0] + offsetPos[0],
pos[1] + offsetPos[1]
];
}
return pos;
},
getElementPosition: function(target) {
var offset = mesr.getElementOffset(target);
var x = offset[0] +
mesr.Metrics.getUnitPixels(target.style.paddingLeft, target) +
mesr.Metrics.getUnitPixels(target.style.borderLeftWidth, target);
var y = offset[1] +
mesr.Metrics.getUnitPixels(target.style.paddingTop, target) +
mesr.Metrics.getUnitPixels(target.style.borderTopWidth, target);
return [x,y];
},
getElementSize: function(target) {
var size = [target.offsetWidth, target.offsetHeight];
size[0] -= mesr.Metrics.getUnitPixels(target.style.paddingLeft, target) +
mesr.Metrics.getUnitPixels(target.style.paddingRight, target) +
mesr.Metrics.getUnitPixels(target.style.borderLeftWidth, target) +
mesr.Metrics.getUnitPixels(target.style.borderRightWidth, target);
size[1] -= mesr.Metrics.getUnitPixels(target.style.paddingTop, target) +
mesr.Metrics.getUnitPixels(target.style.paddingBottom, target) +
mesr.Metrics.getUnitPixels(target.style.borderTopWidth, target) +
mesr.Metrics.getUnitPixels(target.style.borderBottomWidth, target);
return size;
},
getViewPortSize: function () {
var myWidth = 0, myHeight = 0;
if( typeof( window.innerWidth ) == 'number' ) {
myWidth = window.innerWidth;
myHeight = window.innerHeight;
} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
myWidth = document.documentElement.clientWidth;
myHeight = document.documentElement.clientHeight;
} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
myWidth = document.body.clientWidth;
myHeight = document.body.clientHeight;
}
return [myWidth, myHeight];
},
getViewPortScrollPosition: function () {
var scrOfX = 0, scrOfY = 0;
if( typeof( window.pageYOffset ) == 'number' ) {
scrOfY = window.pageYOffset;
scrOfX = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
scrOfY = document.body.scrollTop;
scrOfX = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
scrOfY = document.documentElement.scrollTop;
scrOfX = document.documentElement.scrollLeft;
}
return [ scrOfX, scrOfY ];
},
attachEvent : function(target, eventList, func) {
if(typeof (target) == "undefined" || target == null)
return;
var events = eventList.split(",");
for(var i=0;i<events.length;i++) {
var event = events[i];
if(typeof(target.addEventListener) != 'undefined') {
target.addEventListener(event, func);
} else if(typeof(target.attachEvent) != 'undefined') {
target.attachEvent('on'+event,func);
} else {
console.log("unable to attach event listener");
}
}
}
}
</script>
<!--positioning-->
<script>
function position(){
var viewPortSize = mesr.getViewPortSize();
var viewPortScrollPos = mesr.getViewPortScrollPosition();
var size = mesr.getElementSize(document.getElementById('apa'));
document.getElementById('apa').style.left = Math.floor((viewPortSize[0]/2)-(size[0]/2)+viewPortScrollPos[0])+"px";
document.getElementById('apa').style.top = Math.floor((viewPortSize[1]/2)-(size[1]/2)+viewPortScrollPos[1])+"px";
}
mesr.attachEvent(window,"resize,scroll,load",position);
mesr.attachEvent(document,"load",position);
</script>
<body>
<div id="apa" style="position:absolute;">some text</div>
</body>
</html>
This is the code i'm using right now. On webkit browsers (Chrome and Safari Specifically) if the page is scrolled, it doesn't take into account the amount that page has been scrolled. I need help redesigning the function to work for Webkit browsers. And I don't want to be loading up jQuery as this will be used on a web widget and I need to keep the file size down. Thanks guys!
function __getIEVersion() {
var rv = -1; // Return value assumes failure.
if (navigator.appName == 'Microsoft Internet Explorer') {
var ua = navigator.userAgent;
var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
if (re.exec(ua) != null)
rv = parseFloat(RegExp.$1);
}
return rv;
}
function __getOperaVersion() {
var rv = 0; // Default value
if (window.opera) {
var sver = window.opera.version();
rv = parseFloat(sver);
}
return rv;
}
var __userAgent = navigator.userAgent;
var __isIE = navigator.appVersion.match(/MSIE/) != null;
var __IEVersion = __getIEVersion();
var __isIENew = __isIE && __IEVersion >= 8;
var __isIEOld = __isIE && !__isIENew;
var __isFireFox = __userAgent.match(/firefox/i) != null;
var __isFireFoxOld = __isFireFox && ((__userAgent.match(/firefox\/2./i) != null) ||
(__userAgent.match(/firefox\/1./i) != null));
var __isFireFoxNew = __isFireFox && !__isFireFoxOld;
var __isWebKit = navigator.appVersion.match(/WebKit/) != null;
var __isChrome = navigator.appVersion.match(/Chrome/) != null;
var __isOpera = window.opera != null;
var __operaVersion = __getOperaVersion();
var __isOperaOld = __isOpera && (__operaVersion < 10);
function __parseBorderWidth(width) {
var res = 0;
if (typeof(width) == "string" && width != null && width != "" ) {
var p = width.indexOf("px");
if (p >= 0) {
res = parseInt(width.substring(0, p));
}
else {
//do not know how to calculate other values
//(such as 0.5em or 0.1cm) correctly now
//so just set the width to 1 pixel
res = 1;
}
}
return res;
}
//returns border width for some element
function __getBorderWidth(element) {
var res = new Object();
res.left = 0; res.top = 0; res.right = 0; res.bottom = 0;
if (window.getComputedStyle) {
//for Firefox
var elStyle = window.getComputedStyle(element, null);
res.left = parseInt(elStyle.borderLeftWidth.slice(0, -2));
res.top = parseInt(elStyle.borderTopWidth.slice(0, -2));
res.right = parseInt(elStyle.borderRightWidth.slice(0, -2));
res.bottom = parseInt(elStyle.borderBottomWidth.slice(0, -2));
}
else {
//for other browsers
res.left = __parseBorderWidth(element.style.borderLeftWidth);
res.top = __parseBorderWidth(element.style.borderTopWidth);
res.right = __parseBorderWidth(element.style.borderRightWidth);
res.bottom = __parseBorderWidth(element.style.borderBottomWidth);
}
return res;
}
//returns the absolute position of some element within document
function getElementAbsolutePos(element) {
var res = new Object();
res.x = 0; res.y = 0;
if (element !== null) {
if (element.getBoundingClientRect) {
var viewportElement = document.documentElement;
var box = element.getBoundingClientRect();
var scrollLeft = viewportElement.scrollLeft;
var scrollTop = viewportElement.scrollTop;
res.x = box.left + scrollLeft;
res.y = box.top + scrollTop;
}
else { //for old browsers
res.x = element.offsetLeft;
res.y = element.offsetTop;
var parentNode = element.parentNode;
var borderWidth = null;
while (offsetParent != null) {
res.x += offsetParent.offsetLeft;
res.y += offsetParent.offsetTop;
var parentTagName =
offsetParent.tagName.toLowerCase();
if ((__isIEOld && parentTagName != "table") ||
((__isFireFoxNew || __isChrome) &&
parentTagName == "td")) {
borderWidth = kGetBorderWidth
(offsetParent);
res.x += borderWidth.left;
res.y += borderWidth.top;
}
if (offsetParent != document.body &&
offsetParent != document.documentElement) {
res.x -= offsetParent.scrollLeft;
res.y -= offsetParent.scrollTop;
}
//next lines are necessary to fix the problem
//with offsetParent
if (!__isIE && !__isOperaOld || __isIENew) {
while (offsetParent != parentNode &&
parentNode !== null) {
res.x -= parentNode.scrollLeft;
res.y -= parentNode.scrollTop;
if (__isFireFoxOld || __isWebKit)
{
borderWidth =
kGetBorderWidth(parentNode);
res.x += borderWidth.left;
res.y += borderWidth.top;
}
parentNode = parentNode.parentNode;
}
}
parentNode = offsetParent.parentNode;
offsetParent = offsetParent.offsetParent;
}
}
}
var scrOfX = 0, scrOfY = 0;
if( typeof( window.pageYOffset ) == 'number' ) {
//Netscape compliant
scrOfY = window.pageYOffset;
scrOfX = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
//DOM compliant
scrOfY = document.body.scrollTop;
scrOfX = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
//IE6 standards compliant mode
scrOfY = document.documentElement.scrollTop;
scrOfX = document.documentElement.scrollLeft;
}
return res;
}
if (element.getBoundingClientRect) {
var viewportElement = document.documentElement;
var box = element.getBoundingClientRect();
var scrollLeft = viewportElement.scrollLeft;
var scrollTop = viewportElement.scrollTop;
res.x = box.left + scrollLeft;
res.y = box.top + scrollTop;
}
I'm concerned that this code block only uses one way of attempting to detect the scroll position. I would move the bottom block of code to the top of the function and use scrOfX/Y instead of scrollLeft and scrollTop.