I have a range slider and I want to use the value from that slider in my wordpress functions.php file as an attribute for an already written shortcode function. Basically, it will be a choice of distance from a point. I just need to make the existing distance attribute variable and connected to the range slider which will re-execute the function on submit. I'm very lost on this so any help is appreciated. Thank you!
There are a couple of different ways to do this really, depending on whether or not you want a page reload when they submit.
Method 1 - Pass the range value as a url variable
Submit the value of the form onto the page and then reload it with this data:
<form id="distance-form" action="<?php the_permalink() ?>" method="get">
<input type="range" min="0" max="5000" value="0" id="distance">
</form>
and then elsewhere on the page you might have the shortcode function which would include the distance value if set.
e.g.
function example_shortcode(){
$distance = intval($_GET['distance']); //Get the url value of distance
if(!$distance || $distance < 0){ //Or set to zero if not a valid value
$distance = 0;
}
// Then do whatever we need with the function
}
Method 2 - Use AJAX
We can use a similar method but with AJAX instead, which would need a similar PHP function and a JS function to make the AJAX call.
I'd recommend reading up on AJAX if it's not something you're familiar with, https://premium.wpmudev.org/blog/using-ajax-with-wordpress/ is pretty good.
You'd probably end up with something like the following for the js:
$("#distance-form").submit(function(event){
event.preventDefault();
jQuery.ajax({
url : localisedVars.ajax_url,
type : 'post',
data : {
action : 'function_name',
distance : $("#distance").val()
},
success : function( response ) {
/*Return the shortcode response from our PHP ajax call, we can then put it somewhere on the page*/
}
})
and
add_action( 'wp_ajax_nopriv_function_name', 'function_name' );
add_action( 'wp_ajax_function_name', 'function_name' );
function function_name() {
$distance = intval($_POST['distance']); //Get the ajax posted value of distance
if(!$distance || $distance < 0){ //Or set to zero if not a valid value
$distance = 0;
}
// Then do whatever we need with the function
echo $response //gets passed to the js function above
die();
}
Related
I am trying to fetch a data that has the same id of my input hidden value.
I cannot fetch the id or input hidden value of the data
To start with, this is what I've done to make things clearer for me to debug things I made a hard coded form and a button to bring me to the page
In View - groups/index.php
As you can see I made the posts/index/1 which is a hard coded value but I can change that later easily that is not my problem
<?php echo form_open('posts/index/1') ?>
<input type="hidden" name="txtGroup" value="1" />
<button type="submit" class="btn btn-info"> Submit</button>
</form>
So after I made the form I will make a function in controller to fetch the posts/index
In Controller - Posts.php
public function index(){
$this->load->view('templates/header');
$this->load->view('teachers/posts/index');
$this->load->view('templates/footer');
}
And so I fetched the page. At this point, i can now go through /posts/index/1 and see my page
In my page posts/index.php I have a data and it is fetched through Ajax here it is
So I already fetched this data in posts/showPosts
showAllQuestions();
//Show all data
function showAllQuestions(){
$.ajax({
type: 'ajax',
url: '<?php echo base_url() ?>posts/showPosts',
async: false,
dataType: 'json',
success: function(data){
var html = '';
var i;
var n=1;
for(i=0; i<data.length; i++){
html +='<div class="card">'+
'<div class="card-header" style="color:white; background-color:black">'+
'<h4><span class="iconify" data-icon="ant-design:info-circle-outlined" data-inline="false"></span> Question No. '+ n++ +'</h4>'+
'</div>'+
'<div class="card-body">'+
'<form>'+
'<div class="form-group">'+
'<label for="exampleFormControlTextarea1"><h5> <span class="iconify" data-icon="emojione:check-mark-button" data-inline="false"></span> </h5></label>'+
'<input type="text" value="'+data[i].question+'" class="form-control" disabled />'+
'</div>'+
'<hr>'+
'<span class="iconify" data-icon="el:edit" data-inline="false"></span> '+
'<span class="iconify" data-icon="fa-solid:trash-alt" data-inline="false"></span>'+
// 'Edit '+
'</form>'+
'</div>'+
'</div><br>';
}
$('#showdata').html(html);
},
error: function(){
alert('Could not get Data from Database');
}
});
}
In posts/showPosts - Posts.php, this is the controller
public function showPosts(){
$result = $this->post_model->showPosts();
echo json_encode($result);
}
Finally the Model to Determine if I fetched the correct ID depending on the data id I submit
Problem is the $id is null and I don't have a clue to start with, because I declare a hidden input value on the view page.
public function showPosts(){
// Show questions and answers
$id = $this->input->post('txtGroup');
$this->db->select('*');
$this->db->from('questions');
$this->db->where('group_id', $id);
$query = $this->db->get();
return $result = $query->result_array();
}
I am going to try to understand this question better than your previous one (which is now safe to delete since this is a better description of your issue).
In your groups/index.php view, you want to allow a user to navigate to the posts/index page and pass an integer as a single parameter (which is hard-coded by you, not entered by the user) -- I'll refer to it as $txtGroup for context. Because you are not performing a INSERT|UPDATE|DELETE operation, better practice is to send the data as a $_GET instead of $_POST. Because Codeigniter enables the passing of $_GET parameter as a slash-delimited extension of the url, I don't see any benefit in setting up a <form>.
Style your new hyperlink as a button using your preferred classes.
Link to <?php echo $integer; ?>
This will send your data to the posts/index.php controller. This is where you should be accessing/extracting the $txtGroup value from the url.
Here's where I start to get foggy about what you need. If you want to pass the value to the teachers/posts/index view, then do so by passing an associative array as the second parameter when you load the view.
public function index($txtGroup) {
$this->load->view('templates/header');
// if you want to pass the value to THIS
$this->load->view('teachers/posts/index', ['txtGroup' => $txtGroup]);
$this->load->view('templates/footer');
}
If you are not interested in passing the $txtGroup to the view, then the only other reason to pass the value from groups/index.php to posts/index would be to modify a query and then pass dynamic data to the teachers/posts/index view (which you would need to supply when loading the view anyhow).
public function index($txtGroup) {
$data['posts'] = $this->post_model->showPosts($txtGroup);
$this->load->view('templates/header');
$this->load->view('teachers/posts/index', $data);
$this->load->view('templates/footer');
}
In your model, use the passed argument.
public function showPosts($groupId) {
return $this->db->get_where('questions', ['group_id' => $groupId])->result_array();
}
This way, you don't need to use an ajax call (which looks like you are unconditionally triggering in your view anyhow). Now Codeigniter will work its magic to transfer $data to your view whereby you can access the multidimensional result set as $posts (the variable is named by the first-level key that you assign it). Use a foreach() loop to iterate the rows of results and generate your html content -- all using server-side language.
<?php foreach ($posts as $index => $post) { ?>
<div class="card">
// ... the rest of your content ...
<?php } ?>
As you design the new dynamic content using the above loop:
Use $index as your counter so that you don't have to manually increment.
DO NOT allow INSERT|UPDATE|DELETE operations to be triggered by $_GET events, this is not best practice. Those types of actions should only be initiated by $_POST submissions.
I am trying to save the value of multiple checkboxes in WordPress, So if a guest checks a checkbox (front-end) without clicking any submit buttons, this checked value will be stored in the database.
Next time anyone loads this page, this particular checkbox should be pre-checked.
So far I have got this code in the template file that is responsible for the content of the page I am trying to add these checkboxes to.
(This is no regular WP post/page template but a "collection page" generated by a WooCommerce collection plugin):
//submit code
if(isset($_POST['cadeau']) ){
$data=serialize($_POST['cadeau']);
update_post_meta($post_id, 'cadeau', $data);
}
//edit code
$data=get_post_meta($post_id, 'cadeau');
//$data=unserialize($data[0]);
$data=$data[0];
print_r($data);?>
<input type="checkbox" name="cadeau[]" value="<?php echo $product_id;?>" <?php if(in_array($product_id,$data) ){echo "checked";} ?> >
This is not working however.. Am I on the right track? Or am I doing it completely wrong?
Basically, to make such things in WordPress (and not only) you have to make a POST request to the server. Either by submitting a form or doing an AJAX request. Here is an example of how to make it to work. If you don't want to make AJAX request just skip step 1 and jump directly to step 3 and have a look at the function. I am sure it will help you go on the right track.
1. Create a JS script which sends an AJAX request to admin-ajax.php file:
<script>
jQuery("#submit-button").on("click", function(){
var checkboxValue = jQuery("#your-checkbox").is(":checked") ? 1 : 0;
jQuery.ajax({
url: "http://www.yourdomain.com/admin-ajax.php",
method: 'POST',
data: {action: "save_checkbox", checked: checkboxValue}
}).done(function(response){
console.log("Response: " + response);
//NOTE that 'action' MUST be the same as PHP function name you want to fire
//you can do whatever you want here with your response
}).fail(function(error){
console.log(error);
});
})
</script>
2. Create new file e.x. myajax.php and include it to functions.php
3. Now write a function you want to fire on click, e.x.:
function save_checkbox(){
$checkboxValue = $_REQUEST['checked'];
update_post_meta($coll_id, 'cadeau', $checkboxValue );
$response = array(
"status" => "ok",
"message" => "Post meta saved",
);
$response = json_encode($response);
echo $response;
die();
}
add_action( 'wp_ajax_save_checkbox', 'save_checkbox' );
That's all. As I said note that actionhas to be the same as PHP function. If you want to have some response from your PHP function just echo it and this is what you will get as a response. If you'll get 0 as a response it means that function you want to fire does not exists or you didn't call die() at the end of your function. I hope I could help.
Im trying to update the mini-cart (cart_fragments) after/on an ajax event. It works like this.
HTML Trigger:
<a id="woomps-button-\'.$nr.\'" class="woomps-button" '.$ajax_url.' data-button-nr="'.$nr.'">
jQuery request:
jQuery( document ).on('click', '.woomps-button', function() {
var nr= jQuery(this).data('button-nr');
jQuery.ajax({
url : subpost.ajax_url,
type : 'post',
data : {
action : 'woomps_update_nr',
security : subpost.security,
nr: nr
},
success : function( response ) {
window.alert(nr);
//MAYBE_code to refresh_fragments here
}
});
return false;
});
PHP responder:
function woomps_update_choosen_person () {
$p = $_POST['nr'];
if ($p == 1) {$x= "This must show in cart";}
WC()->session->set( 'woomps_limit_by_persons' , $x );
//MAYBE code to refresh_fragments here
}
And in the mini-cart.php template i have a calculation based on this field.
$items_left_start = WC()->session->get( 'woomps_limit_by_persons' )?: 3 ;
//Do something something here
So this works, except I need to refresh the cart like when an item is added to cart. My assumption is that is should be an ajax request from jQuery that i can put in the success block?
The class i (think) I want to fire is this WC_AJAX::get_refreshed_fragments(); But this is fired from an an add_action, so i tried this add_action( 'wp_ajax_nopriv_woocommerce_get_refreshed_fragments', array( 'WC_AJAX', 'get_refreshed_fragments' ) );. But it did not work either.
I also try to create an jQuery ajax call like it does in the add_to_cart button, but it neither worked.
//MAYBE_code to refresh_fragments here
var data = {};
jQuery.post(
wc_get_refreshed_fragments_params.wc_ajax_url.toString().
replace( '%%endpoint%%', 'get_refreshed_fragments' ), data,
function( response ){
})
}
I do not completely understand how this works, if anyone have some pointers or a snippet i would so much appriciate it. Been struggeling with this for some time now.
After much struggeling this topic on stack helped create the correct code to update mini cart fragments. It was both PHP and jQuery neeeded.
So basically you can call the WC_AJAX::get_refreshed_fragments() at the end of your PHP coode responder; if it comes from an AJAX call. It will not return to your PHP responder code so put it at the end. The PHP respons will end/sent back to jQuery inside the WC_AJAX::get_refreshed_fragments(); so you also need to create some jQuery that responds to this. This i got from the topic:
var fragments = response.fragments;
if ( fragments ) {
jQuery.each(fragments, function(key, value) {
jQuery(key).replaceWith(value);
});
}
I have an app that has rows, each row contains data. The rows are created by the user (just cloning a sample row).
My ajax function looks like this.
save : function(el) {
//Renaming the properties to match the row index and organize
jQuery('#application-builder-layout .builder-row').each(function(row) {
// Iterate over the properties
jQuery(this).find('input, select, textarea').each(function() {
// Save original name attr to element's data
jQuery(this).data('name', jQuery(this).attr('name') );
// Rewrite the name attr
jQuery(this).attr('name', 'application[rows]['+row+'][elements]['+jQuery(this).attr('name')+']');
});
});
//Looping through each row and saving them seperately with new rowkey
setTimeout(function() {
// Iterate over the layers
jQuery('#application-builder-layout .row-box').each(function(row) {
// Reindex layerkey
jQuery(this).find('input[name="rowkey"]').val(row);
// Data to send
$data = jQuery('#application-builder-layout .row-box').eq(row).find('input, textarea, select');
//$data = $data.add( jQuery('#application-builder-layout') );
jQuery.ajax(jQuery('#form').attr('action'), {
type : 'POST',
data : $data.serialize(),
async : false,
success: function( response ) {
//console.log( response );
}
});
});
}, 500);
},
This is the jQuery, it's application style format so this function is inside a var and is called inside a submit function, the problem is not the ajax, looking at it in the console it saves the data fine, just like I have before.
The Problem I cant get all the data into the database (only the last ajax request) take a look below at "Form Data" it shows what my ajax data looks like and how it's inserting into the DB vs how it should insert, I am using json encode and usually this works, but recently I switched to OOP style coding in PHP so I am not sure if that changes anything?
The PHP:
class MyApp {
const Post_Type = 'page';
public function __construct() {
// register actions
add_action('init', array(&$this, 'init'));
}
public function init() {
// Initialize Post Type
add_action('save_post', array(&$this, 'save_post'));
}
//The main save method
public function save_post($post_id) {
// Empty the builder
if($_POST['rowkey'] == 0) {
$builder = array();
}
$builder['rows'][$_POST['rowkey']] = $_POST['application']['rows'][$_POST['rowkey']];
$builder = esc_sql(json_encode($builder));
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if($_POST['post_type'] == self::Post_Type && current_user_can('edit_post', $post_id)) {
// Update the post's meta field
update_post_meta($post_id, 'MY_DATABASE', $builder);
} else {
return;
}
}
}
The above works fine, except its not inserting the data as an array just inserting the last ajax post call, not each. I am sure in my save method I need to reconfig that somehow, but I am just hacking away and cant find info on the web, so I could really use some insight.
I hope I provided enough.
My code summed up: Just to be clear on whats going on here, let me you some basic HTML of my app.
//This gets cloned and the jQuery renames the rowkey to match the index.
<div class="row-box">
<input type="hidden" name="rowkey" value="0">
<div class="builder-row">
<textarea style="display: block;" name="html"></textarea>
<textarea style="display: block;" name="breakingbad"></textarea>
</div>
</div>
So summed up lets say there is 4 rows, the jQuery renames each row, then loops through each and submits an ajax call for each of them. Then the PHP handles the $_POST, in prior applications working with my custom DB I got it to work but working with wp database I am having issues, maybe I am missing something in my method?
Form Data: the ajax form data looks like this (this is the form data inside headers which can be found in the console(firbug) or network(chrome))
//First element
rowkey:0
application[rows][0][elements][html]:A
application[rows][0][elements][breakingbad]:123
Then if there is another row ajax posts again
//Second element
rowkey:1
application[rows][1][elements][html]:B
application[rows][1][elements][breakingbad]:456
So an and so forth, the database looks like this
{"rows":{"2":{"elements":{"html":"B","breakingbad":"456"}}}}
It should be more like this
{"rows":[{"elements":{"html":"A","breakingbad":"123"},{"elements":{"html":"B","breakingbad":"456"}]}
Holy Smokes Batman: I think I got it, It all resides inside how I handle the $_POST ill update soon with an answer..
The database looks good like this
{"rows":[
{"elements":{"html":"A","breakingbad":"123"}},
{"elements":{"html":"B","breakingbad":"456"}}]
}
Now I can continue to build.. whew this was a MASSIVE headache.
I have a multi-page form.
I would like to execute some custom JavaScript on the last page of this form. Theoretically, all I have to do is retrieve the current page number and write a conditional.
Simple, right? Apparently not.
My original workaround was like this:
if ($('gform_page').last().css('display') !== 'none') {
// perform custom scripts now that the last
// Gravity Form page is being shown
}
but $('...').css('display') returns undefined on every element I've tried this on within the form. Custom scripts were being fired every time the user hit the "Next" button. No cigar.
Then, after reviewing the Gravity Forms documentation, I found two useful-looking events: gform_post_render and gform_page_loaded.
However, the documentation gives no instruction on how to access the parameters.
jQuery(document).bind('gform_page_loaded', function(event, form_id, current_page){
console.log(current_page);
// returns nothing when loaded in the footer
// returns [Object, object] when placed in an HTML field in the form
});
In addition to not having the correct code, I also suspect I don't have the code in the correct place as I have also fruitlessly tried the following in functions.php and in header.php (as the documentation suggests):
<?php
function enqueue_custom_script($form, $is_ajax){
if ($is_ajax) :
echo '<script>console.log(current_page);</script>';
endif;
}
add_action("gform_enqueue_scripts", "enqueue_custom_script", 10, 2);
?>
Question:
What code do I need to retrieve the current page number, and more importantly, where do I place that code?
I got it.
The function rgpost is, apparently, crucial in accessing the current page number. After some muddling around on my own, I was able to get the following code working in both functions.php and just before the wp_head() function in header.php.
function run_script_on_last_page($form) {
if (!is_admin()) {
$current_page = rgpost('gform_source_page_number_' . $form['id']) ? rgpost('gform_source_page_number_' . $form['id']) : 1;
if ($current_page == 10) {
wp_enqueue_script('custom_script', get_template_directory_uri() . '/js/custom_script.js', array('jquery'), null, true);
}
}
}
add_action('gform_enqueue_scripts_63', 'run_script_on_last_page');
If you're copy/pasting the code above, make sure to:
replace 10 with the page you want to check
ensure your parameters are correct in wp_enqueue_script
replace 63 with your form ID
Some resources I found useful:
this section of the documentation for the gform_validation filter
the documentation for gform_enqueue_scripts.
The OPs accepted answer might well work but it doesn't work if you have the form setup to paginate using Ajax.
In that case I could only get it working using Javascript and the following method;
http://www.gravityhelp.com/documentation/page/Gform_post_render
jQuery(document).bind('gform_post_render', function (event, formId, current_page) {
if (current_page == 2) {
// do something
}
});
You could of course use the formId parameter to limit this to a specific form
The currently accepted answer only works if the user never goes to a previous page in the form, if they do, then gform_sourge_page_number always lags by one. I found a better solution (using this hook for an example, but you should be able to use it within any hook that has the $form passed to it):
function run_script_on_last_page( $form) {
if ( !is_admin() ) {
if ( \GFFormDisplay::get_current_page( $form['id'] ) == 10) {
wp_enqueue_script( 'custom_script', get_template_directory_uri() . '/js/custom_script.js', array( 'jquery' ), null, true );
}
}
}
add_action( 'gform_enqueue_scripts_63', 'run_script_on_last_page' );
GFFormDisplay::get_current_page( $form_id ) is one of many handy undocumented functions.
I wrote a little function that returns the current page:
// Get Gravity Forms Current Page
// Syntax: gf_current_page()
function gf_get_current_page()
{
return rgpost('gform_source_page_number_' . $_POST['gform_submit']) ? rgpost('gform_target_page_number_' . $_POST['gform_submit']) : 1;
}
Further to the accepted answer, here is an example of finding the current page, and dynamically finding how many pages are in the form. This example changes button text based on whether it is the last page of the form, instead of enqueueing a script.
// Change the text of the 'Next' form button to 'Submit' when
// the current page is the final page of the form
add_filter( 'gform_next_button', 'next_to_submit', 10, 2 );
function next_to_submit( $next_button, $form ) {
$replacement_next_button = $next_button;
$last_page_number = 1;
foreach ($form['fields'] as $field) {
$is_hidden = RGFormsModel::is_field_hidden( $form, $field, array() );
if ($field['pageNumber'] > $last_page_number && !$is_hidden) {
$last_page_number = $field['pageNumber'];
}
}
$current_page_number = rgpost('gform_source_page_number_' . $form['id']) ? rgpost('gform_source_page_number_' . $form['id']) : 1;
if ($last_page_number === $current_page_number) {
// If the current page is the final page
$replacement_next_button = str_replace( 'Next', 'Submit', $next_button );
}
return $replacement_next_button;
}
Following code works for me in JavaScript:
$('.gf_step_active .gf_step_number').html()
It will give you the page number of the current page in multi-page form.
Using Jquery
var current_page_ = 1+parseInt(jQuery('.gform_page:visible').index());
Try using this one:
var current_visible_page = jQuery('.gf_step_active .gf_step_number').html();
console.log(current_visible_page);
Use the above method in the console to check how it's working.