I'm building my own custom login page for wordress. The login form seems to work, however I would like to be able to customize the error message more specifically.
When the login credentials are incorrect and you log in, the error message appears only after the page has reloaded. What I would like to do is show the error message without reloading the page.
I searched on stackoverflow and wordpress reference but couldn't find a solution for my case. Anyone have a suggestion on how I might achieve my goal?
Thanks for any replies, I appreciate any help.
Update 2
I thank the users who helped me with their answers, they were very helpful and I really appreciate it. I literally spent all day on this problem, I finally achieved my goal. The ajax request works and the message is displayed as I wanted. I had to go through a lot of things several times. However I leave the updated code for anyone who needs help.
My custom_login_page.php file
This contains the html structure, the form and the script that executes the ajax requests. Put the file in your active child theme. In my case I called the custom_login_page.php file. For this to be read by wordpress you need to create a new page and select it as a template.
<?php
// Template Name: Custom Login Page
?>
<?php get_header(); ?>
<div class="container_main">
<?php if (is_user_logged_in()) {
?><span>Sei gia loggato</span><?php // If the user is logged in, it shows the message below
} else { // otherwise, if the user is not logged in, it shows the login form
?>
<form id="login" action="login" method="post">
<!-- Message error -->
<p class="status"></p>
<!-- Username -->
<label for="username">Username</label>
<input id="username" type="text" name="username">
<!-- Password -->
<label for="password">Password</label>
<input id="password" type="password" name="password">
<!-- Link Recover -->
<a class="lost" href="<?php echo wp_lostpassword_url(); ?>">Lost your password?</a>
<!-- Submit Button -->
<input class="submit_button" type="submit" value="Login" name="submit">
<?php wp_nonce_field( 'ajax-login-nonce', 'security' ); ?>
</form>
<?php
} ?>
</div>
<?php get_footer(); ?>
<script>
jQuery(document).ready(function($) {
// Perform AJAX login on form submit
$('form#login').on('submit', function(e){
$('form#login p.status').show().text(ajax_login_object.loadingmessage);
$.ajax({
type: 'POST',
dataType: 'json',
url: ajax_login_object.ajaxurl,
data: {
'action': 'ajaxlogin', //calls wp_ajax_nopriv_ajaxlogin
'username': $('form#login #username').val(),
'password': $('form#login #password').val(),
'security': $('form#login #security').val() },
success: function(data){
$('form#login p.status').text(data.message);
if (data.loggedin == true){
document.location.href = ajax_login_object.redirecturl;
}
}
});
e.preventDefault();
});
});
</script>
My functions.php file
In functions.php I put the functions linked to the form and some redirects useful when doing logine logout.
/* Redirect Custom Login Page */
function redirect_custom_login_page() {
wp_redirect(site_url() . "/login");
exit();
}
add_action("wp_logout", "redirect_custom_login_page");
/* Redirect wp-admin & wp-login php */
add_action("init","fn_redirect_wp_admin");
function fn_redirect_wp_admin(){
global $pagenow;
if($pagenow=="wp-login.php" && $_GET['action'] !="logout"){
wp_redirect(site_url()."/login");
exit();
}
}
/* Ajax Form Login */
function ajax_login_init(){
wp_register_script('ajax-login-script', get_template_directory_uri() . '/ajax-login-script.js', array('jquery') );
wp_enqueue_script('ajax-login-script');
wp_localize_script( 'ajax-login-script', 'ajax_login_object', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'redirecturl' => home_url(),
'loadingmessage' => __('Sending user info, please wait...')
));
// Enable the user with no privileges to run ajax_login() in AJAX
add_action( 'wp_ajax_nopriv_ajaxlogin', 'ajax_login' );
}
// Execute the action only if the user isn't logged in
if (!is_user_logged_in()) {
add_action('init', 'ajax_login_init');
}
function ajax_login(){
// First check the nonce, if it fails the function will break
check_ajax_referer( 'ajax-login-nonce', 'security' );
// Nonce is checked, get the POST data and sign user on
$info = array();
$info['user_login'] = $_POST['username'];
$info['user_password'] = $_POST['password'];
$info['remember'] = true;
$user_signon = wp_signon( $info, false );
if ( is_wp_error($user_signon) ){
echo json_encode(array('loggedin'=>false, 'message'=>__('Wrong username or password.')));
} else {
echo json_encode(array('loggedin'=>true, 'message'=>__('Login successful, redirecting...')));
}
die();
}
Introduction
I will briefly describe how HTML forms work, why your page is reloading and how you can communicate with the server without reloading your page, finally, how you can update your page based on this communication.
How HTML forms work
When you create a form tag and a structure into it, with a button of submit type inside of it, specifying an action (or using the default), then, upon clicking on the button mentioned earlier, your form is submitted. On submitting your form, all elements inside the form, having a name attribute (i.e. name="somename") is picked up and a request will be sent to the specified action (defaulting to the same page), where the form data will be represented as key-value pairs, the keys being the names of your form elements and the values being the values of the elements.
Upon form submit, your browser will send a request to the target of the form. The action of the form (if valid) will pick up the request, handle it and respond to your browser.
When the browser receives this response, it will display it as the content of the page. The users experience this behavior as a page reload. You are bothered with this behavior, as you described in your question and you would prefer to have a less obtrusive, smoother behavior. This is possible with AJAX requests.
AJAX
AJAX requests are well-documented, so, if you are unfamiliar with them - which surely is the case -, then I advise to read the content of the link I have given you above and gain some experience with AJAX. If you get stuck with it, let me know your blocker, but, for now, I will assume that the tutorials clarify the matter for you and in a reasonable amount of time you will successfully learn how to tackle them.
You can also communicate with your server (without page reload) with push notifications or websockets, but since this is a request-response use-case, I strongly advise the use of AJAX. Since AJAX stands for Asynchronous Javascript and XML, the asynchronous part suggests that you are calling an asynchronous function that you do not wait for, that is, your request is being sent to the server and there is an event to handle the server response, upon which you can specify function(s) to be executed, known as the callback(s).
If you are going to have an AJAX request, then you do not necessarily need the form and the submit button is definitely not needed, instead, you could use an input type="button" with a click event handler that will pick up the data and send the request.
How to handle server responses
The simplest way to handle the requests is to just take the (HTML) response and refresh your page content for the regions you want to update (without page reload, of course). But this is not necessarily ideal.
If your structure does not change, but your content does, then it makes much more sense to change your server code to just send the content as JSON (Javascript Object Notation) and update only the content of your page. This approach ensures that your server does not have to send very large, superfluous responses to your browser if it's unnecessary. Instead, it just sends the data, reducing the load of your server's networking and, as a result, making your server more scalable. But this means that your browser will have to update the content itself, which is no longer automatic and you need to code the behavior in a client-side language, such as Javascript.
How you should proceed
Since all this is obviously new to you, I advise you to start with the simplest approach, to have some success that will boost your morale, that is, at first stage, send the request as AJAX, the server should only respond with the inner HTML of the body tag, rather than the whole HTML and you could do a
document.body.innerHTML = response;
in your callback.
The reasonable expectation is that your page is not reloaded by the browser, but it is refreshed. If you reach this stage, then you might decide that it is good-enough for you, or you can decide to improve it, change the server-side to respond to the AJAX request with a JSON and implement some client-side functions to handle the request and refresh the content.
I of course advise the latter, but you of course have the liberty of choice here.
Now, let's understand what a request method is.
A GET request is a request defined by a URL (Unified Resource Locator) and the parameters are passed as GET parameters, that is, inside the URL, after the ? mark, like
https://www.yourpage.com?yourparameter=yourvalue&yoursecondparameter=yoursecondvalue
A POST request is a request where POST parameters can also be defined. In PHP you have neat ways to determine the request type, see this excellent page: Detecting request type in PHP (GET, POST, PUT or DELETE)
Now, when you load the page for the first time, a GET request is being send. Once the form is submitted (via AJAX), you need to specify that you are sending a POST request and then the server will know that it will need to send only the data (rather than the HTML) as a response.
What you want isn't achievable using PHP. As quick explanation, PHP is a server side scriptiong language, which means that only the server can execute your code. So whenever you press Login is has to go to the server (doing a request) and then you'll get back the new HTML from your server.
How to do this
Is quite an investment but if you really want to learn or build this you should look into Javascript AJAX requests. In a nutshell, AJAX is how you communicate with your server without any page reload.
Alternative
You could also try to use some plugins that try to do this. I have no experience with them but here's one that claims to do exactly what you want: https://nl.wordpress.org/plugins/login-with-ajax/
If that one doesn't fit your needs, you can at least continue searching using the term AJAX.
I hope this helps :)
TLDR
With PHP, you can't. Use an AJAX WordPress plugin or build a custom solution using Javascript and AJAX.
I have a javascript/jquery function in a perl program that returns a complete HTML page and I'd like to use jquery's .post to submit CGI values to the program and re-load the page for further processing based on the data submitted.
Consider the following mcve:
#!/usr/bin/perl
use CGI;
my $cgivars = CGI->new;
my $data = $cgivars->param('DATA');
my $something = "This is some data.";
my $display = qq|Content-type: text/html\n\n<http><head></head><body>The data submitted was $data</body></http>|;
my $postdata = qq|Content-type: text/html\n\n
<http><head><script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script></head>
<body>
<script type="text/javascript">
function postData() {
\$.post("jqpost.cgi",{DATA:"$something"});
}
</script>
Click the button to submit some data<br>
<button value="submit" onclick="postData()">Submit</button>
</body></html>|;
if ($data) {
print $display;
} else {
print $postdata;
}
end;
When I use
$.post("jqpost.cgi",{DATA:"$something"});
firebug's console shows a 200 (OK) and the All/HTML tab shows the page as I'd like to see it returned, with the data passed being used as expected. I get that the above code doesn't include a function to manage the result returned.
So I'm trying to use a function that will load the page that I know is being returned, using
$.post("jqpost.cgi",{DATA:"$something"},function(data) { document.write(data);});
The page starts to load in the browser, but the page never completes loading. Apache's logs doesn't show any additional data.
What can I use for a success function to properly/completely display the whole page returned from the server?
You need to close the document.open. document.write is open the document.
document.write("Hello there!!!");
document.close();
no more spinning.
I am making a function which searches the database for flight information. I want user to be redirected on "ticket.php" if the response is true. I want to update the content of the page "ticket.php" using jquery. But jquery doesn't work. Am I doing something wrong here ? Here's part of javascript. It's an external javascript. It's included in both "search.php" and "ticket.php" page. This function gets invoked by clicking on search button in "search.php" page.
if(data){
setTimeout("location.href = 'ticket.php';",3000); // Redirect to new page
//Change content of "ticket.php" using jquery.
$("#source").text(x);
$("#destination").text(y);
$("#date").text(z);
$("#no_person").text(person);
$("#trip_type").text(type);
}
else
$("#alert").text("Oops! No Flight matches your criteria ! ");
When you set location.href to ticket.php, the user is then redirected to that new page (ticket.php). Then the browser will load that new page and will no longer use the javascript you have on your current page.
You will have to make the data appear on ticket.php, using e.g. url parameters taken from what they searched like this:
window.location.href = 'ticket.php?from=norway&to=sweden';
The reason this is not working for you is because when you redirect to ticket.php the page is reloaded and all of the javascript on the page is refreshed, losing whatever value they had before. To keep the data you have to send the information to ticket.php
There are a couple of ways to accomplish this, ordered in preferred method.
all assuming you are requesting the page like this: ticket.php?from=norway&to=sweden
php on the page ticket.php
<?php
echo $_GET['from'];
echo $_GET['to'];
?>
javascript on the page ticket.php
solution for getting params from this post:https://stackoverflow.com/a/1404100/2033671
alert(getURLParameter('from'));
alert(getURLParameter('to'));
jQuery from a different page on the same domain
$.get('ticket.php',function(response){
$html = $(response);
$html.find("#destination").text(y);
$html.find("#source").text(x);
$("html").html($html);
});
I have a page with 80+ dynamically generated input boxes, when the user submits the form to another .php page and one of the inputs contains a value that is not numeric, it will send them back to the inputs page using: <?php header("Location: javascript:history.back()"); ?>, at the same time it registers the error in a session variable. The reason why I'm using javascript:history.back(), is because it stores the values that were in the form, even when you press the back button. But because it is caching the page I can't output the error in the same .php script, so I added a an element and some Ajax code. The Ajax code retrieves another file called error.php, this contains:
<?php
header("Cache-Control: no-cache");
session_start();
if(isset($_SESSION['error']))
{
echo $_SESSION['error'];
unset($_SESSION['error']);
}
?>
This is retrieved when the page is loaded on it own, but not when history.back() is used, it looks like the following isn't firing:
<script type="text/JavaScript">
$(document).ready(function(){
$("#error p").load("error.php");
});
</script>
Any ideas?
Thanks,
Justin
Using header("Location: javascript:history.back()") is generally ill-advised.
Use an absolute path i.e.
header('Location: /forms/input.php');
You could avoid submitting the form entirely and send the data via an AJAX call - the server could validate the data and send back either "success" or a list of validation errors.
If success, move on to the next URL (possibly specified alongside the success message)
If failed, modify the current page to indicate what the problems were. This avoids you having to re-create the whole form (as you never leave the page) but also allows for reliable server-side validation
Currently I am using YOURLS PHP URL shorterning script.
In their functions.php, seems like they support both redirection which is with PHP header location and javascript.
Functions.php
I want to redirect with javascript, which will show me the message before redirect. I found this coding inside functions.php
// Redirect to another page using Javascript. Set optional (bool)$dontwait to false to force manual redirection (make sure a message has been read by user)
function yourls_redirect_javascript( $location, $dontwait = true ) {
if( $dontwait ) {
echo <<<REDIR
<script type="text/javascript">
window.location="$location";
</script>
<small>(if you are not redirected after 10 seconds, please click here)</small>
REDIR;
} else {
echo <<<MANUAL
<p>Please click here</p>
MANUAL;
}
}
But I don't know how to do it. Is that coding currently commented or ? What should i change to redirect with javascript ?
Please help me out. Thanks.
The function is all ready to go. A javascript redirect will occur on the client side, so this script outputs the appropriate javascript. Call it like so:
<?php # http://www.myurl.com/was/here.php
yourls_redirect_javascript('http://www.myurl.com/go/here.php');
?>
When this page loads javascript will be used to redirect the user. If the javascript fails, there will be a link for them to click to follow the redirect.
I suspect that the "here document" syntax is throwing you off a bit. Read the PHP Docs to learn more about echo <<<
http://php.net/manual/en/function.echo.php