Excuse me. I'm still learning the amazing JQuery language. I've faced a problem, read a lot, and still in a mess. Hope you can guide me through the solution.
I have three functions which perform three post calls. They return a text var which I lately parse as a JSON if available.
<script>
$(document).ready(function() {
...
afterAction:
a(param1,param2);
...
param1: [other value];
...
b(param1);
select:
a(param1,param2);
b(param1);
...
});
function a (param1,param2) {
// get data from DOM objects, val, texts, whatever
$.post ( "a.php", {
param1: param1,
param2: param2,
stuff1: [data from DOM objects...]
},function(data){
console.log(data)
// do something (change dom objects properties, append..)
}
});
function b (param1) {
// get data from DOM objects, val, texts, whatever
$.post ( "b.php", {
param1: param1,
stuff1: [data from DOM objects...]
},function(data){
console.log(data)
// do something (change dom objects properties, append..)
}
});
function c (param1) {
// get data from DOM objects, val, texts, whatever
$.post ( "c.php", {
param1: param1,
stuff1: [data from DOM objects...]
},function(data){
console.log(data)
// do something (change dom objects properties, append..)
}
});
</script>
The thing is that all these funtions work well... But they are asyncronous, of course. And I need to:
Execute in order, as if they were syncronous
Besides of it, (and this is one of my challenges) function a receives a param1, but after being executed code will change param1 to another value which will be used to function b.
And, whats more, this happens if trigerred certain DOM event (afterAction Owl Carrousel). If trigerred a different DOM event (selectmenu select), function a will be executed, param1 will keep its value, and function b will be called.
Things that I've tried and didn't worked:
Use $.ajax request (post method and type="text");
var posting = $.post () and posting.done ();
Nest functions in a $.when().then(),
$.when(a()).then(function(){
...
...
$.when(b()).then ({ .... });
});
AjaxQ plugin ($.postq) . But it seems to be very slow, and I dont' know why, it doesn't retrieve data.
What the calls do?
function a inserts data , updates it or deletes it using php and mysqli . It works fine for sure.
function b retrieves data from the same table.
function c retrieves a list of dates and changes the before selectmenu html.
Thanks a lot if you can help me...
ADDED 17/03/2015
A partial solution? Working on it! Change $.post by $.ajax ({... type: 'POST' }) and retrieve data using "return $.ajax" and success callback. Later I need a $.when(a(param1,param2), b(param1*), c(param1)).done(function(data1,data2,data3)){ ... }); statement which I can deal with separate data set. The thing is, when param1 is a different value for a and b functions, to be calculated previously,
A quick way is to chain them is to call each one of them in the callback function of the one you want to be executed previous to that.
For example, since a is your first function, call it, then in its callback manipulate the variables as you need and call b, and do the same in it to call c.
A rough example based on your code:
$(document).ready(function() {
//call function a first
a(param1,param2);
});
function a (param1,param2) {
// get data from DOM objects, val, texts, whatever
$.post ( "a.php", {
param1: param1,
param2: param2,
stuff1: [data from DOM objects...]
},function(data){
console.log(data)
// do something (change dom objects properties, append..)
//change the state of param1 to whatever is required and then call function b
b(param1);
}
});
function b (param1) {
// get data from DOM objects, val, texts, whatever
$.post ( "b.php", {
param1: param1,
stuff1: [data from DOM objects...]
},function(data){
console.log(data)
// do something (change dom objects properties, append..)
//change the state of param1 to whatever is required and then call function c
c(param1);
}
});
function c (param1) {
// get data from DOM objects, val, texts, whatever
$.post ( "c.php", {
param1: param1,
stuff1: [data from DOM objects...]
},function(data){
console.log(data)
// do something (change dom objects properties, append..)
}
});
Related
I'm trying to pass dynamically keys for data option into ajax call.
data:{action:'add',id:10},
Actually I'm trying to create global function, which can be use for all tables for disable the specific rows onClick event. For that purpose I need to add different actions and table column names for calling php function. So i want to pass keys also as well as values.
JS Function
function globalDisable(id,table_column,call_action){
// call_action is use for calling the related php function
// table_column is use for calling the column name of that table
action_parm = {call_action:'disable',table_column:id}
$.ajax({
type:'POST',
url:'post.php',
data:action_parm,
success: function(response){
}
});
}
Call JS Function
onclick="return globalDisable(10,'user_id','disableUser');"
Php Script
$disableUser = (isset($_REQUEST['disableUser']))? (string)$_REQUEST['disableUser']:'not';
if($disableUser != 'not'){
$response->disArea($user_id);
}
When I run the function, in console doesn't changing its remains same call_action=disable&table_column=10.
So is this possible to pass dynamically keys for data option in ajax call? I would like to appreciate if someone guide me regarding this. Thank You
Instead of action_parm = {call_action:'disable',table_column:id}, write:
var action_param = {};
action_param[call_action]='disable';
action_param[table_column]='id';
See: How do I add a property to a JavaScript object using a variable as the name?
You are passing your action as a parameter to the function but then not using it in the ajax call
function globalDisable(id,table_column,call_action){
// call_action is use for calling the related php function
// table_column is use for calling the column name of that table
//action_parm = {call_action:'disable',table_column:id}
var action_parm = {call_action: call_action,
table_column: table_column,
user_id: id};
$.ajax({
type:'POST',
url:'post.php',
data:action_parm,
success: function(response){
}
});
}
You could do this like this, maybe you will find it easier to read
function globalDisable(id,table_column,call_action){
// call_action is use for calling the related php function
// table_column is use for calling the column name of that table
$.ajax({
type:'POST',
url:'post.php',
data:{ call_action: call_action,
table_column: table_column,
user_id: id
},
success: function(response){
}
});
}
Also in the PHP you are testing for the wrong parameter in $_REQUEST
$disableUser = (isset($_REQUEST['call_action']))? (string)$_REQUEST['call_action'] : 'not';
if($disableUser != 'not'){
$response->disArea($user_id);
}
Consider "Method A: no ajax":
$(function() {
var emails = [
"john#beatles.com",
"george#beatles.com",
"paul#beatles.com",
"ringo#beatles.com"
];
$( "#invitees" ).autocomplete({
source:emails
});
});
This is given a relatively small, "unfiltered" array. The autocomplete function filters it for you as you type. I want to fetch this data once, thereby only requiring one call to the database.
Consider "Method B: 'internal' URL:
$( "#invitees" ).autocomplete({
source:"/api/get/users"
});
This does not work as I expect it to. No matter what I type, the entire list is always there. Now, after research reading the docs, other S/O questions, and every example I can find- they usually conclude with something like this:
"Data should be filtered server side. The autocomplete widget adds the term parameter to the url, so the resulting url is something like: /search.php?term=whatityped
I can handle that, but that's not totally happening in "Method A", is it? For larger data sets, I get it: no need to pre-load 100,000 results. But in this case, I want the ability to run one query and be done with it. That way if a mobile user is standing in the desert with "one bar" of service, his phone won't lock up while the server repeatedly requests new data every time he types a letter, right?
When the request goes to the internal URL:'/api/get/users'... here's the relevant part of the PHP code:
function get($className,$param1="all",$param2=""){
//above parameters will be refactored...
$stmt=$this->db->prepare('SELECT username FROM users');
$stmt->execute();
$this->data=$stmt->fetchAll(PDO::FETCH_COLUMN);
echo json_encode($this->data);
}
That function returns:
["john#beatles.com","george#beatles.com","paul#beatles.com","ringo#beatles.com"]
So again, If I explicitly do this, the filtering works:
var emails = [
"john#beatles.com",
"george#beatles.com",
"paul#beatles.com",
"ringo#beatles.com"
];
$( "#invitees" ).autocomplete({
source:emails
});
but this does not:
$( "#invitees" ).autocomplete({
source:"/api/get/users"
});
What am I missing here?
PS: Here is an unpolished attempt at method C, by the way- "ajax callback":
(Note: it's meant to accept an associative array from PHP, but the point is that it also does not "self-filter")
$( "#invitees" ).autocomplete({
source: function(request,response){
$.ajax({
url:"/api/get/users",
dataType:"json",
data:{
maxRows:5, // ? does not work
//name_startsWith: request.term // ? does not work
},
error: function(xhr,status){
alert(status);
},
success: function (data){
// alert(data);
response($.map(data,function (item){
return{
label: item.username,
};
}));
}
});
}
});
//ensures autocomplete is not set to "off"
$('input[name=invitees]').attr('autocomplete','on');
For completeness, here's My HTML:
<label for="invitees">Invite by email: </label>
<input id="invitees" name="invitees"/>
You can put the autocomplete function inside a callback function and pass the return data into that.
An example:
$.getJSON('/myJSONdata', function(data) {
$( "#input_field" ).autocomplete({
source: data
});
});
This will assign the autocomplete function to the desired fields after the callback is complete and the data would be assigned just as if it were plain text written into the function.
The autocomplete function obviously won't work until the callback completes successfully so that is something that you might want to keep in mind.
I'm using jQuery ui's sortable. A list of objects is retrieved from the db an dynamically put into a list, the user drag and drops the list objects and the new order of the list should get saved.
Below is the jQuery code for sortable, which include creating an array of the new list order. However, next step is to do something so that I'm able to use this array in my php code.
The thing is that the user, apart from sorting the list objects also should be able to add some comments and do some other stuff and then submit it all. That is, I'm using a form for this. By that reason I must be able to put in the array with the list order into the form in some way, and here's where I need some help.
What method should I use? Ajax? Local storage? How could this be accomplished?
$('#listElements').sortable({
update: function(event, ui) {
var order = [];
$('.listObject li').each( function(e) {
order.push($(this).attr('id'));
});
}
});
You'll want to use AJAX to send the order array to PHP like so:
$('#listElements').sortable({
update: function (event, ui) {
var order = [];
$('.listObject li').each(function (e) {
order.push($(this).attr('id'));
});
$.ajax({
url: "/save_order_to_db",
type: "post",
data: {
order_data: order
}
}).success(function (data) {
console.log(data);
});
}
});
Here is what I have so far:
var Item = Backbone.Model.extend({
defaults: {
id: 0,
pid: 0,
t: null,
c: null
},
idAttribute: 'RootNode_', // what should this be ???
url: 'page.php'
});
var ItemList = Backbone.Collection.extend({
model: Item,
url: 'page.php',
parse: function(data) {
alert(JSON.stringify(data)); // returns a list of json objects, but does nothing with them ???
}
});
var ItemView = Backbone.View.extend({
initialize: function() {
this.list = new ItemList();
this.list.bind('all', this.render, this);
this.list.fetch();
},
render: function() {
// access this.list ???
}
});
var view = new ItemView();
Current (expected) json response:
{
"RootElem_0":{"Id":1,"Pid":1,"T":"Test","C":"Blue"},
"RootElem_1":{"Id":2,"Pid":1,"T":"Test","C":"Red"},
"RootElem_2":{"Id":3,"Pid":1,"T":"Test2","C":"Money"}
}
This successfully polls page.php and the backend acts on $_SERVER['REQUEST_METHOD'] and returns the required information, however I don't know why the collection is not filled.
In the parse function of ItemList it properly shows me all the output, but it does nothing with it.
I left some comments in the code for some more precise questions, but the main question is why doesn't the collection populate with the obviously received data?
Modify your parse method to:
parse: function(response){
var parsed = [];
for(var key in response){
parsed.push(response[key]);
}
return parsed;
}
To follow conventions, change list inside ItemView to model. Also in render():
render: function() {
var template = _.template("<div>some template</div>");
this.model.each(function(item){
this.$el.append(template(item.toJSON()));
}, this);
return this;
}
The parse method you're supposed to be returning the data after doing whatever necessary parsing is required for it.
The common use case for parse would be if you're sending back an object of a form like:
{ "id" : "NaN", "tasks": [ *all your models in a list here *] }
then you'd use parse like so:
parse: function (data) {
return data.tasks
}
Backbone then handles the rest.
Is there a particular reason why you're sending the data back in that dictionary format? It's not exactly clear how you intend to map that to each model of the collection. Is the key irrelevant? if so, you should be passing back a list of the objects in the values.(Although see note at bottom). If not, and you want to attach it to the models, it should be moved to the object you're using as a value and send back a list.
* Note: Don't actually send back a JSON list bare. There is an exploit for GET requests that relies on lists being valid javascript on their own, where a malicious site can use the Array object and override it to use a script tag to your API to use the users credentials to pull down whatever information is available in that call. Instead, when wanting to send back a list you should use something like this:
{ result: [*list here*] }
Then you just use the parse method above to extract the list.
I have a dilemma that just seems beyond my abilities at the moment!
I have a group of connected sortables using the class 'biglist'.
What I want to do is bind #biglist 's sortreceive callback (which is made whenever a list receives an element from another) to take the 'boxnum' value of the element (which signifies which list its coming from) and perform an UPDATE query changing the id's boxnum value from say 5(list it came from) to 7 (list its been dragged to) so that the state persists.
So the exchange would happen like so (roughly)
$( "#biglist" ).bind( "sortreceive", function(event, ui) {
ajax call to boxchange.php
create vars to represent elements 'boxnum' value and 'box moved to' value
});
Then inside boxchange.php ->
$id = $_POST['id']
$box = $_POST['boxnum']
->update query SET boxid to new boxid WHERE id = posted ID of element
I hope this makes sense. It seems like a pretty slick way to make my program work!
Any help is greatly appreciated.
EDIT:
Just cleaned up the function to see if there are any changes that need to be made to it (which I know there are, because it looks sloppy) This function would need to be copied/altered for each sortable separately but it'd totally make the program work at least!
function ReceiveTwo()
{
$('#sortable2').bind('sortreceive', function(event, ui)
{
boxnum = $(this).attr('boxnum');
id = $(this).attr('id');
$.ajax
({
url: "boxchange.php",
type: "POST",
data: boxnum, id,
success : function(feedback)
{
$('#data').html(feedback)
}
})
});
$('#sortable2').sortable("refresh");
});
$('#sortable2').bind('sortreceive', function(event, ui) {
$.ajax({
url: "boxchange.php",
type: "POST",
beforesend: function(){
boxnum = $(this).attr('boxnum');
id = $(this).attr('id');
},
data: {'boxnum': boxnum, 'id': id},
success : function(feedback) {
$('#data').html(feedback),
}
});
});
beforesend is the event that fires before the ajax call. I believe here you could set your properties to accomplish what you want.
I think the way you want to send your Javascript data to your server-side PHP script is using a Javascript associative array, like so:
$.ajax({
url: "boxchange.php",
type: "POST",
data: {'boxnum': boxnum, 'id': id},
success: function(data,status) { ... }
Your "boxchange.php" script would then be able to access those variables via $_POST['boxnum'] and $_POST['id'].
I think that was your goal, but I'm not entirely sure...