GC_CURRENT - Phonegap App crashes - javascript

I want to fill a lottery field with random numbers when the user shakes the phone.
My shake detection
function watchForShake(threshold)
{
console.log ("Am Watching for shakes");
axl.watchAcceleration(
function (Accel)
{
if (true === Accel.is_updating){
return;
}
var diffX = Accel.x - prevX;
if (diffX >= threshold)
{
console.log("Phone shaken");
if (gettingRandomNumbers==false){
randomNumbers();
}
}
prevX = Accel.x
}
, function(){}
, {frequency : 100}
);
}
this Method sets a number in the lottery field as selected.
function clickNumber(number)
{
console.log("ClickNumber invoked with number "+number);
tNumber = $(number).html();
tPosition = $(number).position();
if($(number).hasClass('selected'))
{
lottoNumbers.pop(number);
console.log("number.hasClass = true");
$(number).removeClass('selected');
$(number).children().remove();
}else{
if (lottoNumbers.length <= 5) {
lottoNumbers.push(number);
console.log("number.hasClass = false");
$(number).addClass('selected');
$(number).append('<img src="assets/images/spielschein_kreuz.png" style="position:absolute;top:'+ tPosition.top +'px;left:'+ tPosition.left +'px;"/>');
}
}
}
The next method gets random numbers and sets them in the lotteryfield (using jquery). I think this method is what causes the memory leak. The app doesnt crash when I take out the inner for-loop, but I dont know how to fix it.
function randomNumbers(){
console.log("Am Getting Random Numbers");
gettingRandomNumbers=true;
counter = 0;
clearAllNumbers();
while (counter < 6){
zufallsZahl = Math.floor((Math.random()*49)+1);
zufallsZahlen[counter]=zufallsZahl;
if (isUniqueNumber){
counter++;
console.log("Zufallszahl: "+zufallsZahl);
clickNumber($('#ticket_detail .tipfield .tipbox ul li').filter(function(){return $(this).html() == zufallsZahl;}));
}
}
gettingRandomNumbers = false;
}
I dont know what exactly causes the GC_CONCURRENT message. The app crashes and freezes without an explicit error message. After several shakes detected, the app crashes.
All variables are initialized in the document.ready() method in the index.html file. I dont create new objects on every shake, do I?
any help or hints greatly appreciated.
thank you,
Daniel

Related

JavaScript Choose your own adventure game random number function in loop problem

I'm writing a choose your own adventure program where If a specific option is chosen (example to wait) the user gets a random number between 1-10 to do push ups(the push-ups would be the user clicking on the prompt "ok" button however many times the random number is equal to) here's my code so far but I keep getting errors. I'm a complete noob so go easy on me.
var count = Math.floor((Math.random() * 10) + 1);
var setsOf10 = false;
function pushUps() {
alert("Nice! Lets see you crank out " + pushUps + "!");
}
if (setsOf10 == pushUp) {
alert("Nice! Lets see you crank out " + pushUp + "!");
setsOf10 = true;
}
for (var i=0; i<count; i++){
pushUps();
}
else {
alert("Really, thats it? Try again");
}
while ( setsOf10 == false);
}
After playing with this some more I can tell i'm close but still don't have it. and again, I'M NOT ASKING YOU TO SOLVE THIS FOR ME JUST NEED POINTERS AS TO WHAT IM DOING WRONG OR MISSING. Here's what I have, Its giving me my random number I just need it to allow me to click the "ok" button however many times the random number has assigned me.
var pushUpSets = Math.floor((Math.random() * 10) + 1);
function pushUps(){
alert(pushUpSets);
if (pushUpSets < 3){
var weak = "Thats it? Weak sauce!";
alert(weak);
}
else{
alert("Sweet lets get some reps in!");
}
for (i=0; i>3; i++){
pushUps(pushUpSets);
}
}
Here, the make a choice button is just dummy to allow us to go to do push ups. Each click decrements our count.
// This is important, we use this event to wait and let the HTML (DOM) load
// before we go ahead and code.
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('#choice').addEventListener('click', makeChoice);
});
function makeChoice() {
// Call a method to set random pushups and setup the click event
setUpPushUp();
// Here we change the display style of the push up section so that it shows to the player.
document.querySelector('.activity').style.display = 'block';
}
// The pushups variable is declared at the document level
// This way our setUpPushUp and doPushUp functions have easy access.
let pushUps = 0;
function setUpPushUp() {
// Create a random number of pushups, in sets of 10.
// We add an extra 1 so we can call the doPushUp method to initialize.
pushUps = (Math.floor((Math.random() * 10)+1)*10)+1 ;
// Add a click event to the push up button and call our doPushUp method on each click.
document.querySelector('#push').addEventListener('click', doPushUp);
// This is just an init call, it will use the extra 1 we added and place test in our P tag.
doPushUp();
}
function doPushUp() {
// Get a reference to our output element, we will put text to player here.
let result = document.querySelector('p');
// They have clicked, so remove a push up.
pushUps--;
// See if the player has done all the required push ups (i.e. pushUps is 0 or less.)
if (pushUps > 0) {
result.innerText = `You need to crank out ${pushUps} pushUps`;
} else {
result.innerText = 'Nice work!';
}
}
.activity {
display: none;
}
<button id="choice">Make a choice !</button>
<div class="activity">
<p></p>
<button id="push">Push</button>
</div>

