Embedded php within JQuery within HTML table within PHP ... won't fire - php

Specific questions are at the end of this (very long) pre-amble. Sorry, I tried to make it as short as poss. (took over an hour to write the question).
A .php file uses a (php) function to read rows in a SQL db and dynamically create an HTML table.
For each row, the SQL data is returned via $book['id'], $book['code'], $book['description'], etc.
The $book['code'] is a two-char alpha-numeric ID, eg. B7 or DW
In the HTML for each row is a <td></td> containing an anchor tag with an onclick= event that runs a JQuery script (to show/hide elements for that row).
Suppose a couple or rows were clicked and a couple of elements were hidden by the embedded JQuery script (which is working correctly, by the way)
When the user views a different page and then returns to this one, hidden elements (that were hidden by the JQuery script) are no longer hidden.
I wish to preserve a string of $book['code'] values for each clicked row an d, upon return to the first page, parse that string to reset the hidden elements.
<?php
function render_row_from_mysql() {
$output .= '
...create header row...
foreach ($books as $book)
{
create table row cells 1, 2, 3, 4
after cell 4:
<td>
<a id="addToShelf.php" onclick="
jQuery.ajax(\'./addToShelf.php?id='.$book['id'].'ats'.'\');
jQuery(addToShelfLink'.$book['id'].')[0].style.display = \'none\';
jQuery(rfs'.$book['id'].')[0].style.display = \'block\';
jQuery(mt'.$book['id'].')[0].style.display = \'none\';
jQuery(grn'.$book['id'].')[0].style.display = \'block\';
return false;
">
add to bookshelf
</a>
</td></tr>' ;
}
}
Questions:
Why doesn't the JQuery code above, which works correctly, need closing parentheses?
What is the syntax for creating/updating a var, in the anchor tag, that would preserve the cumulative clicked-row data? I ask because my many attempts all break the code.
Should the var be initialized at the top of the function, before the foreach loop?
I tried using PHP to create/update a cookie by inserting the following code after "return false;" (see below). The below php code does create a cookie when pasted into a separate script for testing.) The php code does not fire. Why?

The answers are:
1) Still not sure, just syntax.
2) As mentioned in Q4, I had been entering code AFTER the "return false;" statement, which is what concludes the onclick event. Therefore, any code placed after "return false;" would not fire as part of the onclick event... and there was nothing else to MAKE it fire.
3) Irrelevant
4a.) The above code is created within a PHP code block -- one cannot create a PHP code block inside JQuery inside HTML that is being created by (i.e. already inside) PHP.
4b.) Further to answer (2), my alert() tests would not fire because they followed the "return false;" statement,
4c.) Any new PHP code must be moved out of the HTML and placed back with the rest of the PHP, such as above the function(render_row_from_mysql){}.
It is now "back to the drawing board" to figure out how to preserve the "clicked items" data between when a user leaves this page and when he returns back to it. At this time, I suspect that will be some kind of a FORM $POST event, but having never done one before I'm not sure what that will look like.

I completely agree with Bjorn comment from 22 minutes ago. You need to remove all that onclick code and add a identifying class to your anchor tags. You sure also make sure that each HTML element has a unique id, it is a W3C validation requirement. If each book's id is unique system wide I would use that, see Example below:
<?php
function render_row_from_mysql() {
$output .= '
foreach ($books as $book)
{
//create table row cells 1, 2, 3, 4
//after cell 4:
<td>
<a id="'.$book['id'].'" class="addToShelf">
add to bookshelf
</a>
</td></tr>' ;
}
}
Add this javascript code to the bottom of your HTML code.
jQuery(document).ready(function($) {
// bind event to all anchor tags with class addToShelf
$('a.addToShelf').click(function() {
var book_id = this.id;
$.ajax('addToShelf.php?id='+book_id, function() {
// execute code after the ajax request is complete...
$('addToShelfLink'+book_id).hide();
$('rfs'+book_id).show();
$('mt'+book_id).hide();
$('grn'+book_id).show();
});
return false;
});
});

Related

jQuery context menu filled with php content based on selection

