Reputation: 87
I am running queries in Wordpress that should return a customer's three most recent orders. When a user clicks on the "Change" button, it should open an order form with a "Save" and "Cancel" button.
My jQuery is only working on the first result of the query. When I click the "Change" button on the second and third entries, nothing happens.
I've tried doing a loop on the jQuery, but it still only applies to the first result, so I am thinking I need to attach a variable unique ID to "order_form"
or request the jQuery to run three times.
Suggestions on what I should try?
function hgf_myhome_dash() {
foreach( array_combine( $menuid, $custom_field_data ) as $menuid => $custom_field_data ) {
$user_menu = json_decode( stripcslashes( $custom_field_data ) );
// The button
echo '<div id="change_button" style="float: left;">' . do_shortcode('[button]Change this menu[/button]') . '</div>';
// The loop
foreach( $user_menu as $single ){
if( $single->id ) {
echo get_post( $single->id )->post_title;
}}
// The form
echo '
<div id="form_show" class="modal">
<form id="order_form" action="" method="POST">
<div class="modal-content">
<div class="col_title"><h3>'.__('Current Menu' ,'rm_domain').'</h3>
<input type="button" id="cancel_button" class="cancel_menu" value="Cancel" />
<input type="submit" class="save_menu" style="" name="msubmit" id="msubmit" value="Save" />
</div>
I am text, hear me roar.
</div>
</form>
</div>
';
}
}
And here is my jQuery:
jQuery(document).ready(function($){
$("#order_form").hide();
$( function() {
$( "#change_button" ).on( "click", function() {
$("#form_show").css('display', 'block');
$("#order_form").show();
});
$( "#cancel_button" ).on( "click", function() {
$("#form_show").css('display', 'none');
$("#order_form").hide();
});
} );
});
Upvotes: 0
Views: 108
Reputation: 566
The id
attributes must be unique. You can’t have more than one tag with the same ID. When you have several elements with the same ID, the browser will ignore all the IDs except the first one.
So, only the first appearances of id="change_button"
, id="form_show"
, id="order_form"
, id="cancel_button"
will be counted. Other tags will behave as if they don’t have IDs.
Instead of ID, you can use the class
element, which doesn’t need to be unique, like this:
echo '<div class="change_button" style="float: left;">' . do_shortcode('[button]Change this menu[/button]') . '</div>';
Then, you need to change your selectors: the #change_button
searches for the element with id="change_button"
, and .change_button
searches for elements with class="change_button"
(you can have several classes separated by spaces, like class="some_class change_button some_other_class"
, and .change_button
will still work).
However, there is a rub: the selector will find all the elements with this class. So, $(".form_show").css('display', 'block');
will show all the forms with class="form_show"
, and clicking on any button will show all the forms. Which is not what you need.
So, your code needs to know which form is clicked, and select the correct one.
You can access the button you’ve clicked with this
inside the click
handler. Note that this
would be a DOM element and not a jQuery object. To convert it into a jQuery object, you need to use $(this)
.
You can use jQuery functions on $(this)
to get elements around the button. For example, the .next()
function will return a jQuery object containing the next element. So, you could use $(this).next().show()
to show the element after .change_button
(which is the form).
However, I would advise agains using .next
. It makes the JavaScript too dependent on the layout. The designer might need to add some other tags between the button and the form, and then you’d need to change your code.
Instead, you can add some data into the .change_button
that will allow to identify the form that needs to be opened. For example, you can assign numbers to all your forms, and add that number to the .change_button
.
To add custom data to any element, you can use data-something="any data"
. This is HTML5 tag for adding arbitrary data. It is very handy because it can be accessed by using $(this).data('something')
in jQuery.
So, you can add unique index to your buttons, and add that index to your form. You can add unique index like this:
function hgf_myhome_dash() {
$index = 1;
foreach( array_combine( $menuid, $custom_field_data ) as $menuid => $custom_field_data ) {
$user_menu = json_decode( stripcslashes( $custom_field_data ) );
// The button
echo '<div class="change_button" data-index="' . $index . '" style="float: left;">' . do_shortcode('[button]Change this menu[/button]') . '</div>';
// The loop
foreach( $user_menu as $single ){
if( $single->id ) {
echo get_post( $single->id )->post_title;
}
}
// The form
echo '
<div id="form_show_' . $index . '" class="modal">
<form id="order_form_' . $index . '" action="" method="POST">
<div class="modal-content">
<div class="col_title"><h3>'.__('Current Menu' ,'rm_domain').'</h3>
<input type="button" class="cancel_menu cancel_button" value="Cancel" />
<input type="submit" class="save_menu" style="" name="msubmit" id="msubmit_' . $index . '" value="Save" />
</div>
I am text, hear me roar.
</div>
</form>
</div>
';
}
++$index;
}
Note that I’ve used class
for change_button
and cancel_button
(because there might be several buttons with these classes), but I’ve kept id
for form_show_{INDEX}
, order_form_{INDEX}
. This is because, when we add index, the IDs become unique (there will be only one form_show_1
, only one form_show_2
and so on in the document), so we use id
and not class
.
N.B. IDs must be unique, so you can only call your function hgf_myhome_dash
only once per page. If you call it more than once, your JavaScript will only work correctly for the first instance. If you want to call the function many times, you can use some global variable instead of $index
— but then you probably need to rename it to something longer, to avoid name clashes.
Then, you can change your JS code like this:
jQuery(document).ready(function($){
$("#order_form").hide();
$( function() {
$( ".change_button" ).on( "click", function() {
var index = $(this).data('index');
$("#form_show_" + index).css('display', 'block');
$("#order_form_" + index).show();
});
$( "#cancel_button" ).on( "click", function() {
var index = $(this).data('index');
$("#form_show_" + index).css('display', 'none');
$("#order_form_" + index).hide();
});
} );
});
P.S. By the way, $menuid
and $custom_field_data
are not defined inside your function. Since it’s not a matter of your question, I assume you’ve removed some part of the code code. If not, you probably need to make them global, or to pass them via function arguments.
Upvotes: 1