Making a step-by-step ajax request - javascript

I'm thinking about how to change a content of a div dynamically. So, here is the ajax request:
$.ajax({
url:'/foos',
cache: false,
type: 'get',
}).done( function( foo_array ) {
for( foo in foo_array ) {
$('#foo-container').append('<div class="foo-var">'+foo+'</div>');
}
});
So bassically, this ajax append all foo-var divs from the server, but if the foo_array is too long or a big very big array there is a problem because i think that takes more and more time depending on the foo_array's length
How can I append one by one??, how can I query one by one and append in foo-container instead query all foos and make an iteration??
I want to do something like this
if(foos.hasNext()){ $.ajax..... append(foo)....}
foos is an array made by many documents from a mongodb database, so I cant get the length of the array because depends of the query's find() arguments..
I'm using nodejs, mongodb, expressjs and jquery for ajax
Sorry for my bad English, and thank you all!
EDIT 2
this is an example of the data in mongodb
{category:1, name:'robert',personal:true,option:'class'}
{category:1, name:'alfredo',personal:false,option:'class'}
{category:4, name:'ricardo',personal:true,option:'class'}
{category:1, name:'genaro',personal:true,option:'class'}
{category:2, name:'andres',personal:false,option:'class'}
{category:1, name:'jose',personal:true,option:'class'}
db.collection.find({personal:true}) // gives me 4 documents
db.collection.find({option:'class'}) // gives me 6 documents
db.collection.find({category:4}) // gives me 1 document
i dont know how many documents can get from the cursor, i need to charge one by one cause there are 5097841 documents in the databse so, ajax can take long time to return all the information, i need to query one by one if hasNext() in the cursor of mongodb

You can use skip and limit and can make multiple requests. It's like paging.The following syntax may help you
db.collection.find().skip(200).limit(100);

Related

Use the same data for multiple tables with tabulator

I'm using jQuery and tabulator to create a fairly simple webpage showing the progress of various live events. I have three table elements on the page showing events in different states. Broadly speaking I have a table for events that are 'Live', 'Finished' and 'Upcoming'.
The tabulator code for each table looks a bit like this:
var eventTable = {
layout:"fitColumns",
columns:[
{title:"Event ID", field:"eventID"},
{title:"Event name", field:"eventName"},
{title:"Event status", field:"eventStatus"}
]
};
I can then generate and populate the tables using data retrieved from the server using an AJAX call:
$('#live-events-table').tabulator(eventTable);
$('#live-events-table').tabulator("setData", "/cgi-bin/getevents.py");
$('#live-events-table').tabulator("setFilter", "status", "in", ["intermission", "mid-event"]);
Then similar code for the finished and upcoming tables.
This creates three requests for getevents.py every time the page is updated. This is undesirable because the data is pulled from another API and I want to avoid sending multiple identical requests. Also, there's a (small) chance the data could change between requests.
Is there a way of using the same data to populate all three tables?
Learnt something today. Never heard of Tabulator. I've been using DataTables for this sort of advanced tabular layout in the form of a jQuery plugin. Tabulator looks promising. Will have to explore more in the future.
In the docs I see Tabulator - Set Table Data, lots of alternative options available to set the data.
Hope I am understanding the problem correctly.
My thoughts/flow for tacking this problem would be:
Assuming your doing this already: Prep server side (getevents.py) needs to return all 'Live', 'Finished' and 'Upcoming' rows in JSON together in 1 response. How do I make a JSON object with multiple arrays?.
Client side on doc ready(), makes a jQuery ajax call to fetch this data before 3 x tabulators are built/called.
You can use a loading indicator. So the client sees something is happening in the 3 x before replaced by jQuery tabulator once the data is returned and you built with tabulator.
In the ajax success callback function you can iterate over the returned json object (containing the 3 x eventTypes). You might have to JSON.parse() if you store it in a JavaScript variable to iterate over.
Now get your specific array of event types nested objects arrays/json.
Then call your tabulator creation methods using the setData pointing to each specific JavaScript array containing the relevant data.
Not sure if this falls under "premature optimization", but I would proceed as the problem itself is rather fun to solve, but you know the requirements/needs better than I.
Good luck.
I fixed this fairly simply, using suggestions from #RoryGS.
Define the table options in a variable, as before:
var eventTable = {
layout:"fitColumns",
columns:[
{title:"Event ID", field:"eventID"},
{title:"Event name", field:"eventName"},
{title:"Event status", field:"eventStatus"}
]
};
Then make a jQuery ajax call to fetch the data, and build the table(s) in the success option of the function:
$(function() {
$.ajax({
dataType: "json",
url: "/cgi-bin/getevents.py",
success: function(data, status){
$('#live-events-table').tabulator(eventTable);
$('#finished-events-table').tabulator(eventTable);
$('#live-events-table').tabulator("setData", data);
$('#live-events-table').tabulator("setFilter", "status", "in", ["intermission", "mid-event"]);
$('#finished-events-table').tabulator("setData", data);
$('#finished-events-table').tabulator("setFilter", "status", "in", ["post-event"]);
}
})})
It seems to be necessary to set the data individually for each table. I would like to specify the data in the constructor, but this doesn't seem to work. I will continue to try to refine this.
If you are getting the data from a URL you can pass it into the ajaxURL property in the table constructor and tabulator will make the request for you:
$("#example-table").tabulator({
ajaxURL:"/cgi-bin/getevents.pyw", //ajax URL
columns:[...] //define columns etc
});

