Extjs4.1 - How to working with Progress bar and php - extjs

I try to create a Progress bar wait for server do something. When server finish then processbar will completed.
Here is my js
var pbar4 = Ext.create('Ext.ProgressBar', {
text:'Waiting on you...',
width: 300,
renderTo:Ext.getBody()
});
Ext.Ajax.request({
url: 'getStatus.php',
success: function(r) {
if (r.responseText == 100)
pbar4.updateText('All finished!');
else
pbar4.updateProgress(r.responseText, r.responseText+'% completed...');
}
});
and getStatus.php
$total = 10000;
for ($i = 0; $i <= $total; $i++) {
echo $i/$total*100;
}
But when i run that look like
How to do that thanks

What you have here is confusion about how ajax reacts with the page on the server. More specifically that pages aren't as stateful as you imagine them to be.
What you are assuming (or wanting) to happen:
Ajax request is made to PHP page from web page
PHP page receieves ajax request
PHP page starts loop
PHP page starts printing numbers
PHP page returns the current number it's on to the web page doing the ajax request
web page updates progress bar with first value
web page requests with ajax again
PHP prints out the current number it's on and returns that value to the requesting page
web page updates progress bar with current value
rinse and repeat steps 7 through 9
What is actually happening is quite simple:
Ajax request is made to PHP page from web page
PHP page receieves ajax request
PHP page starts loop
PHP prints all numbers in loop
PHP returns list of all numbers to web page
Web page prints list of all numbers as an update to the progress listener
To fix this issue you actually need to have the PHP page somehow be stateful as to the progress you want to represent here. This can be done by having PHP start a process (new thread, not sure if php has this) that writes numbers to a file on the first request and then have subsequence requests from the webpage read the last number in the file and have it return it. You could also use a database to do something similar.

In case somebody's looking now, I am also thinking of using a progressbar to monitor my Ajax. As previously mentioned, you cannot loop-print in PHP and read that. I did it like this:
Create a monitor ID in ExtJS.
Do the Ext.Ajax, passing the monitor ID
Create a Ext.util.TaskRunner();, monitoring a server file containing Jand updating progress bar
PHP side creates JSON file from monitor ID passed by ExtJS.
Update the JSON file in PHP by calling this several times:
Code:
$cnt = 0;
$total = 17; //number of times sendStatus(); was called
$monitorPath = '/path/to/file' . $_REQUEST['fileNameFromExtJS']
function sendStatus()
{
global $cnt, $total, $monitorPath;
$statusMessage = array(
"Tinkering stuff..",
"50% complete..",
"Sending...",
"Done!");
$statusMessage = $statusMessage[$cnt];
$cnt ++;
$str = '{"count": '.$cnt.', "total": '.$total.', statusMessage: "'.$statusMessage.'"}';
file_put_contents($monitorPath, $str, LOCK_EX );
}
Reference:
How to update Extjs Progress Bar with JSON results?
Progress bar in your web application, ExtJS / JAVA

Related

Kohana 3.3 request and response

One tutorial thought me, that I can fill my template with content, by putting:
$this->template->body = $this->response->body();
But, I cant see where the response is being populated. Even dumping the request and response, its just empty.
And secondly, how can I make advantage of the already built in Request class, to get some output from a function, without actually redirecting to that method ? Lets say:
$content = Request::factory('news/latest')->execute();
kind regards.
Using $this->template->body assumes that you are using Controller_Template controller. $this->template is a variable within Controller_Template representing View file application/views/template.php.
Setting something to $this->template->body passes $body variable to template view file. You can than use it (like echo $body;) within template view.
To get output from $content = Request::factory('news/latest')->execute(); your controller which handles news/latest Route must produce some output.
Than you can get this output like:
$response = Request::factory('news/latest')->execute();
$content = $response->body();

laravel angularjs update multiple rows

