1

I am working on a WP plugin, and I need to be able to call a URL (specifically an AJAX function) using a button click, but the page refreshes after clicking it, which I think is preventing the AJAX request from finishing.

When the button click is registered, JS is meant to grab the value of an input, combine it to form a URL, then change an iFrame source to that URL (which I think calls it), but this is countermanded by the refreshing of the page.

Code is below:

$intro = get_post_meta($post -> ID, $key = 'podcast_file', true);
?>
        <div class="downloadHolder">
            <h3>Download <?php echo $post->post_title ?> (<?php echo basename($intro, ".ftb") ?>)</h3>
            <a href="<?php echo $intro;?>" download="<?php echo basename($intro) ?>" class="demoBtn">Download <?php echo basename($intro, ".ftb") ?> for PC</a>
            <!--<a href="#" class="demoBtn">Demo</a>--><br>
            <input type="text" name="emailValue" id="emailValue" placeholder="Email Address" class="emailInput" style="text-align: center;">
            <button id="UniqueLevelEmailButton" class="downloadBtn" style="margin-top: 0px; width: 100%;">Email for Mobile</button>
            <span>(We do NOT collect email addresses.)</span>
            <span id="checkMe"></span>      
            <script>
                jQuery(document).ready(function($){
                    $("#UniqueLevelEmailButton").click(function(e){
                            email = document.getElementById('emailValue').value;
                            downloadurl = '<?php admin_url('admin-ajax.php');?>?action=download_email_send&postId=<?php echo $post->ID; ?>&emailValue='+email;
                            document.getElementById('emailsendframe').src = downloadurl;
                        return false;
                    });
                    return false;
                });
            </script>
<!-- iframe for submitting to -->
<iframe name="emailsendframe" id="emailsendframe" src="javascript:void(0);" style="display:none;"></iframe>
        </div>
    <?php
return ob_get_clean();
}
add_shortcode('level', 'file_download');


/*      AJAX        */


add_action('wp_ajax_download_email_send','download_email_send');
add_action('wp_ajax_nopriv_download_email_send','download_email_send');

// note $_REQUEST will work with $_POST or $_GET methods
function download_email_send() {

    $to = $_REQUEST['emailValue'];

    // preferably add some email address format validation here
    // $validate = some_email_validate_function($to);
    // if ($validated) {$message = 'Please check your email for typos.';}
    // else {
        $post_id = $_REQUEST['postID'];

    $page = get_post($post_id);
    $postName = $page->post_title;

        // ! you would need to redefine $intro here !
    $intro = get_post_meta($post_id, $key = 'podcast_file', true);
    $path = str_replace("http://example.com/wp-content","",$intro);
        $subject = 'Download for '.$postName;

        $msg = 'Your download for '.$postName.' ('.basename($intro).') is attached to this email.';

    //Why am I unable to pass HTML in the message?

        $headers = 'From: Example <noreply@example.com>' . "\r\n";
    $headers .= "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
        $mail_attachment = array(WP_CONTENT_DIR . $path);

        $send = wp_mail($to, $subject, $msg, $headers, $mail_attachment);

        if ($send) {$message = 'Success! Your download has been sent to your email address.';}
        else {$message = 'Error: Mail sending failed. Please contact the website administrator using the contact page.';}
    // }

    // alert the user to the result
    echo "<script>alert('".$message."');</script>";
    exit;
}
3

Please do not put this code into production

OK. So there are many things wrong with the code that need fixing before we can even begin to answer your question.

  1. Firstly we're using $_REQUEST without good reason -- $_REQUEST gives us access to all of the information sent in the request, which means that $_POST['foo'] $_REQUEST['foo'] === $_GET['foo'] and also $_COOKIE['foo']! That means that we are able to request ID's from your application simply by setting a cookie locally.

  2. Secondly, we are taking $post_id and doing this with it:

    $post_id = $_REQUEST['postID']; ... $page = get_post($post_id);

Which means that, once we scrutinise the code for [get_post](https://developer.wordpress.org/reference/functions/get_post/) and find that it does no checks for any access rights it means that you are now allowing the user (who you do not know) to get any single 'post' which you have on your website. As WordPress stores all post-like objects in the table wp_posts it means that if you use WordPress post types for any kind of protected information, then the user will be able to access this information (in theory) simply by requesting it.

  1. Thirdly, we are passing an unfiltered variable into a function a la $intro = get_post_meta($post_id, $key = 'podcast_file', true); – thankfully WordPress filters this input for us

  2. Fourthly, we then send the return value of this, unchecked to create another variable $path = str_replace("http://com.areonline.co.uk/wp-content","",$intro);

  3. Fifthly we then use this($path) variable and email it as an attachment to the sender!!!


Other than that, try sending your request using jQuery.post and also consider creating localised variables using Localize Script and (to answer the question) also use event.preventDefault() on whatever you don't want to happen.

In this case:

$("#UniqueLevelEmailButton").click(function(e){
    e.preventDefault();
    // blah
}

|improve this answer|||||
  • Sorry, I'm a C# developer, not used to the PHP syntax. I wasn't aware that using $_REQUEST was so bad, I am guessing using GET would be better for this. We don't store any sensitive information in posts (pages, posts, or CPT's), things like users information isn't stored in there is it, is this an issue? I'm not sure if 4 is really an issue, all this takes place on the page, so it SHOULD always get the correct, valid values. Not sure with the issue on 5, I thought this was what was required for attachments (it works). – K.Briggs Jun 14 '16 at 23:33
0

I can't comment on the validity of the AJAX call; it's a different style than I have used -- but inside the click(function(e) { code, you might try trapping the default page action to prevent it from triggering the page refresh:

 $("#myelement).click(function(e){
     e.preventDefault();
|improve this answer|||||
  • This doesn't seem to have stopped the page from refreshing. I have placed it as the first line in the click function, but it doesn't stop the page from refreshing. – K.Briggs Jun 14 '16 at 22:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.