Reputation: 709
I am trying to change a Jquery function to vanilla JS and I have issues replicating it. I have fixed some errors it threw, but now I am entirely stuck.
The Jquery code
jQuery(window).load(function () {
var windowHeight, windowScrollPosTop, windowScrollPosBottom = 0;
function calcScrollValues() {
windowHeight = jQuery(window).height();
windowScrollPosTop = jQuery(window).scrollTop();
windowScrollPosBottom = windowHeight + windowScrollPosTop;
}
jQuery.fn.revealOnScroll = function (direction, speed) {
return this.each(function () {
var objectOffset = jQuery(this).offset();
var objectOffsetTop = objectOffset.top;
if (!jQuery(this).hasClass("hidden")) {
// if argument is "right"
if (direction == "right") {
jQuery(this).css({
"opacity": 0,
"right": "700px",
"position": "relative"
});
// if argument is "left"
} else {
jQuery(this).css({
"opacity": 0,
"right": "-700px",
"position": "relative"
});
}
jQuery(this).addClass("hidden");
}
if (!jQuery(this).hasClass("animation-complete")) {
// if the page has been scrolled far enough to reveal the element
if (windowScrollPosBottom > objectOffsetTop) {
jQuery(this).animate({"opacity": 1, "right": 0}, speed).addClass("animation-complete");
} // end if the page has scrolled enough check
} // end only reveal the element once
});
}
function revealCommands() {
jQuery(".title").revealOnScroll("right", 1200);
}
calcScrollValues();
revealCommands();
// run the following on every scroll event
jQuery(window).scroll(function () {
calcScrollValues()
revealCommands();
}); // end on scroll
});
This work, if you uncomment the Jquery code in the pen.
Here is the JS code
function calcScrollValues() {
windowHeight = screen.height;
windowScrollPosTop = document.body.scrollTop;
windowScrollPosBottom = windowHeight + windowScrollPosTop;
};
window.onload = function () {
var windowHeight, windowScrollPosTop, windowScrollPosBottom = 0;
function revealOnScroll(direction, speed) {
return this.each(function () {
var objectOffset = this.getBoundingClientRect();
var objectOffsetTop = getBoundingClientRect();
if (!this.classList.contains("hidden")) {
// if argument is "right"
if (direction == "right") {
this.setAttribute('style', 'opacity:0; right:700px; position: relative');
}
;
// if argument is "left"
} else {
this.setAttribute('style', 'opacity:0; right:700px; position: relative');
}
;
this.classList.add("hidden");
});
if (!this.classList.contains("animation-complete")) {
// if the page scrolled far enough to reveal the element
if (windowScrollPosBottom > objectOffsetTop) {
this.setAttribute('style', 'opacity:1; right:0; transition: speed + "ms"');
this.classList.add("animation-complete");
} // end if the page has scrolled enough check
}
; // end only reveal the element once
}
}
function revealCommands() {
document.querySelector(".title").revealOnScroll("right", 1200);
}
calcScrollValues();
revealCommands();
// run the following on every scroll event
window.addEventListener('scroll', function () {
calcScrollValues()
revealCommands();
});
I know that the 'return this.each(function() {}' part cannot possibly work in JS, and have no idea how to get the JS code for that.
And the other main issue is this
'document.querySelector (".title").revealOnScroll("right", 1200);'
obviously gives a Type error"not a function".
There are probably even more issues with this, but this is the one which has me stuck.
Codepen:
http://codepen.io/damianocel/pen/yYKyaN
Upvotes: 0
Views: 117
Reputation: 1969
Your original code added the revealOnScroll
method to the object returned by jQuery when querying for .title
(via jQuery.fn.revealOnScroll
). By querying with the browser, you lost the jQuery
object but got a NodeList
from document.querySelectorAll('.title')
instead (you shouldn't use document.querySelector
as it returns only one element - this is not what you had before with jQuery). You now need to add the revealOnScroll
method to the prototype of the NodeList
in order to use it like you did before with jQuery.
After doing so, you hit some other problems: NodeList
looks like, but is no Array
and has no iterator by itself, but you can lend the one from Array.prototype.forEach
.
You also lose the this
binding, but using the element
provided by forEach
instead should just work fine.
I haven't checked the code completely. It gets interpreted without errors but I had to make some changes to it, like moving function calls inside the onload
function.
Please check it line by line and report back if you encounter problems that you can't solve on your own.
function calcScrollValues() {
windowHeight = screen.height;
windowScrollPosTop = document.body.scrollTop;
windowScrollPosBottom = windowHeight + windowScrollPosTop;
};
window.onload = function () {
var windowHeight, windowScrollPosTop, windowScrollPosBottom = 0;
NodeList.prototype.revealOnScroll = function(direction, speed) {
Array.prototype.forEach.call(self, function (element, index) {
var objectOffset = element.getBoundingClientRect();
var objectOffsetTop = getBoundingClientRect();
if (!element.classList.indexOf("hidden") !== -1) {
// if argument is "right"
if (direction == "right") {
element.setAttribute('style', 'opacity:0; right:700px; position: relative');
};
// if argument is "left"
} else {
element.setAttribute('style', 'opacity:0; right:700px; position: relative');
};
element.classList.add("hidden");
if (element.classList.indexOf("animation-complete") === -1) {
// if the page scrolled far enough to reveal the element
if (windowScrollPosBottom > objectOffsetTop) {
element.setAttribute('style', 'opacity:1; right:0; transition: speed + "ms"');
element.classList.add("animation-complete");
} // end if the page has scrolled enough check
}; // end only reveal the element once
});
}
calcScrollValues();
revealCommands();
}
function revealCommands() {
document.querySelectorAll(".title").revealOnScroll("right", 1200);
}
// run the following on every scroll event
window.addEventListener('scroll', function () {
calcScrollValues()
revealCommands();
});
<div class="title" />
Upvotes: 1