jQuery UI Resizable never reaches the full width with aspect set - javascript

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.

Related

How to properly use a variable to scrollLeft within the animate function

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

Using jQuery draggable() in a responsive environment…

I am working on a fairly typical image "reveal" effect using jQuery UI’s draggable() method; I’m having a lot of trouble making it work in a responsive environment:
http://codepen.io/ProfessorSamoff/pen/qEaNMM
As you’ll see, the reveal functionality works correctly at full size as well as when the browser window size is reduced. But the draggable handle doesn’t always snap to the proper position when the browser window is resized. (Although it does so when it’s clicked and dragged.)
Likewise, you’ll see that I have some commented code that checks against the browser window size:
if($(this).width() != width)
{
}
This works in order to get the draggable handle to the correct place when resizing the browser window, but it breaks the draggable functionality.
I have tried a few of the suggestions on Stack Overflow concerning draggable() and resizable(), but none of them work.
take a look here:
http://codepen.io/anon/pen/LEmgBP
javascript now appears in this way:
var $reveal = $(".reveal");
$reveal.draggable({
axis: "x",
containment: "parent",
iframeFix: true,
refreshPositions: true,
drag: function()
{
var position = $(this).position();
var parentWidth = $(this).parent().width();
var width = (position.left / parentWidth) * 100
$(".featured").width(width + "%");
}
});
$(window).resize(function() {
$reveal.css('left', $(".featured").width()+'px')
});
It's not elegant but it seems to work.
basically I did 2 things:
1) I've setted $(".featured") width with %
2) on windows resize I change the position of the cursor with
$reveal.css('left', $(".featured").width()+'px')
note: point 2) is a workaround but I didn't find any way to move the cursor programatically. Maybe using a library to emulate the drag event (like https://github.com/mattheworiordan/jquery.simulate.drag-sortable.js/blob/master/README.md) you could find something better

expanding container to content missing the 1%

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.

Choosing Parent Height With white-space:nowrap

So I have these DIVs which I have arranged to slide left an right inside of the parent.
See the following JSFiddle to see the design:
http://jsfiddle.net/StevP/C9WL7/
You can see that by adjusting the margin-left of the first child DIV by multiples of -100%, it's rather simple to correctly horizontally position the DIVs inside the parent. Therefore, it's very easy to animate.
Now, this brings me to my issue. I'm using jQuery to move them left and right. It works great. However, I'd like to choose which child the parent gets its height from.
I know, I can just add...
$('#parent').height($('.child:eq()').outerHeight());
...Which is what I have it currently doing. However, the contents of the children are likely to change causing them to resize (by animate) and, therefore, be cut off. So, having a set height isn't a possibility.
I need to use height:auto; on the parent and somehow cause it to ignore the heights of specific children. I can't for the life of me think of a way.
I don't want to use a timer and onresize/.resize() don't seem to work with my Chrome.
You could use jQuery to monitor the DOM subtree and adjust the height of your parent div in the callback like this:
$('.content').bind('DOMSubtreeModified', function(e) {
if (e.target.innerHTML.length > 0) {
$(".parent").height($(".content").height());
}
});
Here's a working jsfiddle: http://jsfiddle.net/9386d/
And a question explaining the dom subtree: jQuery watch for domElement changes?
jQuery docs for bind(): http://api.jquery.com/bind/
Well... To be perfectly honest I'm not really a huge fan of jQuery anymore so I feel bad offering this answer. It just feels so frik'n inefficient, but here is a solution that does three things: 1) it resizes the hight of the container on step and uses a CSS transition attribute for eye candy (works just as well without). 2) it sets the child height of all but the current child to 0 and uses overflow:hidden so they don't affect the flow of the document anymore. 3) it resets these children to automatic height on animation start so they are visible during transition. All I can say is "yuck", but it does work.
CSS
.child{
...
overflow:hidden;
}
jQuery
var animation_prefs = {
duration: 3000,
start: function() {
$('.child').height('auto');
},
step: function(now) {
var current_index = (Math.floor((now + 50) / 100) * -1);
$('#parent').height($('.child:eq(' + current_index + ')').outerHeight());
$('#parent').data('current', current_index);
},
complete: function() {
$('#parent').height('auto');
$('.child:not(:eq('+$('#parent').data('current')+'))').height(0);
}
}
$('.child:eq(0)').animate(
{
marginLeft:'-200%' //~ Move it back 2 children
},
animation_prefs
).animate(
{
marginLeft:'-100%' //~ Move it back 1 child
},
animation_prefs
).animate(
{
marginLeft:'-200%' //~ Move it back 2 children again
},
animation_prefs
);
Demo
http://jsfiddle.net/Gq4xs/show
Source
http://jsfiddle.net/Gq4xs/

