The iPad applicationCache events can't update the screen - ipad

I have an html5 application that listens to all window.applicationCache events. When it needs to download, I write a pretty dialog to the screen, and during the progress event I calculate the percentage of files done by doing the right math on the event.loaded and event.total properties, in order to update the percentage with it.
The result is a fine dialog that says "Installing n%" up to 100. Everything works out as I expect it, and the application caches offline nicely and starts on all browsers.
However, on iPad, this doesn't seem to work. The only thing I can achieve during applicationCache events is write to the console. There I do see these events actually being listened to by my handlers.
I've tried everyting up to function timeouts.
My questions:
Is there a way to update any HTML and visualize this during these events on iPad?
Why is the iPad not downloading everything in one go like all other browsers do? It seems to go into idle state for a reason unknown to me.
PS: I need to cache over 600 files. The total size is under 1Mb in total.

I have the same problem. The other applicationCache events (updateready, cached, downloading) do trigger and you can change the html using jQuery or whatever to indicate changes but not the progress event. I can understand that the iPad might not choose to support this event as this is an event that could get triggered many times and may affect the perfomance of the iPad's slower processor. Regarding the download, you need to make sure that every resource listed in your manifest is available.

Related

Why is this page loading so slowly as an iframe, but normal when visited directly?

I have a set of iPads (3rd gen) running iOS 9.3.5. This is the highest they support. I am attempting to replace the functionality of a custom iOS app with an equivalent web application. The site is built in Angular 11, targeting es2015, and I've declared iOS > 9 in the browser support file. The majority of the site performs exactly as I would expect for such old devices. The linchpin of the whole thing is this third party form that needs to be filled out that is served up as an iframe, and it performs so, so horribly.
Here is the code of component HTML with the iframe (URL changed for privacy):
<div class="row header"><a class="restart" (click)='restart()'>Start Over</a><a routerLink='/welcome'><i class="fa fa-times close-x"></i></a></div>
<iframe src="https://notarealsite.com" (load)="waiverLoaded()"></iframe>
The waiverLoaded function is a simple boolean flip to detect the embedded page reloading upon completion so that I can route to a different component in my app. The performance is unchanged if the iframe is the only element on the page. Other pages that play nice when embedded do not suffer a performance drop like the waiver does, so I have to assume it's something in the code of the waiver page.
The original custom iOS app uses a webviewer to load the page, and it loads in 2 seconds or less. The same performance can be seen by visiting the page directly in Safari. In both instances the responsiveness of the dynamic form is reasonable given the age of the devices. When loading the page via an iframe the performance tanks. We're talking 30-45 seconds of loading, and sometimes up to a full second delay between tapping a button or field, and the form reacting.
I have attached the device to my computer and used the remote inspector in the MacOS Safari to view the timeline. The majority of the initial load time is the several 1-2 kb image files used by the form like the scroll bar and some icons. Usually one of these items ends up taking 20-25 seconds all for themselves. When interacting with the form there's an XML resource that appears in the timeline every field change or button press, and that is what takes around a second or two before the page is up to date again.
I'm not well versed in troubleshooting web application performance like this, and this is my first real Angular application that I've built, so I might be missing something painfully obvious. What can contribute to such a difference in performance between a page being visited directly, vs being placed in an iframe?
Some additional info:
The performance is the same between running locally via npm serve or built and deployed to my local server.
I have tried hosting it via HTTP and HTTPS in case it was some security hangup, as the form is only delivered via HTTPS. However I only have a self-signed cert at the moment.
I have seen no discernable difference in load times between the two methods on my other devices, including an iPad Air running iOS 12.5.2.
There is a warning in the console about jQuery support on iOS 9.3.5 being outdated, but it occurs in both scenarios.
Additional Troubleshooting
I've tried to look into some of the suggestions I've received. I've checked the timings and headers on the slow loading elements in Safari in the following configurations:
In the iframe on my app on the iPad.
Visited directly on the iPad.
In the iframe on my app on my MacBook Pro.
Visited directly on my MacBook Pro.
On my laptop the performance is nearly identical. Comparatively, on the iPad the actual load times of all the elements is within a millisecond or two of their times on my laptop. What ends up being notably different is the latency between request and response for the elements.
The latency when visiting directly is higher than on my laptop. When loading through the iframe all the timings increase fairly proportionally. A time of 750ms jumps to 4s. A time of 6s jumps to 30s.
Lastly, a real oddity to me, is the super high latency image for some reason results in a 302 to Cloudflare, but only on the iPad. It doesn't matter if it's through the iframe or direct. Both devices are using the same WiFi network. I can't think of a reason for the redirect to happen unless the destination site is handling the iPad differently somehow. Changing the UserAgent in Safari on my laptop to match the iPad doesn't result in the same redirect.
So I've confirmed that even outside of the iframe the site in question behaves differently on iOS 9.3.5 than on newer versions, and compared to my computers.
Please post your code for us to diagnose and help. In general there is more overhead for an IFrame my suspicion is the jQuery handler or cookie policy, to be sage I also listed other items to check.
It looks like you already checked the previous unsecured elements which was an issue. Both in the network graph and the calls, double check there are no dependencies or URL calls of the Iframe of unsecured elements then it wont display, it used make multiple round trips if Https had mixed content between secure and non-secure stuff, there's a ticket for A new TLS issue.
Once you fix that ensuring its hosted/called securely, clear the cache, cookies, data completely and reloading the page fixes the problem even on mobile browsers.
Redirects/Bouncing Your order of loading scripts/css, if there are dependent scripts and they are not cached it could be blocking, or if its redirecting back to HTTP this will also slow it down.
For IOS mobile apps only (doesn't apply here) - if you are using the 3rd gen, check the default for Cookie Security policy (HTTPCookieAcceptPolicy) for UIWebView has changed to NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain
Animations Are slow in safari Iframes
You have the click event in your code, could be the issue
..."Turns out that any non-anchor element assigned a click handler in jQuery must either have an onClick attribute (can be empty like below):"...
Put the following element declaration cursor:pointer or tap event

WebGL is it possible to emulate an asynchronous call to gl.finish()

WebGL is nice and asynchronous in that you can send off a long list of rendering commands without waiting for them to complete. However, if for some reason you do need to wait for the rendering to complete, you have to do it synchronously with gl.finish(). Surely it would be better if gl.finish accepted a callback and returned immediately?
Question: Is there any way to emulate this reliably?
Usage case: I am rendering a large number of vertices to a large off-screen canvas and then using drawImage to copy sections of this large canvas to small canvases on the page. I don't actually use gl.finish() but drawImage() seems to have the same effect. In my application, re-rendering is only triggered when the user performs an action (e.g. clicking a button), and it may take several hundred milliseconds. It would be nice if during rendering the browser was still responsive allowing scrolling etc. I am looking in particular for a Chrome solution, though something that also works in Firefox and Safari would be good.
Possible (bad) answer: You could try and estimate how long rendering is going to take and then set a timeout that begins with the call to gl.finish(). However, reliably doing this estimation for all sizes of vertex buffer and all users is going to be pretty tricky and inaccurate.
Possible (non-)answer: requestAnimationFrame does what I'm looking for...it doesn't though, does it?
Possible answer in 2018: Perhaps the ImageBitmap API solves this problem - see MDN docs.
You've already partially hit on your answer: drawImage() does indeed have finish-like behavior in that it forces all outstanding drawing commands to complete before it reads back the image data. The problem is that even if gl.finish() did what you wanted it to, wait for rendering to complete, you would still have the same behavior using it as you do now. The main thread would be blocked while the rendering finishes, interrupting the user's ability to interact with the page.
Ideally what you would want in this scenario is some sort of callback that indicates when a set of draw commands have been completed without actually blocking to wait for them. Unfortunately no such callback exists (and it would be surprisingly difficult to provide one, given the way the browser's internals work!)
A decent middle-ground in your case may be to do some intelligent estimations of when you feel the image may be ready. For example, once you have dispatched your draw call spin through 3 or 4 requestAnimationFrames before you call drawImage. If you consistently observe it taking longer (10 frames?) then spin for longer. This would allow users to continue interacting with the page normally and either produce no delay when doing the draw image, because the contents have finished rendering, or much less delay because you do the synchronous step mid-way through the render. Depending on the intended usage of your site non-realtime rendering could probably even stand to spin for a full second or so before presenting.
This certainly isn't a perfect solution, and I wish I had a better answer for you. Perhaps WebGL will gain the ability to query this type of status in the future, because it would be valuable in cases like yours, but for now this is likely the best you can do.

How to speedup jquery mobile / phonegap?

I have a small web app. Seven pages, 3.6 KB index.html and 855.5 KB total. The only odd thing i have is a database (~500kb) in Javascript with many lines like:
$.data(db,'Aarstraße',['34236:1','34246:2','34270:4','34290:6',...]);
I tested it on iPod/iPhone and Android (HTC Magic) and it is very slow:
Startup
iPhone: 14 seconds
Android: 21 seconds
Simple page transition (slide)
iPhone: 3-4 seconds
Android: 4-6 seconds
How can I make this fast?
I already removed the box shadow.
Update
I remove the database leaving 444.7KB page total. Now it runs faster on Android. Around the same as one iPhone. It still feels very slow.
Update 2
After this question, I switched to the latest jquery mobile build. It improved the page transitions for slow Android devices to ~2 seconds per transition. Release of Version 1.1 will be mid/late February.
There are a few things you can do:
Get to deviceready faster.
Minimize your JS code using YUI Compressor
Move your script tags to the bottom of the body tag.
As you've already mentioned you've moved the database out of the equation which was probably taking a bulk of the time on startup.
What do you do with jQuery-mobile? It's performance is very poor, you should never call it on elements bigger that required. See this discussion about jquery-mobile for details. It is doing very large number of DOM search operations because it works by modifying the DOM tree. As for my tests, it works too slow even on desktop browser.
Try without transitions. Even with jQuery 1.1, the page transitions can be really flickery and slow on an iPhone.
To drop page transitions globally, just add the following to jqm.glocal.config.js
$(document).bind("mobileinit", function(){
$.mobile.defaultPageTransition="none"
});

How might I find out the source of long delays on resizing the main form?

I have a D2006 app that contains a page control and various grids, etc on the tabs. When I resize the main form (which ripples through and resizes just about everything on the form that is aligned to something), I experience long delays, like several seconds. The app freezes, the idle handler is not called and running threads appear to suspend also.
I have tries pausing execution in the IDE while this is happening in an attempt to break execution while it is in the troublesome code, but the IDE is not taking messages.
Obviously I'm not expecting anyone to point me at some errant piece of code, but I'm after debugging approaches that might help me. I have extensive execution timing code throughout the app, and the long delays don't show up in any of the data. For example, the execution time of the main form OnResize handler is minimal.
If you want to find out what's actually taking up your time, try a profiler. Sampling Profiler could answer your question pretty easily, especially if you're able to find the beginning and the end of the section of code that's causing trouble and insert OutputDebugString statements around it to narrow down the profiling.
OK. Problem solved. I noticed that the problem only occurred when I had command-line switches enabled to log some debug info. The debug info included some HTTP responses that were written to a debug log (a TMemo) on one of the tabs. When the HTTP response included a large block with no CR/LFs the TMemo wrapped it. Whenever I resized the main form, the TMemo resized and the control had to render the text again with the new word wrapping.
To demonstrate:
start a new Delphi project
drop a TMemo onto the form
align it to Client
compile and run
paste a large amount of text into the TMemo
resize the main form
I won't award myself the answer, as I hadn't really provided enough info for anybody else to solve it.
BTW #Mason - would SamplingProfiler have picked this one up - given that the execution is inside the VCL, and not in my code?
A brute-force approach that may give results.... Put a debug message to OutputDebugString() from every re-size event, sending the name of the control as the string to be displayed. This may show you which ones are being called "a lot".
You may have a situation where controls are bumping each other, setting off cascading re-size events. Like 3 siblings in the back seat of a compact car, once they start jostling for position, it can take a while for them to "settle down".
Don't make me turn this car arround....
The debug log (viewable in the IDE, or with an external ODS viewer), may show you which ones are causing the most trouble, if they appear multiple times for one "user-initiated re-size event".
Run your application in AQTime's performance profiler (included with XE, but you can get a time-limited version from their website).
Do some fanatic resizing for a while, and then stop the application.
After that, you'll see exactly which function was called many times, and where most time was spent.

Any gottcha's on using TTimer to monitor file dates and update screen?

I want to detect when a file date changes and update a DevX TdxMemData which is used as a Tdatasource which then would be seen in a TDBGrid that uses it.
I've found some code that uses ReadDirectoryChangesW, but seems rather complex for my simple needs.
I'm considering using a TTimer and firing it off every five seconds. (That's fine enough accuracy for me.)
Are there any caveats in doing this? I've read that Threads have all sorts of restrictions on VCL access, etc. Does the same thing apply to TTimer events?
Is there anything I need to watch out for when calling FileAge and updating a DevEx TdxMemData object while in a Timer event? Will those updates be seen by my main app?
Is there a way to detect the "state" of my program when a Timer event gets control so I can avoid problems?
Or am I opening an enormous can of worms in thinking about using a TTimer for this?
TTimer events are called within the main application thread, so there's no problems with accessing VCL objects from them. It's called when your application is idle, so it won't take place while your in an OnClick handler or anything similar unless you manually call Application.ProcessMessages.
I'd suggest using ReadDirectoryChangesW though. If you use a timer you will continue polling even if the application is idle and the file isn't changing. It will keep your CPU from going idle and keep could keep the hard drive from spinning down, which can have negative effects for power saving and battery usage.
In Demos directory there's "ShellChangeNotifier" component, which will fire events when files get modified, added or deleted inside directory. However it has only one OnChange event, so you don't know what really happened.
There's some discussion and solution about the issue in about.com
Windows lets you monitor file changes. As a jump start see http://delphi.about.com/od/kbwinshell/l/aa030403a.htm. There are several ready made components available, too. Google for "delphi monitor file change" or something similar
You can check my: DirectoryWatch
It is a wrapper around "ReadDirectoryChangesW" functions. It is more specific about changes than "ShellChangeNotifier".

Resources