i have a sortable table and after successfully moving an item i want to update all the rows in the databasetable which are effected from sorting.
my problem is that i dont know what's the best way to update multiple rows in my database with eloquent and how to send the data correct with angularjs
in angularjs i did this
//creating the array which i want to send to the server
var update = [];
for (min; min <= max; min++){
...
var item = {"id": id, "position": position};
update.push(item);
...
}
//it doesn't work because its now a string ...
var promise = $http.put("/api/album/category/"+update);
//yeah i can read update in my controller in laraval, but i need the fakeid, because without
//i get an error back from laravel...
var promise = $http.put("/api/album/category/fakeid", update);
in laravel i have this, but is there an possibility to update the table with one call instead of looping
//my route
Route::resource('/api/album/category','CategoryController');
//controller
class CategoryController extends BaseController {
public function update()
{
$updates = Input::all();
for($i = 0; $i<count($updates); $i++){
Category::where('id','=', $updates[$i]["id"])
->update(array('position' => $updates[$i]["position"]));
}
}
}
and yes this works but i think there are better ways to solve the put request with the fakeid and the loop in my controller ;)
update
k routing is solved ;) i just added an extra route
//angularjs
var promise = $http.put("/api/album/category/positionUpdate", update);
//laravel
Route::put('/api/album/category/positionUpdate','CategoryController#positionUpdate');
Try post instead put.
var promise = $http.post("/api/album/category/fakeid", update);
PUT vs POST in REST
PUT implies putting a resource - completely replacing whatever is available at the given URL with a different thing. By definition, a PUT is idempotent. Do it as many times as you like, and the result is the same. x=5 is idempotent. You can PUT a resource whether it previously exists, or not (eg, to Create, or to Update)!
POST updates a resource, adds a subsidiary resource, or causes a change. A POST is not idempotent, in the way that x++ is not idempotent.
By this argument, PUT is for creating when you know the URL of the thing you will create. POST can be used to create when you know the URL of the "factory" or manager for the category of things you want to create.
so:
POST /expense-report
or:
PUT /expense-report/10929
I learned via using following
Laravel+Angular+Bootstrap https://github.com/silverbux/laravel-angular-admin
Laravel+Angular+Material https://github.com/jadjoubran/laravel5-angular-material-starter
Hope this help you understand how to utilize bootstrap & angular and speed up your develop by using starter. You will be able to understand how to pass API request to laravel and get callback response.

What are the best practices for pre-fetching in backbone.js?

What's the best way to pre-fetch the next page in backbone.js?
Is there a build-in mechanism to do that, or do I have to take care of it myself by making Ajax calls and storing the results.
Also, is there a way to preload the entire page like in JQuery mobile( http://jquerymobile.com/demos/1.2.0/docs/pages/page-cache.html)
There is no built in support for a such a thing. It's dependent on your use case but you could do a number of things.
1) Use setTime() to wait a short time before fetching the data you might be needing shortly. (Probably not a good solution)
2) Set up an event handler to fetch the data on a specific event, or something similar:
$('#my-button').on('hover',function() {
//fetch data
});
To fetch the data you can use the fetch() function on a backbone model or collection, which will return a jqXHR (or you can use a straight $.ajax() call). You can then wait and see if it failed or passed:
var fetch = myModel.fetch();
fetch.done(function(data) {
// Do something with data, maybe store it in a variable than you can later use
})
.fail(function(jqXHR) {
// Handle the failed ajax call
// Use the jqXHR to get the response text and/or response status to do something useful
});
No build-in support, but actually easy to add. Please referer to the concept of View Manager, it is able to handle both "view-keeping" tasks and transitions.
In short, the concept is: view manager is component, which is reposible for switching from one application view to another. It will dispose existing view, so it prevents zombies and memory leaks. As well it could handle transitions between view switch.
Here my way how I handle the loading of pages into an "endless scrolling" list.
Make you backend paginate aware
First of all you require a DB backend which is capable of handlling page load requests:
As an example refer to my git modelloader project which provides a small Coffee based framework integrated into a Node.js/Moongoose environment.
Model Loader on GIT will contain additional information and samples.
Here the most important points:
You backend should support the following Pagination features
Each request will return partial response only limiting it to for example 20 records (size of a page).
By default the last JSON record entry returned by a request, will contain additional technical and meta information about the request, necessary for allowing consumers to implement a paging.
{
_maxRec: "3",
_limit: "20",
_offset: "0"
}
_maxRec will list the total amount of records in the collection
_limit will list the maximum number of requests which are given back
_offset will tell you which set of records was passed back, i.e. an _offset of 200 would mean that result list skipped the first 199 records and presents the records from 200-220
The backend should support the following pagination control parameters:
http(s)://<yourDomainName>/<versionId</<collection>?offset=<number>
Use offset to skip a number of records, as for example with a limit of 20, you would send a first request with offset=0 then offset=20, then offset=40 etc. until you reached _maxRec.
In order to reduce the db activities you should provide a possiblity to reduce the _maxRec calculation for subsequent requests:
http(s)://<yourDomainName>/<versionId</<collection>?maxRec=<number>
By passing in a maxRec parameter (normally the one gotten by an earlier paging requerst), the request handler will by pass the database count objects statement, which results in one db activity less (performance optimization). The passed in number will passed back via _maxRec entry. Normally a consumer will fetch in the first request the _maxRec number and pass it back for the subsequent request, resulting in a faster data access request.
Fire of Backbone Model requests if necessary
So now you have to implement on the Backbone side the firing of page loading requests when necessary.
In the example below we assume to have a Backbone.View which has a list loaded into a jquery.tinyscrollbar based HTML element. The list contains the first 20 records loaded via the URL when built up initially:
http(s)://<yourDomainName>/<versionId</<collection>?offset=0
The View would listen in this case to the following scrolling events
events:
'mousewheel': 'checkScroll'
'mousemove': 'checkScroll'
Goal is as soon the user has scrolled down to the bottom of the scrollable list (e.g. he reaches a point which is 30px above the scrollable list end point) a request will be fired to load the next 20 entries. The following code sample desrcribes the necessary step:
checkScroll: () =>
# We calculate the actual scroll point within the list
ttop = $(".thumb").css("top")
ttop = ttop.substring(0,ttop.length-2)
theight = $(".thumb").css("height")
theight = theight.substring(0,theight.length-2)
triggerPoint = 30 # 30px from the bottom
fh = parseFloat(ttop)+parseFloat(theight)+triggerPoint
# The if will turn true if the end of the scrollable list
# is below 30 pixel, as well as no other loading request is
# actually ongoing
if fh > #scrollbarheight && ! #isLoading && #endLessScrolling
# Make sure that during fetch phase no other request intercepts
#isLoading = true
log.debug "BaseListView.checkscroll "+ ttop + "/"+ theight + "/"+ fh
# So let's increase the offset by the limit
# BTW these two variables (limit, offset) will be retrieved
# and updated by the render method when it's getting back
# the response of the request (not shown here)
skipRec = #offset+#limit
# Now set the model URL and trigger the fetch
#model.url = #baseURL+"?offset="+skipRec+"&maxRec="+#maxRec
#model.fetch
update: true
remove: false
merge: false
add: true
success: (collection, response, options) =>
# Set isLoading to false, as well as
# the URL to the original one
#isLoading = false
#model.url = #baseURL
error: (collection, xhr, options) =>
#isLoading = false
#model.url = #baseURL
The render method of the view will get the response back and will update the scrollable list, which will grow in size and allows the user again to start scrolling down along the new loaded entries.
This will load nicely all the data in a paged manner.

