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.
Related
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();
}
I'm working on a WordPress plugin which allows me to choose the proper upload folder regarding the custom post type, taxonomies terms and the title.
I can grab each kind of data when the post is saved, no problem. But how to grab for example a title of a post which hasn't been published?
I tried $_POST, by adding first a name in the title textarea field of WordPress (because it hasn't one) but this totally broke my upload filter with an internal error 500.
I have a partially working code. In a PHP file, I'm enqueuing this Ajax script:
function get_unposted_post_title( $hook ) {
if ( ($hook == 'post-new.php') || ($hook == "post.php" && $_GET['action'] == "edit") ) {
echo "<script>
function posturl(title, url) {
$.ajax({
type: 'POST',
url: url,
data: title,
success: function(title, url) {
console.log(title);
}
});
}
setInterval( function() {
var title = $('#post-title-0').val();
var url = '" .GIA_PLUGIN_URL. "test.php';
posturl(title, url);
}, 5000);
</script>";
}
}
add_action( 'admin_enqueue_scripts', 'get_unposted_post_title', 10, 1 );
Then, in the root of my plugin, I have created a test.php file:
<?php
$keys = array_keys($_POST);
if(isset($keys) && !empty($keys[0])) {
print_r( $keys[0] );
}
?>
This function displays the updated title in the console.log as expected.
However, I'm unable to grab $keys[0] without making the upload filter crashed. Uploaded files are properly moved with the updated path of my filter, except for the last folder which must have a sanitized version of the post title. I'm hooking into wp_handle_upload_prefilter and wp_handle_upload.
If you look at the provided code, I should be able to grab keys[0]... but the problem is that keys[0] give me 'name'... keys[1] give me 'action', keys[2] give me 'wp_nonce'. I don't know why I can't grab keys[0] correctly, it seems that $keys of my test.php isn't updated with a proper value for the key 0.
Why using Ajax if you can use direct MySQLI using the wp_db ?
You can retrieve it the same way as you currently doing it with published one.
If you grab it using MySQLI, there is a column called "post_status"
https://codex.wordpress.org/Post_Status
I am trying to add custom button on top of post type page like this image
Is there any filter or action I can use to add custom button there?
Thanks
I found a way to get it done but I am not very happy with this procedure. Please add your answer if you find better way. Mean while, this might be of help.
add_action('admin_head-edit.php','addCustomImportButton');
I only need this on edit page, so I am using admin_head-edit.php action, but you can use admin_head or some other (not very specific requirement)
/**
* Adds "Import" button on module list page
*/
public function addCustomImportButton()
{
global $current_screen;
// Not our post type, exit earlier
// You can remove this if condition if you don't have any specific post type to restrict to.
if ('module' != $current_screen->post_type) {
return;
}
?>
<script type="text/javascript">
jQuery(document).ready( function($)
{
jQuery(jQuery(".wrap h2")[0]).append("<a id='doc_popup' class='add-new-h2'>Import</a>");
});
</script>
<?php
}
Digging into WordPress core code i did not find any hook or any filter for that buttonm you can also see that code from line no 281 to line number 288 . But you can add your button here according to this filter.
add_filter('views_edit-post','my_filter');
add_filter('views_edit-page','my_filter');
function my_filter($views){
$views['import'] = 'Import';
return $views;
}
Hope it helps you.
If you are using the class WP_Lists_table (and you should) then this is the right way to do it:
add_action('manage_posts_extra_tablenav', 'add_extra_button');
function add_extra_button($where)
{
global $post_type_object;
if ($post_type_object->name === 'shop_order') {
// Do something
}
}
The accepted answer is sadly still the only one that works.
But as the admin heading changed since it was answered, the correct script should now be :
jQuery(jQuery(".wrap .page-title-action")[0]).after('Import');
Unfortunately there is no hook called after showing the "Add New" button.
The closest possible place to add anything without using javascript is below the title and "Add new" like this:
In my example I added a button to my custom post type "Event" using the hook "edit_form_top":
add_action('edit_form_top', 'add_custom_button');
function add_custom_button($id){
if ($post->post_type != 'event') return false;
echo('<button>Custom button</button>');
}
The answer of Touqeer Shafi got me in the right direction, I needed to add a button at the top of my table view for a custom post type (book), I only had to change the post part in the views_edit-post to make it work:
add_action('views_edit-book', function($id) {
echo('Another new book');
});
Now in 2022 with WP 5.9.1, I combined answers from Geza Gog and Tameroski, and it works great:
add_action('edit_form_top', 'my_import_button');
function my_import_button(){
?>
<script type="text/javascript">
jQuery(document).ready( function($)
{
jQuery(jQuery(".wrap .page-title-action")[0]).after('Import');
});
</script>
<?php
}
I've installed the latest version of yii2 using the advanced template. The website is working fine. For some reason the Gii generation tool is stuck and does not react as expected after clicking the preview button. Instead of showing a new form with the "Generate" button, it shows the same form unchanged without any messages as to what is happening.
Using xdebug I can see in the "actionView" method of the DefaultController that the array value $_POST['preview'] is not set, i.e. it doesn't exist in the $_POST array. I have not changed anything in the Form of the view and everything looks OK. The submit button has the name "preview" and the form is submitted but the $_POST array is not being filled with the value of the submit button. Therefore the controller does not proceed with the next steps of the generation process.
public function actionView($id)
{
$generator = $this->loadGenerator($id);
$params = ['generator' => $generator, 'id' => $id];
// ###############################################################################
// ### THIS IF STATEMENT IS NOT TRUE BECAUSE $_POST['preview'] IS NOT SET !!! ###
// ###############################################################################
if (isset($_POST['preview']) || isset($_POST['generate'])) {
// ###############################################################################
if ($generator->validate()) {
$generator->saveStickyAttributes();
$files = $generator->generate();
if (isset($_POST['generate']) && !empty($_POST['answers'])) {
$params['hasError'] = !$generator->save($files, (array) $_POST['answers'], $results);
$params['results'] = $results;
} else {
$params['files'] = $files;
$params['answers'] = isset($_POST['answers']) ? $_POST['answers'] : null;
}
}
}
return $this->render('view', $params);
}
Does anyone have an idea what could be causing this? I have a hunch that it is something quite simple that I'm overlooking, but I've never had a situation where POST variable from a Form are not being sent to the server.
False Alarm. I've found the problem. The Gii view was creating the HTML Form incorrectly.
in the controller i have :
$paginator = Zend_Paginator::factory($mdlPost->getPosts($this->moduleData->accordion, 'name ASC'));
if(isset($params['cities'])) {
$paginator->setCurrentPageNumber(intval($params['cities']));
}
$paginator->setItemCountPerPage(4);
$this->view->posts = $paginator;
in the view's i have some thing like this :
if ($this->posts != null) {?>
<div id="cities_accord" class="news">
<?php echo $this->partialLoop('partials/post-min.phtml', $this->posts); ?>
</div>
<?php echo $this->paginationControl($this->posts,
'Sliding',
'public/pagination_cont.phtml');
}
the partial/post-min.phtml
<?php
$color = array(1=>'spring',2=>'summer',3=>'autumn',4=>'winter');
?>
<div id='<?php echo $color[$this->partialCounter] ?>' class="accordion_post">
<?php
$link = Digitalus_Uri::get(false, false, array('openCity' =>
$this->id));//$color[$this->partialCounter]));
?>
<h1 class="accordion_post_title"><?php echo $this->title ?></h1>
<p><?php echo $this->teaser ?> <i>read more</i></p>
</div>
the pagination_cont.phtml taken from this link zend ( http://framework.zend.com/manual/en/zend.paginator.usage.html )
will show links that will pass params to the controller to fetch the corresponding whole page which is working alright for now
but i want to change this so that i will be able ajaxify the returned ( i.e. only a single paginated value rather than reloading the whole page ) results how can i do that using jquery and what should i change ..
** EDIT: it would be nice to have a fail-save ,if possible, for browsers(users) that disabled javascript to see the same thing by reloading the page (i.e. keeping the current status for if(javascript_not_enabled ))**
This is what I've done in the past.
First, setup the AjaxContext action helper to enable the html context on your controller action.
Add a .ajax.phtml view that just contains the section of markup that may be replaced via AJAX as well as the pagination control links. You can probably just copy this out of your normal view. Replace that section in your normal view with something like
<div id="reloadable-content">
<?php echo $this->render('controller/action.ajax.phtml') ?>
</div>
This will ensure that your initial and any non-AJAX requests will still include the right content. The <div> id is purely for referencing the loadable block in JavaScript.
Also make sure you include your JS file (using headScript) in the normal view only.
Now, in your JS file, unobtrusively add the appropriate event binding to the paginator links. As you'll be replacing the pagination control section in order to reflect the correct current page and other links, it's probably best to do this using the jQuery live binding. I'm also assuming you'll wrap the pagination control with some kind of identifiable element (<div class="pagination-control"> for example)
$('.pagination-control').find('a').live('click', function(e) {
var link = $(this);
$('#reloadable-content').load(link.attr('href'), { format: 'html' });
return false;
});
Keep in mind that in using this method, you will lose the ability to navigate the paged requests using the normal back / forward browser buttons. You will also lose the ability to bookmark pages directly (though you could always provide a permanent link to the current page as part of the AJAX loaded content).
You can use something like the jQuery history plugin if you're really concerned but that will require more client-side work.
Another caveat is that the above will only work with pagination links. If you want to use a form with dropdown page selection, you need to add another event handler for the submission.
GOT IT and big Thanks to #Phil Brown :
in the controller int() change the response type to json
class NewsController extends Zend_Controller_Action
{
public function init()
{
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->addActionContext('list', 'JSON')
->initContext();
}
// ...
}
public listAtcion() {
// .............
$paginator = Zend_Paginator::factory($mdlPost->getPosts($this->moduleData->accordion, 'name ASC'));
if(isset($params['cities'])) {
$paginator->setCurrentPageNumber(intval($params['cities']));
}
$paginator->setItemCountPerPage(4);
$post = array();
foreach($paginator as $post ) {
$post[] = $post;
}
$this->view->post = $paginator;
#TODO //add a check here for non-ajax requests (#improvment)
$this->view->posts = $paginator;
}
in one of the views (most probably in the pagination_cont.phtml) on the pagination controller add the ajax links
<?= $this->ajaxLink (
$this->url('cities'=>$this->page_num),array('id'=>'div_id','complete'=>'js_method(json_data)','method'=>post) ,array('format'=>'JSON'));
and add a JavaScript function of js_method(json_data) to modify the div with id = 'div_id' with a json data
function js_method(json_data) {
var content = parse.JSON(json_data);
$('#div_id').html('');
//fill it with the reposnse content some thing like $('#div_id').append(content);
}