PHP - Update Displayed Info Upon Changing PDF Canvas - javascript

I've been running into an issue while trying to update a script for a client. I'm still somewhat new to the industry, so I wanted to make sure I'm not missing anything.
I am attempting to edit a web page which displays a number of PDFs in canvas views. The issue arises when a user tries to switch which PDF they're viewing. The function that retrieves the PDFs has a setTimeout in place to get the content to reload every minute, as the PDFs themselves are updated with new data every 5 minutes and the users need to be able to monitor the data as it comes in. However, when switching from one PDF canvas to the next, I found that the PDF doesn't update. The only PDF that reloads and updates is the one whose canvas has been open. This is what I'm trying to change. I want the PDF display to update not only every minute, but also whenever a user switches which PDF they're viewing.
What this told me is that I need to add something that loads the PDFs again when switching canvas views. First, I tried taking the function that updates the PDFs and calling it whenever the user switches the canvas view. This seemed to work, but the issue ended up changing. The page would begin to reload more and more often the more times you would change canvas views - I'd assume because the setTimeout within the function had then been called more than once.
My second attempt was to make a new function that simply didn't have the setTimeout code and call that instead. I must have done something wrong however, because after calling that function in the code, none of the PDFs wanted to load at all.
I'll paste the code for the functions I need to work with below. Any help is appreciated, especially if I'm just missing something obvious. If you need any other details, let me know. Thank you to anybody who offers help.
function getReport(reportName, frameId) {
var params = {
report: reportName
};
$.post('/getReport.php', params, function(data){
if (data == "") {
window.location.href="/login.php";
return;
}
if (useBrowserViewer) {
$("#pdfFrame" + frameId).attr("data", "data:application/pdf;base64," + data);
} else {
displayPdf(data, document.getElementById("canvas" + frameId), 1);
if (frameId == "4") {
displayPdf(data, document.getElementById("canvas4Page2"), 2);
}
}
setTimeout(function() {
getReport(reportName, frameId);
}, 60*1000);
}).fail(function() {
console.log("Report not returned.");
setTimeout(function() {
getReport(reportName, frameId);
}, 60*1000);
});
}
function showReport(frameIdNum) {
if (useBrowserViewer) {
$(".pdfFrame").hide();
$("#pdfFrame" + frameIdNum).show();
} else {
$(".pdfCanvas").hide();
document.getElementById("canvas" + frameIdNum).style.display = 'block';
if (frameIdNum == "4") {
document.getElementById("canvas4Page2").style.display = 'block';
}
}
$(".link").removeClass("active");
$("#link" + frameIdNum).addClass("active");
}

Related

Javascript -- any way to force a draw of new elements before processing?

I have a javascript function or two that takes a few seconds to process. I want to show an activity indicator so users don't think it's hung. I tried bootstrap animated progress bars and spin.js -- the problem is, I put the code for them before the processing, but the browser doesn't seem to update to show the new elements until after the function has finished. Obviously, an activity indicator that shows up after processing isn't incredibly useful. Is there a way to force the redraw before the processing occurs?
EDIT: here's an example code. This is from an HTA application, hence the pulling of files and such. I know the forced "wait" portion is a bad idea, usually, but in this program, files are opened and closed immediately, this is to prevent a race conflict and I just want to give it a quick 10 retry timeout before it tells them something is wrong. So, the problem is that this.spin() doesn't display its good until after the alert pops up.
Database.prototype.tryDatabase = function(fileName, toEdit, table, keepAlive) {
if (typeof keepAlive === 'undefined') keepAlive = false;
for (timeInd=0; timeInd < 5; timeInd++) {
var complete = this._addToFile(fileName, toEdit, table, keepAlive);
if (complete === false) {
var until = moment().valueOf() + 2000;
this.spin();
while (moment().valueOf() <= until) {;}
}
else break;
}
if (complete === false) window.alert("Database was locked for an extended period, please try again");
else if (!keepAlive) $('#added_to_db_modal').modal('show');
return complete;
}

Web App stops working