Is there any way to wait for a Dom to be updated or asynchronously update the Dom?

I have a simple loading bar made with css, you update the css and the bar fills, super simple.
I decided to update the bar with jQuery, works great but now I throw it into a practical environment. I have a bunch of files being downloaded and each time a file successfully downloads, it updates the position. The main problem is that it downloads the files so fast, and places the files correctly fast enough that it just doesn't update the loading bar unless I set a timeout interval of 300-400ms..it does log into console and I made an interval function that continously checks to see if a file is finished based on a global variable. No matter where I place the function to update the loading bar or how I update it, it seems the Dom will not react unless there's a big enough delay between files OR it will react at the very end (jumps to 100).
Is there any way to wait for a Dom to be updated by J's OR can you spot a problem in my code that causes this issue?
I also tried promises too but it didn't change how the browser reacts to the function.
This is all being done inside a Cordova environment but I tested it on chrome too and it works as long as the pc is powerful enough it seems.
The file Transfer function has an "on Success" too but that doesn't do anything as the Dom wont update in it until after all the downloads are done OR there's a delay
My solutions so far is to either intentionally lag the downloader, or lag it every 10 or 20 files to update the position
Edit: here's my loading bar Js
var colorInc = 100 / 3;
function setWater(myval)
{
var val = myval;
var waitForMe = $.Deferred();
if(val != ""
&& !isNaN(val)
&& val <= 100
&& val >= 0)
{
setTimeout(function(){waitForMe.resolve()}, 100);
var valOrig = val;
val = 100 - val;
if(valOrig == 0)
{
//$("#percent-box").val(0);
$(".progress .percent").text(0 + "%");
}
else $(".progress .percent").text(valOrig + "%");
$(".progress").parent().removeClass();
$(".progress .water").css("top", val + "%");
if(valOrig < colorInc * 1)
$(".progress").parent().addClass("red");
else if(valOrig < colorInc * 2)
$(".progress").parent().addClass("orange");
else
$(".progress").parent().addClass("green");
}
else
{
setTimeout(function(){waitForMe.resolve()}, 100);
$(".progress").parent().removeClass();
$(".progress").parent().addClass("green");
$(".progress .water").css("top", 100 - 67 + "%");
$(".progress .percent").text(67 + "%");
//$("#percent-box").val("");
}
return waitForMe.promise();
};
Dowload tracker:
var DLProgress = null;
function updateProgress() {
var oldNum = 0;
DLProgress = setInterval(function(){
if(!doneArts) {
doneArts = true;
downloadHelper("Articles",articleSize,33.33,0);
}else if(currPos >= totalSize - 1){
clearInterval(DLProgress);
goNews();
currPos = 0;
doneArticles = false;
doneJson = false;
doneArts = false;
} else if(currPos >= articleSize && !doneArticles) {
doneArticles = true;
downloadHelper("json",jsonSize,33.33,33.33);
} else if(currPos >= articleSize + jsonSize && !doneJson) {
doneJson = true;
downloadHelper("img",imgSize,33.33,66.66);
}
if(oldNum != currPos) {
oldNum = currPos;
setWater(Math.ceil(100 * currPos / totalSize));
}
},5);
}
Download Helper :
function downloadHelper(name,size,maxPerc,startingPoint) {
dataFiles[name].forEach(function(file){
var getItem = localStorage.getItem(name+"/"+file[0]) || null; //might not work
if(getItem === null || getItem !== file[1]) {
//download file.
if(file[0] !== null && file[1] !== null) {
//setWater(Math.ceil(100 * currPos / totalSize)).done(function(){downloader(name+"/"+file[0],file[1]);});
setTimeout(function(){downloader(name+"/"+file[0],file[1])},window.dltime);
window.dltime += 200;
}
}
});
};
File transfer used :
https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file-transfer/
It Does update after each download helper has finished
Is there any way to wait for a Dom to be updated by J's OR can you spot a problem in my code that causes this issue?
The DOM is updated each time the download is completed - it could be a problem.
We should separate upload progress and animation. When file is downloaded you should just change some kind of Model and use requestAnimationFrame recursively to animate a progress bar.
requestAnimationFrame is called 60 times per second, but will generally match the display refresh rate, paused in most browsers when running in background tabs or hidden <iframe>s in order to improve performance and battery life.
I think you have the case with the variable currPos. Use debug tool to mark the lines and inspect value of currPos. Somehow your code is managed to jump it 0 to articleSize.