change css on scroll event w/ requestAnimation Frame

I want to change the background color of in-viewport elements (using overflow: scroll)
So here was my first attempt:
http://jsfiddle.net/2YeZG/
As you see, there is a brief flicker of the previous color before the new color is painted. Others have had similar problems.
Following the HTML5 rocks instructions, I tried to introduce requestAnimationFrame to fix this problem to no avail:
http://jsfiddle.net/RETbF/
What am I doing wrong here?
Here is a simpler example showing the same problem: http://jsfiddle.net/HJ9ng/
Filed bug with Chromium here: http://code.google.com/p/chromium/issues/detail?id=151880
if it is only the background color, well why don't you just change the parent background color to red and once it scroll just change it to pink?
I change your CSS to that
#dad
{
overflow-y: scroll;
overflow-x: hidden;
width: 100px;
height: 600px;
background-color:red;
}​
I remove some of you Jquery and change it to this
dad.bind('scroll', function() {
dad.css('background-color', 'pink');
});
And I remove this line
iChild.css('backgroundColor', 'red');
But is the Red color it is important that won't work for sure http://jsfiddle.net/2YeZG/5/
I like Manuel's Solution.
But even though I don't get what you're exactly trying to do, I want to point out a few things.
In your fiddle code, I saw that you included Paul Irish's Shim for requestAnimationFrame.
But you never use it.
(It's basically a reliable setTimeOut, nothing else) it's from frame based animations.)
So since you just want to change some CSS properties, I don't see why you would need it. Even if you want transitions, you should rely on CSS transitions.
Other than that your code could look something like
dad.bind('scroll', function() {
dad.css('background-color', 'pink');
eachElemNameHere.css('background-color','randomColor');
});
Also you should ideally not use something like that if you can help it. You should just add and remove class names and add all these properties in your CSS. Makes it work faster.
Also, again I don't quite get it, but you could use the jQuery function to find out each elements' position from the top to have better control.
Your problem seems to be that you only change the background color of the elements which have already been scrolled into view. Your code expects that the browser waits for your code to handle the scroll event before the browser redraws its view. This is most probably not a guarantee given by the HTML spec. That's why it flickers.
What you should do instead is to change the elements which are going to be scrolled into view. This is related to off screen rendering or double buffering as it is called in computer games programming. You build your scene off screen and copy the finished scene to the visible frame buffer.
I modified your first JSFiddle to include a multiplier for the height of the scroll area: http://jsfiddle.net/2YeZG/13/.
dad.bind('scroll', function() {
// new: query multiplier from input field (for demonstration only) and print message
var multiplier = +($("#multiplier")[0].value);
$("#message")[0].innerHTML=(multiplier*100)-100 + "% of screen rendering";
// your original code
var newScrollY = newScrollY = dad.scrollTop();
var isForward = newScrollY > oldScrollY;
var minVal = bSearch(bots, newScrollY, true);
// new: expand covered height by the given multiplier
// multiplier = 1 is similar to your code
// multiplier = 2 would be complete off screen rendering
var newScrollYHt = newScrollY + multiplier * dadHeight;
// your original code (continued)
var maxVal;
for (maxVal = minVal; maxVal < botsLen; maxVal++) {
var nxtTopSide = tops[maxVal];
if (nxtTopSide >= newScrollYHt) {
break;
}
}
maxVal = Math.min(maxVal, botsLen);
$(dadKids.slice(minVal, maxVal)).css('background', 'pink');
});
Your code had a multiplier of 1, meaning that you update the elements which are currently visible (100% of scroll area height). If you set the multiplier to 2, you get complete off screen updates for all your elements. The browser updates enough elements to the new background color so that even a 100% scroll would show updated elements. Since the browser seldom scrolls 100% of the area in one step (depends of the operating system and the scroll method!), it may be sufficient to reduce the multiplier to e.g. 1.5 (meaning 50% off screen rendering). On my machine (Google Chrome, Mac OS X with touch pad) I cannot produce any flicker if the multiplier is 1.7 or above.
BTW: If you do something more complicated than just changing the background color, you should not do it again and again. Instead you should check whether the element has already been updated and perform the change only afterwards.

Categories