Should SQL query's ORDER BY columns be written in the JS code?

I'm paging some SQL queries results in my application with LIMIT and OFFSET, now I'd like to add Javascript controls to order the resulting list all the way from the front end to the SQL query's ORDER BY.
Where should I write the column to sort by that will be passed to the SQL's ORDER BY?
Should it be written in the JS code? Should generic string be passed to the server and then, converted to the SQL's column names?
Here are some pieces of code to clarify the problem:
The SQL query to get the rows displayed in the JS:
SELECT *
FROM MY_TABLE
ORDER BY :criteria
LIMIT :limit
OFFSET :offset
The JS code responsible for the AJAX query:
function sortBy(selected) {
$.ajax({
url: "/super/link/to/controller/method?orderBy=" + selected.val(),
type: 'GET',
dataType: "HTML",
success: function (data) {
// Code here doing the list refresh with the data
}
});
}
The parameter under orderBy will be added to the SQL query with the name criteria. It can be manipulated by the server to match the SQL table column's name but is it really a good practice?
I don't see anything inherently wrong with this. There might be other/better options based on different ORM solutions you might be using, but given the information you have provided this solution looks fine as long as you are securing your application against SQL injection.

How to make a form submit return the specified result using AJAX & JSON?

I'm working on a basic year, make, model dependent drop down menu, but started working backwards. I'm currently working on making my success callback dependent on the model drop down selection. For instance, if I choose 2006, lexus, is250, I only want my success callback to display that vehicle.
Most of my code can be found http://codepen.io/cfavela/pen/bozie/ (make sure to collapse the CSS page to make it easier to read)
My results page (modelsTest.html) contains the following:
{
"Car": "2012 Chevrolet Avalanche",
"Price": "$10,999",
"Features": "Soft seats!"
"Img": "/css/img/2012_Avalanche.jpeg"
}
What I've tried to do is add another car using an array and $.each, but the problem with this result is that it returns every vehicle if I click on search. How can I make the success callback dependent on the model selected?
As I commented above, according to this SO How to read the post request parameters using javascript, you can not get post data at client side level, you would need a server side to do that.
So you could try using GET and form your query ($('#vehicle').val()) as part of query string, then base on the query string, do some javascript logic at modelsTest.html and return the json you want. (but I don't think this will work, because I don't think you can return pure json in a real html file, so guessing your modelsTest.html just contain json. but I could be wrong hence I leave this as a possible solution)
or do the filtering in the success: function() before append to the msg.

Breeze EntityManager.executeQuery with expand - httpResponse data does not match result data?

