Force browser to keep focus on a specific element - html

I just finished a web app for iOS using HTML5 and CSS webkit animations.
Lets say I have element "A" which follows my finger when I drag anywhere on the screen. I have noticed some dropped frames when element A follows my finger. This is only noticeable on iPad. If I keep touching element A, it is A LOT better at following my touch move without dropping frames but if I touch anything else rather than element A and comeback to element A then element A drops frames big time trying to follow my finger as if browser lost focus on the element because I tapped some place else.
Is there a way to force the browser to keep the focus on element A so that it doesn't drop frames?
Thanks in advance

You can basically cancel the blur event by refocusing the element. Here's how to do it using jQuery:
$(document).ready(function () {
$(element).blur(function () {
var self = this;
setTimeout(function () { self.focus(); }, 20);
});
});

Related

How to keep fixed html element visible on bottom of screen when the soft keyboard is open on iOS Safari?

In a web page I have an input field and a div that is fixed to the bottom of the window (with these CSS properties: position:fixed; and bottom:0;
I made a Codepen to show what I'm talking about: https://codepen.io/anon/pen/xpQWbb/
Chrome on Android keeps the div visible even when the soft keyboard is open:
However, Safari on iOS seems to draw the soft keyboard over the fixed element:
(I should mention I'm testing on the iOS simulator on my Macbook, because I don't have a working iPhone)
Is there a way to make iOS Safari keep the element visible even when the soft keyboard is open, like how Chrome does it?
I recently ran in to this problem when creating a chat input that should stay fixed at the bottom of the page. Naturally the iOS keyboard displayed on top of the chat input. Knowing the exact keyboard height seems more or less impossible. I embarked on a quest to find a solid value to base my calculations on so i can manually position the chat input container above the keyboard. I wanted to find the actual "innerHeight" value, in other words the currently visible area of the webpage. Due to how the iOS keyboard works, the only way to get that value with the keyboard open seems to be to scroll to the very bottom of the page, and then take a sample of "window.innerHeight".
So, i set up an event listener on my input field on 'click' (since on 'focus' caused a lot of issues for me). This opens the keyboard, which takes a while, so after i set a timeout for 1000ms to make sure (hopefully) that my keyboard is fully open. After 1000ms i quickly scroll to the bottom of the page with javascript, save the value of "window.innerHeight" in this state, and scroll back to where i was. This gives me the actual height of the visible area on the screen.
It seems like the browser window is placed behind the keyboard until you scroll to the very bottom, in which case the whole window 'scrolls up' and the bottom is placed at the top of the keyboard view.
Once i have this value i use currently scrolled value (window.scrollY) plus the value i saved minus the height of my absolute positioned element to determine where to place it. I opted to also hide the input while scrolling since it's flicking around quite a bit. Another downside to this is that you get a quick flick of the page when it does the measurement at the bottom.
Another thing i couldn't solve was the variable height of the address bar. I just made the input a bit higher than i needed so it would have some "padding" at the bottom.
var correctInnerHeight = window.innerHeight;
var isFocused = false;
var docHeight = $(document).height();
var input = $('.myInput');
input.click(function(e){
isFocused = true;
input.css('position', 'absolute');
// Wait for the keyboard to open
setTimeout(function(){
docHeight = $(document).height();
var lastScrollPos = $(document).scrollTop();
// Scroll to the bottom
window.scroll(0, $(document).height());
// Give it a millisecond to get there
setTimeout(function(){
// Save the innerHeight in this state
correctInnerHeight = window.innerHeight;
console.log(correctInnerHeight);
// Now scroll back to where you were, or wish to be.
window.scroll(0, lastScrollPos);
fixInputPosition();
// Make sure the input is focused
input.focus();
}, 1);
}, 1000);
});
input.on('blur', function(){
input.css('position', 'fixed');
input.css('top', 'auto');
input.css('bottom', '');
isFocused = false;
});
$(window).scroll(function(){
fixInputPosition();
});
function fixInputPosition(){
if(isFocused){
var offsetTop = ($(window).scrollTop() + correctInnerHeight) - input.height();
offsetTop = Math.min(docHeight, offsetTop);
input.css('top', offsetTop);
input.css('bottom', 'auto');
}
};
body, html{
margin: 0;
}
html{
width: 100%;
height: 2000px;
}
.myInput{
position: fixed;
height: 30px;
bottom: 0;
width: 100%;
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type='text' class='myInput'>
Check out this thread, it talks about a work around that may be more feasible in terms of code. In brief it talks about using the height of the keyboard to move the content into view. All be it a bit hacky it may be difficult to pin down the exact height of the keyboard across devices.
Unfortunately, due to the nature of the IOs Safari keyboard it's not part of the browser viewport so cannot be referenced as you would do typical elements.
#Bhimbim's answer may a good shot too.
Regards,
-B
i experienced this before. What i did back then was :
Make a listener when keyboard is hit.
When keyboard is hit resize you webview's height with screen height - keyboard height.
To do this trick you need to make sure that you html is responsive.
I can show more code in the IOS side, if you're interested i can edit my answer and show you my IOS code. Thank you.
Hi again, sorry, i was mistaken, i thought you were creating apps with webview inside. If you still wanna do this by listening the keyboard i still have work around for you. It may not the perfect way, but i believe this will work if you want to try. Here my suggestion :
You still can have listener from webpage when the keyboard is up. You can put a listener on your textfield by jquery onkeyup or onfocus.
Then you will know when the input is hit and the keyboard will show.
Then you can create a condition in your java script to manipulate your screen.
Hope this give you an insight friend.
#Beaniie thank you !.
Hi Andreyu !. Yes correct, we can not know the keyboard height, not like my case with WebView, I can know the keyboard height through IOS code. I have another work around, not so smart, but might work. You can get the screen size and compare to array of IOS device screen size. Then you might narrowed down the keyboard height by surveying through IOS devices. Good luck friend.
Try using position:absolute and height:100% for the whole page.
When the system displays the keyboard,it plTaces it on top of the app content.
One way is to manage both the keyboard and objects is to embed them inside a UIScrollView object or one of its subclasses, like UITableView. Note that UITableViewController automatically resizes and repositions its table view when there is inline editing of text fields.
When the keyboard is displayed, all you have to do is reset the content area of the scroll view and scroll the desired text object into position. Thus, in response to a UIKeyboardDidShowNotification, your handler method would do the following:
1.Get the size of the keyboard.
2.Adjust the bottom content inset of your scroll view by the keyboard height.
3.Scroll the target text field into view.
Check the Apple developer's guideline to learn more:https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

Cursor/caret bleeding through overlay in IE

I am doing work on and existing website www.shopthethirdfloor.com. Using IE, if you click on the products menu, give focus to the search box and then scroll the search field under the menu overlay that pops up, the search field goes under the overlay, but the cursor continues to blink where the hidden input field is. This only happens in IE. The search and product display is an iframe also. I am thinking this is an ie bug/feature depending if you are a user or microsoft.
I work on the Internet Explorer team, and can assure you that we don't view this as a feature. It's a bug, plain and simple. I've added this question, and your site, to an internal ticket on the issue for the team to review during the next triage.
For the time being you could add a check for the document.documentMode, and apply a bit of functionality to prevent Internet Explorer from showing the caret over the top of unrelated elements. In the following code I use jQuery's $.fn.one method to attach a one-time-use handler during an element's .onFocus event, and then dispose of it during the window's .onScroll event:
if ( document.documentMode && document.documentMode < 12 ) {
$( document ).on( "focus", ":input", function ( event ) {
$( window ).one( "scroll", function () {
event.target.blur();
});
});
}
The results can be seen here: http://jsfiddle.net/yynsbrat/2/
I'll continue to work with the team on resolving this issue from our end, but until this I hope this approach is able to help you in the interim.

Is it possible to move a <video> element in the DOM without resetting it?

I'd like to create a <video> element within my DOM, and then move it to another position without interrupting the playing of that content.
Perhaps more broadly, is it possible to move any DOM element without disrupting attached events?
Some approaches include using CSS absolute positioning, but is there a way to actually update the DOM in a way that doesn't interrupt the playback?
Unfortunately not. The DOM doesn't really have a concept of move, you just have to detach and reattach. As soon as the DOM node is no longer rooted in a document, it loses its playing state.
You may be able to preserve it somewhat by storing it in JS and re-applying it, but that will probably introduce a little skipping.
As per a workaround, here's the code snippet that worked for me:
function beforeDOMMove() {
if (video.paused) {
const currentTime = video.currentTime
const canPlayListener = () => {
video.removeEventListener('canplay', canPlayListener)
video.currentTime = currentTime
video.play()
}
video.addEventListener('canplay', canPlayListener)
}
}

Hide partial div - toggle open on click

I know how to toggle an entire div, however I only want to hide all but the top 10% or top 100px, for example. And then when the div is clicked, the entire div opens.
I thought I saw this a while ago, but can't remember where.
Thanks.
$(document).ready(function() {
// hides the slickbox as soon as the DOM is ready
$('#slickbox').hide();
// toggles the slickbox on clicking the noted link
$('#slick-toggle').click(function() {
$('#slickbox').toggle(400);
return false;
});
});
Your code should be something in the lines of:
$(document).ready(function() {
// hides the slickbox as soon as the DOM is ready
$('#slickbox').animate({height: '20px'});
// toggles the slickbox on clicking the noted link
$('#slick-toggle').click(function() {
$('#slickbox').animate({height: '100%'});
return false;
});
});
Take a look the image on my home page, is this kind of what you want to do?
http://www.carsonshold.com/
I have it jet out when you hover over it, but that can easily be changed to a click. It somewhat complicated to do, and still isn't perfect in IE (the page loads and the clip isn't recognized until you hover over it).
It may be slightly different from what you want since I did this on an image rather than a div, so I needed to animate the clipping mask. The function I used is as follows:
var featureDuration = 300; //time in miliseconds
$('#featured-img').hover(function() {
$(this).animate({ left : "-164", clip: "rect(0px,384px,292px,0px)" },{queue:false,duration:featureDuration});
}, function() {
$(this).animate({ left : "17px", clip: "rect(0px,203px,292px,0px)" },{queue:false,duration:featureDuration});
});
If you want to animate the clip, you will need to insert this JS as well because it doesn't behave properly otherwise. http://www.overset.com/2008/08/07/jquery-css-clip-animation-plugin/
Take a look at the CSS in my code if you are unsure how I did the rest of it, or comment on here if you have any questions.
Cheers
Did this rather quickly, note it will only hide the bottom portion.
http://jsfiddle.net/loktar/KEjeP/
Simple toggle that changes the height, hiding the rest of the content within. Easy enough to animate as well, just modify the toggle functions to adjust the heights rather than adding a class.

Removing resize handlers on contentEditable div

I created a contentEditable div to use as a rich textarea. It has resize handlers around it that I'd like to get rid of. Any idea how I'd do this?
Edit: This appears to be happening because I am absolutely positioning the div, so Firefox adds an infuriating _moz_resize attribute to the element which I cannot turn off.
Just as a side note, you can disable Firefox's automatic resize handle feature by sending the (somewhat poorly-documented) enableObjectResizing command to the document:
document.execCommand("enableObjectResizing", false, false);
AFAIK, this can only safely be done once the document has loaded, and there's no way I know of to disable the grabber, which is a separate feature.
It looks like I'll be able to work around this by adding a wrapper div and absolutely positioning the wrapper and then making the inner div contentEditable.
In Chrome 39, these handles don't seem to exist, even if you wanted them to.
In Firefox, one can simply use execCommand, like ZoogieZork answered.
But in Internet Explorer this can't be turned off. It must be worked around.
In WYMeditor development, here's what I've found.
The following results in:
In IE, the resize UI shows up for a split second and then disappears. There seems to be no way for the user to use it.
Images are text selected on mouseup
Ability to drag images. In some browsers, they may have to be selected before dragging. As written in the previous item, a simple mouseup will result in an image being selected.
Images are selected using text selection and not "control selection" (that which provides the resize UI).
This is the best I could come up with after hours of very deep breaths. I think it is good enough if you really want to get rid of those handles.
In IE, Setting oncontrolselect to return false on the image, really does prevent those handles from appearing, and you can do it cleverly, by attaching the following handler to the mousedown event:
function (evt) {
var img;
function returnFalse() {
return false;
}
if (evt.tagName.toLowerCase() === "img") {
img = evt.target;
img.oncontrolselect = returnFalse;
}
}
It actually doesn't work completely well. The reason that it didn't work very well is that in order to begin a drag and drop operation on the image, one had to press and hold the mouse, without moving it, for a split second, and only then begin moving it for the drag. If one pressed the mouse and immediately began dragging, the image would remain in its place and not be dragged.
So I didn't do that.
What I did is the following. In all browsers, I used mouseup to text select the target image exclusively. In non-IE and IE11, synchronously:
function (evt) {
if (evt.target.tagName.toLowerCase() === "img") {
selectSingleNode(img); // In my case, I used Rangy
}
}
In IE 7 through 10, asynchronously:
function (evt) {
if (evt.target.tagName.toLowerCase() !== "img") {
return;
}
window.setTimeout(function () {
selectSingleNode(img); // In my case, I used Rangy
}, 0);
}
This made sure that after those handles show up, they disappear ASAP, because the image loses its "control selection" because that selection is replaced with a regular text selection.
In Internet Explorer 7 through 11, I attached a handler to dragend that removes all selection:
function (evt) {
if (evt.target.tagName.toLowerCase() === "img") {
deselect(); // I use Rangy for this, as well
}
}
This makes the handles that show up after drag and drop, disappear.
I hope this helps and I hope you can make it even better.
I just face that problem.
I tried document.execCommand("enableObjectResizing", false, false); but, the move icon was still appearing. What just fix my problem was just e.preventDefault() when onmousedown event occurs.
element.onmousedown = function(e){
e.preventDefault();
}
for IE11 (I havn't tested the older versions of IE, but I feel like it would work) you can add contenteditable="false" attribute to the img tag. This will prevent any re-sizing from being done while keeping drag and drop in place.
... just the best fix ever
<div contenteditable="true">
<label contenteditable="false"><input/></label>
</div>
or any html element that wraps your input/img
Works on IE11 like a charm
Have you tried adding the style
border: none;
to the div?