Is it possible to get an element id into a PHP variable?
Let's say I have a number of element with IDs:
<span id="1" class="myElement"></span>
<span id="2" class="myElement"></span>
How do I get this into a PHP variable in order to submit a query. I suppose I would have to resubmit the page, which is OK. I would like to use POST. Can I do something like:
<script language="JavaScript">
$(document).ready(function(){
$(".myElement").click(function() {
$.post("'.$_SERVER['REQUEST_URI'].'", { id: $(this).attr("id") });
});
});
</script>
I need to pass $(this).attr('id') into $newID in order to run
SELECT * from t1 WHERE id = $newID
jQuery is a very powerful tool and I would like to figure out a way to combine its power with server-side code.
Thanks.
This is like your question: ajax post with jQuery
If you want this all in one file (posting to active file) here is what you would need in general:
<?php
// Place this at the top of your file
if (isset($_POST['id'])) {
$newID = $_POST['id']; // You need to sanitize this before using in a query
// Perform some db queries, etc here
// Format a desired response (text, html, etc)
$response = 'Format a response here';
// This will return your formatted response to the $.post() call in jQuery
return print_r($response);
}
?>
<script type='text/javascript'>
$(document).ready(function() {
$('.myElement').click(function() {
$.post(location.href, { id: $(this).attr('id') }, function(response) {
// Inserts your chosen response into the page in 'response-content' DIV
$('#response-content').html(response); // Can also use .text(), .append(), etc
});
});
});
</script>
<span id="1" class="myElement"></span>
<span id="2" class="myElement"></span>
<div id='response-content'></div>
From here you can customize the queries and response and what you would like to do with the response.
You have two "good" choices in my mind.
The first is to initiate a post request every time the ordering changes. You might be changing the ordering using jQuery UI sortable. Most libraries that support dragging and dropping also allow you to put an event callback on the drop simply within the initialization function.
In this even callback, you'd initiate the $.post as you have written it in your code (although I would urge you to look up the actual documentation on the matter to make sure you're POSTing to the correct location).
The second strategy is to piggyback on a form submission action. If you're using the jQuery Form Plugin to handle your form submissions, they allow you to indicate a before serialize callback where you can simply add into your form a field that specifies the ordering of the elements.
In both cases, you'd need to write your own function that actually serializes the element IDs. Something like the following would do just fine (totally untested; may contain syntax errors):
var order = [];
$('span.myElement').each(function(){
// N.B., "this" here is a DOM element, not a jQuery container
order.push(this.id);
});
return order.join(',');
You're quite right, something along those lines would work. Here's an example:
(btw, using $.post or $.get doesn't resubmit the page but sends an AJAX request that can call a callback function once the server returns, which is pretty neat)
<script language="JavaScript">
$(document).ready(function(){
$(".myElement").click(function() {
$.post(document.location, { id: $(this).attr("id") },
function (data) {
// say data will be some new HTML the server sends our way
// update some component on the page with contents representing the element with that new id
$('div#someContentSpace').html(data);
});
});
});
</script>
Your approach looks perfectly fine to me, but jQuery does not have a $_SERVER variable like PHP does. The url you would want to provide would be window.location (I believe an empty string will also work, or you can just specify the url on your own). You seem to be sending the ID just fine, though, so this will work.
If you want the page to react to this change, you can add a callback function to $.post(). You can do a variety of things.
$.post(window.location, {id: this.id}, function (data) {
//one
location.reload();
//two
$("#responsedata").html(data);
//three
$("#responsedata").load("affected_page.php #output");
});
I think number 2 is the most elegent. It does not require a page reload. Have your server side php script echo whatever data you want back (json, html, whatever), and it will be put in data above for jQuery to handle however you wish.
By the way, on the server side running the query, don't forget to sanitize the $id and put it in quotes. You don't want someone SQL Injecting you.
Related
I have a dropdown selector on a page that allows a user to select a template type (for example, "human" or "dog").
Based on what template is selected, different fields will need to populate below the dropdown (for example, text fields for "parents names" or a dropdown list for "breed") that are unique to each template.
I will have a button that the user will click once the data fields are put in that will output data to an "output div" section of the same page when clicked (no POSTing data as it's not being saved). The output will have different output logic based on the selected template (for example, "I'm a human named X" or "I'm a dog, my breed is Y").
My real program will be more complex and each template will have a php class that stores all of the logic. Since I will be dealing with both php objects and variables gathered by jquery, what's the best way to let them interact?
For 1., I know I can do something easy like -
var selected_template = $('#my-template-dropdown :selected').text();
if (selected_template == 'Human'){
$('#my-fields').html('<?php echo HumanTemplate::render_fields(); ?>');
}
which is easy enough, but for 2. I need to pass variables from jquery to php, then return output back to jquery.
I would like some advice on the easiest way to do this before I start down the wrong path.
HTML
Allow the user to select the template type:
<form>
<select id="my-template-dropdown" name='template'>
<option value="dogs">Dogs</option>
<option value="humans">Humans</option>
</select>
</form>
<div id="my-fields"><div>
<div id="output"><div>
jQuery
Any time the user changes the template selection, request new content to display via AJAX, and insert it on the current page so the page does not have to refresh:
$('#my-template-dropdown').on('change', function() {
var template = $(this).val();
$.ajax({
url: 'http://your-site/path/to/' + template,
success: function(resp) {
$('#my-fields').html(resp);
}
});
});
PHP
http://your-site/path/to/template simply generates the HTML you want to display for that template, eg (just an example, don't know if this is suitable for your app):
if ($template == 'humans') {
echo HumanTemplate::render_fields();
} else if ($template == 'dogs') {
echo DogTemplate::render_fields();
}
For part 2, assuming all the logic you refer to is in the template rendered by PHP, you could then handle it with jQuery. This is pretty crude, you probably need something more sophisticated (eg a full template which you swap variables into?), but you get the idea:
$('#output').on('click', 'button', function(e) {
e.preventDefault();
// fields in your template which the user will fill
var species = $('#species').val(),
title = $('#title').val();
// Probably better to have this text as a template in your source
$('#output').html("I'm a " + species + ' named ' + title);
});
NOTE the gotcha in the event handler. Event handlers will only attach to elements that exist at the time the handler is defined. Since the content is injected after page load, an event handler like $('#button).on('click', function() {... would have no effect when clicking a button inserted via AJAX. The syntax here attaches to the parent #output div, which does exist at page load, and filters for clicks on a button. See the jQuery event delegation docs for more info.
Another option would be to POST the submitted data to some PHP controller, which generates and returns the output. This way all your logic is in the one place. For example, here the user's click will query the same PHP file which generated the initial template, this time including the values the user has entered. It could then generate the required output and return it, to be inserted on the page. You'd need to update the PHP so it can determine which of these cases it is handling (eg hidden field?); alternatively if you wanted to keep those separate you could hit another PHP file all together.
$('#output').on('click', 'button', function(e) {
var template = $('#my-template-dropdown').val(),
$form = $('form'),
data = $form.serialize(); // Values from all fields user has entered
$.ajax({
url: 'http://your-site/path/to/' + template,
data: data,
success: function(resp) {
$('#output').html(resp);
}
});
});
The best way to pass data from jQuery to PHP, is by using AJAX.
Mozilla has an excellent guide on getting started, that i recommend you follow.
An example of how you can achieve what you are requesting, is by trying the following:
var selected_template = $('#my-template-dropdown :selected').text();
var ajaxurl = 'ajax.php',
data = {'select_template': selected_template };
$.post(ajaxurl, data, function (response) {
console.log(response);
});
On the PHP end (Ajax.php in my example) It could look something like this
if(isset($_POST['select_template'])) {
// do something with the input from jQuery
$selected_template = $_POST['select_template'];
// return the result back to the client
echo $seleted_template;
}
?>
$selected_template will be sent back to the client, and response in the AJAX function will be whatever the server returned. So the console.log(response) should display whatever was being sent to the server
You can have a look to the function wp_localize_script.
This function make available PHP datas to JS files on the page load through the wp_enqueue_scripts action.
This will not work like an Ajax request and only populate data for a specific handle on page load. But you can mix this method with ajax in the same script.
Hope it helps even it doesn't seems to fit to your case.
As your class not fires on page load, you can use the action wp_ajax_{custom _action} and wp_ajax_nopriv_{custom_action} . For example, that's usually used to populate multiple dropdown, each time an event is trigger by the user, a php function returns result the js script.
I am trying to post the element information that jQuery pulls, when a user clicks on table cell, to a new page that will use that information (an id in this case) in a sql query. i.e., the user clicks a cell and the job he/she clicks has an id of 25, that is to be passed to my php page that queries the database for the job with that id and then populates the page with said information. The user can then alter the information from the query and submit it to update the database table. I have the id from the click function and a success alert tells me that the info was posted. The problem is that when the page is opened it states that the posted name index is undefined.
Here is my script to get the information:
<script>
$(document).ready(function()
{
$("table.jobs tbody td#job").click(function()
{
var $this = $(this);
var col = $this.text();
var LeftCellText = $this.prev().text();
if (col == '')
alert("Please pick another column");
else
$.ajax(
{
type:"POST",
url:"../php/jobUpdate.php",
data:"name=" + LeftCellText,
success: function()
{
window.location = "../php/jobUpdate.php";
}
});
});
});
</script>
and here is the simple php page it is sending to:
$name = $_POST['name'];
echo $name;
I am new to jQuery, and I cannot figure out why this is not working?
When you use ajax, the second page ../php/jobUpdate.php processes the data sent by the first page, and returns a value (or even a huge string of html, if you want).
The first page receives the new data in the ajax routine's success function and can then update the current page. The updating part happens in the success: function, so you're on the right track.
But in your success function, you are redirecting the user to the 2nd page -- after already being there and processing the data. Redirecting them is probably not what you want to do.
Try replacing this:
success: function()
{
window.location = "../php/jobUpdate.php";
}
with this:
success: function(data)
{
alert(data);
}
If you want to see how to update the first page with the data received via ajax, try adding an empty DIV to your html, like this:
<div id="somestuff"></div>
Then, in the success: function of the ajax routine, do this:
$('#somestuff').html(data);
(Note that the term "data" can be any name at all, it only needs to match the name used in the function param. For example:
success: function(whatzup) {
alert(whatzup);
}
From your comment to my previous post, it seems that you don't need ajax at all. You just need a form in your HTML:
<form id="MyForm" action="../php/jobUpdate.php" method="POST">
<input type="hidden" id="jobID" name="yourJobID">
</form>
Note that forms are invisible until you put something visible inside them.
You can have select controls (dropdowns) in there, or all form elements can be invisible by using hidden input fields (like the HTML just above), which you can populate using jQuery. Code to do that would look something like this:
<script>
$(document).ready(function() {
$("table.jobs tbody td#job").click(function() {
var $this = $(this);
var col = $this.text();
var LeftCellText = $this.prev().text();
//Set value of hidden field in form. This is how
//data will be passed to jobUpdate.php, via its `name` param
$('#jobID').val(LeftCellText);
if (col == '')
alert("Please pick another column");
else
$('#myForm').submit();
});
});
</script>
If you add more values to your form to send over to jobUpdate.php, just ensure that each element has a name, such as <input type="text" name="selectedJobType"> (this element, type="text", would be visible on screen).
In the jobUpdate.php file, you would get these values thus:
$SJT = $_POST['selectedJobType'];
$id = $_POST["yourJobID"];
//Use these vars in MySQL search, then display some HTML based on results
Note that the key referenced in the $_POST[] array (selectedJobType / yourJobID) is always identical to the name specified in the HTML tag. These names are case sensitive (and spelling counts, too).
Hope this isn't TMI, just wish to cover all the bases.
On your success function causing the window to reload will delete any of the variables passed in via .ajax.
What you can try is returning the data and use it in the existing page.
success: function(msg) {
$('#someDiv').append(msg);
}
The reason the index is not defined is because you are using a string in the data-argument, however, that is actually an array-like object. :)
data: { name: col }
that should be the line you need to change. Otherwise I have not seen any problems. Also if I can give you a little idea, I wouldn't use POST actually. In fact, I'd use GET. I can not confirm if that is saver or not, but using $_SERVER["HTTP_REFFERER"] you can check from where that request is coming to determine if you want to let it pass or not.
The way I would suggest is, that you sent the ID in a GET-request and have the PHP code return the data using json_decode(). Now in jQuery, you can use $.getJSON(url, function(data){}) - which is, for one, shorter and a bit faster.
Since you probably will crop the URL yourself here, make sure that you use a function like intVal() in JS to make sure you are sending an intenger instead of a malicious string :)
Following the example here Very Simple jQuery and PHP Ajax Request – Ready to use code
I've been successful in creating a drop down list that passes the value to an external PHP script and returns the HTML output back to a "div" on the same page and it works great.
What I want to do now is post values when I click on link instead of building a drop down list. So ...if I created this link:
Route Number 2
I want "2" passed to that external PHP script and the content changed on the " div " as it currently works with the dropdown. I don't know how to change the javascript to handle this or what "foo.php" really needs to be.
Here's the current javascript from that example:
<script type="text/javascript">
$(document).ready(function() {
$('#route_number').click(function() {
routenumber = $('#route_number').val();
$.post('api.php', { route_number : routenumber }, function(res) {
$("#mainlayer").html(res);
});
});
});
</script>
And here's what the dropdown portion of the HTML looks like:
<select name="route_number" id="route_number">
<option value="notchosen">Please Choose A Route</option>
<option value="2">Riverfront</option>
<option value="11">Magazine</option>
<option value="16">Claiborne</option>
</select>
<div id="mainlayer">
</div>
So, to be clear, instead of a dropdown that passes values, I want to create links that accomplish the same result.
Thanks in advance,
dan -
Create a class, capture its (meaning whatever link you clicked on) value, then post.
<a class="RouteNumber" href="foo.php?route_number=2">Route Number 2</a>
$(function(){
$('a.RouteNumber').on('click',function(event){
// prevent the browser's default action for clicking on a link
event.preventDefault();
// break href attribute into array, then parse desired value as int
var routenumber = $(this).attr('href').split('='),
rtnum = parseInt(routenumber[1]);
$.post('api.php',{route_number:rtnum},function(res){
$("#mainlayer").html(res);
});
});
});
If you don't need to parse the integer out of it (if a string is good enough), you don't need that second variable. You can just use routenumber[1] in the post data.
Just a heads up, I modified the jQuery to use the .on() syntax. .click() is shorthand for it, but I like using .on() just because it allows for less potential codewriting if you want to do more (like mouseenter/mouseleave, for example) because you can combine them into a single codeset.
I had hoped simply fixing #LifeInTheGrey's example would've sufficed, but there are some things I would've done differently that probably need some explaining.
Your HTML could look something like this:
<a class="route" href="foo.php?route_number=2" data-route="2">Route Number 2</a>
The JavaScript would look something like this:
$(function() {
var fill_div_with_response = function(res) {
$("#mainlayer").html(res);
};
var handle_error = function(res) {
alert('something went wrong!');
};
$(document.body).on('click', '.route', function(event) {
// prevent the browser's default action for clicking on a link
event.preventDefault();
// grab route number from data attribute
var route = $(this).data('route');
// make that post request
$.post('api.php', {route_number: route})
// handle the response
.done(fill_div_with_response)
// handle errors
.fail(handle_error);
});
});
The example uses delegated events. They're cheap to initialize and consume the least amount of memory.
The example handles errors. Most answers to questions like these neglect that. errors happen. Always. Make people aware of that. Surely throwing an alert() is not the thing you want to be doing, but it's still better than simply ignoring errors completely.
The example uses Deferreds (Promises) rather than callbacks, as this usually makes code much cleaner.
We're defining the callbacks fill_div_with_response() and handle_error() at the root closure to prevent redefining them on the next click. There's no need to feed the garbage collector.
The data attribute poses the optimal alternative to <option value="123"> in the way that it prevents you from having to parse the href attribute to extract that number from a string.
since you want to make a menu, I would modify your markup
<ul name="route_number" id="route_number">
<li value="2">Riverfront</li>
<li value="11">Magazine</li>
<li value="16">Claiborne</li>
</ul>
then simply process that list:
$('#route_number').find('li').click(function () {
var routenumber = $(this).attr('value');
$.post('api.php', {
route_number: routenumber
}, function (res) {
$("#mainlayer").html(res);
});
});
EDIT1: As an improvement (as you seem to be pretty new to this stuff) you could use the data with altered markup as such:
<ul name="route_number" id="route_number">
<li data-routenumber="2">Riverfront</li>
<li data-routenumber="11">Magazine</li>
<li data-routenumber="16">Claiborne</li>
</ul>
Then the code would be:
$('#route_number').find('li').click(function () {// add click event manager to each li
var routenumber = $(this).data('routenumber');// get routenumber of clicked
$.post('api.php', {
route_number: routenumber
}, function (res) {
$("#mainlayer").html(res);
});
});
Alternate code using .on() form
$('#route_number').on('click, 'li', function () {//click event manager for ul/li
var routenumber = $(this).data('routenumber');// get routenumber of clicked
$.post('api.php', {
route_number: routenumber
}, function (res) {
$("#mainlayer").html(res);
});
});
Note that this last form binds to the #route_number element so you could add more menu options during processing and they would still work. This is also better than attachment to the document as it is a more focused approach to the event attachment.
My understanding of your question is that the functionality you have is fine, and you just need to change the look to a piece of text from a dropdown. If so, good news! You can keep (almost) the same JavaScript.
Right now, your JavaScript is getting the value of your select box, sending it via AJAX, and using the returned value. The only change you need is to get the 'value' of the text clicked.
You don't want to use a link, since that's designed to take the user someplace. Instead you can use a span and format it to look like a link, or even a button if you want that kind of look.
You will also need to change $('#route_number').val();, probably to something passed by the click event. For example:
<span id="route1" class="routeSpan" onclick="sendVal(1)">Route 1 Name</span>
<span id="route2" class="routeSpan" onclick="sendVal(2)">Route 2 Name</span>
And your JavaScript:
function sendVal(routeVal) {
$.post('api.php',{route_number:routeVal},function(res){
$("#mainlayer").html(res);
});
}
On my page I have a search result that contains a list with users where each is followed by an "addfriend" button. Each row contains a username and userID. Meanwhile the ID of the user that requested the searchresult is stored in a Session variable.
When the addfriend-botton is clicked the following 2 things should happen:
Store the userID and $_SESSION['userID'] is a MySQL table which describes the relationship.
Do NOT refresh the page (this the core of my problem) but stay focussed and change the state of the button to e.g. "friend request send". I'm thinking of GetElementByID().style method.
I was thinking of this:
<a href="#" onClick="addFriend('<? echo $_SESSION['userID'];?>','<? echo $rij['userID']; ?>')">
which calls the javascript function addfriend
I was hoping to catch the two ID's like this:
<script>
function addfriend(id1, id2)
{
//server side php code where I use value of
//the client-side javascript variables: +id1+ and +id2+ .
}
</script>
Is this at all possible or I'm I thinking the wrong way? Any suggetions on how to accomplish this?
You are in the right way, inside your addFriend() function, you can call one php file (via AJAX) and send the IDS without refresh the page. I think better you work with Jquery in this case, something like this:
<script>
function addfriend(id1, id2)
{
$.ajax({
type: 'POST',
url: 'yourPHPfile.php',
data: { your_id_1:id1, your_id_2:id2 },
success: function(data){
if(data){
alert('Done!');
}
},
dataType: 'text'
});
}
</script>
And in your PHP File you can do this:
<?php
//receive Ids
$id1 = $_POST['your_id_1'];
$id2 = $_POST['your_id_2'];
//do something here
echo "OK!";
<?
to do this work you need download and add the jQuery plugin in your page, rather into head tag
<head>
<script type="text/javascript" src="jquery.js"></script>
</head>
Good work and don't give up! (:
You can do this using AJAX (asynchronous JavaScript and XML), which is really just a fancy term for "sending stuff to a server with JavaScript and getting a response back, without reloading the page". There's nothing special about AJAX; it just involves using plain old JavaScript to send an HTTP request.
Check out jQuery, a JavaScript library that handles most of the technical stuff for you. Specifically, look at its post() function, which allows you to send data to a PHP script using the $_POST system variable. There are lots of clear examples on that page.
Note that you don't need jQuery to use AJAX; jQuery is just a library that makes things easier. If you really want to learn how the JavaScript side of AJAX works, try following one of the many tutorials out there, such as Mozilla's or this one.
AJAX is the answer you're looking for.
It sounds like you already have a basic understanding of this, but to clarify, Javascript executes on the client side, and PHP executes on the server side. So you would have to make a call back to your server in order to interact with PHP/MySQL.
The purpose of AJAX is to do this without requiring a page refresh.
I'm using CakePHP for a small web app and on one form page there's a dropdown to select a job number. I'd like to update two text fields based on the job number selected in the dropdown using jQuery (I'm also open to using the default ajax helper but I didn't have a lot of success with it).
Here's my jQuery snippet:
<script>
$(document).ready(function() {
$('#job_id').change(function() {
$.post('/surveys/jobdetails', {id: $(this).attr('id')});
})
.change();
});
</script>
jobdetails is a method in my controller that gets the current job based on the job id passed in. However, it doesn't get called when the dropdown changes value. I tried substituting an alert function in place of .post and that worked, so onchange is being called correctly.
Here's the <div> I'm trying to update:
echo "<div id='job_details'>";
echo $form->label('jobtitle', 'Job Title');
echo "<input type='text' name='jobtitle' id='jobtitle'>";
echo $form->label('department', 'Department');
echo "<input type='text' name='department' id='department'>";
echo "</div>";
I want to set the value of each text field to be the corresponding value for the job returned from the ajax call. There's a lot of really good jQuery and CakePHP documentation but I haven't found anything that quite covers what I'm trying to do. Can anyone see what I'm doing wrong? Is there a better way to use ajax to update a div with CakePHP?
Right now, it appears that the AJAX request hits the "/surveys/jobdetails" URL, but does nothing with the results. You need to add a callback to your AJAX request, like so:
$(document).ready(function() {
$('#job_id').change(function() {
$.post('/surveys/jobdetails', {id: $(this).attr('id')},
function(result) {
$('#job_id').html(result);
});
})
.change();
});
There is also a convenience function in jQuery called load() which simplifies it even further, getting the contents of a URL and applying it to the selected element:
$(document).ready(function() {
$('#job_id').change(function() {
$(this).load('/surveys/jobdetails', {id: $(this).attr('id')});
})
.change();
});
Your CakePHP controller needs to look something like this:
function jobdetails() {
// get the data however you want
// $_POST['id'] will have the job_id
print json_encode(array(
'jobtitle' => $jobtitle,
'department'=>$dept
));
exit;
}
Then you need to add a callback to your $.post that will actually update the fields:
$(document).ready(function() {
$('#job_id').change(function() {
$.post('/surveys/jobdetails', {id: $(this).attr('id')}, function(json) {
// now that we are in the callback,
// the variable json is an object
// with the values we passed above
// so we can update the fields with the new values
$('#jobtitle').val(json.jobtitle);
$('#department').val(json.department);
});
})
.change();
});
I also recommend you get a tool like Firebug so you can see the progress of your AJAX requests and make sure the server is returning what you think its returning. It makes testing and debugging anything related to AJAX way easier.
In my opinion this is more elegant than outputting the whole DIV to update, but if you want to go that route you would just use jQuery's .load to achieve what you want.