When a user selects a word in a text on my website (PHP), and then right clicks, i want a jQuery context menu to come up, this can be done by using one of the already existing jQuery context menu plugins.
But besides the options like copy / paste / cut, etc. I also want something to be done with the selected word using PHP. Which, i think, is a little harder.
For example using this script:
$selection = //the selected word or text
$target = //fetch from MYSQL database
$output = array();
while ($row = //fetch $target) {
If ($selection == $row->input) { array_push($output,$row->output); }
}
echo '//menu '.print_r($output).''; // of course not print_r! Just for the example's sake.
Databse example:
(Sorry for the oversized image)
Ok so selecting the word 'lazy' in the example text, and then right clicking, the jQuery box should pop up showing the results from the database extracted by PHP.
Example:
Ok, so i know you can't just combine javascript with PHP and it can only be parsed, but i thought loading an iframe withing the menu, which does the database extraction would do the job by using javascript to set the iframe src containing the selected word in the url.
However, iFrames are not really a nice way to solve this.
The question: How can i do this effectively? Execute this script on right-click and show the database-related content in the menu?
I would need to know the plugin you're using to give you some code examples but, general, I would go about this like this:
There has to be a click handler on the items in the jQuery context menu. Use it to submit an AJAX request to the server when the "selection" term is clicked.
Make sure to give the user some feedback (a loader or spinner)
Put the results into an array server-side.
JSON encode the array and send it as the response (e.g. echo json_encode($output)
JSON.parse(response) on client-side and you now have a JS object with the results
Put those results in the context menu (again, how depends on the plugin you're using)
AJAX is a great way to do what you want.
Here is a simple AJAX example. Note that in the 2nd .PHP file, that is where you put your database lookup etc.
Whatever you echo from the 2nd script is received by the calling javascript (first script again) and can be inserted into your context menu on-the-fly. Here is another example with a very detailed, step-by-step explanation of the process at the bottom of the answer.
I think you have to use Ajax to get JSON from a PHP file, which you would process on the actual page.
I you create a PHP file called test.php, with the following in it:
<?php
echo json_encode(array('time' => time(), 'hour', date('H')));
?>
Then the Javascript:
<script>
$('#curr_menu_entry').click(function() {
$.getJSON('test.php', function(data) {
$.each(data, function(key, val) {
$('#curr_menu_entry').append('<li id="' + key + '">' + val + '</li>');
});
});
});
</script>
Would that work?

from PHP, how to make a jQuery button inside an HTML li element

I have a PHP script that queries a database and returns the rows as li elements to a div in a jQuery Dialog. It does this by building an array in the PHP while loop that processes the query row responses. So far, so good. It displays a set of rows inside the Dialog in a div with an id=dialogResponse . It is the first two parts (2 rows of code) of the array instruction below. BTW, it is just li elements - there is no ul.
Now, I want to put a jQuery Button in each li response to give the user an action choice to inactivate/pause that posting. I'm pretty new at this, and I can't get a button to appear or anything to work. I get an Internal Server Error message so I can't tell if it is a selector problem, php syntax, or something else.
How do I get a jQuery button at the end of each li that will be the trigger point for a function that takes action on that row in the database? The event.preventDefault is a placeholder for a future function that will do a MySQL UPDATE on the selected streetAddress and city. Here's the code.
$messages[] = "<li>
$storedStreetAddress, $storedCity
"<script type="text/javascript"> $(function() { $( "#dialogResponse li")
.button( label: Pause posting).click(function( event ) event.preventDefault();});});
</script>"
</li>";
Please be specific and code helps a lot. I don't follow general instructions well in this area.
Why does the <script> have to be printed in with the PHP? Why not have it included with in a JS file? For the button, why not create a standard HTML [or whatever your preference] in each <li> and have jQuery target them for the actions? - You will need an <a>, <input>, <button>, etc. for the .button()

Adding Nested form rows PHP/Javascript

