Redirect in iframe with ios browser freezes Phaser canvas - ios

I use Phaser to create a game but I found an problem for using it in for example facebook. When an redirect is done within an iframe the canvas is not responding after a click.
Example:
I have a IFrame and within the iframe I redirect to the game.html. When I click in the game.html everything freezes.
Everything works fine when using a computer (any browser), windows phone or android, but with an iphone or ipad it won't work.
Below are the example files to replay the problem...
index.html:
<html>
<body>
<iframe src="click.html" height="900" width="800"/>
</body>
</html>
click.html
<!DOCTYPE html>
<html>
<body>
CLICK HERE
</body>
</html>
Game.html
<!DOCTYPE html>
<html>
<head>
<style>
body{overflow:hidden;}
#game_div {
width: 760px;
height: 1100px;
margin: auto;
}
</style>
<script type="text/javascript" src="./Game/phaser.min.js"></script>
<script type="text/javascript" src="./Game/main.js"></script>
</head>
<body>
<div id="game_div"> </div>
</body>
</html>
main.js
var game = new Phaser.Game(760, 1100, Phaser.AUTO, 'game_div');
var overlay, countdownText;
var counter = 0;
var main_state = {
preload: function() {
},
create: function () {
//game overlay
overlay = game.add.graphics(0, 0);
overlay.beginFill(0x00A54F, 0.8);
overlay.drawRect(0, 0, game.width, game.height);
countdownText = game.add.text((game.width / 2), (game.height / 2), counter, { font: "65px Arial", fill: "#ffffff", align: "center" });
countdownText.anchor.set(0.5,0.5);
},
update: function() {
countdownText.setText(counter++);
}
}
game.state.add('main', main_state);
game.state.start('main');
TNX

Found the solution, with thanks to Rich Davey.
When I add the following code it works:
game.stage.disableVisibilityChange = true;

Related

RTSP (video stream) in Electron

I've installed fluent-ffmpeg and ffmpeg-static to convert a stream into an HTML reproducible video. How can I use these packages to display the stream in the client?
Server side (main.js):
const { app, BrowserWindow } = require('electron');
const ffmpeg = require('fluent-ffmpeg');
const ffmpegPath = require('ffmpeg-static').replace('app.asar', 'app.asar.unpacked');
ffmpeg.setFfmpegPath(ffmpegPath);
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
});
win.loadFile('index.html');
}
function testStream () {
let source = 'rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov';
}
app.whenReady().then(createWindow).then(testStream);
Client side (index.html):
<!DOCTYPE html>
<html>
<head>
<meta charset = 'UTF-8'>
</head>
<body>
<h1>I want to reproduce the video here</h1>
</body>
</html>
If I understand correctly; you're probably looking to start with something like this:
<video id="video-player" controls preload="none" style="border: 5px solid red; height: 1080px; width: 1920px; ">
<source src="index.m3u8" type="application/x-mpegURL">
</video>

Strange default size in leaflet map