This question is a bit vague as I am not sure how to phrase it. I fully accept this can be voted down but if anyone has an insight it would be most helpful.
I am trying to determine whether it is my web app code that is at fault or the inherit nature of Mobile Web apps (especially on Android devices).
I have this web app.
It has been designed using asp.net, C#, JavaScript and Jquery.
I have 1 page with 2 divs in it.
The 1st div shows a login page (i.e. Username and Password).
When logged in this div is hidden and the 2nd div is shown.
This 2nd div 'starts' a timer that downloads an image from my server every now and again.
I use the SetTimeout function and I recall it if there is no image ready to download or/and the image.src has finished its onload event.
I can look at this web app on my phone for hours and it will always work.
Then, I logoff (i.e. no timer is active) and the 1st div is shown.
I go to bed.
I wake up.
I go to my Android browser.
The web app shows the login div
I login
All OK.
{so the call to my server works}
But no images are downloaded.
I have put a visual counter in to show whether my timer is working.
It is not.
I refresh the page and relogin. Everything works again.
Now, I can accept if it is my code but is it the way Android handles web apps?
Any suggestions would be grand.
I can post this code if anyone needs to see it,. But it is very simple and I did not want to obscure my question.
CODE#
In DIV 1
<script type="text/javascript">
jQuery(function ($) {
$("#btnGoToLogin").click(function () {
function StartRefresh() {
try {
Start();
//display div 2
//hide div 1
}
catch (err) {
$("#divVersion").html("1# " + err);
}
}
});
});
</script>
In DIV 2
function Start() {
try {
if (timer4x4) window.clearTimeout(timer4x4);
timer4x4 = window.setTimeout(swapImages4x4, 100);
}
catch (err) {
$("#divVersion").html("1# " + err);
}
}
function Stop() {
if (timer4x4) window.clearTimeout(timer4x4);
}
function setImageSrc1x1(src) {
live1x4.src = src;
Start();
}
function swapImages4x4() {
try {
serverImage1x4.onload = function () {
setImageSrc1x1(serverImage1x4.src);
};
serverImage1x4.onerror = function () {
Start();
};
GetImageStatus();
}
catch (err) {
$("#divVersion").html("2# " + err);
}
}
function GetImageStatus() {
serverImage1x4.src = url + '/Mobile/LiveXP.ashx?Alias=' + Alias + '&camIndex=' + camIndex + '&Guid=' + createGuid();
}
jQuery(function ($) {
$("#btnExitLogin").click(function () {
function ExitDiv2() {
try {
Stop();
//display div 1
//hide div 2
}
catch (err) {
$("#divVersion").html("1# " + err);
}
}
});
});
Without the code it's difficult to say where is the problem, but try this 3 approaches:
1) Is this happening if you log off, than log back in again, without leaving the activity?
If so, you should dig in your javascript more
2) Is this happening if you log off, put app in background, than bring it to foreground, log back in? If so look at on pause on resume events
3) It's only happening if you log out, put the app in background leave it for a longer period, I will look more in the onStop
E
Well, I guess you stopped the timeout when you logged out.
So when you login again, you start it again.
But something might fail with the start after the next login.
I guess it's definitively your Javascript code.
(...) but is it the way Android handles web apps?
I guess the automatic lock screen is one thing, that could cause timers to pause / stop.You didn't use your device over the night, so I guess it locked itself. That might cause the browser to stop draining your battery.
E.g. when your screen locks, you won't be able to watch Youtube videos.
That's what I know about it. Hope that helped a bit.

Downloading multiple images with Phonegap - FileTransfer