Overview:
I am creating a dynamic web invoicing system,
Most of the page are textareas and I have used tables to nest as they will post data into seperate tables after the form is submitted. When the "Nested" Add a Row is selected, it should add a row inside with form field that has details on which row and which position so it can be gathered in a for loop when it is posted.
Image:
Problem:
Adding a row in the circled area does not add it in the last row, It add's it as it is in the image. Additionally it only works on the first item, the second add a row does not even register a click.
I am unsure how to get the variables to create the form name[][] in this particular index size and the parents index number (located in javascript line 2-3)
Relevent Code:
Javascript
$("#additemrow").click(function(){
var currentListItem = $(this).length;
var currentJobItem = $(this).parents('#items').index('#items');
currentListItem++;
$("#listitem:last").after(/*Blank Form Row*/);
bind();
})
PHP
<table id="items">
<tr class="item-row"><td>/*form elements*/</td></tr>
<tr class="list-row">
<td colspan=5>
<table class="itemlist">
<?php
$itemCount = 0;
foreach($jobListItem as $items) {
foreach($items as $item) {
if($problem['item_id'] == $item['item_id']) {
?>
<tr id="listitem">
<td class="list-item">
<div class="delete-wpr">
<textarea class="item" name="item[/*A PARENT ITEM NUMBER*/][<?php echo $itemCount;?>][item]"></textarea>
<a class="deleteitem" href="javascript:;" title="Remove row">X</a>
</div>
</td>
</tr>
<?php
}
$itemCount++;
}
}
?>
<tr>
<td colspan="5"><a id="additemrow" href="javascript:;" title="Add a row">Add a row</a></td>
</tr>
</table>
//NEXT ITEMLIST GOES HERE
</table>
EDIT: Foreach Loop is just used to get variables from a array.
Please let me know if you need more details or bits of code as im not sure if I have given enough information.
Regarding the problem where your row gets insertet at the top:
Like Bertrand Lefort already said: in JQuery you can append nodes to the end of another (parent) node by calling parent_node.append(child_node) (more information here)
You can also add elements before/after another element by calling another_element.before(element) / another_element.after(element) or (be aware of reversed syntax!) element.insertBefore(another_element) / element.insertAfter(another_element)
Regarding the problem where only the first "add a row" registers a click:
You're selecting by id. Id's are (or should be) unique, so when you call $("#additemrow").click(function(){ ... }) the onClick-function will only be attached to the first element that matches the given id (as far as I remember).
If you want to attach the same onClick-function to multiple elements use class instead. However, if you do so, you got to make sure you insert the new element relative to the clicked element (eg. by using .parent(), .siblings() or similar functions).
Regarding your problem #2, I don't really know what you're trying to do, but this is what I noticed:
currentListItem and currentJobItem seem to be unused in their scope, since you are declaring them as local variables but not using them
.parents('#items').index('#items') is redundant because .parents('#items') already selects only the parent elements that match '#items'. If you want to get the index of the matched element, use index() (without parameters, see jquery API for more)
Some other notes:
If you have the time (and the need of a clean project) I recommend using template engines like Smarty to separate your logic from the output. This improves the readability of your code and also makes it easier to find/eliminate bugs.
I hope this helped a little bit. If you provide more information on what you're trying to do and what doesn't work as you expext, I will try to provide further help and update my answer.
You could add an id to the parent html element, then in your click handler:
$("#additemrow").click(function(){
$("#parent").append(/*Blank Form Row*/);
})

Validating dynamic number of form elements in PHP

I need to make a form where client information can be added by people at the administration department. On the first form page, information like client name, address and contact details can be entered, as well as whether or not the client has children.
The form gets validated by PHP. If the client does not have children, the data is saved to the database. If the client does have children, the form data gets saved in hidden form fields, and a second form page is shown, where up to 10 children and can be added.
However, on initial page view, only one text input is visible. With a javascript button, more text input fields can dynamically be added (until the limit of 10 is reached).
The problem is the validation in PHP. If one of the text inputs contains a non-valid string, the form should be re-displayed with the right number of fields, and those containing errors in a special HTML class (in the CSS i give that class a red border for usability reasons, so the user can immediately see where the error resides). However, because the adding of fields happens with Javascript, the form gets re-displayed with only one field.
Any ideas on how to address this problem are very welcome. I'm proficient in PHP, but JavaScript is very new to me, so I'm not able to make big changes to the script i found to dynamically add fields.
I've dealt with something similar in the past. There are a couple of options that come to mind.
Since you have JS code to generate new fields at the click of the button, why not expand that JS function so it can also be called with some parameters passed. If there are parameters, it will populate the fields with existing data.
Then, if the form is being re-displayed due to errors, or for editing, from PHP, pass some information to Javascript so that when the page loads, you create the fields and populate them with data.
To illustrate, I assume you have something like this:
Add Another Child
And you have the function:
function addNewFormField() {
// create new HTML element to contain the field
// create new input, append to element container
// add container to DOM
}
Change it so it is like this:
function addNewFormField(data) {
// create new HTML element to contain the field
// create new input, append to element container
// add container to DOM
if (data != undefined) {
newFormElement.value = data.value;
newContainerElement.class = 'error';
}
}
And from PHP, add some code that runs onload:
<script type="text/javascript">
window.onload = function() { // replace me with jQuery ready() or something proper
<?php foreach($childInList as $child): ?>
addNewFormField({ value: '<?php echo $child['name'] ?>' });
<?php endforeach; ?>
}
</script>
Hope that helps, its a high level example without knowing exactly how your form works but I've used similar methods in the past to re-populate JS created fields with data from the server side.
EDIT: Another method you could use would be to create the HTML elements on the PHP side and pre-populate them from there, but that could end up with duplicate code, HTML generation from JS and HTML generation of the same stuff from PHP. As long as the JS side was smart enough to recognize the initial fields added by PHP you can go with whatever is easiest to implement. Personally I'd just extend your JS code to handle optional data like illustrated above.