JavaScript to toggle relay through website

I apologize I am new to javascript. I am trying to toggle a relay from a website using setInterval. The relay is a Sainsmart with 16 channels and it is connected to an arduino controlled by a raspberry pi. The goal is to eventually have three independent relays toggling at particular intervals. However, every attempt to get the first one working fails. In addition, every time I add a setInterval within a function or global, freezes the live streaming video from my ip camera. I am using a sandbox key through ably.
The html code and script work to toggle the relay on, and then a second button will toggle it off, but I need a single button to accomplish it.
The button initiates the sequence with a counter dictating whether the relay toggles on or off. It is set up to toggle on with an even number and off with an odd number. Any help would be greatly appreciated.
Here is the updated code I am trying to work with.
<div class="grid-item"><button id="37" onclick="startOnOff()">Start</button>
</div>
<script src="http://cdn.ably.io/lib/ably.min-1.js"></script>
<script>
var count = 0;
function startOnOff() {
var on = "37" + "on";
var off = "37" + "off";
if (counter % 2 == 0) {
toggleRelay(on);
count += 1;
} else if (count % 2 == 1) {
toggleRelay(off);
}
setInterval(startOnOff, 2000);
}
You have count in a few places and counter in one place where it should be count.
Assuming toggleRelay() is defined somewhere else in your code, try this:
var count = 0;
var on = "37" + "on";
var off = "37" + "off";
function startOnOff() {
if (count % 2 == 0) {
toggleRelay(on);
} else {
toggleRelay(off);
}
count += 1;
setTimeout(startOnOff, 2000);
}
count += 1; should be outside of the if conditional statement,
and use setTimeout() when calling startOnOff() recursively.

Send Geolocation in background service [Titanium]

