Prevent IOS autofocus first input when page opens ionic - ios

There is a page in our app that has a single input field. When going to that state on IOS, the keyboard automatically pops up. This is not what is desired. This doesn't happen on the Android version.
I've tried all sorts of things, but nothing is sorting it. My last attempt was to call $cordovaKeyboard.close() in the app.js run block within a $stateChangeSuccess handler. Alas, nothing.
Any pointers would be greatly appreciated!
There's not much to put in code terms. The offending input:
<ion-item class="item-input-inset">
<label class="item-input-wrapper bg-light-grey-30 text-center">
<input type="text" class="text-center tracker" ng-model="values.exploreSearch" placeholder="Enter city, street, username or keyword"/>
</label>
</ion-item>
And the JS in the $ionicPlatform.ready block in the main app.js run block:
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams, error) {
if (window.cordova && $cordovaKeyboard.isVisible) {
$cordovaKeyboard.close();
}
});
I previously tried putting a block in the page controller that looked like this:
$ionicPlatform.ready(function () {
if (window.cordova && $cordovaKeyboard.isVisible) {
$cordovaKeyboard.close();
}
}]);
This last block, according to my client (as I don't have an IOS device to test on), worked the first time the page loaded, but not subsequently. If you left the page, and came back, the keyboard would pop up.

I had the same issue, and it seems to have something to do with the way the iOS browser sends click events (more here: http://blog.ionic.io/hybrid-apps-and-the-curse-of-the-300ms-delay/)
The way I worked this out was to hide my form on $stateChangeStart and then show the form 400ms later. An slightly better way is to have a transparent div covering everything, that you hide 400ms after $ionicView.enter.
<div style="position: absolute; top: 0px; bottom: 0px; left: 0px; right: 0px; z-index: 1000;" ng-hide="showFields" class="ng-hide"></div>

Related

Angular: Mat-card keyboard navigation

I am trying to make a mat-card navigable from the keyboard. Right now, when pressing tab the element is focused however the redirect event (should be the same as the click event) isn't triggered when pressing enter.
I've tried keydown.enter and onKeyDown (from a11y package) but no success so far.
HTML
<mat-card role="group" (click)="addQueryParam(group.name)" (keydown.enter)="addQueryParam(group.name)" class="mat-elevation-z0"
[ngClass]="'background-'+index" (mouseout)="mouseOver=false"
(mouseover)="mouseOver=true" style="padding: none; margin: 5px">
Typescript
addQueryParam(groupName) {
this.router.navigate(['/data'], { queryParams: { ['groups.title']: groupName }, queryParamsHandling: 'merge' });
}
Any idea how to solve this issue?
TIA,
Isabela
I suggest you two things:
try using (keyup.enter)=.... I used it a couple of times and it worked well
If that doesn't work try using (keyup) or (keydown) and in your function check if the key code is 13 (enter key code), something like this:
HTML
<mat-card role="group" (click)="addQueryParam(group.name)" (keydown)="addQueryParam($event, group.name)" class="mat-elevation-z0"
[ngClass]="'background-'+index" (mouseout)="mouseOver=false"
(mouseover)="mouseOver=true" style="padding: none; margin: 5px">
Typescript:
addQueryParam($event, groupName) {
if($event.keyCode === 13){
this.router.navigate(['/data'], { queryParams: ...);
}
}
If i remember correctly you can check the type of the event in a field like event.type, or something like that.
Additionally check this discussion out, because theese functions are not well documented, and here you can find som infos :
What are the options for (keyup) in Angular2?
EDIT
I also found this very useful article: https://medium.com/claritydesignsystem/angular-pseudo-events-d4e7f89247ee

Uploading images via dynamic input element not working on iOS

I am working on an app in which users can upload images to their profile.
The following function is invoked when an event is fired from a child element. It dynamically creates an input element so the user can select a file to upload.
_changeImage: function () {
var input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.addEventListener('change', this._imgChanged.bind(this));
input.click();
},
It works on browser and android platforms but fails on iOS.
Could anyone point out what might be causing this problem and how I could approach it?
This problem appears to be related to a security measure in iOS. File input must be manually clicked by the user, not done programatically.
In order to work around this we overlay an invisible input element over the target element.
<input id="inputpic" type="file" accept="image/*" on-change="someFunction">
*keep in mind that on-change is polymer specific so you may want to use onChange
Then we style it with css to have 0 opacity.
#inputpic {
opacity: 0;
position: absolute;
top: [position_of_target_element];
left: [position_of_target_element];
width: [width_of_target_element]px;
height: [width_of_target_element]px;
z-index: 10;
}
I am not particularly happy about this workaround but I tried several other proposed solutions (link below) and found that:
Using a 'hidden' attribute instead of css opacity does not work.
Wrapping the input element in a label element does not work.
More info in this thread.
If anyone else has a better solution I would love to hear back. Thanks!

Reveal.js: Add fragments inside code

I've got a presentation running with reveal.js and everything is working. I am writing some sample code and highlight.js is working well within my presentation. But, I want to incrementally display code. E.g., imagine that I'm explaining a function to you, and I show you the first step, and then want to show the subsequent steps. Normally, I would use fragments to incrementally display items, but it's not working in a code block.
So I have something like this:
<pre><code>
def python_function()
<span class="fragment">display this first</span>
<span class="fragment">now display this</span>
</code></pre>
But the <span> elements are getting syntax-highlighted instead of read as HTML fragments. It looks something like this: http://imgur.com/nK3yNIS
FYI without the <span> elements highlight.js reads this correctly as python, but with the <span>, the language it detects is coffeescript.
Any ideas on how to have fragments inside a code block (or another way to simulate this) would be greatly appreciated.
To make fragments work in code snippets, you can now use the attribute data-noescape with the <code> tag
Source: Reveal.js docs
I got this to work. I had to change the init for the highlight.js dependency:
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() {
[].forEach.call( document.querySelectorAll( '.highlight' ), function( v, i) {
hljs.highlightBlock(v);
});
} },
Then I authored the section this way:
<section>
<h2>Demo</h2>
<pre class="stretch highlight cpp">
#pragma once
void step_one_setup(ofApp* app)
{
auto orbit_points = app-><span class="fragment zoom-in highlight-current-green">orbitPointsFromTimeInPeriod</span>(
app-><span class="fragment zoom-in highlight-current-green">timeInPeriodFromMilliseconds</span>(
app->updates.
<span class="fragment zoom-in highlight-current-green" data->milliseconds</span>()));
}
</pre>
</section>
Results:
I would try to use multiple <pre class="fragment">and change manually .reveal pre to margin: 0 auto; and box-shadow: none; so they will look like one block of code.
OR
Have you tried <code class="fragment">? If you use negative vertical margin to remove space between individual fragments and add the same background to <pre> as <code> has then you get what you want.
Result:

changePage "jumps" back to old page

I've a big problem with a jQuery Mobile Application:
I'm using custom functions (they are triggered by onClick) to switch the page with currentPage.
It only happens on Android-Devices on sites in which has changed (due to ajax requests) with the integrated browser. iOS and Chrome works nice.
After clicking on an element, the animation started but just before it ends, it switches back to the old page. After a half second, it switches back to the new.
I made a movie of the bug here: http://www.youtube.com/watch?v=sXxvVUxniNg
Thank you very much
Code (CoffeeScript):
class Guide
#categoriesLoaded = false
#loadSearch: ->
$.mobile.changePage $("#guide"),
transition: 'slide'
changeHash: false
if !#categoriesLoaded
#categoriesLoaded = true
GuideApi.getCategories (data) ->
output = Mustache.render $("#tmpl-guide-categories-select").html(),
categories: data
$("#guide-search-category").append output
$("#guide-search-category").val($("#guide-search-category option:first").val());
window.WgSwitchGuide = ->
Guide.loadSearch
I was having the same issue. And I tried everything, I finally end with the solution. What I found was the error was principally within the browser. So I set the configuration of the pushStateEnabled as false. I did it by doing the following, adding this script.
<script type="text/javascript">
$(document).bind("mobileinit", function(){
$.mobile.pushStateEnabled = false;
});
</script>
It should be add before the jquery-mobile script is call, for more information you could see it on JQuery description
And it solved the problem no more jumping back.
I was having the exact same issue on both android and ios. For me, it was happening for heavy pages, i.e., pages with complex elements etc. Looks like you are using "slide" transition, which was what I was using as well. Taking out the page transitions (i.e., $.mobile.changePage("page.html", { transition: "none" })) for those pages resolved this issue for me. Hope this helps.
If you want to retain the transition, you can try preloading the page first when the previous page is being shown, by using the $.mobile.loadPage, and then show the transition. I am myself exploring this route, but it is probably worth trying.
Edit: OK - I explored the last suggestion and this doesn't seem to be working. Will stick with the first option.
Would you try to add the event stopPropagation and preventDefault methods on the first page's click event? This way the default action of the click event will not be triggered. Moreover the stopPropagation prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
event.stopPropagation();
event.preventDefault();
Example:
$("p").click(function(event){
event.stopPropagation();
event.preventDefault();
// change page
});
After trying for weeks to find a solution to this, I ended up doctoring the JQM library to disable page transitions one right after another. It's not a good solution, but it's the only thing I could get to work.
I was getting pages jumping back on both $.mobile.changePage and on anchor links. I used the slide transition, but removing it did not fix the problem. Setting pushStateEnabled to false did not work either. The jumps were happening on all devices and browsers (that I tested, anyway).
So here's what I did to the JQM library (v1.3.2).
Before the $.mobile.changePage function is defined, I added:
var justChangedPage = false;
Then within the function there's a line that goes:
if ( pbcEvent.isDefaultPrevented()) {
return;
}
which I changed to:
if ( pbcEvent.isDefaultPrevented() || justChangedPage) {
return;
}
Then right after this part of the $.mobile.changePage function:
if ( toPage[ 0 ] === $.mobile.firstPage[ 0 ] && !settings.dataUrl ) {
settings.dataUrl = documentUrl.hrefNoHash;
}
I added:
justChangedPage = true;
setTimeout(function() {
justChangedPage = false;
}, 500);
(Putting that earlier in the function didn't work -- all that stuff executes more than once within a single page transition. And half a second seemed to be the minimum timeout that prevented the page jumps.)
I hope this helps someone even if it is a hack...
What is your JQM and Android version?
I'm not sure If I understand correctly. I think transition flicker maybe come from the following assumption.
Heavy page DOM transition.
Using "translate3d" somewhere in css file.
Not using "H/W Acceleration" feature. Enable by add this line to your AndroidManifest.xml in <application>
android:hardwareAccelerated="true"
I encountered exactly the same behaviour and it seems that few people are having the same issue. At first I thought it is caused by jQuery mobile library. Later on, I manage to find where the problem came from and it is a bug in my own code.
I made a demo to explain the issue.
http://jsfiddle.net/pengyanb/6zvpgd4p/10/
Hopefully, this can be hint for people having the same problem.
$(document).on('pagebeforeshow', '#page2', function(){
console.log('Page2 before show');
var htmlGeneratedOnTheFly = '<ul data-role="listview" data-inset="true">';
for(var i=0; i<4; i++)
{
htmlGeneratedOnTheFly += '<li><a>Random html element</a></li><li data-role="list-divider"></li>';
}
htmlGeneratedOnTheFly += '</div>';
$('#page2UiContent').empty();
$('#page2UiContent').append(htmlGeneratedOnTheFly);
$('#page2UiContent').trigger('create');
//////////////////////////////////////////////////
//The following section is where the bug is generated.
//Each on "page2 before show event" will add a OK Button click handler.
//The handlers never get cleared.
//More and more handler is added to the Page2 OK button as pages going back and forth.
//Open the browser's console window to see multiple "Page 2 OK Button clicked!!!" lines on one button click.
//To fix the bug, move the following section out of the $(document).on('pagebeforeshow', '#page2', function(){});
//////////////////////////////////////////////////
$('#page2OkButton').click(function(){
console.log("Page 2 OK Button clicked!!!");
$.mobile.changePage('#page1', {transition:"flip"});
});
//////////////////////////////////////////////
//////////////////////////////////////////////
});
<link href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.css" rel="stylesheet"/>
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-role="page" id="page1" data-theme="a">
<div data-role="header" data-position="fixed">
<h5>Demo Page 1</h5>
</div>
<div data-role="main" class="ui-content">
<h2>jQuery mobile changepage jumps back to old page demo</h2>
<p>Click "Go To Page 2" button to go to page2</p>
<p>On Page2 click Ok Button to come back to page1</p>
<p>Keeping going back forth between two pages for few times.</p>
<p>Eventually, you will find that clicked on "Go To Page2" button to flip to Page2 but it soon jumps back to page1 automatically. </p>
<h2>Please read the comments in the javascript for explaination</h2>
Go To Page 2
</div>
</div>
<div data-role="page" id="page2" data-theme="a">
<div data-role="header" data-position="fixed">
<h5>Demo Page 2</h5>
</div>
<div id="page2UiContent" data-role="main" class="ui-content">
</div>
<div data-role="footer" data-position="fixed" style="text-align:center;">
<div data-role="navbar">
<ul>
<li><a id="page2OkButton" class="ui-btn ui-icon-check ui-btn-icon-left">OK</a></li>
</ul>
</div>
</div>
</div>

jQuery iframeFix on a Sortable

On my CMS I have a list of thumbnails (Sortable). The thumbnails work great and now I'm writing a plug-in to drag-them to a tinyMCE window.
As the tinyMCE window has an iFrame it doesn't work that well.
jQuery has an option for Draggables called iframeFix that works exactly as I need. However that list must be a Sortables. I've looked quite extensively on Google and found no-one with my requirements. Has anyone here on StackOverflow done it?
Apply the iframeFix to a Sortables?
If not... I'm on my way to a jQuery plug-in.
Thank you in advance!
I've done it.
You need to have a DIV on top of the iFrame to let the Draggable/Sortable flow without problems. So I used jQuery to create a DIV right on top of the iframe. Then it show's it when you grab the element and destroys it when you drop it. Works like a charm. If anyone is in need of something like that let me know.
update (by popular request):
On my specific scenario I use the following DIV:
<div id="iframeDivFixer" class="ui-draggable-iframeFix" style="background-color: rgb(255, 255, 255); display: none; width: 665px; height: 665px; position: absolute; opacity: 0.001; z-index: 1000; left: 362px; top: 290px; background-position: initial initial; background-repeat: initial initial;"></div>
And, as soon as I grab the thumbnail javascript is used to set the display property to block. The process is reversed when you release the dragabble.
A seriously old question here, but there's another way to do it using css - pointer-events:none; which is supported on all the currently supported browsers (IE11 and above - caniuse.com)
$("#sortable").sortable({
start: function() {
$("iframe").css("pointer-events", "none");
},
stop: function() {
$("iframe").css("pointer-events", "");
},
});

Resources