I'm building a Laravel4 website currently. With one main feat : downloading (updating) multiple files.
I'd like to display a progressBar (something simple as x% = (file n°)/(file total number), to ensure UX feedback for users.
Something already brainstormed # Displaying progressbar for file upload
Do you know a way to do this without Flex?
And what would the best one ?
try to pass $_SESSION vars... inspired from {session.upload_progress}
http://www.sitepoint.com/tracking-upload-progress-with-php-and-javascript/
For instance, in your php foreach :
$_SESSION['percentdownload'] = 95;//or any var e.g. $runningPercent;
and run a JS loop which refresh the HTML/CSS progressBar periodically :
var xpercent = '#Session["percentdownload"]';
$("#myProgressElemId").updateFunction(xpercent);
But doing a JS loop is quite dirty ...
Actually you look for pushing updates.
ISNT it saner/safer to make oneByOne download ??
- 1st you query (Jquery get) the infos (number of files, names, sizes, etc)
- 2nd you $.each() (JQuery) and request download for each file... dumb ?
Related
Today, I were updating some legacy code. It was some vanilla PHP small application with ajax queries to export data from database.
The application allows you to select a type of data you want to extract, you click on "Export" button, it posts an Ajax query that will query a database and writes the result in a .xlsx file.
The previous developer made a system to display a progress bar while the export is being written.
A system I have never seen nor thought.
He has made a jQuery function, that will read a .txt file that contains the number of elements being processed, example :
1205/15000
The function :
$.get( "./suivis/" + <?php echo $idUser ?>+"_suivis.txt", function( data ) {
if(data === "save"){
$("#results").html('<p>Creating Excel file, thank you for waiting.</p>' );
}
var elem = data.split('/');
if( elem[0] != '' && elem[1] != '' && data != "save")
{
$("#results").html( '<progress value="'+elem[0]+'" max="'+elem[1]+'"></progress>' );
}
})
So he uses the content of the .txt file to manage the progress bar. That function is called every 0.5 seconds.
Now, on the part of the script executed by the Ajax query, we query the database, count the array of results to get the total of lines to write, create a counter for the foreach, and while we write the .xlsx file, we also do :
$current = ($i-1).'/'.$total;
file_put_contents($file, $current);
That's how we write the processing state in the .txt file.
The error I got, happened only when I had many lines being written (more than 10K).
Once during the process, I'd randomly get (around 5K / 7K) an error from file_put_contents function : failed to open stream. Permission denied.
I have two guesses about why it's happening.
First : It may be because I'm getting it's content with Jquery every 0.5 seconds, and opening, writing and closing it really fast inside a foreach loop. Maybe that the file is "locked" while Jquery accesses its content and PHP can't open it at the same time. Many lines being processed would mean a greater probability that this issue could happen.
Second : It's more unlikely, but maybe doing too manies file_put_contents in a row, could make the system struggle and would try to open and write while the file is still not closed. But as file_put_contents is a wrapper for open, write, close, I doubt it, but who knows, I'm not an expert.
I eventually "fixed" the problem, at least it's not showing anymore for the volume I treat, by making it write the .txt file every 200 records instead of every record.
What do you think is happening ? Is my first guess correct ? Do you see any better approach ?
Thank you for your insights.
So this function works fine, however everytime i refresh the page the WINNER (person1 to 4) changes, i want to save the output and have it FIXED so that it wont change everytime i refresh..
Basicly: There is a timer on my website and when it hits 0 , it should automaticly pick someone from the list as the winner... but the winner should appear on the website for everyone and stay there
function randomNavn(){
document.getElementById("utskrift").innerHTML = "";
for (i = 0; i < 1; i++){
randName.push(nname.splice(Math.floor(Math.random() * nname.length), 1));
}
document.getElementById("utskrift").innerHTML = randName.join(", ");
}
var nname = ["Person1", "Person2", "Person3", "Person4"],
randName = [];
You need server-side code to do this -- and most likely a database. You can't do what you want from JavaScript. Each person's browser will run that javascript and get their own answer, bit it is only on their browser. Someone else will get a different answer, etc. That's not what you want to happen I assume.
To save data more permanently to be used in a web page, you have a few options:
Create a web service that accepts POST or PUT requests and saves the data on a server. This will allow you to share data between users.
Use a cookie. This will only save a value for each user's session. It won't share data between users.
You could use localStorage:
$window.localStorage.setItem('initData', {data: 'here'}
after some nights spent i've managed to found the perfect solution.
1) I've eliminated the javascript function for the array and instead craeted a php file where a winner or more is choosed.
2) From that php file we write the winners into a text file.
3) From that text file we read it through ajax and list it when countdown is over.
If anyone is ever in need, its good solution.
Thanks for everytning
I need some help in understanding what to do next.
I need to write a web based search function to find medical records from an XML file.
The operator can enter either part or all of a patient name and Hit Search on the JSP web page.
The server is suppose to then return a list of possible patient names with the opportunity for the operator to go to next page until a possible patient is found. They can then select the person and view more details.
On the Server side
I have an XML file with about 100,000 records. There are five different types of records in the file. (This is roughly about 20,000 x 5 = 100,000).
I have a java class to source the xml file and create a DOM to traverse the data elements found on the file.
-- XML File Begin
100k - XML file outline
<hospital>
<infant key="infant/0002DC15" diagtype="general entry" mdate="2015-02-18">
<patient>James Holt</patient>
<physician>Michael Cheng</physician>
<physician>David Long</physician>
<diagnosisCode>IDC9</diagnosisCode>
..
</infant>
<injury key="injury/0002IC15" diagtype="general entry" mdate="2015-03-14">
<patient>Sara Lee</patient>
<physician>Michael Cheng</physician>
<diagnosisCode>IEC9</diagnosisCode>
..
</injury>
<terminal key="terminal/00X2IC15" diagtype="terminal entry" mdate="2015-05-14">
<patient>Jason Man</patient>
<physician>John Hoskin</physician>
<diagnosisCode>FEC9</diagnosisCode>
<diagnosisCode>FXC9</diagnosisCode>
..
</terminal>
<aged key= xxxx ... >
...
</aged>
<sickness key= xxxx ... >
...
</sickness>
</hospital>
approx 5 ( )x 20,000 = 100K records.
Key and patient are the only mandatory fields. The rest of the elements are Optional or multiple elements.
-- XML File End
Here is where I need help
Once I have the DOM how do I go forward in letting the client know what was found in the XML file?
Do I create a MAP to hold the element node links and then forward say 50 links at a time to the JSP and then wait to send some more links when the user hits next page?
Is there an automated way of displaying the links, either via a Java Script, Jquery, XSLT or do I just create a table in HTML and place patient links inside the rows? Is there some rendering specific thing I have to do in order to display the data depending on the browser used by client?
Any guidance, tutorials, examples or books I can refer to would be greatly appreciated.
Thank you.
I don't know an automatic way to match the type in jQuery, but you can test the attributes, something like verify if a non optional attribute in the object is present:
// Non optional Infant attribute
if(obj.nonOptionalAttribute) {
// handle Infant object
}
Or you may add an attribute to differentiate the types (something like a String or int attribute to test in your Javascript).
if(obj.type == 'infant') {
// handle Infant object
}
#John.west,
You can try to bind the XML to a list of objects (something like Injure implements MyXmlNodeMapping, Terminal implements MyXmlNodeMapping, Infant implements MyXmlNodeMapping and go on and have a List) to iterate and search by the value at the back end or you can pass this XML file to a Javascript (if you are using jQuery you can use a get or a post defining the result type as XML) and iterate over the objects to find what the user is trying to find...
Your choice may be based on the preference to use processor time in the server side or in the client side...
I would like to dump all the names on this page and all the remaining 146 pages.
The red/orange previous/next buttons uses JavaScript it seams, and gets the names by AJAX.
Question
Is it possible to write a script to crawl the 146 pages and dump the names?
Does there exist Perl modules for this kind of thing?
You can use WWW::Mechanize or another Crawler for this. Web::Scraper might also be a good idea.
use Web::Scraper;
use URI;
use Data::Dump;
# First, create your scraper block
my $scraper = scraper {
# grab the text nodes from all elements with class type_firstname (that way you could also classify them by type)
process ".type_firstname", "list[]" => 'TEXT';
};
my #names;
foreach my $page ( 1 .. 146) {
# Fetch the page (add page number param)
my $res = $scraper->scrape( URI->new("http://www.familiestyrelsen.dk/samliv/navne/soeginavnelister/godkendtefornavne/drengenavne/?tx_lfnamelists_pi2[gotopage]=" . $page) );
# add them to our list of names
push #names, $_ for #{ $res->{list} };
}
dd \#names;
It will give you a very long list with all the names. Running it may take some time. Try with 1..1 first.
In general, try using WWW::Mechanize::Firefox which will essentially remote-control Firefox.
For that particular page though, you can just use something as simple as HTTP::Tiny.
Just make POST requests to the URL and pass the parameter tx_lfnamelists_pi2[gotopage] from 1 to 146.
Example at http://hackst.com/#4sslc for page #30.
Moral of the story: always look in Chrome's Network tab and see what requests the web page makes.
I'm trying to display a progress bar during mass mailing process. I use classic ASP, disabled content compression too. I simply update the size of an element which one mimics as progress bar and a text element as percent value.
However during the page load it seems Javascript ignored. I only see the hourglass for a long time then the progress bar with %100. If I make alerts between updates Chrome & IE9 refresh the modified values as what I expect.
Is there any other Javascript command to replace alert() to help updating the actual values? alert() command magically lets browser render the content immediately.
Thanks!
... Loop for ASP mail send code
If percent <> current Then
current = percent
%>
<script type="text/javascript">
//alert(<%=percent%>);
document.getElementById('remain').innerText='%<%=percent%>';
document.getElementById('progress').style.width='<%=percent%>%';
document.getElementById('success').innerText='<%=success%>';
</script>
<%
End If
... Loop end
These are the screenshots if I use alert() in the code: As you see it works but the user should click OK many times.
First step is writing the current progress into a Session variable when it changes:
Session("percent") = percent
Second step is building a simple mechanism that will output that value to browser when requested:
If Request("getpercent")="1" Then
Response.Clear()
Response.Write(Session("percent"))
Response.End()
End If
And finally you need to read the percentage with JavaScript using timer. This is best done with jQuery as pure JavaScript AJAX is a big headache. After you add reference to the jQuery library, have such code:
var timer = window.setTimeout(CheckPercentage, 100);
function CheckPercentage() {
$.get("?getpercent=1", function(data) {
timer = window.setTimeout(CheckPercentage, 100);
var percentage = parseInt(data, 10);
if (isNaN(percentage)) {
$("#remain").text("Invalid response: " + data);
}
else {
$("#remain").text(percentage + "%");
if (percentage >= 100) {
//done!
window.clearTimeout(timer);
}
}
});
}
Holding respond untill your complete processing is done is not a viable option, just imagine 30 people accessing the same page, you will have 30 persistent connections to the server for a long time, especially with IIS, i am sure its not a viable option, it might work well in your development environment but when you move production and more people start accessing page your server might go down.
i wish you look into the following
Do the processing on the background on the server and do not hold the response for a long time
Try to write a windows service which resides on the server and takes care of your mass mailing
if you still insist you do it on the web, try sending one email at a time using ajax, for every ajax request send an email/two
and in your above example without response.flush the browser will also not get the % information.
Well, you don't.
Except for simple effects like printing dots or a sequence of images it won't work safely, and even then buffering could interfere.
My approach would be to have an area which you update using an ajax request every second to a script which reads a log file or emails sent count file or such an entry in the database which is created by the mass mailing process. The mass mailing process would be initiated by ajax as well.
ASP will not write anything to the page until it's fully done processing (unless you do a flush)
Response.Buffer=true
write something
response.flush
write something else
etc
(see example here: http://www.w3schools.com/asp/met_flush.asp)
A better way to do this is to use ajax.
Example here:
http://jquery-howto.blogspot.com/2009/04/display-loading-gif-image-while-loading.html
I didn't like ajax at first, but I love it now.