I'm working on a web app that uses Breeze and Knockout. I have the following function:
function getArticle(id, articleObservable) {
var query = EntityQuery.from('KbArticles')
.where("articleId", "==", id)
.expand("KbArticleType, KbSubject, KbArticleTags");
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
if (articleObservable) {
articleObservable(data.results[0]);
}
log('Retrieved [Article] from remote data source', data.results.length, true);
}
}
A 1 to many relationship exists between the KbArticles entity and the KbArticleTags entity. The goal of this function is to fetch a specific article and the list of tags associated with the article. The function executes successfully (and I DO get data for the other 2 expanded entities - they are 1 to 1), however, I get an empty array for the KbArticleTags in data.results. Interestingly, the tags are populated in data.httpResponse:
So, it appears that the data is coming over the wire, but it's not making it to the results in the querySucceeded function. I tried to step through the breeze code to determine how the httpResponse is mapped to the result, but got lost fairly quickly (I'm a javascript newb). Does anyone have any troubleshooting tips for figuring out why the expanded entity doesn't show in the results, but is returned in the httpResponse? Or am I trying to do something that isn't supported?
Ok, so for whatever reason (I probably deleted it one day while testing and didn't add it back), the navigation property (in my Entity Framework diagram) was missing on the KbArticleTag entity:
All I had to do was add that back and everything is working as expected.

Too much JSON crashes browser :(

I have an ajax country/city selector. When I select United States the browser crashes. Doh!
I have a dropdown list of countries. When I select a country a jQuery ajax call is run which gets a JSON response of cities belonging to that country.
I should have seen it coming when I had to increase my allowed memory during execution. Here's the JSON response from selecting the UK.
{"5947":"Aberdeen","12838":"Aberystwyth","15707":"Aldershot","18575":"Alsagers Bank","18682":"Altrincham","4863":"Andover","41802":"AOL","6471":"Armagh","18945":"Ascot","4864":"Ashby-de-la-Zouch","4865":"Ashford","5948":"Aviemore","12985":"Aylesbury","12281":"Ballymena","14446":"Banbury","12445":"Bangor","13631":"Barking","4866":"Barnet","17004":"Barnsley","16423":"Barrow-in-Furness","16254":"Basildon","12402":"Basingstoke","5826":"Bath","13289":"Beddgelert","15082":"Bedford","4868":"Belfast","4869":"Belper","13874":"Benfleet","5827":"Benson","15514":"Berkhamsted","4870":"Berwick Upon Tweed","12948":"Betws-y-Coed","18776":"Bexley","14530":"Bicester","4871":"Billericay","18436":"Birkenhead","4872":"Birmingham","14592":"Blackburn","14686":"Blackpool","12526":"Bolton","12480":"Bournemouth","13062":"Bracknell","18772":"Bradford","4873":"Braemar","4874":"Brecon","4875":"Brentwood","18820":"Brighton","14260":"Bristol","4876":"Broomfield","42004":"Burgess Hill","14654":"Burnley","4877":"Burton Upon Tren","13812":"Bury","15835":"Bury St Edmunds","16500":"Camberley","4878":"Cambridge","4879":"Canterbury","5957":"Cardiff","14443":"Carlisle","14065":"Carrickfergus","42384":"Chalgrove","5832":"Chatham","13641":"Chelmsford","4880":"Cheltenham","4881":"Chester","42879":"Chesterfield","12160":"Chichester","41768":"Chorley","14056":"Church Stretton","5949":"Cladich","4884":"Colchester","16204":"Congleton","17534":"Coniston","42888":"Corsham","4885":"Coventry","13575":"Crawley","15410":"Crewe","13913":"Croydon","4886":"Cumbernauld","13711":"Dartford","4887":"Dartmouth","5833":"Derby","17468":"Derry","4889":"Doncaster","13696":"Dorchester","15377":"Dorking","5834":"Dover","16659":"Dudley","41867":"Dumbarton","18091":"Dumfries","4890":"Dunbar","14217":"Dunblane","4891":"Dundee","14067":"Dunfermline","4892":"Durham","16058":"East Molesey","17521":"East Preston","12501":"Eastbourne","12374":"Eastrea","4893":"Edinburgh","18992":"Elgin","41763":"Ellesmere","12883":"Ely","16825":"Enfield","14510":"Epsom","5835":"Exeter","4894":"Falkirk","5836":"Falmouth","42388":"Faringdon","42034":"Farmington","14604":"Farnham","42347":"Feltham","12829":"Fleet","4895":"Forres","42315":"Frosterley","5950":"Glasgow","4896":"Glastonbury","12562":"Gloucester","15956":"Gosport","4898":"Grangemouth","12626":"Gravesend","16057":"Grays","4899":"Great Wilbraham","4900":"Greenock","12752":"Grimsby","11747":"Guildford","14506":"Guilford","11938":"Halifax","5010":"Hamilton","15553":"Harlow","41733":"Harpenden","14713":"Harrow","4902":"Hartlepool","18952":"Haslemere","13977":"Hastings","14917":"Hatfield","12529":"Haverfordwest","4903":"Haverhill","4904":"Hawarden","5951":"Hawick","11776":"Hemel Hempstead","15302":"Hereford","14999":"Hertford","41893":"Heston","16056":"Hexham","13019":"High Wycombe","13643":"Hoddesdon","5958":"Holyhead","12420":"Hornchurch","14160":"Horsham","12108":"Huddersfield","5837":"Hull End","13296":"Huntingdon","14801":"Hyde","17707":"Ilford","41721":"Inverkeithing","4905":"Inverness","5838":"Ipswich","4906":"Keighley","4907":"Kelso","18628":"Kendal","17805":"Kenilworth","4908":"Kennet","4909":"Kettering","18578":"Kidsgrove","18984":"Kilmarnock","4910":"Kingston Upon Hull","5952":"Kirkwall","18257":"Lakenheath","15425":"Lampeter","13182":"Lancaster","4911":"Laughton","13488":"Leamington","18824":"Leeds","13135":"Leek","17849":"Leicester","17716":"Leigh","12836":"Lerwick","13387":"Letchworth","4912":"Lewes","41767":"Leyland","13546":"Lichfield","5840":"Lincoln","19039":"Little Chalfont","16778":"Liverpool","13442":"Llandrindod Well","5953":"Loch Ness","12008":"London","15035":"Loughborough","15518":"Loughgall","15011":"Louth","18492":"Lowestoft","14023":"Luton","4913":"Machynlleth","12416":"Maidenhead","12230":"Maidstone","14722":"Manchester","4914":"Mansfield","4915":"Margate","4916":"Marlborough","17889":"Marlow","18870":"Melborne","16170":"Melton Mowbray","4917":"Merton","5844":"Middlesbrough","5959":"Milford","15181":"Millom","12315":"Milton Keynes","12089":"Mold","18816":"Montrose","5954":"Motherwell","18574":"Nantwich","4918":"Newark","17097":"Newbury","5845":"Newcastle","4919":"Newcastle Upon Tyne","19040":"Newport","41682":"Newquay","13629":"Northallerton","4922":"Northampton","18577":"Northwich","42209":"northwold","15080":"Norwich","5847":"Nottingham","4923":"Oban","11975":"Oldham","6474":"Omagh","17161":"Oxford","15422":"Oxshott","18627":"Penrith","4925":"Penzance","16404":"Perth","5848":"Peterborough","4926":"Plains","4927":"Plymouth","15551":"Pontypridd","14208":"Poole","4928":"Portsmouth","17642":"Portstewart","41766":"Preston","5011":"Prestwick","18579":"Radway Green","42069":"Ramsgate","11775":"Reading","14706":"Redditch","16276":"Ringwood","15522":"Ripon","14673":"Rochester","15968":"Romford","41857":"Rugby","15289":"Runcorn","17520":"Rustington","14052":"Saint Albans","16462":"Salford","4931":"Salisbury","42295":"Sandwich","17690":"Sandy","4932":"Scarborough","13975":"Seaford","12003":"Shaftesbury","18891":"Sheffield","5850":"Shrewsbury","13178":"Slough","14708":"Solihull","4935":"Southampton","4936":"Southborough","14524":"Southend-on-Sea","13970":"Southport","42260":"St Albans","5955":"St Andrews","15841":"St Asaph","18576":"St Helens","16114":"St Ives","12717":"Stafford","41746":"Staines","14051":"Stanmore","16656":"Stansted","42032":"Stevenage","5012":"Stirling","11801":"Stockport","14198":"Stockton-on-Tees","4937":"Stoke On Trent","42386":"Stranraer","4938":"Stratford-Upon-Avon","4939":"Stroud","18615":"Sudbury","11860":"Sunderland","16393":"Sutton","5960":"Swansea","12853":"Swindon","4941":"Taunton","5851":"Teeside","13973":"Telford","4943":"Truro","17702":"Virginia Water","5852":"Waddington","12059":"Wakefield","4945":"Wallingford","4947":"Wareham","5853":"Warrington","4948":"Warwick","4949":"Watford","12009":"Wellingborough","12528":"Wellington","13366":"Wells","12530":"Welwyn Garden City","16785":"Weston Under Lizard","16334":"Wetherby","18171":"Weymouth","4950":"Whitby","13308":"Whitehaven","42387":"Whitehead","5956":"Wick","17581":"Wilmslow","5854":"Wimbledon","12524":"Wimborne Minster","12551":"Winchester","15946":"Windsor","18573":"Winsford","4952":"Wisbech","4953":"Wisborough Green","12982":"Woking","18769":"Wokingham","13287":"Wolverhampton","17904":"Woodford","18086":"Woolavington","11783":"Worcester","12128":"Worthing","5961":"Wrexham","13630":"Yarm","17015":"Yeovil","11824":"York"}
Here is my Javascipt:
$('#current-country').change(function(){ //any select change on the dropdown with id country trigger this code
$('.select-current-city').show();
$("#current-cities > option").remove(); //first of all clear select items
var country_id = $('#current-country').val(); // here we are taking country id of the selected one.
$.ajax({
type: "POST",
url: "<?php echo base_url()?>map/get_cities/"+country_id, //here we are calling our user controller and get_cities method with the country_id
success: function(cities) //we're calling the response json array 'cities'
{
$.each(cities,function(id,city) //here we're doing a foeach loop round each city with id as the key and city as the value
{
var opt = $('<option />'); // here we're creating a new select option with for each city
opt.val(id);
opt.text(city);
$('#current-cities').append(opt); //here we will append these new select options to a dropdown with the id 'cities'
});
}
});
});
Has anyone any suggestions on how I can process this much data in the browser?
I'm using PHP (Codeigniter), MySQL and jQuery.
I would recommend creating an array of your new option nodes, and then appending them en masse. Doing them one at a time may be what's killing you.
var newOptions = [];
$.each(cities,function(id,city) {
var opt = $('<option />', { "val": id, "text": city });
newOptions.push(opt[0]); //need to push actual dom node - thanks RightSaidFred
});
$('#current-cities').append(newOptions);
Or should this be clearing previous options in the dropdown? If so:
$('#current-cities').html(newOptions);
First double check you are not making the same AJAX request more than once.
A quick and easy solution would be to split your AJAX requests in more than one. Start by dividing it into two, and if that still isn't enough, divide them by 3 or more.
You can then check which JSON size is the right one for you, and use that one. Or you can have your php determine how much requests are needed based on the number of total cities.
For really large lists, I had to split the requests into 100 items each. The first request I would get the first piece of list along with a bit of data indicating how much requests I had to make to obtain the full list, append the new nodes, then I would make the remaining requests, until I got the full list.
I don't see how that would crash for you. Here I am doing the worst possible thing and it is blazing fast:
http://jsfiddle.net/HZnYQ/
Each time you select something, I remove all elements one by one and then append them one by one, and it's still instant. Actually my CPU doesn't even make a note of it.

Categories

Resources