I have a dialog page that's saving the address and port of a server in localStorage:
localStorage.SERVER['address'] = address;
localStorage.SERVER['port'] = port;
I've cut my subsequent request down to just console logging the data in localStorage to check things are working.
$("#login_submit").click(function(event) {
event.preventDefault();
console.log(localStorage.SERVER['address'] + ' ' + localStorage.SERVER['port']);
}
What's happening though is that this executes fine when I submit the form without anything in localStorage (I get 'undefined undefined'). However after i've saved some values in the localStorage SERVER object the form reverts to behaving as normal and tries to open
http://mydomain/?username=&password=
and doesn't log anything to the console.
Take a look at this jsFiddle example: http://jsfiddle.net/Gajotres/J9NTr/, I made it for my other ARTICLE, or it can be found HERE.
Basically localStorage data can be added/modified at any time.
Try to access them like this, this example works on desktop browsers, android and iOS devices.
localStorage.firstname="Dragan";
localStorage.lastname="Gaic";
Related
I have an MVC 5 mobile website that I am trying to make a standalone mobile web app running full screen on an iPhone. Everything works well until the app launches an external link that will, for example, launch in Safari. Upon returning to the web app the Session data seems to disappear and a new Session Id is assigned, wiping out any existing trace of previous user progress prior to the external launch. The User Name, however, remains intact and “logged in”. What do I need to do to persist the Session data?
I’ve been at this for hours now, googling and trying different approaches, but to no avail and my head is spinning. A similar post is HERE but my problem is the Session data.
Any help/direction would be greatly appreciated.
UPDATE 1
It seems that this behavior is limited to iOS -- currently testing on 9.3.3. Same behavior whether the "Back to [App] upper left link in the status bar is used or double-tap on the home button to return to WebApp. Android OSs seem to work just fine. Go figure. We are using cookies.
So it was a "Hail-Mary pass" but it worked... just persist the ASP.NET_SessionId cookie in javascript. It may have worked elsewhere but here's what I did:
In _Layout.vbhtml I added this to $(document).ready:
if (window.navigator.standalone || window.matchMedia('(display-mode: standalone)').matches) {
document.cookie = "ASP.NET_SessionId=#(Session.SessionID); " + extendTimeStr(5);
}
along with the function:
function extendTimeStr(extMins) {
var d = new Date();
d.setTime(d.getTime() + (extMins*60*1000));
return "expires="+ d.toUTCString();
}
Magically, it worked! Hope it helps someone.
Update for AspNetCore 2.0:
$(document).ready(function () {
if (('standalone' in window.navigator) && window.navigator['standalone']) {
var cookie = '#(Context.Request.Cookies[".AspNetCore.Identity.Application"])';
document.cookie = ".AspNetCore.Identity.Application=" + cookie + "; " + extendTimeStr(5);
}
})
Thank you #HumbleBeginnings for your excellent and simple solution to a problem I can't find answers to elsewhere!
I am working on a hybrid HTML5/iOS app that uses the Safari Webview. We are using AirPrint to allow the user print the contents of the webview. The problem I am having is that after the print dialog is opened, the print styles are taking affect on the screen, and even after printing is complete or canceled do not go away. This does not happen in our Windows or Android versions of the app, which use CEF and Android System Webview respectively. Print styles in those versions of the application are only applied to the print out, as expected.
Anyone have any experience using AirPrint with Safari Webview that could shed some light on a solution? I have considered just adding/removing the link tag containing the CSS with javascript before and after printing, but that feels hacky, and doesn't answer the curious question of why print styles are being applied to the screen.
Any help appreciated! Sorry there is no real way to attach code to this!
Yes, this is indeed a not expected behaviour. However, we can try to solve this using JavaScript.
Theory: When the print is done, let's reload the stylesheets. The browser will paint the page again and hopefully using screen definitions.
Practice: As we don't have a JavaScript callback after printing, you could try reload your stylesheets using the window.onfocus event, as follows:
function updateStylesheets(){
var links = document.getElementsByTagName("link");
for (var x in links) {
var link = links[x];
if (link.getAttribute("type").indexOf("css") > -1) {
link.href = link.href + "?id=" + new Date().getMilliseconds();
}
}
}
window.onfocus = updateStylesheets;
In detail, it grabs all <link> tags and appends a random number after, forcing a reload on the stylesheets.
Please let me know if that worked, I'd be glad to help.
So currently working on a project and experiencing a strange issue with the ios version of Safari involving the playback of an audio file from a server.
I'm currently facing the following issue:
Person comes onto the page which has a standard html5 audio tag, and a direct link to the audio file for downloading purposes.
Person tries to listen to audio from audio tag, content plays for x number of minutes, cuts off then repeats (the x number of minutes is NOT the length of the recording, and is not consistent).
Person tries direct link of recording, rather then downloading the recording, Safari appears to go to a new page and wraps the download url in a video element, and the same issue as step 2 occurs.
Now the audio file is served up via a java scriptlet, which serves the file with the following code snippet:
String fn = saveTo + file_name;
f = new File(fn);
String fname = f.getName();
String contentType = "audio/wav";
if(fname.endsWith("mp3")){
contentType = "audio/mp3";
}
response.setContentType(contentType);
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-disposition", "attachment;filename="+f.getName());
response.setHeader("Content-Length", ""+f.length());
FileInputStream fin = null;
try{
fin = new FileInputStream(f.getCanonicalFile());
byte[] data = new byte[1024];
int x = 0;
while((x = fin.read(data, 0, 1024))>=0){
response.getOutputStream().write(data, 0, x);
Thread.sleep(1);
}
} finally {
if(fin != null) {
try{
fin.close();
}catch(Exception ex){}
}
}
Now I know the code isn't the best by any measure, it isn't my code, and we're obviously working on the assumption that the file is found.
I'm finding when debugging on the iPhone with debug mode on a mac, it doesn't seem to show a return status code. It shows no response headers but it obviously must be receiving something. The server log seems to think its returning a status 200, this showing in Chrome and Firefox.
The code above appears to work fine with Chrome, and Firefox, but not Safari.
The only thing I am guessing is it has something to do with how the file is being pushed to the output stream that Safari isn't liking, or maybe its getting confused and should have a different status code. I've been banging my head against this for a good few days, and reading as much as I can about Safari, though most of the documentation I'm finding is on its "unique" implementation of web audio, and the use of a single channel which seems to be irrelevant to this.
Any Help would be appreciated.
I experienced the same issue with Safari on iOS, and after a lot of debugging, I found the issue was related to the combination of headers applied to the response.
My application is C#-based, but this solution should be platform independent (because as previously stated, it is a response header issue).
Necessary Headers:
Content-Range: bytes 0-[content length]/[content length]
Content-Transfer-Encoding: binary
Content-Length: [content length]
Accept-Ranges: bytes
I devised this after inspecting a response from MP3s delivered via Akamai's content delivery service.
I'm afraid im having the same probem as this unasnwered question.
I have a blank IFRAME In my cordova ionic IOS App for embedded YouTube videos.
I change the NG-SRC="" of iframe by clicking Next Video. But upon testing it appears that the phone/cordova/webview is caching the old content of the iframes. I can only get through 20 videos or so before crashing out of memory.
I have tried using angular.element.remove() to remove the iframe as well as setting the iframe src to blank first, and neither seemed to affect how much memory is in use, per Xcode. I've also tried the cordova plugin ClearCache and that didnt clear any memory either.
Please help! Is there a better way to embed youtube in a cordova app?
I have spent weeks working on this all to have it crashing down around me (no pun intended)
My Video view is like:
<ion-view view-title="Random Video">
<iframe id="youtube" sandbox="allow-scripts allow-same-origin" ng-src="{{video.url | trustAsResourceUrl}}" frameborder="0" allowfullscreen></iframe>
<h4>{{video.title}}</h4>
<button ng-click="nextVideo()">
</ion-view>
My controller is like:
angular.module('starter.controllers')
.controller('VideoCtrl', function(VideoService) {
$scope.video = {};
$scope.nextVideo = function() {
$scope.video = null; //doesnt seem to help
//$scope.$destroy(); //doesn't help
//angular.element(document.querySelector( '#youtube' )).attr("src", " ");
//angular.element(document.querySelector( '#youtube' )).remove();
//neither of the above 2 remove any memory
VideoService.getVideo().then(function(response){
$scope.video = response.data;
});
}
$scope.nextVideo();
});
Note, when I load my app onto a website instead, and load in chrome, I can cycle through videos without seeing the memory usage go up (looking at taskmgr.exe at least)
It might seem like setting the iframe to an empty string should be enough, but for some browsers and some situations it isn't. It might be necessary to recursively delete event listeners and elements one by one. Maybe surprisingly, the recursive method (1) below is faster than just setting to an empty string (2):
1.Recursive
while (box.lastChild) {
box.removeChild(box.lastChild);
}
2. Setting empty string
myNode.innerHTML = '';
See https://stackoverflow.com/a/3955238/1158376 for reference.
Additionally, in the recursive approach, one might need to apply special treatment to some items, for example first remove event listeners, nullify functions (http://javascript.crockford.com/memory/leak.html), and use dedicated cleanup methods, like with jQuery (http://javascript.info/tutorial/memory-leaks).
Another strategy you could try is to load a new web page with a fresh iframe for every video you play. Loading a new page should enable the browser to release the previously claimed memory.
I have started developing html applications for mutliple platforms. I recently heard about Cordova 2.0(PhoneGap) and ever since I have been curious to know how the bridge works.
After lot of code walking, i saw that the Exec.js is the code where call from JS -> Native happens
execXhr = execXhr || new XMLHttpRequest();
// Changeing this to a GET will make the XHR reach the URIProtocol on 4.2.
// For some reason it still doesn't work though...
execXhr.open('HEAD', "file:///!gap_exec", true);
execXhr.setRequestHeader('vc', cordova.iOSVCAddr);
if (shouldBundleCommandJson()) {
execXhr.setRequestHeader('cmds', nativecomm());
}
execXhr.send(null);
} else {
execIframe = execIframe || createExecIframe();
execIframe.src = "gap://ready";
But want to understand how that works, what is the concept here, what does file:///!gap_exec or gap://ready do? and how does the call propgate to the lower layers (native code layers)
thanks a bunch in advance.
The trick is easy:
There is a webview. This displays your app. The webview will handle all navigation events.
If the browser navigates to:
file:///!gap_exec
or
gap://
the webview will cancel the navigation. Everything behind these strings is re-used as an identifier, to get the concrete plugin/plugin-method and parameter:
pseudo-url example:
gap://echoplugin/echothistext?Hello World
This will cause phonegap to look for an echoplugin and call the echothistext method to send the text "Hello World" to the (native) plugin.
update
The way back from native to javascript is (or may be) loading a javascript: url into the webview.
The concrete implementation is a little bit more complex, because the javascript has to send a callback-id to native code. There could be more than one native call are running at the same time. But in fact this is no magic at all. Just a number to get the correct JSON to the right javascript-callback.
There are different ways to communicate between the platform and javascript. For Android there are three or four different bridges.
I am trying to figure this out in more detail, too. Basically there are 2 Methods on the iOS side that can help ...
- webView:shouldStartLoadWithRequest:navigationType: and
- stringByEvaluatingJavaScriptFromString:script
From the sources it seems cordova sends a "READY" message using webView:shouldStartLoadWithRequest:... and then picks up results with the second message, but I am not sure.
Cordova Sources iOSExec
There is much to learn there.