Capturing keyboard shortcuts in an iframe: focusing? - focus

I'm creating an IFrame to house an app that wants to listen to keypress events -- is there any way to give this iframe focus, so keypresses get passed to its own handlers, and not to the main page's? (Clicking within the iframe works, but makes for an awful user-interface...)
Thanks!
-B

calling focus on the iframe itself does the trick. E.g. in jquery:
$("#MyIFrame").focus()

Related

How to Fix JQuery UI Autocomplete in Combination with Touch Punch?

Selection of words in an autocomplete input field (within a dialog) is not working properly when using JQuery UI in combination with Touch Punch. It seems to work if the autocomplete field is directly on the HTML page, but not in a dialog.
Note that selection by mouse is working perfectly in all cases, but selection by touch (i.e. on mobile device) not.
I have reduced the whole case to a few lines of HTML and JavaScript code.
Once with JQuery UI Touch Punch, once without JQuery UI Touch Punch.
I am able to reproduce the error with all combinations of browser and OS, e.g. Chrome on an iPhone, Chrome on an Android mobile as well as with Safari on an iPad,
Would be nice if somebody knows a workaround.
I think this behavior is a result of the fact that on one the one hand Touch Punch developers are not that smart and on the other hand jQuery UI seems to be not very cooperative with Touch Punch.
There are two ways how mouse event might be triggered:
browser might simulate click events after touch events
some library might simulate click events after touch events
Your example without Touch Punch works because mobile browsers currently simulate click events.
So how Touch Punch works and how it messes things up? If you look at the source code https://github.com/furf/jquery-ui-touch-punch/blob/master/jquery.ui.touch-punch.js you'll see that it wraps $.ui.mouse.prototype._mouseInit with its own code and the main intention is to attach various touch-related listeners for all widgets that inherit $.ui.mouse. So far so good. But what exactly those listeners do? The _touchStart handler runs a check using $.ui.mouse internal API:
self._mouseCapture(event.originalEvent.changedTouches[0])
to check if it needs to simulate mouse events. The logic is: if there is no click handler in the widget, there is no need to simulate click. It looks OK at the first glance but what's going wrong? The autocomplete widget puts its dropdown menu to the outside context of the containing dialog and thus touch events on the menu items actually hit listeners registered by touch-punch for the dialog (or rather for its draggable and resizable sub-components). But the dialog subcomponents have no click listeners and thus events are not simulated by the library. Moreover, draggable in your version (see https://github.com/jquery/jquery-ui/blob/1-11-stable/ui/draggable.js) calls
this._blurActiveElement( event );
unconditionally and this seems to stop browser from generating mouse events. So now neither browser nor library simulate click event.
It seems that in the development branch of jQuery UI the bug is fixed https://github.com/jquery/jquery-ui/commit/8c66934434214ab92cbcf46240beb739154fdfbf but for a bit different reason. This fix seems to be available in the jQuery UI 1.12.1 but not in your 1.12.0
So the simplest solution seems to be to upgrade jQuery UI to 1.12.1
See working demo with jQuery UI 1.12.1 at https://jsfiddle.net/cjvgv102/1/ and http://jsfiddle.net/cjvgv102/1/embedded/result/
Ugly hack (stop here unless you really have to)
If for some reasons you can't upgrade jQuery UI, you can do a hack by explicitly creating a fake mouse object on the dropdown and calling its _mouseInit so event will not be handled by dialog's sub-components.
$( "#demoDlg" ).dialog({
autoOpen: false,
modal: true,
buttons: {
"Close": function() {
$( this ).dialog( "close" );
}
},
open: function(event, ui) {
$( "#words" ).autocomplete({
source: ["these", "are", "some", "words"]
});
// super-hack
$( "#words" ).autocomplete("instance").menu.element.mouse().mouse("instance")._mouseInit();
}
});
See full demo at
https://jsfiddle.net/3ptgks3t/1/

jQuery Mobile - preventDefault() on button (link)

