I am developing a web application:
http://filebox.vt.edu/users/sharni/Radio/spectrum.html
Clicking on the help button pops up a resizeable help window. However, if the cursor moves outside of the dialog when resizing, the dialog stops resizing! Does anyone know how to prevent this from happening? Still, it is possible to resize the window by moving the cursor very slowly.
Thanks in advance!
Hey i got short solution for you:
Step 1: Create layer that will appears when user works with UI. That layer will cover canvas.
var coverLayer = $('<div>').appendTo("body").css({ "width" : "100%", "height" : "100%", "z-index" : "2", "background-color" : "rgba(124, 124, 124, 0.5)", "position" : "absolute" }).hide();
Step 2: Make layer visible only when user works with UI.
$(".ui-dialog").on( "resizestart dragstart" , function( event, ui ) {
coverLayer.show();
// here you can add some code that will pause webgl while user works with ui, so resizing and moving will be faster and smoother
});
$(".ui-dialog").on( "resizestop dragstop" , function( event, ui ) {
coverLayer.hide();
// here you unpause webgl
});
Step 3 (optional): Pause webgl while user works with UI. Couse if he does, he isn't probably interested in canvas, so you can make other stuff happening faster and smoother...
PS: You had same problem with dragging dialog, so I fixed this too simply with adding dragstart/dragstop. You can also add more events there.
EDIT:
Why that problem happen?
I guess its because of resize event. It is happening in some short periods and is responsible for element redraw (setting new width and height). I also think that it can detect if another event is triggered, then resize is not triggered anymore.
Now, because you are using webgl that eats a lot of javascript calculation power, then short periods for resize event are not short anymore. Since then, element is not redrawed that often as you want and mouse will appear futher from element which probably trigger some event that cause stop calling resize.
If you stop webgl, calling period will be short again, so it could prevent that problem, but I'm not very sure about that...
Related
I have 2 divs (left and right) and i want to scroll the left based on the right.
https://jsfiddle.net/3jdsazhg/2/
This works fine on desktop, but when i change to mobile, it's not smooth anymore...
This can be noticed very easily, by changing
_left.style.top = _content.scrollTop - (_content.scrollTop * ratioLeftRight) + 'px';
to
_left.style.top = _content.scrollTop + 'px';
Where it should act as a fixed positioned div
I would like to know the exact reason why this isn't smooth... I know that it's not the animation. Simple animation on the div is smooth, the issue comes up when it's based on scroll.
How can i make this animation smooth?
It's probably choppy because it's being fired ALOT when being scrolled, in fact i'm pretty sure IOS mobile pauses the javascript execution whilst the user is scrolling.
Instead I'd suggest using an interval, you could tweak the time between each interval to what feels good for your use-case.
Although it may seem intensive that it's firing this logic every X millisecond when using the scroll event you could be firing the event off hundreds of times per second, which is going to be far more intensive and noticeable to a user using a device with limit processing power.
(function () {
var interval = null,
//Currently set at 0.4 seconds, play with the code
//and change this value to see what works best for
//this use-case
time_between_interval = 400;
setInterval(scrollLogic, time_between_interval);
function scrollLogic () {
//The function body of what you're assigning
//to the scroll event.
}
//I have omitted clearing the interval but you would want to do that, perhaps on page change, or something.
//clearInterval(interval);
})();
I finally managed to think out a solution.
From my point of view, i'm guessing the mobile view fires the scroll event less often and because we are scrolling the wrapper, we first scroll the whole page and then scroll back with js the left part and because it's different from the desktop version, this issue becomes visible...
The solution was to change the left side to fixed position, and substract from the top instead of adding to it.
_left.style.top = -(_content.scrollTop * ratioLeftRight) + 'px';
Introduction
I'm using Semantic-UI's sidebar functionality, which gives you a button that triggers a sidebar that pushes the content from the left (in this case).
I want to unfold that same sidebar by hovering with the mouse on the left side. I realize there are several ways to do it (as these often do. Maybe just checking the X position of the mouse would work but that's beside the point); I chose to create a transparent div on the left side and make its :hover pseudo-class to trigger the sidebar:
// create sidebar and attach to menu open
$('.ui.sidebar').sidebar('attach events', '.toc.item');
// hover transparent div to trigger the sidebar too:
$('.sidebar-trigger').hover(function() {
$('.ui.sidebar').sidebar('show')
});
// hide() and show() the sidebar accordingly to use the sidebar:
$('.ui.sidebar').sidebar('setting', {
onShow: function() {
$('.sidebar-trigger').hide();
},
onHidden: function() {
$('.sidebar-trigger').show();
}
});
Problem
Now, it all works except for one occasion: when you don't stop moving the mouse as the sidebar opens. I've looked at $(document).on('transitionend', function(event) { ... } and that mouse effectively prevents the transition to finish.
Resources
I've put a blue background on my .sidebar-trigger and made a small video/gif so as to be clearer.
I moved the mouse like a crazy creature but with natural gestures the problem occurs as well.
I'm using Semantic-UI's guide on this thing: http://semantic-ui.com/modules/sidebar.html#/settings (I've also tried onVisible and onHide with no luck)
This is a OSX Yosemite 10.10.3 running Chrome 45.0.2454.101 (64-bit)
jsfiddle with the problem at hand
PS: It seems it might be an OSX Chrome bug?
I would try using one and mouseover:
$('.sidebar-trigger').one('mouseover', function() {
$('.ui.sidebar').sidebar('show')
});
Then, when it has finished animating, reattach the event:
$(document).on('transitionend', function(event) {
$('.sidebar-trigger').one('mouseover', function() {
$('.ui.sidebar').sidebar('show')
});
});
I think what is happening is that the hover event is getting called multiple times - every time the element is hovered, then goes over a child element, and then goes back over the hover element, and things are getting mixed up at some point. So you need to only call show if it's not already shown.
Here is a working example: Fiddle
I believe when the element was hovered, it was adding a classes 'uncover' and 'visible', and another called 'animating' which wouldn't fire until the mouse stopped moving. I changed the jQuery slightly to only add classes 'uncover' and 'visible', and it still animated okay. However, the body was pushing right too far by 175px, so I had to edit the class that was causing that (noted below) from 260px to 85px. This DOES get the menu acting properly though from my understanding.
$('.sidebar-trigger').mouseenter(function() {
$('.ui.sidebar').addClass('uncover, visible');
$('body').addClass('mleft175');
});
$('body').click(function() {
$('.ui.sidebar').removeClass('uncover, visible');
$('body').removeClass('mleft175');
});
and then add overriding class
.ui.visible.left.sidebar ~ .pusher
{
-webkit-transform: translate3d(85px, 0, 0);
transform: translate3d(85px, 0, 0);
}
Right now it is set to hide the menu when the body is clicked. Alternatively you can hide it when the mouse leaves the sidebar menu:
$('.ui.sidebar').mouseleave(function(){
$(this).removeClass('uncover, visible')
});
Ok, my first answer was (of course) way too much work for what it really needed. The onVisible seems to work perfectly. Was that not working for you? Demo HERE
Simply change 'onShow' to 'onVisible' in your sidebar setting:
$('.ui.sidebar').sidebar('setting', {
onVisible: function() {
$('.sidebar-trigger').hide();
},
onHidden: function() {
$('.sidebar-trigger').show();
}
});
As shown on the Semantic UI site, the onVisible fires when the animating starts. The onShow fires when the animating finishes. So what you were doing was hiding that blue / transparent bar when the animation was finally done (the .animating class noted in my previous answer), as opposed to when it starts. If you need further explanation please let me know.
Is there a way to reinitialize stellar.js on browser/window resize so that the element offsets get readjusted?
First of all, it sounds like you might be having an issue with horizontal alignment (assuming it's a vertical site). If so, it's likely that you only need to disable horizontal scrolling:
$.stellar({
horizontalScrolling: false
});
If this doesn't solve your issue, Stellar.js has an undocumented feature that allows you to refresh the plugin.
For example, let's assume you used Stellar.js like this:
$.stellar();
You can refresh it with the following:
$.stellar('refresh');
So, to refresh it on resize, you could do something like this:
$(window).resize(function() {
$.stellar('refresh');
});
Hopefully this should fix everything for you.
After a bit of sleuthing, I've figured this one out. In my case, I have 'slides', which contain my stellar elements, and they are sized to full width/height of the viewport. I needed to resize them for tablet orientation change.
$(window).resize(function(){
winHeight = $(window).height();
$("#scrollWrapper > div").height(winHeight);
// Find out all my elements that are being manipulated with stellar
var particles = $(window).data('plugin_stellar').particles;
// Temporarily stop stellar so we can move our elements around
// data('plugin_stellar') let's me access the instance of stellar
// So I can use any of its methods. See stellar's source code
$(window).data('plugin_stellar').destroy();
$.each(particles, function(i, el){
// destroy() sets the positions to their original PIXEL values.
// Mine were percentages, so I need to restore that.
this.$element.css('top', '');
// Once the loop is finished, re-initialize stellar
if(particles.length - 1 == i){
$(window).data('plugin_stellar').init();
}
});
});
If it doesn't matter that the elements get set to their original pixel values for left/top, then you can just call destroy & init one after the other:
$(window).data('plugin_stellar').destroy();
$(window).data('plugin_stellar').init();
If you instantiate stellar on an element (i.e., $("#element").stellar(); instead of $.stellar();) then replace "window" with your selector.
I also noticed odd offsets on mobiles that may be caused by the way Firefox/Chrome resizes the webview when scrolling down, when the location bar becomes visible again?
The answer to your question is in a section of the documentation: "Configuring everything":
// Refreshes parallax content on window load and resize
responsive: false,
So, this is false by default. To enable this, use .stellar( {responsive:true} )
The real question is... why is this disabled by default? It seemed to fix the problem I was noticing, except for iOS.
I'm having issue with VML (which I use as fallback for svg)
I use jQuery UI draggable to let user be able to move an element around. The problem occurs when I resize the image (which is a v:image) by changing the style attribute of height and width.
What happen at this point is that the element get stuck at the left top corner of it's container and cannot be dragged anymore.
A strange thing is that when I ask for the position (top, left) of the draggable element in the JavaScript console, I get value, and those values change when I click and drag - even though the element isn't visually moving...
Anyone run into this problem before?
Here's where I change then size of my element.
$($image)
.css({
'width' : zoomInPx_width + "px",
'height' : zoomInPx_height + "px"
});
The draggable is set pretty straight forward
$($image).draggable({
drag: function () { /*callback here*/ }
})
Finaly I manage to make this work.
Seems that VML crash on IE 8 when we change size of a draggable element. So, I had to destroy the element and recreate it from scratch when sliding occurs...
That's not really performant, but that's the only fix to work for me up here.
By the way, .detach() didn't work, you have to destroy it and recreate it from scratch.
You can get some info there too: http://www.acumen-corp.com/Blog/tabid/298/EntryId/26/Using-jqueryRotate-ui-draggable-and-resizable-images-in-IE7-IE8-and-any-other-browser.aspx
on my application I used this code:
var $cloned_image = $($image).clone().get(0);
$($image).remove();
// need add draggable again
$($cloned_image).draggable();
document.getElementById('k').appendChild($cloned_image);
$image = $cloned_image;
See the following fiddle:
[edit: updated fiddle => http://jsfiddle.net/NYZf8/5/ ]
http://jsfiddle.net/NYZf8/1/ (view in different screen sizes, so that ideally the image fits inside the %-width layouted div)
The image should start the animation from the position where it correctly appears after the animation is done.
I don't understand why the first call to setMargin() sets a negative margin even though the logged height for container div and img are the very same ones, that after the jqueryui show() call set the image where I would want it (from the start on). My guess is that somehow the image height is 0/undefined after all, even though it logs fine :?
js:
console.log('img: ' + $('img').height());
console.log('div: ' + $('div').height());
$('img').show('blind', 1500, setMargin);
function setMargin() {
var marginTop =
( $('img').closest('div').height() - $('img').height() ) / 2;
console.log('marginTop: ' + marginTop);
$('img').css('marginTop', marginTop + 'px');
}
setMargin();
Interesting problem...after playing around with your code for a while (latest update), I saw that the blind animation was not actually firing in my browser (I'm testing on Chrome, and maybe it was firing but I wasn't seeing it as the image was never hidden in the first place), so I tried moving it inside the binded load function:
$('img').bind('load', function() {
...
$(this).show('blind', 500);
});
Now that it was animating, it seemed to 'snap' or 'jump' after the animation was complete, and also seemed to appear with an incorrect margin. This smacks of jQuery not being able to correctly calculate the dimensions of something that hadn't been displayed on the screen yet. On top of that, blind seems to need more explicit dimensions to operate correctly. So therein lies the problem: how to calculate elements' rendered dimensions before they've actually appeared on the screen?
One way to do this is to fade in the element whose dimensions you're trying to calculate very slightly - not enough to see yet - do some calculations, then hide it again and prep it for the appearance animation. You can achieve this with jQuery using the fadeTo function:
$('img').bind('load', function() {
$(this).fadeTo(0, 0.01, function() {
// do calculations...
}
}
You would need to work out dimensions, apply them with the css() function, blind the image in and then reset the image styles back to their original states, all thanks to a blind animation that needs these dimensions explicitly. I would also recommend using classes in the css to help you manage things a little better. Here's a detailed working example: jsfiddle working example
Not the most elegant way of doing things, but it's a start. There are a lot more easier ways to achieve seemingly better results, and I guess I just want to know why you're looking to do image blinds and explicit alignment this way? It's just a lot more challenging achieving it with the code you used...anyways, hope this helps! :)