PHP variable as part of a jQuery function doesn't work, but plain text does

I have the following jQuery code in my PHP file (edited Jan 19 2010 # 10:40 MST):
<?php
$count = 0;
foreach($attachments as $attachment) :
echo '<script type="text/javascript">
$(\'#a_'.$count.'\').click(function() {
$(\'#d_'.$count.'\').show(200);
});
// if "no" is clicked
$(\'#d_'.$count.' .no\').click(function() {
$(\'#d_'.$count.'\').hide(200);
});
// if "yes" is clicked
$(\'#d_'.$count.' .yes\').click(function() {
$(\'#d_'.$count.'\').hide(200);
// update database table -- this is why I need the script inside the for loop!
var jsonURL = \'http://path/to/update_db_script.php\';
$.getJSON(jsonURL, {\'post_id\' : '.$attachment->ID.'}, function(data) {
alert(\'Thank you. Your approval was received.\');
});
$(\'#a_'.$count.'\').replaceWith(\'<span>Approved</span>\');
});
</script>';
echo '<li>';
if($attachment->post_excerpt == 'approved') {
// Check the proof's status to see if it reads "approved"
echo '<span>Approved</span>';
} else { ?>
// If not yet approved, show options
<a class="approve" id="a_<?php echo $count; ?>" href="#">Click to Approve</a>
<div class="confirm-approval" id="d_<?php echo $count; ?>">
<p>Please confirm that you would like to approve this proof:</p>
<a class="yes" href="#">Yes, I approve</a>
<a class="no" href="#">No, not yet</a>
</div><?php
} ?>
</li>
<?php $count++;
endforeach; ?>
The page in question is available here. The "click to approve" links do not work (that's my problem).
When I view source, the PHP variables appear to have echoed properly inside the jQuery:
<script type="text/javascript">
$('#a_0').click(function() {
$('#d_0').show(200);
});
... etc ...
</script>
This looks correct, but nothing happens when I click any of the links. However, when I replace the PHP echo statements with plain numbers (0, 1, etc.) the click functions work as expected.
You may be asking: why on earth do you have this inside a for loop? The reason is that I need to retrieve the attachment->ID variable and pass it to an external PHP script. When someone clicks "approve" and confirms, the external script takes the attachment->ID and updates a database value to read "approved".
Why won't the click function fire when PHP is in place? Is there some kind of greater force at work here (e.g., hosting limitation), or am I missing a fundamental piece of how PHP and JavaScript interact?
Since you didn't post your HTML its a little hard to troubleshoot.
First, I am not sure why one is working and the other is not since the code it is outputting looks correct. Either way, I still would make some changes. Move your a_0,a_1, etc and d_0,d_1, etc into the id attribute instead of a class:
<div>Click Me</div>
<div class="confirm_approval" id="d_0">Show Me</div>
<div>Click Me</div>
<div class="confirm_approval" id="d_1">Show Me</div>
Now, instead of outputting your code in a loop in PHP, place this jQuery code once on your page:
$(document).ready(function(){
$("a.approve[id^='a_']").click(function(e){
var id = this.id.replace('a_',''); // Get the id for this link
$('#d_' + id + '.confirm-approval').show(200);
e.preventDefault();
});
});
This code finds any a element with the approve class that has an id that starts with a_. When this is clicked, it grabs the number off the id a_0 = 0 and uses that id to find the confirm-approval element and show it.
Since the javascript is run on the client and has no way of knowing whether the script was generated using PHP or not, I think that particular part is a wild goose chase...
When I replace the PHP echo statements
with plain numbers (0, 1, etc.) the
click function works as expected.
Do this again and compare the actual output using view-source in a browser. I'll bet you find that there is a difference between the working and failing scripts, other than one of them being generated by PHP.
It seems that the problem is in jQuery selectors. Instead of dynamically binding click() events on multiple objects with an output of PHP code, use just one class selector and bind to objects with this class. And you can specify an id attribute to make them unique.
Something strange too is to have the script tag and the
$(document).ready(function()
in the loop. I don't know if this causes any problems, but it's sure not very efficient, one time is enough.

Categories