Can someone tell me how to adjust this .js? I want it to be able to apply on H1 and H2 with an ID in my html. Now it is only working on css background-image. Below is the .js I'm using. I'm a beginner with javascript;)
Hope you guys can help me out!
(function( $ ){
var $window = $(window);
var windowHeight = $window.height();
$window.resize(function () {
windowHeight = $window.height();
});
$.fn.parallax = function(xpos, speedFactor, outerHeight) {
var $this = $(this);
var getHeight;
var firstTop;
var paddingTop = 0;
//get the starting position of each element to have parallax applied to it
$this.each(function(){
firstTop = $this.offset().top;
});
if (outerHeight) {
getHeight = function(jqo) {
return jqo.outerHeight(true);
};
} else {
getHeight = function(jqo) {
return jqo.height();
};
}
// setup defaults if arguments aren't specified
if (arguments.length < 1 || xpos === null) xpos = "50%";
if (arguments.length < 2 || speedFactor === null) speedFactor = 0.1;
if (arguments.length < 3 || outerHeight === null) outerHeight = true;
// function to be called whenever the window is scrolled or resized
function update(){
var pos = $window.scrollTop();
$this.each(function(){
var $element = $(this);
var top = $element.offset().top;
var height = getHeight($element);
// Check if totally above or totally below viewport
if (top + height < pos || top > pos + windowHeight) {
return;
}
$this.css('backgroundPosition', xpos + " " + Math.round((firstTop - pos) * speedFactor) + "px");
});
}
$window.bind('scroll', update).resize(update);
update();
};
})(jQuery);
It should be background-position. Can you try changing?
$this.css('background-position', xpos + " " + Math.round((firstTop - pos) * speedFactor) + "px");
Related
I have the problem with the scenario.
We have a page with text which is scrollable
When image is detected, scrolling should be slower
When image is over, scrolling gets back to default speed.
I have detection of element and trying to do slowing scroll with using transform, but without luck. It is slower a little bit, but it does not look like properly.
function elementInViewport2(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
);
}
/*window.addEventListener('scroll', function(e) {
var el = document.getElementById('slides');
console.log(elementInViewport2(el));
});*/
$.fn.moveIt = function(){
var $window = $(window);
var instances = [];
$(this).each(function(){
instances.push(new moveItItem($(this)));
});
window.addEventListener('scroll', function(){
var scrollTop = $window.scrollTop();
var el = document.getElementById('slides');
if (elementInViewport2(el)) {
instances.forEach(function(inst){
inst.update(scrollTop, -20);
});
}
}, {passive: true});
}
var moveItItem = function(el){
this.el = $(el);
console.log(el);
this.speed = parseInt(this.el.attr('data-scroll-speed'));
};
moveItItem.prototype.update = function(scrollTop, speed){
this.el.css('transform', 'translateY(' + -(scrollTop / speed) + 'px)');
};
// Initialization
$(function(){
$('[data-scroll-speed]').moveIt();
});
https://jsfiddle.net/pnrszyzn/
I am creating two radwindow dialogs: a parent and its child.
Parent radwindow has size 1082x630
Child radwindow has size 1500x900
On parent radwindow dialog, when I click on button "Show Child Dialog", its child radwindow will be shown.
The problem here is the size of child dialog larger than its parent. So, I want to resize the size of child dialog and show it in the center of its parent dialog.
And here is my code in Javascript that I use for resizing child dialog manually. To center child dialog, I also use childRadWindow.left and childRadWindow.top . BUT, it does not work as my expected. The child dialog does not place in the center of its parent.
Please reference my expected, actual images and my code to get the problem.
My expected result:
Actual result:
Here is my code to resize child dialog manually. I put it on child dialog *.aspx
<script type="text/javascript">
$(document).ready(function () {
resizeRWndDialog();
});
</script>
function resizeRWndDialog() {
var radWindows = [];
var radWindow = GetRadWindow();
while (true) {
if (radWindow != undefined && radWindow != null) {
radWindows.push(radWindow._popupElement);
radWindow = radWindow.BrowserWindow.GetRadWindow();
} else {
break;
}
}
var numsOfRadWindow = radWindows.length - 1;
if (numsOfRadWindow > 0) {
for (var i = numsOfRadWindow; i > 0; i--) {
var parentWindow = radWindows[i];
var parentWidth = parentWindow.clientWidth; //parentWidth =1082
var parentHeight = parentWindow.clientHeight; //parentHeight = 630
var chidWindow = radWindows[i - 1];
var childWidth = chidWindow.clientWidth; //childWidth = 1500
var childHeight = chidWindow.clientHeight; //childHeight = 900
var rateMinWidth = 0,
rateMinHeight = 0,
rateMaxWidth = 0,
rateMaxHeight = 0;
if (chidWindow.style.minWidth != "") {
rateMinWidth = parseInt(chidWindow.style.minWidth) / childWidth;
}
if (chidWindow.style.minHeight != "") {
rateMinHeight = parseInt(chidWindow.style.minHeight) / childHeight;
}
if (chidWindow.style.maxWidth != "") {
rateMaxWidth = parseInt(chidWindow.style.maxWidth) / childWidth;
}
if (chidWindow.style.maxHeight != "") {
rateMaxHeight = parseInt(chidWindow.style.maxHeight) / childHeight;
}
if ((parentWidth - 40) > 0 && childWidth >= parentWidth - 40) {
childWidth = parentWidth - 40; //parentWidth = 1082, childWidth = 1042
}
if ((parentHeight - 80) > 0 && childHeight >= parentHeight - 80) {
childHeight = parentHeight - 80; //parentHeight = 630, childHeight = 550
}
setSizeRWndDialog(chidWindow.getElementsByClassName("rwTable")[0], rateMinWidth * childWidth, rateMinHeight * childHeight, rateMaxWidth * childWidth, rateMaxHeight * childHeight, childWidth, childHeight);
setSizeRWndDialog(chidWindow, rateMinWidth * childWidth, rateMinHeight * childHeight, rateMaxWidth * childWidth, rateMaxHeight * childHeight, childWidth, childHeight);
chidWindow.left = Math.round((parentWidth - childWidth) / 2, 0) + "px";
chidWindow.top = Math.round((parentHeight - childHeight) / 2, 0) + "px";
chidWindow.focus();
radWindows[i - 1] = chidWindow;
}
}
}
function setSizeRWndDialog(element, minWidth, minHeight, maxWidth, maxHeight, width, height) {
if (minWidth != 0 && minHeight != 0) {
element.style.minWidth = minWidth + "px";
element.style.minHeight = minHeight + "px";
}
if (maxWidth != 0 && maxHeight != 0) {
element.style.maxWidth = maxWidth + "px";
element.style.maxHeight = maxHeight + "px";
} else {
element.style.maxWidth = width + "px";
element.style.maxHeight = height + "px";
}
element.style.width = width + "px";
element.style.height = height + "px";
}
I solved the problem myself, guys.
I just added one more line at the end of the resizeRWndDialog() as the snippet code below:
function resizeRWndDialog() {
//.........
if (numsOfRadWindow > 0) {
//...........
}
GetRadWindow().center(); // >> Just use this line
}
I have a page that only uses this excellent parallax function and I don't want to load jQuery just for that.
Can you write this function in plain javascript and keep it small and readable? (Has to work in IE10+, modern browsers)
$(document).ready(function(){
function draw() {
requestAnimationFrame(draw);
// Drawing code goes here
scrollEvent();
}
draw();
});
function scrollEvent(){
if(!is_touch_device()){
viewportTop = $(window).scrollTop();
windowHeight = $(window).height();
viewportBottom = windowHeight+viewportTop;
if($(window).width())
$('[data-parallax="true"]').each(function(){
distance = viewportTop * $(this).attr('data-speed');
if($(this).attr('data-direction') === 'up'){ sym = '-'; } else { sym = ''; }
$(this).css('transform','translate3d(0, ' + sym + distance +'px,0)');
});
}
}
function is_touch_device() {
return 'ontouchstart' in window // works on most browsers
|| 'onmsgesturechange' in window; // works on ie10
}
You can do what you're asking here by looking at You Might Not Need jQuery.
Your code, translated to vanilla javascript, should be something like this:
document.addEventListener('DOMContentLoaded', function() {
function draw() {
requestAnimationFrame(draw);
// Drawing code goes here
scrollEvent();
}
draw();
});
function scrollEvent() {
if (!is_touch_device()){
var viewportTop = window.scrollY;
var windowHeight = document.documentElement.clientHeight;
var viewportBottom = windowHeight + viewportTop;
if (document.documentElement.clientWidth) {
var parallax = document.querySelectorAll('[data-parallax="true"]');
for (var i = 0; i < parallax.length; i++) {
var item = parallax[i];
var distance = viewportTop * item.getAttribute('data-speed');
var sym = item.getAttribute('data-direction') === 'up' ? '-' : '';
item.style.transform = 'translate3d(0, ' + sym + distance +'px,0)';
}
}
}
}
function is_touch_device() {
return 'ontouchstart' in window || 'onmsgesturechange' in window;
}
I'm attempting to output on a page multiple 'labels' over an image using absolute positioned divs. Each of these divs has a unique number and are placed according to an x and y position on the map (these are percentage based so the image may be scaled).
As some of these labels may overlap, I need a way to either stop them from overlapping, or to essentially 'bump' them off eachother so they no longer overlap. (At this point, it doesn't matter if they are not in their correct position as long as they are near enough as there is a separate 'Pin' view).
They need to stay within the confines of their container and not overlap with eachother.
HTML:
<div id="labelzone">
<div class="label" style="left:0%;top:8%">001</div>
<div class="label" style="left:0%;top:11%">002</div>
<div class="label" style="left:1%;top:10%">003</div>
</div>
CSS:
#labelzone{
float:left;
width:500px;
height:500px;
border: 1px solid black;
position: relative;
}
.label{
position:absolute;
border:1px solid black;
background-color:white;
}
Jsfiddle: https://jsfiddle.net/79cco1oy/
There's a simple example of what I have as an output, these pins could be placed anywhere and there is no limit to how many is on the page, however there shouldn't be any occasion where there are too many to fit in the area.
I'm toying around with doing some form of collision detection and currently attempting to figure out an algorithm of some sort to get them to no longer overlap, and ensure they also don't overlap another item.
My solution is a bit more object oriented.
One object (LabelPool) will contain labels and will be in charge of storing and accomodating them so that they don't collide. You can customize the x/y values that you want to add/substract of the Label's positions in order to avoid their collision. The other object (Label) defines a Label and has some convenient methods. The collision algorithm that I used in LabelPool was taken from this post
var Label = function ($el) {
var position = $el.position(),
width = $el.outerWidth(true),
height = $el.outerHeight(true);
this.getRect = function () {
return {
x: position.left,
y: position.top,
width: width,
height: height
};
};
this.modifyPos = function (modX, modY) {
position.top += modY;
position.left += modX;
updatePos();
};
function updatePos() {
$el.css({
top: position.top,
left: position.left
});
}
};
var LabelPool = function () {
var labelPool = [];
function collides(a, b) {
return !(((a.y + a.height) < (b.y)) || (a.y > (b.y + b.height)) || ((a.x + a.width) < b.x) || (a.x > (b.x + b.width)));
}
function overlaps(label) {
var a = label.getRect();
return labelPool.some(function (other) {
return collides(a, other.getRect());
});
}
this.accomodate = function (label) {
while (labelPool.length && overlaps(label)) {
label.modifyPos(0, 1);// You can modify these values as you please.
}
labelPool.push(label);
};
};
var labelPool = new LabelPool;
$(".label").each(function (_, el) {
labelPool.accomodate(new Label($(el)));
});
Here's the fiddle.
Hope it helps.
Using js and jquery, you can find a basic collision engine based on left/top abs position and size of the label.
https://jsfiddle.net/Marcassin/79cco1oy/6/
Every time you want to add a Label, you check if the positionning is overlaping any existing div, in this case, you translate the new Label to position. This operation may not be the most beautiful you can find, there can be a long process time in case of lots of labels.
$(document).ready (function () {
addLabel (0, 8);
addLabel (0, 11);
addLabel (1, 10);
addLabel (2, 7);
});
function addLabel (newLeft, newTop)
{
var newLab = document.createElement ("div");
newLab.className = "label";
$(newLab).css({"left": newLeft+"%", "top": newTop + "%"});
var labels = $("#labelzone > div");
newLab.innerHTML = "00" + (labels.length + 1); // manage 0s
$("#labelzone").append (newLab);
var isCollision = false;
var cpt = 1;
do
{
isCollision = false;
$(labels).each (function () {
if (! isCollision && collision (this, newLab))
isCollision = true;
});
if (isCollision)
$(newLab).css({"left": (newLeft + cpt++) + "%",
"top": (newTop + cpt++) + "%"});
} while (isCollision);
}
function isInside (pt, div)
{
var x = parseInt($(div).css("left"));
var y = parseInt($(div).css("top"));
var w = $(div).width () + borderWidth;
var h = $(div).height ();
if (pt[0] >= x && pt[0] <= x + w &&
pt[1] >= y && pt[1] <= y + h)
return true;
return false;
}
function collision (div1, div2)
{
var x = parseInt($(div1).css("left"));
var y = parseInt($(div1).css("top"));
var w = $(div1).width () + borderWidth;
var h = $(div1).height ();
var pos = [x, y];
if (isInside (pos, div2))
return true;
pos = [x + w, y];
if (isInside (pos, div2))
return true;
pos = [x + w, y + h];
if (isInside (pos, div2))
return true;
pos = [x, y + h];
if (isInside (pos, div2))
return true;
return false;
}
Here's another implementation of collision detection close to what you asked for. The two main goals being:
move vertically more than horizontally (because boxes are wider than tall)
stay within a reasonable range from the origin
Here goes:
function yCollision($elem) {
var $result = null;
$('.label').each(function() {
var $candidate = $(this);
if (!$candidate.is($elem) &&
$candidate.position().top <= $elem.position().top + $elem.outerHeight() &&
$candidate.position().top + $candidate.outerHeight() >= $elem.position().top) {
$result = $candidate;
console.log("BUMP Y");
}
});
return $result;
}
function xCollision($elem) {
var $result = null;
$('.label').each(function() {
$candidate = $(this);
if (!$candidate.is($elem) &&
yCollision($elem) &&
yCollision($elem).is($candidate) &&
$candidate.position().left <= $elem.position().left + $elem.outerWidth() &&
$candidate.position().left + $candidate.outerWidth() >= $elem.position().left) {
$result = $candidate;
console.log("BUMP X");
}
});
return $result;
}
function fuzzyMoveY($elem, direction) {
var newTop = $elem.position().top + $elem.outerHeight() / 4 * direction;
// stay in the canvas - top border
newTop = (newTop < 0 ? 0 : newTop);
// stay in the canvas - bottom border
newTop = (newTop + $elem.outerHeight() > $("#labelzone").outerHeight() ? $("#labelzone").outerHeight() - $elem.outerHeight() : newTop);
// stay close to our origin
newTop = (Math.abs(newTop - $elem.attr("data-origin-top")) > $elem.outerHeight() ? $elem.attr("data-origin-top") : newTop);
$elem.css({'top': newTop});
}
function fuzzyMoveX($elem, direction) {
var newLeft = $elem.position().left + $elem.outerWidth() / 4 * direction;
// stay in the canvas - left border
newLeft = (newLeft < 0 ? 0 : newLeft);
// stay in the canvas - right border
newLeft = (newLeft + $elem.outerWidth() > $("#labelzone").outerWidth() ? $("#labelzone").outerWidth() - $elem.outerWidth() : newLeft);
// stay close to our origin
newLeft = (Math.abs(newLeft - $elem.attr("data-origin-left")) > $elem.outerWidth() ? $elem.attr("data-origin-left") : newLeft);
$elem.css({'left': newLeft});
}
function bumpY($above, $below) {
if ($above.position().top > $below.position().top) {
$buff = $above;
$above = $below;
$below = $buff;
}
fuzzyMoveY($above, -1);
fuzzyMoveY($below, 1);
}
function bumpX($left, $right) {
if ($left.position().left > $right.position().left) {
$buff = $right;
$right = $left;
$left = $buff;
}
fuzzyMoveX($left, 1);
fuzzyMoveX($right, -1);
}
$('.label').each(function() {
$(this).attr('data-origin-left', $(this).position().left);
$(this).attr('data-origin-top', $(this).position().top);
});
var yShallPass = true;
var loopCount = 0;
while (yShallPass && loopCount < 10) {
yShallPass = false;
$('.label').each(function() {
var $this = $(this);
$collider = yCollision($this);
if ($collider) {
bumpY($this, $collider);
yShallPass = true;
}
});
loopCount++;
}
console.log("y loops", loopCount);
var xShallPass = true;
var loopCount = 0;
while (xShallPass && loopCount < 10) {
xShallPass = false;
$('.label').each(function() {
var $this = $(this);
$collider = xCollision($this);
if ($collider) {
bumpX($this, $collider);
xShallPass = true;
}
});
loopCount++;
}
console.log("x loops", loopCount);
This is not production code obviously but please report back if it helps.
I have a 2 column layout. The left column is way longer than the sidebar. I want the sidebar only to stick when its bottom reaches the bottom of the browser window. So the user can continue to scroll down the left column content while the right sidebar sticks.. how use jquery and javascipt
$(function() {
var $window = $(window);
var lastScrollTop = $window.scrollTop();
var wasScrollingDown = true;
var $sidebar = $("#sidebar");
if ($sidebar.length > 0) {
var initialSidebarTop = $sidebar.position().top;
$window.scroll(function(event) {
var windowHeight = $window.height();
var sidebarHeight = $sidebar.outerHeight();
var scrollTop = $window.scrollTop();
var scrollBottom = scrollTop + windowHeight;
var sidebarTop = $sidebar.position().top;
var sidebarBottom = sidebarTop + sidebarHeight;
var heightDelta = Math.abs(windowHeight - sidebarHeight);
var scrollDelta = lastScrollTop - scrollTop;
var isScrollingDown = (scrollTop > lastScrollTop);
var isWindowLarger = (windowHeight > sidebarHeight);
if ((isWindowLarger && scrollTop > initialSidebarTop) || (!isWindowLarger && scrollTop > initialSidebarTop + heightDelta)) {
$sidebar.addClass('fixed');
} else if (!isScrollingDown && scrollTop <= initialSidebarTop) {
$sidebar.removeClass('fixed');
}
var dragBottomDown = (sidebarBottom <= scrollBottom && isScrollingDown);
var dragTopUp = (sidebarTop >= scrollTop && !isScrollingDown);
if (dragBottomDown) {
if (isWindowLarger) {
$sidebar.css('top', 0);
} else {
$sidebar.css('top', -heightDelta);
}
} else if (dragTopUp) {
$sidebar.css('top', 0);
} else if ($sidebar.hasClass('fixed')) {
var currentTop = parseInt($sidebar.css('top'), 10);
var minTop = -heightDelta;
var scrolledTop = currentTop + scrollDelta;
var isPageAtBottom = (scrollTop + windowHeight >= $(document).height());
var newTop = (isPageAtBottom) ? minTop : scrolledTop;
$sidebar.css('top', newTop);
}
lastScrollTop = scrollTop;
wasScrollingDown = isScrollingDown;
});
}
});
SeeDemo
i have this error when scroll top
i wanted this style