Element.focus() + css animation positioning issue in IE 10+ - javascript

Came across a strange behavior in IE 11 and wanted to see if anyone else has seen this. I have an input element inside a container with height: 0px; and overflow: hidden;. Another element triggers an active class on the container to give it some height, with a CSS transition. The same trigger calls focus() on the input.
In IE 10 and 11, it seems as though calling focus() during a CSS animation causes the input element to freeze in it's position at that stage in the animation.
Here is a fiddle
Notice, in IE 10+, the input cursor is off vertical center. If you remove the transition from the CSS, it will be centered.
Anyone else seen this or have a better solution?

For now, my solution is to wrap the focus() call in a setTimeout matching the CSS animation duration, to ensure the focus won't happen until the field reaches the end of the transition. Not ideal, since it mixes CSS and JS values independently, but it works for now.

It is known IE issue - the cursor stay in the same position before the input transition. The solution is as #steve wrote - put a focus only after the transition is ended.
You can use this angular solution:
angular.module('my.directive')
  .directive('custom-auto-focus', function ($timeout) {
    return {
      link: function (scope, elm) {
        $timeout(function() {
          elm[0].focus();
        }, 350);
      }
    };
  });
More information here:
Cursor in wrong position in IE11 after CSS transform w/ transition

Related

IE, and iframe.elementFromPoint not passing event

Update: Fiddle Demonstration -- http://jsfiddle.net/7tfbtso6/2/ -- Most of the settings work in chrome and firefox, but the only one that works in IE is Left-align: 105px. I do have overflow set to hidden on html and body, but this makes no difference. IE will not work if the element is not visible on screen. And overflow: visible on html and body give the effect of auto and no effect on the problem here.
My site uses two contentEditable divs.
#rInput is part of the document.
#rSyntax is part of an iframe under (z-index) #rInput.
In every browser I've tried so far, except IE (I'll get to that in a moment.), I'm able to determine what element is contained within the iframe using elementFromPoint().
In IE's case, this is only possible if they're not overlapping which isn't possible because a secondary purpose, as the name implies, is to provide syntax-highlighting.
The IE IFrame has to be visible, on screen, not obstructed by any objects. I've tried display: none;, visibility: hidden, and pushing it down in a div with overflow: hidden, but all of these attempts cause it not to work. I've also tried setting the height and width to small proportions.
If any of these could work, I could use two copies of rSyntax, one on top (z-index), hidden somehow, for mouse events and one for syntax highlighting.
Most of these solutions work in every browser but IE. The IE box simply demands that it be on top.
"Flickering" it with css (display, visibility, pointer-events) seems awfully hacky (and just plain awful). I haven't really tried to implement it because it seems like a last resort.
The problem is further complicated because I'm trying to capture clicks and mouseovers, for different purposes (clicks for finding content, mouseovers for tooltips--created with a div mimicking attr("title").
I've briefly tried placing the iframe on top (z-index) of the div, but there's no way to intercept the clicks and pass to the lower object because it runs in to the same problem.
Here's the script I'm using to get the objects, partly in case it's useful to anyone.
$(document).on("mousemove", "#rInput", function (e) {
$element = $(document.getElementById('frSyntax').contentDocument.elementFromPoint(e.pageX+$("#rInputContainer").scrollLeft()-10,e.pageY+$("#rInputContainer").scrollTop()-12));
if ($element.is("span") && $element.attr("title") && $element.attr("title").length) {
$("#syntip").text($element.attr("title"));
$("#syntip").css({"top": e.pageY+10, "left": e.pageX, "display": "inline-block"});
} else {
$("#syntip").hide();
}
});
I have considered transparency, and that works for this element, because it's small, but I use a similar setup with a large element that takes up more than 50% of the screen, there would be problems.
After many frustrating efforts, I concluded that pushing the top (z-index-wise) element offscreen was the only solution for IE/Edge. Flickering it with display: none causes some properties I needed, like width, to not be accurate.
Just make sure you push it farther than the element will ever be. My application is sidescrolling so I merely needed to place the css top to something like 2000.

Javascript Slide-In Onload