I have built an offline app in Phonegap, the JSON data gets pushed and gets to where it needs to go. But there are always a bunch of images that need to follow, and html5 cache will just not do it seeing it clears when an app is closed. I have been breaking my nugget on this for quite a while now.
The issue is that you want to check if the image exists on the file system. I've chosen to do so with a "async:false" AJAX call, and therefore have the code running up to a point. I haven't used the phonegap (almost hack) way by writing and setting overwrite to false (which produces an error) seeing that was another async function I didn't want to deal with (wherein lies the problem: async).
Another problem is that the Phonegap browser allows best for 3 downloads at the time (looked it up). My previous function was suffering from this debacle as it would just cut off downloading images if the amount simultaneous downloads was to high, which was around 20 to 40 (depending on size) images at the time (which of course is not strange seeing download speed plummets when you divide it over multiple downloads at the time).
So the question is, how to build:
A function that loops through JSON data (image variables).
Downloads them three at the time (and set the meta data because Apple told it had to)
Deletes from disk those who are not needed anymore (this last one is problem all over the inet as far as I've read, so we'll keep this optional and because by now I really don't actually care about space anymore).
Should run a function when all images are downloaded.
My code as far:
var datadir = "";
var pics_at_the_time = 0;
var external_url_pics = "http://Folder on server where images are";
// new_config.pics holds the JSON data. Built: '[ key (same as id) { "id": 1234567890, "tld":"jpg" }'. id+'.'+tld = the image name.
window.requestFileSystem( // get the root folder path
LocalFileSystem.PERSISTENT,
0,
function(fileSystem) {
datadir = fileSystem.root.fullPath;
},
function() {
console.log("Could not get root FS");
}
);
function fetch_images() {
var len = new_config.pics.length; // amount of pictures that need to be here
var all_in_counter = 0;
$.each(new_config.pics,function(index,val){ // loop through all pics
pic_exists(val);
});
}
function pic_exists(val) {
$.ajax({ // pic on disk or not
async:false,
url: 'file://'+datadir+'/'+val.id+'.'+val.tld, //or your url
success: function(){
var obj = val.id;
delete new_config.pics.obj;
},
error: function(){
var obj = val.id;
delete new_config.pics.obj;
downloadImage(val);
}
});
}
function downloadImage(val){
if(pics_at_the_time < 3) { // only 3 at a time. else wait for a download to finish
pics_at_the_time++;
var ft = new FileTransfer();
ft.download(
external_url_pics+val.id+'.'+val.tld,
datadir + "/" + val.id+'.'+val.tld,
function(entry) {
if(debug_console) { console.log("download complete: " + entry.name); }
entry.setMetadata(function(metadata) { } , function(error) { console.log("Could not set meta data: "+val.id); }, { "com.apple.MobileBackup": 1}); // no apple cloudbackup for these pics. We can always re-download apparently
pics_at_the_time--;
fetch_images();
},
function(error) {
if(debug_console) { console.log("download error target " + error.target); }
pics_at_the_time--;
fetch_images();
});
}
}
As you can probably tell, the code is not very sophisticated and it definitely does not check for already existing images. Cause although this works, it is far from perfect seeing it reloops the bunch every time, which at first seemed like a good idea. But now I'm having second thoughts.
Any help is obviously appreciated

Ajax call makes sprite movement flicker javascript

i've just implemented movement for my main character sprite on my JavaScript/HTML5 game and all is well except for when i load existing users saved data.
In my main JavaScript file depending on whether the user clicked the new game button or load game button either a new game is loaded or the users data is loaded from a DB via PHP and Ajax.
If the user clicks new game it runs the code below and the player moves fine:
else{
//set beginning params
//Change screens
ui.new_game();
layer = scene.load("level_"+1);
layer = $.isArray(layer) ? layer : layer.layers;
layer.forEach(function(layer){
if (layer.hasOwnProperty("properties") && layer.properties.hasOwnProperty("collision"))
{
scene.collisionLayer(layer);
}
});
gameGUI.set_level(1);
gameGUI.set_location(20,20);
gameGUI.init_inv();
player.init_Player(20,20);
player.draw();
last_update = Date.now();
}
BUT if the player decides to load their previous game settings the code below is run and instead of the sprite moving fluidly in the canvas, when a key is pressed e.i right arrow key, the sprite will disappear, then flicker somewhere on the right side of the screen then disappear again.
function game_settings(state){
if(state == "load"){
ui.load_game();
//do ajax call to load user last save
var dataString = {"user_data": "true"};
$.ajax({
type:"POST",
url:"PHP/class.ajax.php",
data: dataString,
dataType: 'JSON',
async:false,
success: function(success) {
player_details_init(success);
},
error: function(){
alert("ERROR in User data");
}
});
layer = scene.load("level_"+level);
layer = $.isArray(layer) ? layer : layer.layers;
layer.forEach(function(layer){
if (layer.hasOwnProperty("properties") && layer.properties.hasOwnProperty("collision"))
{
scene.collisionLayer(layer);
}
});
player.init_Player(location_X,location_Y);
player.draw();
last_update = Date.now();
}
I know the Ajax is whats causing the problem because when i comment it out the Sprite moves like it should do, the only problem is i don't know why the Ajax is causing this weird behavior?
I have uploaded the current version of the game to HERE, so you can witness the weird behavior if you so wish.
To log in use
guest - username
guest - password
Thanks for your time
EDIT
Ok i have narrowed down the problem even further to the variables location_X, location_Y. Whne i stick in a hardcoded number say 20, 20 in the playr.init call the movement works fine, but when i use location_X, location_Y like you see in the example the problem still occurs as above.
I retrieve location_X and location_Y from a function called when the Ajax returns success called player_details_init.
Here is that function:
function player_details_init(success){
$.each(success, function(key,value){
if(level == null){
level = value.level;
}
if(location_X == null){
location_X = value.location_X;
}
if(location_Y == null){
location_Y = value.location_Y;
}
//items.push([value.game_item_id, value.quantity]);
gameGUI.set_level(level);
gameGUI.set_location(location_X,location_Y);
gameGUI.init_inv();
});
}
SO my guess is it is something to do with this function although when i do a console.log the location returns fine and the sprite does appear where it should it just doesnt move correctly
From the symptoms you describe, it looks like location_X and location_Y are strings instead of numbers. In this situation, computations will not work as you expect (addition will result in concatenation, for instance).
I would suggest you try applying parseInt() to these values (and possibly others as well) when reading your JSON payload.

Navigating / scraping hashbang links with javascript (phantomjs)

I'm trying to download the HTML of a website that is almost entirely generated by JavaScript. So, I need to simulate browser access and have been playing around with PhantomJS. Problem is, the site uses hashbang URLs and I can't seem to get PhantomJS to process the hashbang -- it just keeps calling up the homepage.
The site is http://www.regulations.gov. The default takes you to #!home. I've tried using the following code (from here) to try and process different hashbangs.
if (phantom.state.length === 0) {
if (phantom.args.length === 0) {
console.log('Usage: loadreg_1.js <some hash>');
phantom.exit();
}
var address = 'http://www.regulations.gov/';
console.log(address);
phantom.state = Date.now().toString();
phantom.open(address);
} else {
var hash = phantom.args[0];
document.location = hash;
console.log(document.location.hash);
var elapsed = Date.now() - new Date().setTime(phantom.state);
if (phantom.loadStatus === 'success') {
if (!first_time) {
var first_time = true;
if (!document.addEventListener) {
console.log('Not SUPPORTED!');
}
phantom.render('result.png');
var markup = document.documentElement.innerHTML;
console.log(markup);
phantom.exit();
}
} else {
console.log('FAIL to load the address');
phantom.exit();
}
}
This code produces the correct hashbang (for instance, I can set the hash to '#!contactus') but it doesn't dynamically generate any different HTML--just the default page. It does, however, correctly output that has when I call document.location.hash.
I've also tried to set the initial address to the hashbang, but then the script just hangs and doesn't do anything. For example, if I set the url to http://www.regulations.gov/#!searchResults;rpp=10;po=0 the script just hangs after printing the address to the terminal and nothing ever happens.
The issue here is that the content of the page loads asynchronously, but you're expecting it to be available as soon as the page is loaded.
In order to scrape a page that loads content asynchronously, you need to wait to scrape until the content you're interested in has been loaded. Depending on the page, there might be different ways of checking, but the easiest is just to check at regular intervals for something you expect to see, until you find it.
The trick here is figuring out what to look for - you need something that won't be present on the page until your desired content has been loaded. In this case, the easiest option I found for top-level pages is to manually input the H1 tags you expect to see on each page, keying them to the hash:
var titleMap = {
'#!contactUs': 'Contact Us',
'#!aboutUs': 'About Us'
// etc for the other pages
};
Then in your success block, you can set a recurring timeout to look for the title you want in an h1 tag. When it shows up, you know you can render the page:
if (phantom.loadStatus === 'success') {
// set a recurring timeout for 300 milliseconds
var timeoutId = window.setInterval(function () {
// check for title element you expect to see
var h1s = document.querySelectorAll('h1');
if (h1s) {
// h1s is a node list, not an array, hence the
// weird syntax here
Array.prototype.forEach.call(h1s, function(h1) {
if (h1.textContent.trim() === titleMap[hash]) {
// we found it!
console.log('Found H1: ' + h1.textContent.trim());
phantom.render('result.png');
console.log("Rendered image.");
// stop the cycle
window.clearInterval(timeoutId);
phantom.exit();
}
});
console.log('Found H1 tags, but not ' + titleMap[hash]);
}
console.log('No H1 tags found.');
}, 300);
}
The above code works for me. But it won't work if you need to scrape search results - you'll need to figure out an identifying element or bit of text that you can look for without having to know the title ahead of time.
Edit: Also, it looks like the newest version of PhantomJS now triggers an onResourceReceived event when it gets new data. I haven't looked into this, but you might be able to bind a listener to this event to achieve the same effect.

Categories

Resources