CakePHP - spitting out XML for webservice

What is the best way to spit out XML for webservice in CakePHP?
I have it like the following but it's displaying an empty page.
Sample call /service/config.xml
In Controller
var $helpers = array('Xml');
function config() {
$this->autoRender = false;
$obj = array("response" => array("config" => array(...)));
$objXmlHelper = new XmlHelper();
$objXml = $objXmlHelper->header();
$objXml .= $objXmlHelper->serilize($obj);
echo $objXml;
}
That gives empty page. However, if I echo json_encode($obj); that actually prints out json.
Thanks,
Tee
You probably have an error in your code. My guess is you are not including the XML helper.
Check you CakePHP (app/tmp/logs/) and PHP logs. In addition you may need to set the DEBUG flag to a higher level ( i.e. > 0).
I'd also recommend considering moving such things to a model. Web Services are typically data access layers and that belongs in the Model.

Asynchronously pull data from datastore and draw map

I have a Spring MVC 3 app (that uses JSP) running on Google App Engine and saving information on the Datastore. I'm using the Google Maps API v3 to project some of the data on maps by drawing shapes, colouring etc. My database will potentionally hold millions of entries.
I was wondering what the best way is to keep pulling data from the datastore and project them on the map until there are no more database entries left to project. I need to do this to avoid hitting the 30 seconds limit (and getting a DeadlineExceededException) but also for good user experience.
Is it worth using GWT?
Any advice would be great.
Thanks!
You could use a cursor similar to the pagination technique described here:
Pagination in Google App Engine with Java
When your page with the map loads, have it make an AJAX request with a blank cursor parameter. The request handler would fetch a small number of entities, then return a response containing them and a cursor (if there are entities remaining).
From the client javascript, after displaying the items on the map, if there is a cursor in the response start a new request with the cursor as an argument. In the request handler if a cursor is provided, use it when making the query.
This will set up a continuous loop of AJAX requests until all items have been fetched and displayed on the map.
Update:
You could write a service which returns JSON something like this:
{
items:
[
{ lat: 1.23, lon: 3.45, abc = 'def' },
{ lat: 2.34, lon: 4.56, abc = 'ghi' }
],
cursor: '1234abcd'
}
So, it contains an array of items (with lat/lon and whatever other info you need per item), as well as a cursor (which would be null when the last entity has been fetched).
Then, on the client side I would recommend using jQuery's ajax function to make the ajax calls, something like this:
$(document).ready(function()
{
// first you may need to initialise the map - then start fetching items
fetchItems(null);
});
function fetchItems(cursor)
{
// build the url to request the items - include the cursor as an argument
// if one is specified
var url = "/path/getitems";
if (cursor != null)
url += "?cursor=" + cursor;
// start the ajax request
$.ajax({
url: url,
dataType: 'json',
success: function(response)
{
// now handle the response - first loop over the items
for (i in response.items)
{
var item = response.items[i];
// add something to the map using item.lat, item.lon, etc
}
// if there is a cursor in the response then there are more items,
// so start fetching them
if (response.cursor != null)
fetchItems(response.cursor);
}});
}

Resources