So I'm trying to have a div slide in on pageload. It has an id of "#crazyslide" and is absolutely positioned to the right -800px in the css.
So I used this code in the head:
<script type="text/javascript">
$(document).ready(function() {
$("#crazyslide").animate( { right: '0px' }, 2000 );
});
</script>
Shouldn't this work?
No, you can't hide it off the edge of the screen. Devices like mobiles will let people scroll past the edge and it will look bad.
I recommend using this example of hiding and showing it with javascript.
http://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_hide_show
Yes it should. I just tested with your exact code, and it worked fine. There are ways to prevent a parent element from showing scroll bars for offscreen content.
Check to be sure your div is properly named: (console.log($("#crazyslide"));
Be sure a parent element's css isn't preventing the div from being
shown at all, such as a strange body width or something.
Be sure the div has content, and a set width.
*This turned out to be a load order issue where jquery was not yet defined when the animation code was called.

Force browser to trigger reflow while changing CSS

I am building non-jQuery responsive image slider based on CSS3 transitions.
The structure is simple: a viewport and inside relatively positioned UL with left floated LIs.
I am facing a problem in such situation:
User clicks "prev" arrow.
JS appends proper LI before currently displayed LI node.
For now UL has set CSS transition as none 0s linear to prevent animation changes. In this moment I decrease UL CSS left value by slider width (let's say: from 0px to -1200px) to make view the same as it was.
Now I am changing UL's transition property to all 0.2s ease-out.
Now I am changing UL's left property to trigger CSS3 animation. (let's say: from -1200px to 0px).
What is the problem? Browser simplifies changes and does not make any animations.
Stoyan Stefanov wrote about reflow problem at his blog here, but in this case trying to force a reflow on element doesn't work.
This is a piece of code doing this (I skipped browser prefixes for simplification):
ul.style.transition = 'none 0s linear 0s';
ul.style.left = '-600px';
ul.style.transition = 'all 0.2s ease-out';
ul.style.left = '0px';
Here is fiddle to see problem in action: http://jsfiddle.net/9WX5b/1/
Requesting the offsetHeight of an element does everything nicely. You can force a reflow using this function and passing it the element that styles have been changed on:
function reflow(elt){
console.log(elt.offsetHeight);
}
And call this where reflows are needed. See this example: http://jsfiddle.net/9WX5b/2/
EDIT: recently needed to do this, and wondered if there was a better way than to console.log it. You can't just write elt.offsetHeight as it's own statement, as the optimizer (Chrome's, at least) will not trigger a reflow because it is just accessing a property with no getter set, no need to even evaluate it. So, AFAIK the cheapest way to do this is void(elt.offsetHeight), as it does not know for sure if void has side effects or not. (could be overridden or something, idk).
function reflow( element ) {
if ( element === undefined ) {
element = document.documentElement;
}
void( element.offsetHeight );
}
It works OK with Chrome and FF, and seems to be the simplest and most portable way to do it ATM.

Mootools slide not working in dropdown

I have an html5 page with a dropdown menu using mootools. It's working if I use the hide() and show() functions. But, I want the menu's to slide in and out, like this:
var m = e.getElement(".dropdown-menu, .sidebar-dropdown-menu");
if (e.hasClass('active')) {
m.hide();
e.removeClass('active');
} else {
m.show();
e.addClass('active');
}
Instead of hide and show I want slideIn and slideOut:
var m = new Fx.Slide(e.getElement(".dropdown-menu, .sidebar-dropdown-menu"));
if (e.hasClass('active')) {
m.slideOut();
e.removeClass('active');
} else {
m.slideIn();
e.addClass('active');
}
Working example: http://jsfiddle.net/wzzeZ/
Not working: http://jsfiddle.net/37V53/1/
It's not throwing errors; where do I look to fix it?
There are a few things going on here.
First of all, you're not seeing any errors because there are none. If you litter the code with console.log() calls, they all run.
It's a style issue that's preventing the menus from displaying.
The FX.Slide Class in Mootools doesn't seem to explicitly set the 'display' property of the element you're sliding to block. You still need to call .show() for it to work.
Next, if you check out the docs for FX.Slide, you'll notice that it creates a wrapper element to do the slide effect (the container is needed for the height animation, overflow: hidden, etc.)
Unfortunately that seems to be messing with the positioning of the menu, which is positioned relatively to its containing element - but the containing element has height and overflow: hidden styles which then hide the menu (not to mention, even if you could see it, it's in the right place).
To see what I'm talking about check out this updated Fiddle here: http://jsfiddle.net/37V53/2/
If you run that in Firefox with Firebug, and you hover your cursor over the element that's logged to the console, you'll see Firebug's blue hilight appearing where your element actually is being displayed - in the middle of the window, and hidden from view.
This is a combination of assumptions made in the MooTools Classes you're using working against each other; You'll probably be better off writing your own (simple) slide-out script using FX.Tween rather than FX.Slide.
I created a sample of how to do this based on the original Fiddle (that works) - http://jsfiddle.net/LkLgk/
Trick is to show the element to the browser but not the user (by setting visibility: hidden before display: block, grab the height, set height to 1px, visibility back to visible, then tween the height to the previously detected value.
Hope that points you in the right direction; remember, when in doubt, console.log everything!

CSS Overflow Property / Div mouseover problem - IE & Chrome

I have a div inside a main div having following properties:
#inner {
width:149px;
overflow:auto; //Note this
margin:35px 0 0 0;
height:575px;
display:none;
}
on main div I am calling two functions on two events (onmouseover & onmouseout). On mouseover inner div displays with scrollbars. It seems whenever the mouse is moved off the scrollbar into the DIV after it being scrolled down, the DIV returns to the top.
You can find the code here: [a link] http://www.designworks.com.pk/example/
Please test in IE & chrome when we scroll down the DIV returns to the top. Please help me to solve this issue.
I don't have time to fully investigate it at the moment, but I believe it is caused by one of the strange behaviors of mouseover/mouseout that occur with child elements.
If jquery is an option, using hover deals with a lot of these issues and seems to fix your problem:
http://jsfiddle.net/ZJBXX/13/
EDIT: Note this is working off of the fiddle posted in the comments and may not be exactly the same as your current code.

Categories

Resources