I'm developing jQuery Mobile (jQm) app.
I wanna utilize taphold event to some crucial elements, such as remove button, to assure, that this element is secured from unwanted trigger.
I created Remove button on jQm popup and aded some JS to it, but I cannot force default action to quit, not with event.preventDefault() and event.stopImmediatePropagation(), nor with return false.
I prepared jsFiddle as duplicate of my code. The popup there contains simple progress bar as indicator of holded tap. You can try it here: jsFiddle (note: HTML5 data tag taphold="true" is not jQm default)
As a workaround, I'm currently replacing <a href="#" data-role="button"...></a> with <div>styled like button. This works well, since it doesn't have any default action, but I'm curious why the "proper" solution doesn't work?
$("a:jqmData(taphold='true')").bind("vmousedown vmouseup", function(event) {
event.preventDefault();
event.stopImmediatePropagation();
The event.preventDefault(); and event.stopImmediatePropagation(); used in the above piece of code, refer to the vmousedown and vmouseup events and not to every event which is bound to the selected element(s).
This means that the default behaviour for the click event still exists. So when you click the remove button, the click event is triggered and that's why the pop up closes immediately.
I hope this helps.

video.js videos are destroyed when container div hidden iPad

The document has a number of divs only one of which is visible at any one time (others are display:none).
When a div which was visible is hidden and then made visible again the videos within the div don't play any more.
However this is only a problem on iPad.
Any suggestions as to how to re-initialise them?
thanks
Derek
Having searched in every possible way for a solution it does seem that videos using video.js in a container that is hidden after video.js has initialised them become unplayable when made visible again.
So for now, when my pages detect that the browser is on iPad/iPhone they use the native video player.
To do this I place the includes for the video.js inside a javascript block in the head of the page so they are not loaded if iPad or iPhone is detected.
<script type="text/javascript">
if(!navigator.userAgent.match(/iPad/i) && !navigator.userAgent.match(/iPhone/i)) {
document.write('<link href=\"\/\/vjs.zencdn.net/c/video-js.css\" rel=\"stylesheet\" type=\"text/css\" \/\>');
document.write('<script src=\"\/\/vjs.zencdn.net/c/video.js\" type=\"text/javascript\"\>\<\/script\>');
}
</script>
I had this problem on firefox but it was because I was trying to stop the video after move its container div to a hidden div. I removed the "stop" code, the player seems to reinitalize?(and stop by itself) after being moved from one div to another on chrome, firefox and opera.
Before this simple solution, I thought to just re-add the video original html via javascript, it probably can be done after the div is hidden or before it is shown.

Using jQuery selectable within an iFrame

Im developing an HTML generator using jQuery through a drag & drop interface. Currently the user drags "block" elements onto an invisible div overlaying an iFrame (so that it appears to be dropping onto the iframe). When the element is dropped on this invisible div, the corresponding HTML is appended to the iFrame body.
Next, i want to give the user the ability to select an element in the iFrame, and change the properties of the selected element.
I have appended CSS imports and the jQuery/jQueryUI scripts into the iFrame head.
The issue I am facing is when the appended iFrame element is clicked, the jQuery select lasso only appears when the mouse leaves the iFrame, and on it appears outside of the iframe.
The reason I am using the iFrame is so when the code is "generated" for the user, i can just append the iFrame body content to a dialog box.
Has anyone faced issues with the iFrame and jQuery before? and is there any documentation/javaScript library that can assist me in this process?
Thanks!
Rory
The "fix" around this issue is convoluted, but works in my situation.
I created a click event on each added element in the iframe like so:
$('iframe').contents().find('.elem'+blockVal).on('click', function(){
$('iframe').contents().find('.selected').removeClass('selected');
$(this).addClass('selected');
//alert('you have selected the block with class element'+ blockVal);
});
blockVal is a variable passed in from the function that appends the html to the iframe. The above function just adds a click listener to each element appended to the iframe. When any of the elements are clicked, they are given a class of 'selected', and any other element that already has that class, loses it.
Im sorry if that doesn't make any sense.
My advice to anyone doing something similar: Don't use an iframe.

touchmove event in Safari/iOS5/iPad disables contenteditable - any workaround?

I have a serious problem in Safari on iPad. The new contenteditable features doesn't seem to work with touchmove event!
code:
...
<script>
function doNothing(event) { return; }
function initIFrame() {
var iframe=document.getElementById("iframeedit");
iframe.contentWindow.document.designMode="on";
iframe.contentWindow.document.addEventListener("touchmove", doNothing, true);
}
</script>
</head>
<body onload="initIFrame()">
<iframe style="width:500ppx;height:200px" src="content.html" id="iframeedit"></iframe>
...
By adding touchmove somewhere to the document the editable content can not be edited anymore after a touchmove (hold finger down to get the magnifier). The cursor can be set but typing by onscreen keyboard is not allowed anymore.
Test script (for iPad + iOS5):
http://flyingdog.biz/tests/ipad/test2.html
Another test script which is working:
http://flyingdog.biz/tests/ipad/test1.html
As you can see in that other script I put a few lines of text in front of iFrame - very strange! I am looking for another/better workaround or did I have done something wrong? Without the touchmove event it is working but I need this for a good editing experience.
I found a workaround for this bug: It seems that the iframe document looses the focus after a touch event, especially when the copy&paste menu appears. To workaround this bug add a keydown event handler to the iframe-document and reset the focus to the document:
var iframeDoc = $(iframe.contentWindow.document);
iframeDoc.keydown(function(event) {
iframe.contentWindow.focus();
});
This fixes the bug mostly for me. Only if the user types very fast (e.g. on a connected bluetooth keyboard) it can happen that some keystrokes are lost, because the javascript keydown handler execution is a little bit delayed on the iPad.

Resources