I'm creating an app for Android and iOS with titanium which sends a new Geolocation to a server every 5 seconds for as long as the server runs. On iOS however the app stops sending those locations after a random interval. Although i myself are not completely convinced this is due to the fact that the app pauses in iOS(Since it stops randomly and not on a fixed time) i'm still eager to try and be certain.
However; i really have NO CLUE to do this whatsoever. I've created a background service in an eventListener to see what happens and it starts logging right away(I've put a console log in it for now). Nonetheless, my geolocation is still ticking normally aswell.
Now, could someone please give me some pointers on how to get through this? Do i want to stop my normal geolocation listener and let the BG service take over? Or does the BGservice keep the geolocation eventlistener in my normal code active now?
At this point i'm afraid to say that i'm pretty much desperate to get any help, haha!
Here's my geolocation handling now, along with the BGservice:
//Start button. listens to an eventHandler in location.js
btnStart.addEventListener('click', function (e) {
if( Titanium.Geolocation.locationServicesEnabled === false ) {
GPSSaved.text = 'Your device has GPS turned off. Please turn it on.';
} else {
if (Titanium.Network.online) {
GPSSaved.text = "GPS zoeken...";
//Empty interval and text to make a clean (re)start
clearInterval(interval);
//Set a half second timer on the stop button appearing(So people can't double tap the buttons)
stopTimeout = setTimeout(showStopButton, 1000);
//Switch the textlabels and buttons from startview to stopview
stopText.show();
startText.hide();
btnStart.hide();
//Locationhandler
location.start({
action: function (e) {
//Ti.API.info(e.coords.longitude);
if (e.coords) {
//If the newly acquired location is not the same as the last acquired it is allowed
if (e.coords.longitude != lastLon && e.coords.latitude != lastLat) {
//set the last acquired locations+other info to their variables so they can be checked(and used)
lastLat = e.coords.latitude;
lastLon = e.coords.longitude;
lastKnownAltitude = e.coords.altitude;
lastKnownHeading = e.coords.heading;
lastKnownSpeed = e.coords.speed;
if (lastLat != 0 && lastLon != 0) {
setGPSholder(lastLat, lastLon, lastKnownAltitude, lastKnownHeading, lastKnownSpeed);
} else {
GPSSaved.text = 'Geen coordinaten.';
}
}
}
}
});
/*
A second interval which shows a counter to the user and makes sure a location is sent
roughly every 5 seconds(setInterval isn't accurate though)
A lot of counters are tracked for several reasons:
minuteInterval: Counter which makes sure the last location is sent after a minute if no new one is found in the meantime
secondsLastSent: The visual counter showing the user how long its been for the last save(Is reset to 0 after a succesful save)
*/
interval = setInterval(function () {
minuteInterval++;
minuteIntervalTest++;
secondsLastSent++;
counterBlock.text = "De laatste locatie is " + secondsLastSent + " seconden geleden verstuurd";
//If the counter is higher than 5 send a new coordinate. If at the same time the minuteInterval is over a minute
//The last location is put in the array before calling the sendCoordinates
if (counter >= 5) {
if (minuteInterval > 60) {
if (lastLat != 0 && lastLon != 0) {
setGPSholder(lastLat, lastLon, lastKnownAltitude, lastKnownHeading, lastKnownSpeed);
}
}
counter = 0;
sendCoordinates();
Ti.API.info(1);
} else {
counter++;
}
if (minuteIntervalTest > 60) {
sendTestRequest();
}
}, 1000);
if (Titanium.Platform.osname == 'iphone' || Titanium.Platform.osname == 'ipad') {
//var service = Ti.App.iOS.registerBackgroundService({url:'send_geolocation_service.js'});
var service;
// Ti.App.iOS.addEventListener('notification',function(e){
// You can use this event to pick up the info of the noticiation.
// Also to collect the 'userInfo' property data if any was set
// Ti.API.info("local notification received: "+JSON.stringify(e));
// });
// fired when an app resumes from suspension
Ti.App.addEventListener('resume',function(e){
Ti.API.info("app is resuming from the background");
});
Ti.App.addEventListener('resumed',function(e){
Ti.API.info("app has resumed from the background");
// this will unregister the service if the user just opened the app
// is: not via the notification 'OK' button..
if(service!=null){
service.stop();
service.unregister();
}
Titanium.UI.iPhone.appBadge = null;
});
Ti.App.addEventListener('pause',function(e){
Ti.API.info("app was paused from the foreground");
service = Ti.App.iOS.registerBackgroundService({url:'send_geolocation_service.js'});
Ti.API.info("registered background service = "+service);
});
}
} else {
stopGPS();
GPSSaved.text = "Geen internetverbinding.";
}
}
});
As you can see there's some counters running in an interval to decide if a geolocation should be sent every 5 seconds or every minute(If no new location since the last is found)
tl;dr: I want geolocations to be sent every 5 seconds but somehow iOS(iPhone 4s and 5 tested) stop sending after a random timeperiod and restart sending the moment i get the phone out of standby.
actually background service has a limitation to stop after 10 mins so if you want to catch location when device is in background mode then you need to set mode tag in tiapp.xml file.
just refer this online doc for how it works.
http://docs.appcelerator.com/titanium/3.0/#!/guide/tiapp.xml_and_timodule.xml_Reference-section-29004921_tiapp.xmlandtimodule.xmlReference-LegacyiPhonesection