I have taken a working Leaflet map, but when I added a JQuery Mobile header and back button the formatting went crazy.
Initially loading the page all the contents is loaded in the upper-left-hand corner, but when the page is resized the smallest bit on a desktop, or rotated on a mobile, everything is fine.
This is what it looks like when opened:
and what it looks like after rotating (and what it should be):
Here is the code for the page
<!DOCTYPE html>
<html>
<head>
<title>Toronto CAD Activity Map</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../css/leaflet.css" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../css/tfscad.mobile.css" />
<link rel="stylesheet" href="../css/jquery.mobile-1.4.5.min.css">
<link rel="stylesheet" href="../css/font-awesome.min.css">
<script src="../js/jquery-1.11.1.min.js"></script>
<script src="../js/jquery.mobile-1.4.5.min.js"></script>
<script src="../js/iframeResizer.contentWindow.js"></script>
<!--[if lte IE 8]><link rel="stylesheet" href="../dist/leaflet.ie.css" /><![endif]-->
<style>
#mapPage {
height: calc(100% - 42px);
}
#map {
height: 100%;
}
#map-content{
height: 100%;
padding: 0px;
margin:0px;
z-index: -1;
}
#curLoc{
position: absolute;
bottom: 0;
left: 10px;
}
</style>
</head>
<body>
<body>
<div data-role="page" id="mapPage" data-theme="a">
<div data-role="header" data-position="fixed" data-theme="a">
<a id="backButton" href="#" data-rel="back"
data-transition="slide" data-direction="reverse">Back</a>
<h1>Toronto CAD Map</h1>
</div>
<div id="map-content" data-role="content">
<div id="map"></div>
</div>
<a id="curLoc" data-role="button" data-icon="location" data-iconpos="notext"></a>
</div>
<script src="../js/jquery-1.11.1.min.js"></script>
<script src="../js/leaflet.js"></script>
<script type="text/javascript">
window.onload = function() {
getGeoJson();
getTPSJson();
};
var map = L.map('map').setView([43.7178,-79.3762], 11);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © 2011 OpenStreetMap contributors, Imagery © 2012 CloudMade',
}).addTo(map);
function getGeoJson(){
// load GeoJSON from an external file
$.getJSON("../appdata/geo.json",function(data){
L.geoJson(data ,{
pointToLayer: function(feature,latlng){
var TFS = new L.icon({
iconUrl: '../images/tfs_logo.png',
iconSize: [22, 22],
popupAnchor: [0, -22]
});
var TPS = new L.icon({
iconUrl: '../images/tps_logo.png',
iconSize: [22, 22],
popupAnchor: [0, -22]
});
var ESC = new L.icon({
iconUrl: '../images/tps_logo.png',
iconSize: [22, 22],
popupAnchor: [0, -22]
});
if(feature.properties.icon == 'TFS'){
var marker = L.marker(latlng,{icon: TFS});
marker.bindPopup('<strong>' + feature.properties.event_type + '</strong><br/>' + feature.properties.OPEN_DT);
return marker;
}else if(feature.properties.icon == 'TPS'){
var marker = L.marker(latlng,{icon: TPS});
marker.bindPopup('<strong>' + feature.properties.event_type + '</strong><br/>' + feature.properties.OPEN_DT);
return marker;
}else if(feature.properties.icon == 'ESC'){
var marker = L.marker(latlng,{icon: ESC});
marker.bindPopup('<strong>' + feature.properties.event_type + '</strong><br/>' + feature.properties.OPEN_DT);
return marker;
}
}
} ).addTo(map);
});
}
function getTPSJson(){
var myStyle = {
"color": "#ff7800",
"weight": 5,
"opacity": 0,
"offset": 1.5
};
// load GeoJSON from an external file
$.getJSON("../appdata/TPSDiv.json",function(myLines){
L.geoJson(myLines, {
style: myStyle
}).addTo(map);
})
}
setInterval(function()
{
getGeoJson();
}, 10000);//time in milliseconds
function onClick(e) {
//console.log(this.options.win_url);
window.open(this.options.win_url);
}
</script>
</body>
jQuery Mobile has its own way to create pages from div's, so you may better stick to JQM events.
Here is a great post of Omar which explain how to solve this (typical) issue when loading Google Maps. You should wait for pagecontainershow or use a placeholder to pre-load the maps in advance.
In my example below, you will find a variation of this approach for Leaflet which uses the same canvasHeight() function (see also the answers here: set content height 100% jquery mobile).
I noticed you are about to implement a footer button for the geo-location feature, so for your convenience i show you also a possible way to do that (credits: Getting current user location automatically every “x” seconds to put on Leaflet map?).
Please note: i had to reposition the default map attribution so it won't overlap with the footer button.
var map, actualPosition, actualAccuracy, autoUpdate;
function canvasHeight(canvas) {
var mapPage = $("#page-map"),
screen = $.mobile.getScreenHeight(),
header = $(".ui-header", mapPage).hasClass("ui-header-fixed") ? $(".ui-header", mapPage).outerHeight() - 1 : $(".ui-header", mapPage).outerHeight(),
footer = $(".ui-footer", mapPage).hasClass("ui-footer-fixed") ? $(".ui-footer", mapPage).outerHeight() - 1 : $(".ui-footer", mapPage).outerHeight(),
newHeight = screen - header - footer;
$(canvas).height(newHeight);
}
$(window).on("throttledresize orientationchange", function() {
canvasHeight("#map");
})
function onLocationFound(e) {
var radius = e.accuracy / 2;
actualPosition = L.marker(e.latlng).addTo(map);
actualAccuracy = L.circle(e.latlng, radius).addTo(map);
}
function onLocationError(e) {
alert(e.message);
}
function showLocation() {
if (actualPosition) {
map.removeLayer(actualPosition);
map.removeLayer(actualAccuracy);
}
map.locate({setView: true,maxZoom: 16});
}
function loadMap(canvas) {
map = L.map(canvas).setView([43.7178, -79.3762], 11);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(map);
map.on('locationfound', onLocationFound);
map.on('locationerror', onLocationError);
// Your custom initialization
//getGeoJson();
//getTPSJson();
}
function toggleAutoUpdate() {
if (autoUpdate) {
$("#autoUpdate").removeClass("ui-btn-active");
clearInterval(autoUpdate);
autoUpdate = null;
if (actualPosition) {
map.removeLayer(actualPosition);
map.removeLayer(actualAccuracy);
}
} else {
$("#autoUpdate").addClass("ui-btn-active");
showLocation();
autoUpdate = setInterval(function() {
showLocation();
// Your custom Update
//getGeoJson();
}, 10 * 1000);
}
}
$(document).on("pagecontainershow", function(e, ui) {
if (ui.toPage.prop("id") == "page-map") {
canvasHeight("#map");
if (!map) {
loadMap("map");
}
}
});
#map {
margin: 0;
padding: 0;
}
#page-map .footer {
position: fixed;
z-index: 1000;
bottom: .1em;
width: 100%;
}
#footer-button {
width: 100%;
text-align: center;
background: transparent;
}
#map-attribution {
text-align: center;
background: rgba(255, 255, 255, 0.7);
}
.leaflet-control-attribution.leaflet-control {
display: none;
}
/* Don't show scrollbars on SO code snippet */
.ui-mobile .ui-page {
min-height: 100px !important;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<link rel="stylesheet" href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.1.0/leaflet.css">
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.1.0/leaflet.js"></script>
</head>
<body>
<div data-role="page" id="page-map">
<div data-role="header" data-position="fixed" data-theme="a">
Back
<h1>Toronto CAD Map</h1>
</div>
<div id="map" data-role="content">
<div class="footer">
<div id="footer-button">
<button id="autoUpdate" onclick="toggleAutoUpdate();" class="ui-btn ui-btn-inline ui-corner-all ui-icon-location ui-btn-icon-notext"></button>
</div>
<div id="map-attribution">
Leaflet Map data © 2011 OpenStreetMap contributors, Imagery © 2012 CloudMade
</div>
</div>
</div>
</div>
</body>
</html>
jQuery Mobile manages the pages of your multi-pages document and resizes them appropriately when DOM is loaded.
The issue is that you have already instantiated your map with Leaflet before that event happens, so the map container (i.e. <div id="map"></div>) is not displayed yet by jQuery Mobile, and therefore its size is not computed yet by the browser.
This is a variant of map container size not being valid yet at map instantiation. See Data-toggle tab does not download Leaflet map
Since you already have a listener on window.onload, which executes after jQuery Mobile does its stuff, you could very simply call map.invalidateSize() at that moment:
window.onload = function() {
// Request Leaflet to re-evaluate the map container size
// AFTER jQuery Mobile displays the page.
map.invalidateSize();
getGeoJson();
getTPSJson();
};
Demo: https://plnkr.co/edit/TigW44s5MlqMifimWkSw?p=preview

iOS 7 UIWebView memory leak with Google Maps Javascript API

I have an iOS application which displays a map using the Google Maps Javascript API in a UIWebView. It seems that in iOS 7.0, something has changed in the UIWebView implementation that is causing map objects to not be released when there are no longer any references.
Using the XCode memory profiler, I see a 7-20 MB increase in RAM each time a map is created. Removing the map, and clearing references to it does not decrease the memory usage. Memory warnings do not seem to trigger Javascript garbage collection. When running the code on a physical device, the application logs memory warnings and inevitably will crash.
Here is some simplified Javascript which demonstrates the problem:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title></title>
<style type="text/css" media="screen">
body { padding-top: 20px;}
#container { width:100%; height:200px; }
#container > div { height: 100%; width: 100%; }
</style>
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" charset="utf-8">
var domEl;
function createMap() {
var container = document.getElementById( 'container' );
// Create fresh dom element
//
if( domEl ) {
container.removeChild( domEl );
console.log('removed old dom element');
}
domEl = document.createElement( 'div' );
container.appendChild( domEl );
// Create map
//
var mapOptions = {
center: new google.maps.LatLng( -34.397, 150.644 ),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
new google.maps.Map( domEl, mapOptions );
return false;
}
</script>
</head>
<body>
Create map
<div id="container"></div>
</body>
</html>
I've also posted a complete XCode project on GitHub.
Has anyone seen this before? Can someone suggest a fix or workaround? In this case I have to use the Google Maps API; a native solution isn't an option.

jquery returning to previous state

when i click the add image button a new image appears
when i click the new image can i revert it back to my previous state using jquery...showing the previous image with add image on hover
http://jsfiddle.net/6MmMe/37/
providing my js code below
$("div").hover(
function () {
$("<div>add image</div>").click(function() {
$(this).parent().unbind("hover").children("img").attr("src", "http://www.onlinegrocerystore.co.uk/images/goodfood.jpg");
$(this).remove();
}).appendTo(this);
},
function () {
$(this).find("div:last").remove();
}
);
The problem is that you are handling the first div, then removing it. There are a few ways to accomplish what I think are your goals.
I would recommend doing it with hide/show for easier management.
If you want to do this in jQuery, you can do it like this:
<!DOCTYPE html>
<html>
<head><script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.js'></script>
<style type='text/css'>
div div { color:red; display:none}
</style>
<script>
$(function(){
$('body > div').hover(function(){
// show "add image"
$('div', this).show();
}, function(){
// hide "add image" and reet image src.
$('div', this).hide();
$('img', this).attr("src", "http://imgs.zinio.com/magimages/500299032/2012/416238969_170.jpg");
})
// top-level click handler
.click(function(){
$('img', this).attr("src", "http://www.onlinegrocerystore.co.uk/images/goodfood.jpg");
});
});
</script>
</head>
<body>
<div>
<img src="http://imgs.zinio.com/magimages/500299032/2012/416238969_170.jpg" alt="Nov-12" title="Food Network Magazine" class="cover">
<div href="#">add image</div>
</div>
</body>
</html>
If you want to do this mostly in CSS, just toggling a class with jQuery, you can do this:
<!DOCTYPE html>
<html>
<head><script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.js'></script>
<style type='text/css'>
body > div {
background-image: url(http://imgs.zinio.com/magimages/500299032/2012/416238969_170.jpg);
width: 170px;
height:222px;
position:relative;
}
body > div.newImage:hover {
background-image: url(http://www.onlinegrocerystore.co.uk/images/goodfood.jpg);
width: 249px;
height:274px;
}
div div {
color:red;
position:absolute;
bottom:0;
margin-bottom:-16px;
display:none;
}
div:hover div {
display:block;
}
</style>
<script>
$(function(){
$('body > div').click(function(){
$(this).addClass('newImage');
}).hover(false, function(){
$(this).removeClass('newImage');
});​
});
</script>
</head>
<body>
<div>
<div>add image</div>
</div>
</body>
</html>
If you really prefer to add/remove things, you can do it like this:
<!DOCTYPE html>
<html>
<head><script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.js'></script>
<style type='text/css'>
div div { color:red;}​
</style>
<script>
$(function(){
$('body > div').hover(function(){
// show "add image"
$(this).append('<div>add image</div>');
}, function(){
// hide "add image" and reset image src.
$('div', this).remove();
$('img', this).attr("src", "http://imgs.zinio.com/magimages/500299032/2012/416238969_170.jpg");
})
// top-level click handler
.click(function(){
$('img', this).attr("src", "http://www.onlinegrocerystore.co.uk/images/goodfood.jpg");
});
});
</script>
</head>
<body>
<div>
<img src="http://imgs.zinio.com/magimages/500299032/2012/416238969_170.jpg" alt="Nov-12" title="Food Network Magazine" class="cover">
</div>
</body>
</html>

cordova 1.7 iOS audiorecord plugin

I've implemented the audio record plugin on IOS using phonegap/cordova 1.7. IOS5.1
I'm using it over the standard media.startrecord() function as I want to change the bitrate to reduce the size of the file.
It works fine in the simulator.
On the real iphone it records successfully once but subsequently refuses.. it seems to work but on playback I'm getting an error 4 MediaError.MEDIA_ERR_NONE_SUPPORTED
I've created a new project with just a bare bones record and playback and I'm still getting the same issue.
Here's the test code - It's very basic - just a couple of links to record two separate files and play them back. The setTimeout is there to record just a couple of seconds of audio each time.
I've googled til I've worn out my fingerprints but haven't found a resolution.
Any insight you can give would be very gratefully received.
I'm wondering if I'm failing to close out the recording/playback properly? Or are files referenced differently on the sim v the iPhone?
Many thanks!
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
<meta charset="utf-8">
<link rel="stylesheet" media="only screen and (max-device-width: 480px)" href="iphone.css" type="text/css" />
<script type="text/javascript" charset="utf-8" src="cordova-1.7.0.js"></script>
<script type="text/javascript">
var fs,mediaRec=null, recInterval,recordSettings = {"FormatID": "kAudioFormatULaw","SampleRate": 16000.0,"NumberOfChannels": 1,"LinearPCMBitDepth": 16};
function recfile1() {recordAudio("test.wav");}
function recfile2() {recordAudio("test2.wav");}
function success(){console.log("ok");}
function recordAudio(fname) {
fs.root.getFile(fname, {create: true, exclusive: false}, function(entry){
mediaRec = new Media(entry.fullPath, success, function(){alert("failed");});
mediaRec.startRecordWithSettings(recordSettings);
recInterval = setTimeout(function() {
mediaRec.stopRecordWithSettings();
}, 2000);
}, function(){console.log("error");});
}
function playfile(fname) {
var my_media;
fs.root.getFile(fname, {create: false, exclusive: false},
function success(entry) {
my_media = new Media(entry.fullPath,function(){console.log("ok");},function(err){alert(err.code+" "+err.message);});
my_media.play();
},
function() {
console.log("not found file");
}
);
}
function onBodyLoad() {
document.addEventListener("deviceready", onDeviceReady, false);
}
function onDeviceReady(){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){fs=fileSystem;}, function(){console.log("failed");});
Media.prototype.startRecordWithSettings = function(options) {
Cordova.exec(null, null, "AudioRecord","startAudioRecord", [this.id, this.src, options]);
};
Media.prototype.stopRecordWithSettings = function() {
Cordova.exec(null, null, "AudioRecord","stopAudioRecord", [this.id, this.src]);
};
}
</script>
</head>
<body onload="onBodyLoad()">
<a onclick="playfile('test.wav');">play</a>
<a style='margin-top:100px;' onclick="recfile1();">record 1</a>
<a style='margin-top:100px;' onclick="recfile2();">record 2</a>
<a onclick="playfile('test2.wav');">play2</a>
</body>
</html>

Resources