Basically the code below works just as it should: it refreshes the page base on value of 'rate' and maintains page scroll position after page refresh.
What I am trying to do is add a select table to adjust the rate of refresh, or in other words the value of 'rate'. with my little experience in js I was able to add the select table and set the rate by the selected value, problem is that when the page refreshes the value in the select table defaults to first value in the table, in my case '5'. Second problem is that when i change the value in the table, page scrolls to the top each time a new value is selected.
var rate = 10; // refresh rate
function refresh() {
document.cookie = 'scrollTop=' + filterScrollTop();
document.cookie = 'scrollLeft=' + filterScrollLeft();
document.location.reload(true);
}
function getCookie(name) {
var start = document.cookie.indexOf(name + "=");
var len = start + name.length + 1;
if (((!start) && (name != document.cookie.substring(0, name.length))) || start == -1) return null;
var end = document.cookie.indexOf(";", len);
if (end == -1) end = document.cookie.length;
return unescape(document.cookie.substring(len, end));
}
function deleteCookie(name) {
document.cookie = name + "=" + ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
}
function setupRefresh() {
var scrollTop = getCookie("scrollTop");
var scrollLeft = getCookie("scrollLeft");
if (!isNaN(scrollTop)) {
document.body.scrollTop = scrollTop;
document.documentElement.scrollTop = scrollTop;
}
if (!isNaN(scrollLeft)) {
document.body.scrollLeft = scrollLeft;
document.documentElement.scrollLeft = scrollLeft;
}
deleteCookie("scrollTop");
deleteCookie("scrollLeft");
setTimeout("refresh()", rate * 1000);
}
function filterResults(win, docEl, body) {
var result = win ? win : 0;
if (docEl && (!result || (result > docEl))) result = docEl;
return body && (!result || (result > body)) ? body : result;
}
// Setting the cookie for vertical position
function filterScrollTop() {
var win = window.pageYOffset ? window.pageYOffset : 0;
var docEl = document.documentElement ? document.documentElement.scrollTop : 0;
var body = document.body ? document.body.scrollTop : 0;
return filterResults(win, docEl, body);
}
// Setting the cookie for horizontal position
function filterScrollLeft() {
var win = window.pageXOffset ? window.pageXOffset : 0;
var docEl = document.documentElement ? document.documentElement.scrollLeft : 0;
var body = document.body ? document.body.scrollLeft : 0;
return filterResults(win, docEl, body);
}
I did not include my attempt at it but I can included it if need be, basically I am just looking for the right way to go about it,
thanks
You could use one of the HTML5 specs for client side storage for this.
Related
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!
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 totally novice for JS and cookies. I got this code online and tried to change it for 30 days (it was set to 365) but it's probably resetting the cookie for every page and the pop up appears if I go to other page or even return back to the original page. Only things I changed in the code was expire days to 30 and load delay of 30 secs.
It seems either it's resetting the cookie every time I move to other page or some other problem which I don't understand yet :). I was wondering if there is some more efficient way to have it rather putting the code in every html article page. Something like setting up a cookie in headers or something and recalling using body onload.
Here is the code:
<SCRIPT language=JavaScript>
<!--
var expDays = 30; // number of days the cookie should last
function GetCookie (name) {
var arg = name + "=";
var alen = arg.length;
var clen = document.cookie.length;
var i = 0;
while (i < clen) {
var j = i + alen;
if (document.cookie.substring(i, j) == arg)
return getCookieVal (j);
i = document.cookie.indexOf(" ", i) + 1;
if (i == 0) break;
}
return null;
}
function SetCookie (name, value,expires) {
var argv = SetCookie.arguments;
var argc = SetCookie.arguments.length;
var expires = (argc > 2) ? argv[2] : null;
var path = (argc > 3) ? argv[3] : null;
var domain = (argc > 4) ? argv[4] : null;
var secure = (argc > 5) ? argv[5] : false;
document.cookie = name + "=" + escape (value) +
((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
((path == null) ? "" : ("; path=" + path)) +
((domain == null) ? "" : ("; domain=" + domain)) +
((secure == true) ? "; secure" : "");
}
function DeleteCookie (name) {
var exp = new Date();
exp.setTime (exp.getTime() - 1);
var cval = GetCookie (name);
document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
}
var exp = new Date();
exp.setTime(exp.getTime() + (expDays*24*60*60*1000));
function getCookieVal(offset) {
var endstr = document.cookie.indexOf (";", offset);
if (endstr == -1)
endstr = document.cookie.length;
return unescape(document.cookie.substring(offset, endstr));
}
function checkCount() {
var count = GetCookie('poponce');
if (count == null) {
count++;
SetCookie('poponce', count, exp);
// Action to take
dothis()
}
}
setTimeout(function dothis(){
var windowprops = "left=300,top=240,width=600,height=400,location=no,toolbar=no,menubar=no,scrollbars=no";
window.open("/subscribepopup.html", "", windowprops); // Use to load a page
}, 30000);
// -->
</SCRIPT>
<body OnLoad="checkCount()">
I have a div with its contenteditable property set to true. When user types '#' or '#', I would like to get whatever he/she type until spacebar is pressed. This way, I can bring suggestions from db according to the word he/she may type.
Please have a look at example below,
<div id="editableDiv" contenteditable="true">
I may tweet from #twitter in the near #future
<ul id="suggestUL"></ul>
</div>
As soon as user type '#' or '#', I must be able to collect whatever he/she may type (according to above example, after # t, tw, twi, twit, twitt, twitte and twitter. And after # f, fu... future). After 'twitter', user typed spacebar so, the word collection must stop and must start from # again.
Edited
Code to get the pixel where I could display suggestion list
function getCaretPixelPos($node) {
var offsetx = 0;
var offsety = 0;
var nodeLeft = 0,
nodeTop = 0;
if ($node) {
nodeLeft = $node.offsetLeft;
nodeTop = $node.offsetTop;
}
var pos = { left: 0, top: 0 };
if (document.selection) {
var range = document.selection.createRange();
pos.left = range.offsetLeft + offsetx - nodeLeft + 'px';
pos.top = range.offsetTop + offsety - nodeTop + 'px';
} else if (window.getSelection) {
var sel = window.getSelection();
var range = sel.getRangeAt(0).cloneRange();
try {
range.setStart(range.startContainer, range.startOffset - 1);
} catch (e) { }
var rect = range.getBoundingClientRect();
if (range.endOffset == 0 || range.toString() === '') {
// first char of line
if (range.startContainer == $node) {
// empty div
if (range.endOffset == 0) {
pos.top = '0px';
pos.left = '0px';
} else {
// firefox need this
var range2 = range.cloneRange();
range2.setStart(range2.startContainer, 0);
var rect2 = range2.getBoundingClientRect();
pos.left = rect2.left + offsetx - nodeLeft + 'px';
pos.top = rect2.top + rect2.height + offsety - nodeTop + 'px';
}
} else {
pos.top = range.startContainer.offsetTop + 'px';
pos.left = range.startContainer.offsetLeft + 'px';
}
} else {
pos.left = rect.left + rect.width + offsetx - nodeLeft + 'px';
pos.top = rect.top + offsety - nodeTop + 'px';
}
}
//console.log('pos left : ' + pos.left + ' pos top : ' + pos.top);
//console.log($('#suggestUL'));
$('#suggestUL').css('left', pos.left);
$('#suggestUL').css('top', pos.top);
//console.log('suggestUL left : ' + $('#suggestUL').css('left') + ' suggestUL top : ' + $('#suggestUL').css('top'));
};
This is how I am calling above function
var event = e || window.event;
var keyCode = event.keyCode || event.which;
if (keyCode == 35 || keyCode == 64)
getCaretPixelPos($('#editableDiv')[0]);
PS: I don't know why I have been fined by -2 reputation for Title. Anyway I edited title for more clarity. I am a learner, If I do any mistake in choosing title or asking question, kindly do suggest.
Thanks in advance.
You can use following script, along with this you need to use some UL/LI element combination which will show one suggestion per line, once data is fetched from the sever. You can use the jQuery Ajax to to fetch the data from sever and create the ul/li list dynamically.
var fetchData = false;
var suggestionChar = '';
$('#editableDiv').on('keypress',function(event){
var keyCode = event.which || event.keyCode.
var hashKey; // Set keyCode for #
var atKey; // Set keycode for #
var spaceKey //SpaceKey code
if(keyCode == hashKey || keyCode == atKey){
fetchData = true
suggestionChar = '';
return; //flag is set now look out for next key cod.
}
else if ( keyCode == spaceKey ){
fetchData = false;
suggestionChar = '';
}
if( fetchData){
var data = String.fromCharCode(keyCode);
suggestionChar = suggestionChar + data;
// use "suggestionChar" for fetching the data from server.
// fetch suggestions from Server.
// On success call back create the dynamic list of ul/li which will show the suggestion to user. You need to bind the user click event and/or keypress event for ul/li so that user can select the suggestion using mouse and keyboard along with 'Space' key.
}
})
I've made this stuff (textarea only) : http://jsfiddle.net/wared/sL2sZ/. I've tried to match your requirements but it's a bit more time-consuming to make things work using an editable DIV. I've decided to give up and to take inspiration from StackOverflow. You might pick up some ideas from my code in order to achieve your goal, hopefully.
More on getCaret() here : https://stackoverflow.com/a/263796/1636522.
Shirt-tail...
Currently, you are able to get the pixel position of the caret, while my code brings you a way to get the word around the current caret index. The missing link is a cross-browser solution to get the caret index from an editable DIV (this is where I gave up, too much work for me), indeed, the current version of getCaret() only accepts a textarea.
In other words, all you have to do is to modify the body of getCaret() in order to make it work with an editable DIV. Once you have the index, you have the word around it through getWord(), so, you can check if it's prefixed with "#", then display appropriate suggestions using getCaretPixelPos().
$('textarea').on('click keyup', function isAt() {
var idx = getCaret(this),
text = $(this).val(),
word = getWord(text, idx);
$('p').html([
'"', word, '" ', word.charAt(0) === '#'
? '<span style="color:blue">is prefixed</span>'
: '<span style="color:red">is not prefixed</span>'
].join(''));
}).focus();
function getWord(s, i) {
var r = /\s/g;
if (!i || r.test(s[i - 1])) return '';
while (i && !r.test(s[--i])) {}
r.lastIndex = i && ++i;
return s.slice(i, (
r.exec(s) || { index: s.length }
).index);
}
Try this:
var str = '';
$('#editableDiv').keyup(function(e){
if($(this).val() == '#' || $(this).val() == "#"){
if(e.keyCode !=32){
str += String.fromCharCode(e.keyCode);
}
}
});
alert(str);
I was finally able to solve the issue from all of your inputs.
Here is the code
Function called on KeyDown
var fetchSuggestions = false;
var suggestForString = '';
function fnShowSuggestionUL(e) {
var event = e || window.event;
var keyCode = event.keyCode || event.which;
// KeyCode = 35 -> #
// KeyCode = 64 -> #
// KeyCode = 32 -> space
// KeyCode = 13 -> Enter (Carriage Return)
if (keyCode == 35 || keyCode == 64) {
fetchSuggestions = true;
suggestForString = '';
$('#suggestUL').css('display', 'block');
fnPositionSuggestUL();
}
else if (keyCode == 32 || keyCode == 13) {
fetchSuggestions = false;
suggestForString = '';
$('#suggestUL').css('display', 'none');
return;
}
if (fetchSuggestions == false)
return;
var data = String.fromCharCode(keyCode);
suggestForString = suggestForString + data;
// TODO: bring suggestions from database and append them as list items to "suggestUL"
}
Position suggestUL at character '#' or '#'
function fnPositionSuggestUL() {
var $node = $('#editableDiv')[0]
var offsetx = 0;
var offsety = 0;
var nodeLeft = 0,
nodeTop = 0;
if ($node) {
nodeLeft = $node.offsetLeft;
nodeTop = $node.offsetTop;
}
var pos = { left: 0, top: 0 };
if (document.selection) {
var range = document.selection.createRange();
pos.left = range.offsetLeft + offsetx - nodeLeft + 'px';
pos.top = range.offsetTop + offsety - nodeTop + 'px';
} else if (window.getSelection) {
var sel = window.getSelection();
var range = sel.getRangeAt(0).cloneRange();
try {
range.setStart(range.startContainer, range.startOffset - 1);
} catch (e) { }
var rect = range.getBoundingClientRect();
if (range.endOffset == 0 || range.toString() === '') {
// first char of line
if (range.startContainer == $node) {
// empty div
if (range.endOffset == 0) {
pos.top = '0';
pos.left = '0';
} else {
// firefox need this
var range2 = range.cloneRange();
range2.setStart(range2.startContainer, 0);
var rect2 = range2.getBoundingClientRect();
pos.left = rect2.left + offsetx - nodeLeft;
pos.top = rect2.top + rect2.height + offsety - nodeTop;
}
} else {
pos.top = range.startContainer.offsetTop;
pos.left = range.startContainer.offsetLeft;
}
} else {
pos.left = rect.left + rect.width + offsetx - nodeLeft;
pos.top = rect.top + offsety - nodeTop;
}
}
//Create suggestUL if does not exist or destroyed
fnCreateSuggestUL();
$('#suggestUL').css('left', pos.left + 'px').css('top', (pos.top + 18)+'px');
};
I would like to thank one and all who answered/commented here.
Please optimize above code as much as possible so that one who in need gets perfect code.
PS: Works perfect in Chrome and firefox. suggestUL is not properly positioning in IE.
Happy Coding!!
Is there a better way to do this to reduce code duplication?
Maybe somehow loop the 'pagesTop' array?
The following function is initialized on the windows scroll event.
Thanks.
function redrawSideNav() {
var pagesTop = new Array();
$('.page').each(function(index, elem){
pagesTop[index] = $(this);
});
$('.menu, .page').find('a').removeClass('active');
if ( $(document).scrollTop() >= pagesTop[0].offset().top && $(document).scrollTop() < pagesTop[1].offset().top) {
var target = '#' + pagesTop[0].attr('id');
$('[href^="'+target+'"]').addClass('active');
} else if ( $(document).scrollTop() >= pagesTop[1].offset().top && $(document).scrollTop() < pagesTop[2].offset().top) {
var target = '#' + pagesTop[1].attr('id');
$('[href^="'+target+'"]').addClass('active');
} else if ( $(document).scrollTop() >= pagesTop[2].offset().top && $(document).scrollTop() < pagesTop[3].offset().top) {
var target = '#' + pagesTop[2].attr('id');
$('[href^="'+target+'"]').addClass('active');
} else if ( $(document).scrollTop() >= pagesTop[3].offset().top && $(document).scrollTop() < pagesTop[4].offset().top) {
var target = '#' + pagesTop[3].attr('id');
$('[href^="'+target+'"]').addClass('active');
} else if ( $(document).scrollTop() >= pagesTop[4].offset().top) {
var target = '#' + pagesTop[4].attr('id');
$('[href^="'+target+'"]').addClass('active');
}
}
Well, it seems that only the number changes in the following code, so you can use a for-loop with a break-statement. When the break get's triggered, the rest of the for-loop will not be executed. The last else if(...) is the same, but without the last condition. We can fake this by appending a dummy-element to pagesTop, that makes the last condition always true.
var a = {
offset: function() {
return {'top': 9999999999999};
}
};
pagesTop.push( a );
for( var i = 0; i < pagesTop.length-1; i++ ) {
if ( $(document).scrollTop() >= pagesTop[i].offset().top && $(document).scrollTop() < pagesTop[i+1].offset().top) {
var target = '#' + pagesTop[i].attr('id');
$('[href^="'+target+'"]').addClass('active');
break;
}
}
Do it step by step:
First I would create a variable for $(document).scrollTop() and replace the code inside the if statements:
var scrollTop = $(document).scrollTop();
var targetIndex = null;
$('.menu, .page').find('a').removeClass('active');
if ( scrollTop >= pagesTop[0].offset().top && scrollTop < pagesTop[1].offset().top) {
targetIndex = 0
} else if ( scrollTop >= pagesTop[1].offset().top && scrollTop < pagesTop[2].offset().top) {
targetIndex = 1;
} else if ( scrollTop >= pagesTop[2].offset().top && scrollTop < pagesTop[3].offset().top) {
targetIndex = 2;
} else if ( scrollTop >= pagesTop[3].offset().top && scrollTop < pagesTop[4].offset().top) {
targetIndex = 3;
} else if ( scrollTop >= pagesTop[4].offset().top) {
targetIndex = 4;
}
var target = '#' + pagesTop[targetIndex].attr('id');
$('[href^="'+target+'"]').addClass('active');
After that I would start building a loop instead if of using else if cascades:
var scrollTop = $(document).scrollTop();
var targetIndex = null;
for (var i = 0; i < 4 && !targetindex; i++) {
if (scrollTop >= pagesTop[i].offset().top && scrollTop < pagesTop[i + 1].offset().top) {
targetIndex = i;
}
}
targetIndex = targetIndex || 4;
var target = '#' + pagesTop[targetIndex].attr('id');
$('[href^="'+target+'"]').addClass('active');
(untested.. maybe I made some indices/syntax errors..)
the code below works for dynamic sized arrays:
var scrollTop = $(document).scrollTop();
for (var i=0;i<pagesTop.length ;i++) {
tempCond = pagesTop[i+1] ? (scrollTop <= pagesTop[i+1].offset().top) : true;
if(scrollTop >= pagesTop[i].offset().top && tempCond ) {
var target = '#' + pagesTop[i].attr('id');
$('[href^="'+target+'"]').addClass('active');
break;
}
}
difference with samurai answer:
rather than adding a fictional item to the array to guarantee the loop is executed at least one time and the second condition of if statement is always true,
I check inside the loop if the current element is the last item in the array: if it is , the second condition in the if statement is directly set to true, else, the condition is set to scrollTop <= pagesTop[i+1].offset().top