Background:
I'm helping an old friend who has a mixed media slideshow, and one of the slides is an iframe embed of a lytro camera image (it's interactive and you can click or tap on mobile to change the focus).
Issue:
The issue that I'm having is that when you interact with the iframe, it steals keyboard focus on desktops and that prevents the arrow keys from allowing you to change slides.
What I've tried:
My main attack angle on this had been trying to use jquery to set a timer that periodically sets focus on the parent document, to remove focus from the iframe and allow the keystrokes to be captured properly. I've noticed that if I click anywhere outside of the iframe then I can use the arrow keys properly.
Here's my jquery code, along with comments about why I tried each method. Unfortunatly nothing has worked (I've also tried including the lytro image with an embed tag instead of the iframe tag with no change in results).
<script>
//make sure body maintains focus, so that swipe and arrows still work
function focusit(){
$('#focushere').focus(); // this is a div on the main page that I tried to set focus to
$('body').focus(); // tried moving focus to the body
$('embed').blur(); // tried bluring the embed
$('iframe').blur(); // tried bluring the iframe
$('body').click(); // tried faking a click on the body
$('#focushere').click(); //tried faking a click on a element
$(document).click(); // tried click on document
$(document).focus(); //tried setting focus to document
}
setTimeout(focusit, 100);
</script>
Your issue seems to be two-fold.
You are using setTimeout which will only run your callback once. I think you mean to use setInterval, which will repeatedly run the callback.
You can't set focus to document using the focus method natively or in jQuery. In order to restore focus to the body, you should call the blur method on the currently active element using document.activeElement.
Example:
function focusit(){
if(document.activeElement)
{
document.activeElement.blur();
}
}
setInterval(focusit, 100);
CodePen Demo
Related
I'm working on a note-taking app that uses CKEditor's inline mode to expose dynamically created editable divs. (I'm using CKEditor version 4.5.8.)
When using the inline editor, you can click your mouse away from the div to leave editing mode, which results in the following behavior changes:
The blue highlight around the div disappears
The blinking cursor disappears
Keypresses are no longer "typed" into the div (ie. the editor is now inactive).
But I can't figure out how to escape editor focus (ie. reproduce the above changes) without requiring the user to physically click the mouse. Here's what I've tried so far:
Called Jquery .blur() on the inline-editable element: This visually removes focus and CKEDITOR.currentInstance becomes null; but keypresses still cause characters to be added to the div, which re-activates focus.
Called Jquery .removeClass('cke_focus') on the inline-editable element - no visible effect.
Called Jquery .click() or .focus() on other elements on the page - no visible effect.
Called CKEDITOR.currentInstance.focusManager.blur() - no visible effect.
Called CKEDITOR.currentInstance.container.fire('blur') - no visible effect.
Called CKEDITOR.currentInstance.element.fire('blur') - no visible effect.
Called CKEDITOR.currentInstance.destroy() - it looks like the editor automatically re-initializes after destruction due to the contenteditable="true" attribute, or something like that. At any rate the div retains focus and continues to trap keypresses.
All I want is to recreate what happens when you click away from an inline editing div: the focus indicators disappear, and keypresses no longer add text to the div. Any ideas how I can accomplish this? Thanks in advance!
The trick was to combine the blur with removing all selection ranges that you currently have:
CKEDITOR.instances.editor1.on( 'contentDom', function() {
CKEDITOR.instances.editor1.document.on('keydown', function(event) {
if (event.data.getKey() == 27) {
$(CKEDITOR.currentInstance.element.$).blur();
window.getSelection().removeAllRanges();
}
});
});
And a working example:
https://jsfiddle.net/bwuhp14s/
I'm using curtain.js and would like to keep a DIV (which holds navigation) visible at all times except for when the user is looking at the very first panel, i.e. at the top of the page.
Currently the DIV resides within panel two
I'm thinking perhaps of using the hash change as you scroll through the page to trigger an append to the body. Curtain.js creates an individual URL for each panel and the URL changes each time a panel is brought into view.
I can append the div to the body (below) but I need to work out when to do this but I am unsure how? Could anyone help me out?
$("body").append($('.nav-wrap'));
you can use onhashchange event:
The hashchange event fires when a window's hash changes
$(window).bind('hashchange', function() {
$("body").append($('.nav-wrap'));
})
You can use JQuery to bind the Event
$(window).bind('hashchange', function(){ ... });
And add some workarounds for when it doesn't have the onhashchange event.
jQuery - hashchange event
Ok well instead of using some hacky solution, after much digging around in the plugin's file, I just added:
$("body").append($('.nav-wrap'));
to the setHash function on line 491. Works a treat.
I have an image+text slider with recent blogposts which loop through the recent posts whilst a vistor keeps looking at a certain page.
You can see all the code on http://jsfiddle.net/GsgPM/16/
It is about the big image + text slider where it doesn't fire.
THe event does fire on the pink button.
Does not compute for me really... why does it work for the one, and not for the other?
Now I want to redirect people to the right blogpost with an onclick event on the containing div(slider) with the black borders.
The only puzzling thing is, the click event doesn't fire, nor does the cursor get changed to the right image(a hand) as defined in the css stylesheed, but the 1px border does get added.
On a test div, in my code on http://jsfiddle.net/GsgPM/16/ below my trouble code it does fire.
On another page of my blog I have no issues at a ll with the click event.
when I view the code changes in google chrome inspect elements window the click event does get transported on the div changes.
JSLint shows no errors, my console doesn't show any errors either. The entire event simply doesn't fire.
Who knows what the underlying cause is for this problem?
The problem is the shadow div. When you click on your slider, the click is registered on the div with id="shadow". Try to remove that div, and then it works. If you need that div, you have to make sure it is below the slider divs.
In your code you have
onclick="window.alert('Hello Raxacoricofallapatorius'
your missing a ); so it would be
onclick="window.alert('Hello Raxacoricofallapatorius');
A more Jquery way to react to click on img is to use on
$('#smallphotos div').on('click','img',function() {
alert('here');
});
to further this you could store the target on a data attribute like
<img src="http://www.freedigitalphotos.net/images/gal_images/av-_50.jpg" title="test2" data-target="www.google.com" />
which could then redirect your page like so.
$('#smallphotobox').on('click','#smallphotos div',function() {
window.location.href=$(this).data('target');
});
Also #slider is in the way you will notice i removed it and everything works.. try setting its z index to be behind the rest.
NOTE this wont work on jsfiddle due to restrictions.
fiddle
I have a silly (and hopefully easily fixed) problem, which I will now attempt to describe.
The scenario-> I am trying to create a context menu using HTML / CSS / JS. Just a DIV with a high z-order that appears where a user right-clicks. Simple, and that portion works. The portion which does not is my attempt to make the menu disappear if the user clicks somewhere where a context menu is not supported; I am attempting to achieve this end with a general function in the BODY tag that fires onclick. Since the BODY tag is given a z-order of -1, and any other tags which might trigger the context menu to appear are given a higher z-order value, my hope was that if I right-clicked an element with a z-order of, say, 3, then it would fire the showMenu() function; instead, it appears that it does this, as well as passes the event to the underlying BODY tag, which causes the menu to become hidden again.
As you might imagine, it is incredibly frustrating. Does anyone know how to make prevent events from being passed down? (The INPUT button is what you may want to look at, the A anchor is something similar, but not coded to work just yet).
Here's the HTML code:
http://pastebin.com/YeTxdHYq
And here's my CSS file:
http://pastebin.com/5hNjF99p
This appears to be a problem with IE, Firefox, and Chrome.
A lot of DOM events "bubble" from the bottom object up through container objects, which means they'll eventually reach the body. But you can stop this - try adding the following code to the click handler on your element:
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
...where e is the variable you already have in your function representing the event object.
event.stopPropagation(); should work in modern browsers, but the old IE way was event.cancelBubble = true; - to be safe you can just do both (but as shown above check that .stopPropagation is defined before trying to call it).
With the above code added, if you click on the element your function will stop container objects (include the body) from seeing the click. If you click somewhere else your function isn't called so then the body will process the click.
There's more info about this at MDN and QuirksMode.org.
Note: I've ignored the z-order issue because in this case I think it is a non-issue - all elements are descendents of the body so (unless you stop it) I would expect events to bubble to the body regardless of z-order.
I have a .hover() action assigned to an element to hide/show something depending on the cursor being over it. The problem I am running into is that when the page loads and the cursor is OVER the element it doesn't register as being over because its not firing the mouseenter event.
Is there a another way to tell if the cursor is over a desired element?
Using the mouse position on page load you could call
var currentElement = document.elementFromPoint(x, y);
then if the element found at that position is the one with the hover event. You can trigger that hover event manually
$(currentElement).trigger('hover');
If you hide the element(s) until the page is done loading and then show them all at once, will your mouseover event now fire?
<div id='allmyelementsinhere' style='display:none'>
then use javascript to remove the display:none on page load.
I'm thinking that your mouseevent will fire as soon as you display the elements.
I also had this issue with next and previous navigation buttons that navigate between consistently designed pages.
A user would click next to go to the next page, and because their mouse was in the same position on the page load of the second page, they were able to click next again to continue navigating through the collection of pages. Essentially a convenient next/previous UI.
Except of course that the hover state didn't display on page load for the second and subsequent pages.
So I added a url parameter (action='next or action=prev) and then on load I put the next or previous button into the hover state if the relevant url parameter is present. If the user has somehow moved their mouse and isn't over the button then you do get a button incorrectly in it's hover state until the first mousemove event.
It's not perfect and it only suits this specific circumstance where a user is using a consistent UI within pages on your site, but as this sort of UI is a fairly common - especially in blogs/galleries I though I'd mention it.
Here is the jquery method to track mouse position starting from page load.
(function($) {
$.mousePos = {x: 0, y: 0};
var recordPos = function(e) {
$.mousePos.x = e.pageX;
$.mousePos.y = e.pageY;
};
$(document).mousemove(recordPos).mouseover(recordPos);
})(jQuery);
This will populate $.mousePos.x and $.mousePos.y as soon as the mouse starts to interact with the page.
Script to get mouse coordinates on load