DOM manipulation slow in Chrome (hiding / showing elements)

I've put together a small test at http://jsfiddle.net/Hwqb3/3/ this morning. This is on the back of a larger project with pagination. I have tried this with native JS and jQuery. The test uses jQuery.
A quick search on SO says that Chrome handles things poorly if background-size is set, but this is not the case here. No trace of background-size in the source, and inspecting elements shows no background-size being set / inherited.
Ignore the initial page load while 5,000 elements are added to the list. It is only a few seconds, but it just so there are some elements to test with.
In Firefox 18.0.1, the moving between pages is almost instant and in IE9 there is maybe a 0.1s delay between mouse click and the paged results refreshing; However, in Chrome (24.0.1312.57 m) the delay is a noticeable 1-2 seconds.
I spent the majority of my night last night pouring over my code to see if I can find the cause before writing this test. This is bare bones and still has the issue.
I can only assume that Chrome is handling the element.style.display=''; poorly. Without that (even looping through the 5,000 elements to display='none') the thing is snappy.
Any ideas? Client wants pagination on a result set of around 4,000 - 7,500, but doesn't want page reloads and doesn't understand that they should apply filters to whittle that list down to <100, as no one is ever going to page through 200 - 375 pages looking for something specific.
Last resort is AJAX calls, which may be slightly quicker on Chrome. Untested yet though.
Thanks in advance.
Code from jsfiddle, excluding the jQuery CDN link
HTML:
First
Previous
Next
Last
<br>
<ul id='list'>
</ul>
JS:
window.onload=function() {
window.list=$('#list'), window.max=20, window.page=0, window.pages=0, window.elements;
var i=0;
while(i<5000) {
i++;
list.append("<li>"+i+"</li>");
}
jump('first');
};
function jump(operation) {
window.elements=list.find('li');
window.pages=Math.ceil(window.elements.length/window.max);
if(operation=='first') {
window.page=0;
}
else if(operation=='last') {
window.page=(window.pages-1);
}
else if(operation=='+1') {
window.page=(window.page+1);
if(window.page>=window.pages) {
window.page=(window.pages-1);
}
}
else if(operation=='-1') {
window.page=(window.page-1);
if(window.page<0) {
window.page=0;
}
}
var showing=0, total=0;
window.elements.each(function() {
var show=false, self=$(this);
if(showing<window.max) {
if(total>=(window.page*window.max) && total<((window.page*window.max)+window.max)) {
self[0].style.display='';
showing++;
show=true;
}
}
if(!show) {
self[0].style.display='none';
}
total++;
});
}
check this
window.onload = function() {
window.list = $('#list'),
window.max = 20,
window.page = 0,
window.pages = 0,
window.elements;
var i = 0;
var html = '';
while(i < 5000) {
i++
html += '<li>' + i + '</li>';
}
list.append(html);
window.elements = list.find('li');
window.pages = Math.ceil(window.elements.length/window.max);
jump('first');
};
function jump(operation) {
if (operation == 'first')
window.page = 0;
else if (operation == 'last')
window.page = window.pages - 1;
else if (operation == '+1')
(window.page + 1 >= window.pages) ? window.page = window.pages - 1 : window.page++ ;
else if (operation == '-1')
(window.page - 1 < 0) ? window.page = 0 : window.page--;
var index = page * window.max;
window.elements.hide().slice(index, index + window.max).show();
}
http://jsfiddle.net/Hwqb3/16/

Categories