I have function that works after window.onload, but how to run it just after scrolled to the needed . I understand that using jQuery is easier, but I need to do in native JS.
window.onload = function move() {
var width = 1;
var elem = document.getElementsByClassName("myBar");
var maxValue = document.getElementsByClassName('max-value');
for(var i = 0; i < elem.length; i++) {
var params = {
elem: elem[i],
maxElem: maxValue[i],
width: width,
interval: null
};
params.interval = setInterval(frame, 20, params);
}
function frame(aParams) {
if (aParams.width >= aParams.maxElem.dataset.max) {
clearInterval(aParams.interval);
} else {
aParams.width++;
aParams.elem.style.backgroundColor = 'blue';
aParams.elem.style.width = aParams.width + '%';
aParams.maxElem.innerHTML = aParams.width + '%';
}
};
};
https://codepen.io/Slava91/pen/PjpGGr
Try this, it will trigger the animation again when you will scroll near to the ul element. #percentage is the id I have given to the ul element in your html.
window.onload = move();
function move() {
var width = 1;
var elem = document.getElementsByClassName("myBar");
var maxValue = document.getElementsByClassName('max-value');
for(var i = 0; i < elem.length; i++) {
var params = {
elem: elem[i],
maxElem: maxValue[i],
width: width,
interval: null
};
params.interval = setInterval(frame, 20, params);
}
function frame(aParams) {
if (aParams.width >= aParams.maxElem.dataset.max) {
clearInterval(aParams.interval);
} else {
aParams.width++;
aParams.elem.style.backgroundColor = 'blue';
aParams.elem.style.width = aParams.width + '%';
aParams.maxElem.innerHTML = aParams.width + '%';
}
};
}
isScrolled = false;
window.onscroll = function loadItBack(){
var rec = document.getElementById("percentage").getBoundingClientRect();
if(window.scrollY > 600 && !isScrolled){
isScrolled = true;
move();
}else if(window.scrollY < 600){
isScrolled = false;
}
};
For your every li, you can use getBoundingClientRect to execute your animation.
Don't forget to set a flag once animation completed, else, it will execute on every scroll.
Related
I have a very strange problem with some jquery code that scrolls a group of images. It seems to work in all browsers for the first several clicks, advancing the images by a number. And in Safari, it will work perfectly all the way to the end of the slideshow. But in FF and Chrome it will stop after a certain number of images. And this number is NOT always the same for some reason.
For example, on this page FF/Chrome will stop after clicking the next arrow 7 times.
And on this page, FF/Chrome will stop after clicking the next arrow 6 times.
Yet on this page, FF/Chrome will work all the way to the end as expected (and as Safari does all the time).
This is the code that controls the clicking:
<script>$(window).load(function(){
var currentElement = $("#ngg-gallery-list > div:nth-child(2)");
var onScroll = function () {
//get the current element
var container = $("#ngg-galleryoverview");
var wrapper = $("#ngg-gallery-list");
var children = wrapper.children();
var position = 0;
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
var childLeft = container.offset().left < child.offset().left;
if (childLeft) {
currentElement = child;
return;
}
}
}
var scrollToElement = function ($element) {
var container = $("#ngg-galleryoverview");
var wrapper = $("#ngg-gallery-list");
var children = wrapper.children();
var width = 0;
console.log(children.length);
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
if (child.get(0) == $element.get(0)) {
if (i == 0) {
width = 300;
}
container.animate({
scrollLeft: width
}, 300);
onScroll();
}
if (child.next().length > 0) {
//make sure we factor in borders/padding/margin in height
width += child.next().offset().left - child.offset().left
} else {
width += child.width();
}
}
}
var next = function(event) {
event.preventDefault();
scrollToElement(currentElement);
}
var prev = function(event) {
event.preventDefault();
var container = $("#ngg-galleryoverview");
if (currentElement.prev().length > 0) {
if (container.offset().left == currentElement.prev().offset().left) {
currentElement = currentElement.prev().prev().length > 0 ? currentElement.prev().prev() : currentElement.prev();
} else {
currentElement = currentElement.prev();
}
}
scrollToElement(currentElement);
}
$("#ngg-galleryoverview").on('scroll', onScroll);
$("#nexty").click(next);
$("#prevy").click(prev);
});
</script>
I'm stumped.
Well, making my code look more like what I found here fixed the problem. (Even if I am not entirely sure why). Hoping it helps someone else, here is the final code:
<script>
$(document).ready(function () {
var currentElement = $("#ngg-galleryoverview > div:nth-child(1)");
var onScroll = function () {
var container = $("#ngg-galleryoverview");
var children = $(".list");
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
var childLeft = container.offset().left < child.offset().left;
if (childLeft) {
currentElement = child;
//console.log(currentElement);
return;
}
}
};
var scrollToElement = function ($element) {
var container = $("#ngg-galleryoverview");
var children = $(".list");
var width = 0;
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
if (child.get(0) == $element.get(0)) {
if (i === 0) {
width = 0;
}
container.animate({
scrollLeft: width
}, 500);
onScroll();
}
if (child.next().length > 0) {
width += child.next().offset().left - child.offset().left;
} else {
width += child.width();
}
}
};
var buttonright = function (e) {
scrollToElement(currentElement.next());
};
var buttonleft = function (e) {
var container = $("#ngg-galleryoverview");
if (currentElement.prev().length > 0) {
if (container.offset().left == currentElement.prev().offset().left) {
currentElement = currentElement.prev().prev().length > 0 ? currentElement.prev().prev() : currentElement.prev();
} else {
currentElement = currentElement.prev();
}
}
scrollToElement(currentElement);
};
onScroll();
$("#ngg-galleryoverview").scroll(onScroll);
$("#nexty").click(buttonright);
$("#prevy").click(buttonleft);
});</script>
I'm working on some web pages that use a button to scroll to the next div. I can get it to work on every page, except in this particular instance (see jsfiddle).
My problem is that the buttons don't work on loading the page, the user first has to start scrolling manually, before the buttons work. I'm assuming that's because of some fault in my jQuery coding, which I've looked over and over, but I can't seem to find the problem. Is there anyone who is a bit more familiar with jQuery than I am who can offer me a solution?
http://jsfiddle.net/y5wx7nst/3/
$(document).ready(function () {
var currentElement = $("#bodytext > div:nth-child(1)");
var onScroll = function () {
var container = $("#bodytext");
var children = $(".section");
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
var childLeft = container.offset().left < child.offset().left;
if (childLeft) {
currentElement = child;
console.log(currentElement);
return;
}
}
};
var scrollToElement = function ($element) {
var container = $("#bodytext");
var children = $(".section");
var width = 0;
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
if (child.get(0) == $element.get(0)) {
if (i === 0) {
width = 0;
}
container.animate({
scrollLeft: width
}, 500);
onScroll();
}
if (child.next().length > 0) {
width += child.next().offset().left - child.offset().left;
} else {
width += child.width();
}
}
};
var buttonright = function (e) {
scrollToElement(currentElement.next());
};
var buttonleft = function (e) {
var container = $("#bodytext");
if (currentElement.prev().length > 0) {
if (container.offset().left == currentElement.prev().offset().left) {
currentElement = currentElement.prev().prev().length > 0 ? currentElement.prev().prev() : currentElement.prev();
} else {
currentElement = currentElement.prev();
}
}
scrollToElement(currentElement);
};
$("#bodytext").scroll(onScroll);
$("#buttonright").click(buttonright);
$("#buttonleft").click(buttonleft);
});
You are only calling the onScroll() function after you initially scroll:
$("#bodytext").scroll(onScroll);
I added this before that declaration and it all worked:
onScroll();
jsfiddle: http://jsfiddle.net/y5wx7nst/5/
When code run value of currentElement is not correct. So you should calculate it calling a function onScroll();
...
$("#bodytext").scroll(onScroll);
$("#buttonright").click(buttonright);
$("#buttonleft").click(buttonleft);
onScroll();
});
I am new to JavaScript. I would like to add to add two buttons for my visitors to control font size. I would like to include two tags - 'p' and 'blockquote". Can you please help me edit this code in order to include both?
var min = 8;
var max = 18;
function increaseFontSize() {
var p = document.getElementsByTagName('p');
for (i = 0; i < p.length; i++) {
if (p[i].style.fontSize) {
var s = parseInt(p[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += 1;
}
p[i].style.fontSize = s + "px"
}
}
function decreaseFontSize() {
var p = document.getElementsByTagName('p');
for (i = 0; i < p.length; i++) {
if (p[i].style.fontSize) {
var s = parseInt(p[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != min) {
s -= 1;
}
p[i].style.fontSize = s + "px"
}
}
Thank you.
Here's a working version:
http://jsfiddle.net/ny4p7pg9/
I took the liberty of refactoring a bit the functions to make the code more parameterized.
function changeFontSize(delta) {
var tags = document.querySelectorAll('p,blockquote');
for (i = 0; i < tags.length; i++) {
if (tags[i].style.fontSize) {
var s = parseInt(tags[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += delta;
}
tags[i].style.fontSize = s + "px"
}
}
function increaseFontSize() {
changeFontSize(1);
}
function decreaseFontSize() {
changeFontSize(-1);
}
Instead of using:
p = document.getElementsByTagName('p');
you could, instead use:
elems = document.querySelectorAll('p, blockquote');
(the variable name is irrelevant, and was changed only because the elements are no longer exclusively <p> elements):
function increaseFontSize() {
var elems = document.querySelectorAll('p, blockquote');
for (i = 0; i < elems.length; i++) {
if (elems[i].style.fontSize) {
var s = parseInt(elems[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += 1;
}
elems[i].style.fontSize = s + "px"
}
}
var min = 8;
var max = 18;
function increaseFontSize() {
var elems = document.querySelectorAll('p, blockquote');
for (i = 0; i < elems.length; i++) {
if (elems[i].style.fontSize) {
var s = parseInt(elems[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += 1;
}
elems[i].style.fontSize = s + "px"
}
}
function decreaseFontSize() {
var elems = document.querySelectorAll('p, blockquote');
for (i = 0; i < elems.length; i++) {
if (elems[i].style.fontSize) {
var s = parseInt(elems[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != min) {
s -= 1;
}
elems[i].style.fontSize = s + "px"
}
}
document.querySelector('#increase').addEventListener('click', increaseFontSize);
document.querySelector('#decrease').addEventListener('click', decreaseFontSize);
<button id="increase">↑A</button>
<button id="decrease">A↓</button>
<p>Some text to have its text adjusted by the buttons just up there.</p>
<blockquote>Some text in a blockquote</blockquote>
The querySelectorAll() method accepts CSS-style selectors, and returns a (non-live) NodeList, and is supported in all modern browsers, including IE from version 8 onwards.
That said, it's probably better to increase the font-size of the <body> element, otherwise font-adjustment is redundant (since other elements will still be unclear), so, instead, I'd suggest:
function increaseFontSize() {
// retrieving, and caching, the <body> element:
var body = document.body,
// finding the current computed fontSize of the <body> element, parsing it
// as a float (though parseInt() would be just as safe, really):
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
// if the currentFontSize is less than the specified max:
if (currentFontSize < max) {
// we set the fontSize of the <body> to the incremented fontSize,
// increasing the current value by 1, and concatenating with the 'px' unit:
body.style.fontSize = ++currentFontSize + 'px';
}
}
function decreaseFontSize() {
var body = document.body,
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
if (currentFontSize > min) {
body.style.fontSize = --currentFontSize + 'px';
}
}
var min = 8;
var max = 18;
function increaseFontSize() {
var body = document.body,
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
if (currentFontSize < max) {
body.style.fontSize = ++currentFontSize + 'px';
}
}
function decreaseFontSize() {
var body = document.body,
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
if (currentFontSize > min) {
body.style.fontSize = --currentFontSize + 'px';
}
}
document.querySelector('#increase').addEventListener('click', increaseFontSize);
document.querySelector('#decrease').addEventListener('click', decreaseFontSize);
<button id="increase">↑A</button>
<button id="decrease">A↓</button>
<p>Some text to have its text adjusted by the buttons just up there.</p>
<blockquote>Some text in a blockquote</blockquote>
References:
document.body.
document.querySelectorAll().
Window.getComputedStyle().
I am trying to render the list based on virtual rendering concept. I am facing some minor issues, but they are not blocking the behaviour. Here is the working fiddle http://jsfiddle.net/53N36/9/ and Here are my problems
Last items are not visible, I assume some where I missed indexing.(Fixed, Please see the edit)
How to calculate scrollPosition if I want to add custom scroll to this.
Is this the best method or any other?
I have tested it with 700000 items and 70 items in chrome. Below is the code
(function () {
var list = (function () {
var temp = [];
for (var i = 0, l = 70; i < l; i++) {
temp.push("list-item-" + (i + 1));
}
return temp;
}());
function listItem(text, id) {
var _div = document.createElement('div');
_div.innerHTML = text;
_div.className = "listItem";
_div.id = id;
return _div;
}
var listHold = document.getElementById('listHolder'),
ht = listHold.clientHeight,
wt = listHold.clientWidth,
ele = listItem(list[0], 'item0'),
frag = document.createDocumentFragment();
listHold.appendChild(ele);
var ht_ele = ele.clientHeight,
filled = ht_ele,
filledIn = [0];
for (var i = 1, l = list.length; i < l; i++) {
if (filled + ht_ele < ht) {
filled += ht_ele;
ele = listItem(list[i], 'item' + i);
frag.appendChild(ele);
} else {
filledIn.push(i);
break;
}
}
listHold.appendChild(frag.cloneNode(true));
var elements = document.querySelectorAll('#listHolder .listItem');
function MouseWheelHandler(e) {
var e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
console.log(delta);
//if(filledIn[0] != 0 && filledIn[0] != list.length){
if (delta == -1) {
var start = filledIn[0] + 1,
end = filledIn[1] + 1,
counter = 0;
if (list[start] && list[end]) {
for (var i = filledIn[0]; i < filledIn[1]; i++) {
if (list[i]) {
(function (a) {
elements[counter].innerHTML = list[a];
}(i));
counter++;
}
}
filledIn[0] = start;
filledIn[1] = end;
}
} else {
var start = filledIn[0] - 1,
end = filledIn[1] - 1,
counter = 0;
if (list[start] && list[end]) {
for (var i = start; i < end; i++) {
if (list[i]) {
(function (a) {
elements[counter].innerHTML = list[a];
}(i));
counter++;
}
}
filledIn[0] = start;
filledIn[1] = end;
}
}
//}
}
if (listHold.addEventListener) {
listHold.addEventListener("mousewheel", MouseWheelHandler, false);
listHold.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
} else listHold.attachEvent("onmousewheel", MouseWheelHandler);
}());
Please suggest me on this.
EDIT:
I have tried again and I am able to fix the indexing issue. http://jsfiddle.net/53N36/26/
But how can I calculate the scroll position based on the array list currently displayed.
Is this the best method or any other?
I think something that would make this much easier is not to try to handle scrolling yourself.
In this fiddle I show that you can let the browser handle scrolling for you, even though we are using virtual rendering.
Using .scrollTop I detect where the browser thinks the user is looking, and I draw in items based on that.
You'll note that if you set hidescrollbar to false and the user uses it to scroll, my method still runs fine.
Therefore, to calculate scroll position you can just use .scrollTop.
And as for custom scrolling, just make sure you influence the .scrollTop of #listHolder and recall refreshWindow()
CODE FROM FIDDLE
(function () {
//CHANGE THESE IF YOU WANT
var hidescrollbar = false;
var numberofitems = 700000;
//
var holder = document.getElementById('listHolder');
var view = null;
//get the height of a single item
var itemHeight = (function() {
//generate a fake item
var div = document.createElement('div');
div.className = 'listItem';
div.innerHTML = 'testing height';
holder.appendChild(div);
//get its height and remove it
var output = div.offsetHeight;
holder.removeChild(div);
return output;
})();
//faster to instantiate empty-celled array
var items = Array(numberofitems);
//fill it in with data
for (var index = 0; index < items.length; ++index)
items[index] = 'item-' + index;
//displays a suitable number of items
function refreshWindow() {
//remove old view
if (view != null)
holder.removeChild(view);
//create new view
view = holder.appendChild(document.createElement('div'));
var firstItem = Math.floor(holder.scrollTop / itemHeight);
var lastItem = firstItem + Math.ceil(holder.offsetHeight / itemHeight) + 1;
if (lastItem + 1 >= items.length)
lastItem = items.length - 1;
//position view in users face
view.id = 'view';
view.style.top = (firstItem * itemHeight) + 'px';
var div;
//add the items
for (var index = firstItem; index <= lastItem; ++index) {
div = document.createElement('div');
div.innerHTML = items[index];
div.className = "listItem";
view.appendChild(div);
}
console.log('viewing items ' + firstItem + ' to ' + lastItem);
}
refreshWindow();
document.getElementById('heightForcer').style.height = (items.length * itemHeight) + 'px';
if (hidescrollbar) {
//work around for non-chrome browsers, hides the scrollbar
holder.style.width = (holder.offsetWidth * 2 - view.offsetWidth) + 'px';
}
function delayingHandler() {
//wait for the scroll to finish
setTimeout(refreshWindow, 10);
}
if (holder.addEventListener)
holder.addEventListener("scroll", delayingHandler, false);
else
holder.attachEvent("onscroll", delayingHandler);
}());
<div id="listHolder">
<div id="heightForcer"></div>
</div>
html, body {
width:100%;
height:100%;
padding:0;
margin:0
}
body{
overflow:hidden;
}
.listItem {
border:1px solid gray;
padding:0 5px;
width: margin : 1px 0px;
}
#listHolder {
position:relative;
height:100%;
width:100%;
background-color:#CCC;
box-sizing:border-box;
overflow:auto;
}
/*chrome only
#listHolder::-webkit-scrollbar{
display:none;
}*/
#view{
position:absolute;
width:100%;
}
javascript for elements re-size works fine on my tumblr theme, but I get the object required error on the following line in IE8:
fschildren = $("fs_wrapper").childNodes;
Thanks for help
Peter
<script type="text/javascript">
function resizedivs() {
$ = function(id) { return document.getElementById(id); }
fschildren = $("fs_wrapper").childNodes;
postc = 0;
thedivs = new Array();
for(i = 0; i < fschildren.length; i++) {
if(fschildren[i].tagName == "DIV") {
thedivs[postc] = fschildren[i];
postc++;
}
}
newwidth = 0;
for(i = 0; i < thedivs.length; i++) {
if(newwidth <= document.body.clientWidth) {
newwidth = newwidth + (thedivs[i].clientWidth)+15;
}
if(newwidth >= document.body.clientWidth || newwidth >= 1300) { // 100 for padding minus 15 extra
newwidth = newwidth - (thedivs[i].clientWidth+15);
break;
}
}
$("fs_wrapper").style.width = newwidth-0+"px";
$("fs_wrapper").style.position = "relative";
$("fs_wrapper").style.left = "0px";
$("sec2").style.width = newwidth-0+"px";
$("sec2").style.position = "relative";
$("sec2").style.left = "0px";
$("sec3").style.width = newwidth-0+"px";
$("sec3").style.position = "relative";
$("sec3").style.left = "0px";
}
window.onresize = function() {
resizedivs();
}
window.onload = function() {
resizedivs();
}
</script>
Does object really exist?
myObj = document.getElementById('myObj');
if(!myObj) {
alert("4004 not found");
return;
}
You are missing the right selector . for class or # for id
see this http://www.w3schools.com/jquery/jquery_ref_selectors.asp