First, thanks in advance for any help.
Second, I would like to mention that I have looked at different questions related to this topic as well as read documentation for both animate() and scrollLeft() on MDN I think my question is actually more based on syntax rather than function usage and that is why the other questions have not been as helpful to me.
Now, on to the issue. I am attempting to modify javascript code that I have previously written so that one function can react to the viewport of any user.
On the HTML side, I have a table with one <tr> and 3 <td>'s. The 3 <td>'s are filled with a picture and info and when the user clicks on buttons below, the table scrolls itself to the appropriate content. The buttons work fine. The problem is actually that the images are bigger than the viewport (on any device) and so on initial page load, the image needs to be scrolled by a distance proportional to both the viewport and the asset size (I load different assets based on viewport also). The formula for scroll distance, I discovered, is
0.5( assetWidth ) - 0.5( viewportWidth ).
So, here is the JS I have come up with (this is all inside a jQuery(document).ready(function($){
var scrollDistance;
if ($('#interactive-row:visible').length == 0) {
//Viewport > 801px
var assetWidth = 1920;
console.log("bouta set scrolDistance");
scrollDistance = ( 0.5 * assetWidth ) - ( 0.5 * $( window ).width() );
} else {
//Viewport < 800px
var assetWidth = 1428;
scrollDistance = ( 0.5 * assetWidth ) - ( 0.5 * $( window ).width() );
}
//scroll to zero so that whne user goes "back" slider position is reset (w/o variable lastClick gets messed up)
$('.table-container').animate({
scrollLeft: 0
}, "slow");
console.log( "Scroll Distance is " + scrollDistance + " calculation is about to begin." );
//move slider to middle of SSI screen
$('.table-container').animate({
scrollLeft: += scrollDistance.valueOf()
}, "slow");
The problem (I believe) is on the second-to-last line at which point my intentions are to have the browser scroll to whatever number is inside scrollDistance.
Note: here is what firefox and chrome say: "SyntaxError: expected expression, got '+='[Learn More]"
Also, I have already tried using scrollDistance with out adding the .valueOf(). I put that on recently in case there was some sort of type issue in javascript that I wasn't aware of.
Feel free to take a look at this graphic to better understand what I am trying to do. Graphic of what browser should display
Thanks in advance for the help, I am new to Javascript and anything at all that you all can tell me (even just general pointers about how I write my code) is much appreciated!
Edit: It just occurred to me that it may also worth noting that my console.log() is not working at all but I could care less about that if the scroll starts working :D
Related
I am using jQuery ui resizable with an aspect ratio set to 16/9.
$(".select").resizable({
containment: "#container",
aspectRatio: 16 / 9,
grid: 1,
stop: function (e, ui) {},
});
I want to be able to drag the resizable element full width to match the container but if never quite reaches it see this image.
You should notice the gap far right.
Here is a working demo I am testing with.
https://output.jsbin.com/cimorikefu/2/
I want to be able to drag the element full width any suggestions?
What you encounter seems to be caused by combination of miscalculations in jQuery UI Resizable plugin. It's hard to label those as 'bugs': when it was written, the code worked just fine.
Some of those issues are covered in the ticket created 9 (!) years ago. The last message there was written 5 years ago, so there's little chance of fixing that; the world has moved on.
Here's the suspicious parts of the code (1.12 source is analyzed):
// in _mouseStart()
this.sizeDiff = {
width: el.outerWidth() - el.width(),
height: el.outerHeight() - el.height()
};
// ... in resize()
woset = Math.abs( that.sizeDiff.width + // ... )
This part seems to ignore the fact that elements might have different box-sizing models, always attempting to process those based on content-box - and take border width into account.
While the behavior of outerWidth() and width() has been corrected in jQuery 1.8, the corresponding adjustments didn't reach Resizable source in time. Now the PR prepared and listed in the linked ticket is no longer applicable (after the code has been refactored in ~1.10).
Still, there's more:
if ( woset + that.size.width >= that.parentData.width ) {
that.size.width = that.parentData.width - woset;
if ( pRatio ) {
that.size.height = that.size.width / that.aspectRatio;
continueResize = false;
}
}
// ...
if ( !continueResize ) {
that.position.left = that.prevPosition.left;
that.position.top = that.prevPosition.top;
that.size.width = that.prevSize.width;
that.size.height = that.prevSize.height;
}
In this case pRatio is set, which means whenever your resizing operation is about to make the resizable object the same size as container, its width is reset to the previous size. So if you move your mouse fast enough, the resizable element gets stuck way before the hitting the container's borders.
While the first issue here might be mitigated a bit by replacing border with outline when styling .ui-widget-content, the only way to fix the second part is to fix the plugin's code.
I need to know if the end of a div element is currently visible in the users' browser.
I tried something I saw on the web, but scrollTop() always gave me zero in my Browser. I read something about an issue in Chrome, but I didn't understand quite well.
jQuery(
function($) {
$('#flux').bind('scroll', function() {
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
alert('end reached');
}
})
}
);
My idea is the following:
1- User loads page and sees a Bar (sticky div at bottom visible page) with some information.
2- After scrolling a bit, and reaching the end of a div element, this bar will position there, after the div. This is the bar's original position
I wasn't really able to know when I was at the end of the div element. Eventually I found this code:
if ($(window).scrollTop() >= $('#block-homepagegrid').offset().top + $('#block-homepagegrid').outerHeight() - window.innerHeight) {
$('.hero-special-message').removeClass('hero-special-messege-scrolling');
} else {
$('.hero-special-message').addClass('hero-special-messege-scrolling');
}
});
I see that it's working, but I'm having a bit of trouble understanding what it does.
I know the following:
1. $(window).scrollTop();
this gives me the amount of pixels the user has scrolled, pretty self explanatory.
2. $('#block-homepagegrid').offset().top;
I THINK this is the distance between the start of the page and the start of the div. I know it's the current coordinates, but what is top exactly here?
3. $('#block-homepagegrid').outerHeight();
this gives the height of the element, I know there are 3, like
height(), innerHeight() and outerHeight(), if you want to take into
account border, margin, padding, which is the better to use?
4. window.innerHeight;
I understand this is what the user sees, but I'm having troubles understanding why does it matter for my situation.
Thanks!
You may be interested in the native JavaScript IntersectionObserver API. It automatically figures out what percentage of a given element is visible in the window and triggers callbacks based on that. So then you can do this:
function visibleHandler(entries) {
if (entries[0].intersectionRatio >= 1.0) {
// The whole element is visible!
} else {
// Part of it is scrolled offscreen!
}
}
const observer = new IntersectionObserver(visibleHandler, {threshold: 1.0});
observer.observe(document.getElementById('flux'));
Now, whenever the element with ID flux is 100% in view, it will trigger the visibleHandler. It will also trigger again if it's scrolled back out of view; that's why the function checks the ratio of visibility to see if it just hit 100% or just got reduced from 100%. You could be more fancy and use the observer entry's insersectionRect, which gives you the rectangle containing the visible portion of the element, and use that to determine top/bottom visibility.
I have a carousel (Owl Carousel) with vertically centered controls. Because of the structure, I have to absolutely position the previous and next arrow. Because the page is responsive, their position is dynamic. The size of the controls may also change.
I've written a function that runs on load and resize. It gets the height of the image and the height of the controls, subtracts the latter from the former, divides by two, and then uses that number as the controls' margin-top.
It works, but I'm questioning if I'm getting and using all the variables correctly. Does JavaScript read in order? Where it runs the first line, then the next, then the next... I'm strong in CSS but JS has always been a crutch.
Can I write this more efficiently?
function centerCarouselControls() {
var carouselImage = $('.carousel-card > img');
var carouselControls = $('.owl-nav > div');
var carouselHeight = carouselImage.outerHeight();
var controlHeight = carouselControls.outerHeight();
var controlMargin = (carouselHeight - controlHeight) / 2;
carouselControls.css('margin-top', controlMargin);
}
$('.carousel-card > img').load(centerCarouselControls);
$(window).on('resize', centerCarouselControls);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I feel like this might be the type of question that gets flagged on here for not being specific enough. If that's the case, could someone please point me to a community where this would be more appropriate? Thanks!
In some browsers your code works like firefox 51, but it is more complete code this:
carouselControls.css('margin-top', controlMargin + 'px');
im currently working on this site:
http://dingwangbag.com/
Unfortunately i still have a problem with the slideshow:
most browsers seem ok by now ( sometimes still a little flicker at the end but it shows up )
my HTML setup is like this
<content>
<gallery_item>
<image>
<image>
<image>
<gallery_item>
<gallery_item>
<image>
<image>
<image>
<gallery_item>
</content>
on document.ready a function is called that runs
this block of code for every image after it has been fully loaded
(basically getting the width of every image and adding it to the container width)
function show_image(image){
var $item = $(image.img);
img_width = Math.ceil(parseInt($item.width()));
gallery_width += img_width;
$("#content").width(gallery_width);
if(images_loaded === false){
$item.css("opacity",0);
$item.removeClass('offscreen');
$item.animate().animate({
opacity: 1
}, 2000, function() {
// Animation complete.
});
}
};
and this block is runs on resize
(".gallery_slides").each(function(i){
current_slide_item = $(this);
current_slide_item_width = 0;
$(this).find("img").each(function(){
current_slide_item_width += $(this).width();
});
gallery_width += current_slide_item_width;
});
$(".gallery #content").width(gallery_width);
simple right
its workin so far
but it seems to me that the scaling of the images result in some odd numbers wich sum up to a value that might be 1 or 2 px short
resulting in the last container not beeing positioned properly (all containers and images are floated left)
NOW where are these off numbers come from and how can i fix it
( i added 2px to the container width did help )
BUT
internet explorer 9 is doing something really special
by being somewhat reactive to scrolling and the mouse position
randomly showing or hiding images (even within the group) SOB
and i swear i have no hover or scroll functionality accociated with this in any way
so if anyone could have a look at it and hopefully help me this would be great
thanks in advance
Don't ceilit.
img_width = parseInt($item.width());
Also: you should update jQuery to 1.11.1 There have been bugs in the versions before.
I have a horizontally scrolling website, and I have a block that I want to stay in frame at all times as the user scrolls right. It looks perfectly smooth in webkit browsers, but is crazy jagged in Firefox and I don't really care about IEs.
function fixMyId(){
$('#myId').css({'margin-left': 150 + $(window).scrollLeft()});
}
function fixMyIdAlt(){
$('#myId').stop().animate({'margin-left': 150 + $(window).scrollLeft()}, 300);
}
And then I have it triggered on window scroll.
What would be a best way to average out the scrolling, so that maybe every so many seconds or pixels of scrolling it fires the function, or upon stopping the scrolling it animates the block into place? I tried playing with delay() but that doesn't do anything. And this one just looks stupid (plus I have no idea what the overhead of this kind of crunching is):
function fixMyIdStupid(){
window.scrollCounter++;
if(window.scrollCounter % 20 == 0) $('#myId').stop().animate({'margin-left': 150 + $(window).scrollLeft()}, 300);
}
So what do I do? setTimeout and setInterval may be required, but those always make my head hurt.
EDIT: Here's a jsfiddle of it in action: http://jsfiddle.net/xsxSq/
The #f0f square is the #myId.
I tried to do such things as well, problem is that the scroll event isn't fired as much as you want. A nice workaround was subscribing the calculation function to the mousemove event, so it triggers A LOT. But on the other hand, I came up with another solution.
Why not turn things around and ask yourself:
Lets make it a position:fixed object and calculate what happens on resize. Because you actually are trying to create a position-x:fixed; and a position-y:absolute;
I actually did the following for the opposite kind of thing. A block that has to be exactly in the middle of the x-document, but in the y it was fixed.
$(document).ready(function ()
{
replaceFixed();
$(window).resize(replaceFixed);
$('#content').ajaxSuccess(replaceFixed);
$(window).scroll(replaceFixed);
function replaceFixed()
{
var jEl = $('#centeredFixedContainer');
var winW = $(window).width();
var docW = $(document).width();
var scrL = $(window).scrollLeft();
var divW = jEl.width();
var result = 0;
// window bigger than the element
if(winW > divW)
{
result = -scrL + ((docW-winW)/2);
}
else
{
result = $('#mainContainer').offset().left - scrL;
}
jEl.css('left',result);
}
});
Copying this code will not give you the solution, but will indicate another way to look at your problem.