Device Info: Android 9;HUAIWEI COL-AL10; Chrome 80.0.3987.99
I am working on applying A-Frame to my mobile phone based HMD with my customized camera orientation and distortion.
However after I modified the cardboad distorter (CardboardDistorter.prototype.computeMeshVertices_ in Line 63069 in aframe.js) and run the samples, the distortion is still using cardboad's distortion. While I modified the same distorter in webvr-polyfill js, the new distortion works for me.
And when I use other phones to test my a-frame demo, the new distortion also works......
Seems like a-frame treat my phone as a native VR device so it triggered Google VR service in the backend....
How to enable the new distortion I changed in CardboardDistorter? I need to run webVR-polyfill DIRECTLY on my phone.
I have built some unity VR games based on Google VR recently, maybe they made my phone a "Native google VR Device"?
cardboard distortion:
cardboard distortion
my test distortion(when using polyfill it should display like this):
new distortion
Here is my new distortion for test:
CardboardDistorter.prototype.computeMeshVertices_ = function (width, height, deviceInfo) {
var vertices = new Float32Array(2 * width * height * 5);
var lensFrustum = deviceInfo.getLeftEyeVisibleTanAngles();
var noLensFrustum = deviceInfo.getLeftEyeNoLensTanAngles();
var viewport = deviceInfo.getLeftEyeVisibleScreenRect(noLensFrustum);
var vidx = 0;
for (var e = 0; e < 2; e++) {
for (var j = 0; j < height; j++) {
for (var i = 0; i < width; i++, vidx++) {
var u = i / (width - 1);
var v = j / (height - 1);
var s = u;
var t = v;
var x = lerp(lensFrustum[0], lensFrustum[2], u);
var y = lerp(lensFrustum[3], lensFrustum[1], v);
var d = Math.sqrt(x * x + y * y);
var r = deviceInfo.distortion.distortInverse(d);
var p = x * r / d;
var q = y * r / d;
// test distortion
u = u - 0.5;
v = v - 0.5;
u = u * (v + 0.7);
v = v * 0.7;
u = u + 0.5;
v = v + 0.5;
//u = (p - noLensFrustum[0]) / (noLensFrustum[2] - noLensFrustum[0]);
//v = (q - noLensFrustum[3]) / (noLensFrustum[1] - noLensFrustum[3]);
u = (viewport.x + u * viewport.width - 0.5) * 2.0;
v = (viewport.y + v * viewport.height - 0.5) * 2.0;
vertices[vidx * 5 + 0] = u;
vertices[vidx * 5 + 1] = v;
vertices[vidx * 5 + 2] = s;
vertices[vidx * 5 + 3] = t;
vertices[vidx * 5 + 4] = e;
}
}
var w = lensFrustum[2] - lensFrustum[0];
lensFrustum[0] = -(w + lensFrustum[0]);
lensFrustum[2] = w - lensFrustum[2];
w = noLensFrustum[2] - noLensFrustum[0];
noLensFrustum[0] = -(w + noLensFrustum[0]);
noLensFrustum[2] = w - noLensFrustum[2];
viewport.x = 1 - (viewport.x + viewport.width);
}
return vertices;
};
Here is what I have tried:
Line 3511
function shouldUseNative() {
return false;
}
Line 80341
window.hasNativeWebVRImplementation = false;
window.hasNativeWebXRImplementation = false;
[UPDATE]
I find that A-Frame 0.9.2 uses polyfill directly and since 1.0.0 it uses native Google VR service to display.
enterVR: {
value: function (useAR) {
var self = this;
var vrDisplay;
var vrManager = self.renderer.xr;
// Don't enter VR if already in VR.
if (this.is('vr-mode')) { return Promise.resolve('Already in VR.'); }
// Has VR.
if (this.checkHeadsetConnected() || this.isMobile) {
vrDisplay = utils.device.getVRDisplay();
vrManager.enabled = true;
vrManager.setDevice(vrDisplay);
if (this.hasWebXR) {
// XR API.
if (this.xrSession) {
this.xrSession.removeEventListener('end', this.exitVRBound);
}
navigator.xr.requestSession(useAR ? 'immersive-ar' : 'immersive-vr', {
requiredFeatures: ['local-floor'],
optionalFeatures: ['bounded-floor']
}).then(function requestSuccess (xrSession) {
self.xrSession = xrSession;
vrManager.setSession(xrSession);
xrSession.addEventListener('end', self.exitVRBound);
if (useAR) {
self.addState('ar-mode');
}
enterVRSuccess();
});
} else {
vrDisplay = utils.device.getVRDisplay();
vrManager.setDevice(vrDisplay);
if (vrDisplay.isPresenting &&
!window.hasNativeWebVRImplementation) {
enterVRSuccess();
return Promise.resolve();
}
var rendererSystem = this.getAttribute('renderer');
var presentationAttributes = {
highRefreshRate: rendererSystem.highRefreshRate,
foveationLevel: rendererSystem.foveationLevel
};
return vrDisplay.requestPresent([{
source: this.canvas,
attributes: presentationAttributes
}]).then(enterVRSuccess, enterVRFailure);
}
return Promise.resolve();
}
// No VR.
enterVRSuccess();
return Promise.resolve();
// Callback that happens on enter VR success or enter fullscreen (any API).
function enterVRSuccess () {
// vrdisplaypresentchange fires only once when the first requestPresent is completed;
// the first requestPresent could be called from ondisplayactivate and there is no way
// to setup everything from there. Thus, we need to emulate another vrdisplaypresentchange
// for the actual requestPresent. Need to make sure there are no issues with firing the
// vrdisplaypresentchange multiple times.
var event;
if (window.hasNativeWebVRImplementation && !window.hasNativeWebXRImplementation) {
event = new CustomEvent('vrdisplaypresentchange', {detail: {display: utils.device.getVRDisplay()}});
window.dispatchEvent(event);
}
self.addState('vr-mode');
self.emit('enter-vr', {target: self});
// Lock to landscape orientation on mobile.
if (!isWebXRAvailable && self.isMobile && screen.orientation && screen.orientation.lock) {
screen.orientation.lock('landscape');
}
self.addFullScreenStyles();
// On mobile, the polyfill handles fullscreen.
// TODO: 07/16 Chromium builds break when `requestFullscreen`ing on a canvas
// that we are also `requestPresent`ing. Until then, don't fullscreen if headset
// connected.
if (!self.isMobile && !self.checkHeadsetConnected()) {
requestFullscreen(self.canvas);
}
self.renderer.setAnimationLoop(self.render);
self.resize();
}
function enterVRFailure (err) {
if (err && err.message) {
throw new Error('Failed to enter VR mode (`requestPresent`): ' + err.message);
} else {
throw new Error('Failed to enter VR mode (`requestPresent`).');
}
}
},
writable: true
},
I find that in 0.9.2 this.hasXR = false and in 1.0.0 this.hasXR = true. So in 1.0.0 I set this value to false and then in else{} it says vrDisplay.isPresenting is not defined. It seems that vrDisplay = utils.device.getVRDisplay(); cannot get the right value like those in 0.9.2.
Then I find this code:
function getVRDisplay () { return vrDisplay; }
For the right return vrDisplay, I tried to change the codes above it:
if (false) {
var updateEnterInterfaces = function () {
var sceneEl = document.querySelector('a-scene');
if (sceneEl.hasLoaded) {
sceneEl.components['vr-mode-ui'].updateEnterInterfaces();
} else {
sceneEl.addEventListener('loaded', updateEnterInterfaces);
}
};
var errorHandler = function (err) {
error('WebXR session support error: ' + err.message);
};
if (navigator.xr.isSessionSupported) {
// Current WebXR spec uses a boolean-returning isSessionSupported promise
navigator.xr.isSessionSupported('immersive-vr').then(function (supported) {
supportsVRSession = supported;
updateEnterInterfaces();
}).catch(errorHandler);
navigator.xr.isSessionSupported('immersive-ar').then(function (supported) {
supportsARSession = supported;
updateEnterInterfaces();
}).catch(function () {});
} else if (navigator.xr.supportsSession) {
// Fallback for implementations that haven't updated to the new spec yet,
// the old version used supportsSession which is rejected for missing
// support.
navigator.xr.supportsSession('immersive-vr').then(function () {
supportsVRSession = true;
updateEnterInterfaces();
}).catch(errorHandler);
navigator.xr.supportsSession('immersive-ar').then(function () {
supportsARSession = true;
updateEnterInterfaces();
}).catch(function () {});
} else {
error('WebXR has neither isSessionSupported or supportsSession?!');
}
} else {
console.log('navigator.getVRDisplays',!!navigator.getVRDisplays);
if (navigator.getVRDisplays) {
navigator.getVRDisplays().then(function (displays) {
console.log('displays[0]',displays[0]);
var sceneEl = document.querySelector('a-scene');
vrDisplay = displays.length && displays[0];
console.log(vrDisplay);
if (sceneEl) { sceneEl.emit('displayconnected', {vrDisplay: vrDisplay}); }
});
}
}
Then the vrDisplay has the right value(CardboardVRDisplay). However, in this way when I enter VR mode the screen becomes black. After comparing the vrDisplay between 0.9.2 and 1.0.0, I find the distorter of vrDisplay is null in 1.0.0.
I think the keypoint is vrDisplay = utils.device.getVRDisplay() in EnterVR but I don't know how to solve it, hope someone could see this question and help this poor newbie..
Related
original post: ( before fix )..
I develop an application (transformer.html) with XDK (ThreeJS and WebGL ) to control another application. The communication is established via a WebService (VB ASP.Net). The first version of this transformer.html had NO WebGL neither crosswalk. In debug and emulator-mode all is fine. Also compiled as a legacy hybrid mobile APK and published to my Samsung Galaxy Tab 3 without any problems. The problems pop up when I implement CrossWalk AND XMLHTTPRequest in my app.
The same origin policy seems not to be a problem. I placed this on web server side (in web.config).
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
As said - the constellation Transformer-APP on Tablet -- WebService --- TargetWebApplication is running perfectly in my local network!
The Problem:
The problem I run into came up with implementing a simple WebGL graphic. Everything is running perfectly in simulation and debug, and when I just run this in a Firefox browser. But when I build an APK this combination (CrossWalk & XMLHTTPRequest) fails!
*kristina/14.03.15: it´s working now. i consequently used this XDK-example: https://github.com/gomobile/sample-webgl-threejs
i took my httprequest in and it was working fine!*
Before:
XMLHTTPRequest (or even the POST via jQuery!) work fine under Android Legacy build. I could make the APK running but there was no Crosswalk WebGL graphic visible on my app. So HTTP Post was OK, but not Crosswalk. I´m wondering if it is possible to build a legacy App with Crosswalk. Even with the XDK's own Crosswalk demo, I was not able to build as a hybrid Legacy APK.
CrossWalk was OK on my app when I build with CrossWalk for Android, but, in this case, XMLHTTPRequest seems not possible. My connection to the WebService fails; I got a 404. But, as I said, all communication should be there, as in other modes (legacy, emulation, browser, whatever...), its working.
kristina/14.03.15: XDK recomment to build it in Android/Crosswalk. This is working NOW. The trick is to set specific host parameters in the build section!
<access origin="*"/>
( handle with care. e.g. reduce this to limited hosts! my setup only is working in my smal local environment. This way it´s ok for me )
those info was very helpful during the errorTracking:
*https://software.intel.com/en-us/xdk/docs/adding-special-build-options-to-your-xdk-cordova-app-with-the-intelxdk-config-additions-xml-file
https://software.intel.com/en-us/xdk/docs/using-the-cordova-for-android-ios-etc-build-option
http://www.ilinsky.com/articles/XMLHttpRequest/#usage
This was NOT very helpful - as in XDK/cordova/Crosswalk the manifest.json seem not effect anything(!?):
https://crosswalk-project.org/documentation/manifest/content_security_policy.html
As so soften it was the same-origine topic i struggled..
Many Thanks to Paul (Intel) who gave me the final hint :-)
Now the construction
CrossWalk - WebGL - XMLHttpRequest - Webservice is working perfect
*
My Setup:
XDK1826 (latest release I got automatically!)
Samsung Galaxy Tab 3
If you need more info please let me know.
THIS code is running after the fixes:
main.js::
/*jslint browser:true, devel:true, white:true, vars:true, eqeq:true */
/*global THREE:false, requestAnimationFrame:false*/
/*
* Based on http://threejs.org/examples/canvas_geometry_cube.html
*/
document.addEventListener ('DOMContentLoaded', function () {
var camera, scene, renderer;
var cube, plane;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var mouseX = 0;
var mouseXOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var auto_timer = 0;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true, devicePixelRatio: 1 } );
renderer.setSize (window.innerWidth, window.innerHeight);
document.body.appendChild (renderer.domElement);
camera = new THREE.PerspectiveCamera (
70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.y = 150;
camera.position.z = 500;
scene = new THREE.Scene();
// Cube
var geometry_cube = new THREE.CubeGeometry (200, 200, 200);
var texture = THREE.ImageUtils.loadTexture ('textures/crosswalk.png');//Works on mobile Android NOT in Browser or Intel XDK
texture.anisotropy = renderer.getMaxAnisotropy ();
var material_cube = new THREE.MeshBasicMaterial ( { map: texture } );
cube = new THREE.Mesh (geometry_cube, material_cube);
cube.position.y = 150;
scene.add( cube );
// Plane
var geometry_plane = new THREE.PlaneGeometry (180, 180);
geometry_plane.applyMatrix (new THREE.Matrix4 ().makeRotationX (-Math.PI / 2));
var material_plane = new THREE.MeshBasicMaterial ( { color: 0xde613e } );
plane = new THREE.Mesh (geometry_plane, material_plane);
scene.add (plane);
document.addEventListener ('mousedown', onDocumentMouseDown, false);
document.addEventListener ('touchstart', onDocumentTouchStart, false);
document.addEventListener ('touchmove', onDocumentTouchMove, false);
// Generic setup
window.addEventListener ('resize', onWindowResize, false);
}
function onWindowResize () {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix ();
renderer.setSize (window.innerWidth, window.innerHeight);
}
function stopAutoRotate () {
if (auto_timer)
window.clearTimeout (auto_timer);
auto_timer = window.setTimeout (startAutoRotate, 1000);
}
function startAutoRotate () {
auto_timer = 0;
}
function animate () {
requestAnimationFrame (animate);
plane.rotation.y = cube.rotation.y += (targetRotation - cube.rotation.y) * 0.05;
if (auto_timer === 0) {
targetRotation += 0.025;
}
renderer.render (scene, camera);
}
function onDocumentMouseDown (e) {
e.preventDefault();
document.addEventListener ('mousemove', onDocumentMouseMove, false);
document.addEventListener ('mouseup', onDocumentMouseUp, false);
document.addEventListener ('mouseout', onDocumentMouseOut, false);
mouseXOnMouseDown = e.clientX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
stopAutoRotate ();
}
function onDocumentMouseMove (e) {
mouseX = e.clientX - windowHalfX;
targetRotation = targetRotationOnMouseDown +
(mouseX - mouseXOnMouseDown) * 0.02;
stopAutoRotate ();
}
function onDocumentMouseUp (e) {
document.removeEventListener ('mousemove', onDocumentMouseMove, false);
document.removeEventListener ('mouseup', onDocumentMouseUp, false);
document.removeEventListener ( 'mouseout', onDocumentMouseOut, false);
stopAutoRotate ();
}
function onDocumentMouseOut (e) {
document.removeEventListener ('mousemove', onDocumentMouseMove, false);
document.removeEventListener ('mouseup', onDocumentMouseUp, false);
document.removeEventListener ('mouseout', onDocumentMouseOut, false);
stopAutoRotate ();
}
function onDocumentTouchStart (e) {
if (e.touches.length === 1) {
e.preventDefault ();
miniHttpTest();
getSphereParametersWSxhr();
mouseXOnMouseDown = e.touches[ 0 ].pageX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
stopAutoRotate ();
}
}
function onDocumentTouchMove (e) {
if (e.touches.length === 1) {
e.preventDefault ();
mouseX = e.touches[0].pageX - windowHalfX;
targetRotation = targetRotationOnMouseDown +
(mouseX - mouseXOnMouseDown) * 0.05;
stopAutoRotate ();
}
}
});
function XHRObject() {
var xhr;
xhr = new XMLHttpRequest();
xhr.onerror = function () {};
xhr.onstart = function () {};
xhr.success = function () {};
return xhr;
}
function getSphereParametersWSxhr() {
var url = "http://192.444.2.444/transporter.asmx/getVideoCubeParameters";
xhr = new XMLHttpRequest();
var params = "";
console.log(xhr);
alert("----------------------------- getSphereParametersWSxhr - before open POST : " + xhr);
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// forbidden xhr.setRequestHeader("Content-length", params.length);
alert("after open POST : " + xhr);
try {
xhr.onreadystatechange = function () {
alert("xhr.readyState == " + xhr.readyState + " xhr.status == " + xhr.status + " xhr.statusText: " + xhr.statusText + " xhr.responseText" + xhr.responseText);
if (xhr.readyState == 2 && xhr.status == 404) {
console.log("404 page not found: " + xhr);
alert("404 page not found: " + xhr);
}
if (xhr.readyState == 3) {
console.log("ready state 3: " + xhr.statusText + " " + xhr.status);
alert("ready state 3: " + xhr.statusText + " " + xhr.status);
}
if (xhr.readyState == 4) { //&& xhr.status == 200
console.log("ready state 4: " + xhr.statusText + " " + xhr.responseText);
alert("ready state 4: " + xhr.statusText + " " + xhr.responseText);
var erg1 = xhr.responseXML.getElementsByTagName("videoCubeSizeX")[0].textContent;
var stringList = erg1.split(";");
console.log(erg1);
alert("videoCubeSizeX: " + erg1);
alert(xhr.responseText);
}
}
xhr.send(params);
} catch (e) {
console.log("XHR Post : " + e);
alert("XHR Post : " + e);
}
}
function miniHttpTest() {
alert("miniHttpTest: mit GET ");
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://crosswalk-project.org/", true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
alert("ready state 4: " + xhr.statusText + " " + xhr.responseText);
}
}
xhr.send();
}
I'm working on a simple Alloy app. I have a view I want to move back and forth horizontally (thus to move and then return to its original position).
I wrote this function
function move(view) {
var origin = view.getCenter();
console.log("origin ", origin);
console.log("rect ", view.getRect());
var forth = Titanium.UI.createAnimation();
forth.duration = 700;
forth.center = {
x: 0
};
forth.addEventListener('complete', function() {
view.animate(back);
});
var back = Titanium.UI.createAnimation();
back.duration = 300;
back.center = {
x: origin.x
};
back.addEventListener('complete', function() {
alert('completed');
});
view.animate(forth);
}
I you run it, it crashes at x: origin.x because origin is undefined. Moreover, both view.center and view.rect are undefined, thus it's impossible for me to store the original position.
Any help?
Thanks
PS: Code has been tested on iOS simulator, although is meant to be Android and iOS compatible.
Why dont you just animate the left position and work with the view.getRect() ?
var origin = view.getRect();
//console.log("origin ", origin);
console.log("rect ", view.getRect());
var forth = Titanium.UI.createAnimation();
forth.duration = 5000;
forth.left = 0;
forth.addEventListener('complete', function() {
view.animate(back);
});
var back = Titanium.UI.createAnimation();
back.duration = 5000;
back.left = origin.x;
back.addEventListener('complete', function() {
alert('completed');
});
view.animate(forth);
How to pull to refresh?
In Titanium appcelerator I need to show a list of content in tableview. If I pull the view it needs to update. In iPhone I complete but in Android it won't work. Please any one help to solve this problem in Android.
My Android code:-
tableView.addEventListener('scroll',function(e)
{
var offset = e.contentOffset.y;
if (offset < -65.0 && !pulling && !reloading)
{
var t = Ti.UI.create2DMatrix();
t = t.rotate(-180);
pulling = true;
arrow.animate({transform:t,duration:180});
statusLabel.text = "Release to refresh...";
}
else if((offset > -65.0 && offset < 0 ) && pulling && !reloading)
{
pulling = false;
var t = Ti.UI.create2DMatrix();
arrow.animate({transform:t,duration:180});
statusLabel.text = "Pull down to refresh...";
}
});
tableView.addEventListener('dragEnd', function(e)
{
if(pulling && !reloading)
{
reloading = true;
pulling = false;
arrow.hide();
actInd.show();
statusLabel.text = "Reloading...";
tableView.setContentInsets({top:60},{animated:true});
tableView.scrollToTop(-60,true);
arrow.transform=Ti.UI.create2DMatrix();
beginReloading();
}
});
Titanium now supports pull to refresh for BOTH Android (> v6.2.0) and iOS (>3.2.0) with a Titanium.UI.TableView, Titanium.UI.ListView or Titanium.UI.ScrollView object.
See the docs:
https://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.ListView
https://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.RefreshControl
Sample code taken from the docs:
var win = Ti.UI.createWindow({
fullscreen:true
});
var counter = 0;
function genData() {
var data = [];
for (var i=1; i<=3; i++) {
data.push({properties:{title:'ROW '+(counter+i)}})
}
counter += 3;
return data;
}
var section = Ti.UI.createListSection();
section.setItems(genData());
var control = Ti.UI.createRefreshControl({
tintColor:'red'
})
var listView = Ti.UI.createListView({
sections:[section],
refreshControl:control
});
control.addEventListener('refreshstart',function(e){
Ti.API.info('refreshstart');
setTimeout(function(){
Ti.API.debug('Timeout');
section.appendItems(genData());
control.endRefreshing();
}, 2000);
})
win.add(listView);
win.open();
Is this just the IOS code form the Kitchen Sink example?
There are a couple of attempts at getting this working on Android, though I haven't confirmed that any of them work as expected. From what I understand, the problem is that you can't get the offset the same way in Android as in IOS.
A quick Google search turned up this link, which was referenced from the official Appcelerator forums.
https://gist.github.com/903895
Original Title but too long for post:
"ASP.NET MVC 4, Razor, JQuery, JQueryMobile, Problems with Mobiscroll - orientationchange and access address bar crashes some mobile browsers. Changing scroller width and height does not work on some phones."
The crash issue happens on Android 2.1.
It does not happen on iPhone, HTC EVO 4G LTE or other HTCs.
Changing the scroller width and height does not work on HTCs. If I change to landscape then the scroller is the same size as it should be in portrait. If I change it back to portrait then the scroller is the size it should have been in landscape.
Here is the JQuery/Mobiscroll code:
function createDatePicker(selector){
if($("#input_date_1").scroller('isDisabled') != 'undefined'){
var scrollWidth = ($("div[id='main_content']").width()) / 4;
var scrollHeight = scrollWidth / 2.5;
$("#input_" + selector).scroller({
preset: 'date',
minDate: new Date(2000, 0, 1),
maxDate: new Date(2020, 11, 31),
theme: 'android',
display: 'inline',
mode: 'scroller',
dateOrder: 'mmddyy',
width: scrollWidth,
height: scrollHeight,
onChange: function (valueText, inst) {
var lbl = $("#lbl_" + selector);
var date = $("#input_" + selector).scroller('getDate');
lbl.text(date.toDateString());
}
});
}
function setDatePickerWidthAndHeight(){
var scrollWidth = ($("div[id='main_content']").width()) / 4;
var scrollHeight = scrollWidth / 2.5;
var selectorBase1 = "date_1";
$("#input_" + selectorBase1).eq(0).scroller('option', 'width', scrollWidth);
$("#input_" + selectorBase1).eq(0).scroller('option', 'height', scrollHeight);
}
$(function () {
createDatePicker('date_1');
$(window).bind('orientationchange', function (event) {
setTimeout(setDatePickerWidthAndHeight(),100);
});
});
I am including these scripts in #section scripts {} which is rendered at the bottom of the page ( not sure if that is relevant ).
Any help would be appreciated.
It turns out the problem was that the older Android phones do not like the resize event the way it was written above.... and newer phones did not like the orientationchange event. The code at this link made everything work perfectly:
http://paulirish.com/2009/throttled-smartresize-jquery-event-handler/
And here is how I used it:
//
// usage:
//$(window).smartresize(function () {
// // code that takes it easy...
//});
//http://paulirish.com/2009/throttled-smartresize-jquery-event-handler/
(function ($, sr) {
// debouncing function from John Hann
// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
var debounce = function (func, threshold, execAsap) {
var timeout;
return function debounced() {
var obj = this, args = arguments;
function delayed() {
if (!execAsap)
func.apply(obj, args);
timeout = null;
};
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
};
}
// smartresize
jQuery.fn[sr] = function (fn, threshold, execAsap) { return fn ? this.bind('resize', debounce(fn, threshold, execAsap)) : this.trigger(sr); };
})(jQuery, 'smartresize');
$(function () {
createDatePicker('date_1');
$(window).smartresize(function () {
setDatePickerWidthAndHeight();
}, 200);
});
I found the link in the answer of this post: window.resize in jquery firing multiple times
Thanks!
var style1 = document.createElement("link");
style1.id = "rel";
style1.rel = "stylesheet";
style1.href = "http://www.mysite.com/css.css";
style1.onload = function(){document.body.innerHTML+="fffffff";};
document.getElementsByTagName("head")[0].appendChild(style1);
This code works in Chrome/Firefox, and yet stock browsers on my Froyo (2.3) and Jellybean (4.1) Android devices will print nothing. What's the problem? I'd like if I could execute some js onload of a link. Anything else would in my case amount to a hack. :/
The problem isn't innerHTML. Try it with alerts if you want (at your own peril).
Another answer mentions checking for this functionality by doing
var huh = 'onload' in document.createElement('link');
..but this is true in both stock browsers! wtf guys?
Android browser doesn't support "onload" / "onreadystatechange" events for element: http://pieisgood.org/test/script-link-events/
But it returns:
"onload" in link === true
So, my solution is to detect Android browser from userAgent and then wait for some special css rule in your stylesheet (e.g., reset for "body" margins).
If it's not Android browser and it supports "onload" event- we will use it:
var userAgent = navigator.userAgent,
iChromeBrowser = /CriOS|Chrome/.test(userAgent),
isAndroidBrowser = /Mozilla\/5.0/.test(userAgent) && /Android/.test(userAgent) && /AppleWebKit/.test(userAgent) && !iChromeBrowser;
addCssLink('PATH/NAME.css', function(){
console.log('css is loaded');
});
function addCssLink(href, onload) {
var css = document.createElement("link");
css.setAttribute("rel", "stylesheet");
css.setAttribute("type", "text/css");
css.setAttribute("href", href);
document.head.appendChild(css);
if (onload) {
if (isAndroidBrowser || !("onload" in css)) {
waitForCss({
success: onload
});
} else {
css.onload = onload;
}
}
}
// We will check for css reset for "body" element- if success-> than css is loaded
function waitForCss(params) {
var maxWaitTime = 1000,
stepTime = 50,
alreadyWaitedTime = 0;
function nextStep() {
var startTime = +new Date(),
endTime;
setTimeout(function () {
endTime = +new Date();
alreadyWaitedTime += (endTime - startTime);
if (alreadyWaitedTime >= maxWaitTime) {
params.fail && params.fail();
} else {
// check for style- if no- revoke timer
if (window.getComputedStyle(document.body).marginTop === '0px') {
params.success();
} else {
nextStep();
}
}
}, stepTime);
}
nextStep();
}
Demo: http://codepen.io/malyw/pen/AuCtH