1

I am trying to create and edit button, like Reddit has, for my forum. I have got it to work but I was wondering if I'd be able to do it without having to refresh the page.

For example, when I click the edit button, it reloads the page and displays the form for editing, then when I click save it will reload yet again to display the new edited post.

Code (EDITED from IncredibleHat's answer):

<?php

session_start();

$host = "host"; // Host name 
$user = "username"; // Mysql username 
$password = "password"; // Mysql password 
$db_name = "database"; // Database name 
$tbl_name = "fquestions"; // Table name 

// Connect to server and select databse.
$conn = mysqli_connect($host, $user, $password)or die("cannot connect"); 
mysqli_select_db($conn, $db_name)or die("cannot select DB");

// get value of id that sent from address bar 
$id = $_GET['id'];
$sql = "SELECT * FROM $tbl_name WHERE id='$id'";
$result = mysqli_query($conn, $sql);
$rows = mysqli_fetch_array($result);

/*Check if topic is locked or not */
$locked = $rows['locked'];

if ($_SESSION['username'] == $rows['username']) {
    $editPost = true;
}
?>

<head>

    <!-- ****** faviconit.com favicons ****** -->
    <link rel="shortcut icon" href="../images/favicon.ico">
    <!-- ****** faviconit.com favicons ****** -->

    <link id ="pageStyle" rel="stylesheet" href='../css/defaultStyle.css' type='text/css'> <!-- Loads Default Stylesheet -->
    <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
    <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Roboto' type='text/css'>
    <script src='https://www.google.com/recaptcha/api.js'></script>

</head>

<body>     
    <div id="mainContent">
        <div id="question">
            <p id="date"><?php echo $rows['datetime']; ?></p>
            <h2><?php echo $rows['topic']; ?></h2>
            <b><p><?php echo $rows['username']; ?></p></b>
            <?php
            // The Regular Expression filter
            $reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";

            // The Text you want to filter for urls
            $text = htmlspecialchars($rows['detail']);

            // Check if there is a url in the text
            if(preg_match($reg_exUrl, $text, $url)) {
                $url = preg_replace("/^http:/i", "https:", $url);

                // make the urls hyper links
                echo preg_replace($reg_exUrl, '<a title="Opening this link will take you to a new page" alt="External Link Deleted" target="_blank" href="'.$url[0].'" rel="nofollow">'.$url[0].'</a><br>', '<p id="post">'.$text.'</p>');

            } else {
                ?>
            <p id="post"><?php echo htmlspecialchars($rows['detail']); ?></p>
            <?php
            }

            if ($editPost == true) {
                $_SESSION['detail'] = $rows['detail'];
                $_SESSION['id'] = $rows['id'];
                ?>
                <style>
                    #editPostButton {
                        border: none; outline: 0; background-color: #D8D8D8; margin-left: -5px;
                    }

                    #editPostButton.dark {
                        color: white;
                        background-color: #1C1C1C;
                    }
                </style>
                <input type="submit" value="Edit" name="editPostButton" id="editPostButton" data-postId="<?php echo $rows['id']; ?>">
                <div id="editFormBlock"></div>

                <script>
                   $(document).ready(function() {
                       // for clicking on the edit button, to grab the edit form
                       $("#editPostButton").on('click',function(e) {
                           e.preventDefault();
                           $.post(
                               'ajaxhandler.php',
                               { action: 'editform', postid: $(this).data('postId') },
                               function(htmlReturn) {
                                   $("#editFormBlock").html( htmlReturn ); // replace editForm content
                                },
                                'HTML'
                                );
                       });

                       // for clicking the save button for a edit form
                       // using .on so it catches dynamically added content
                       $("#editFormBlock").on('click',"#saveButton",function(e) {
                           e.preventDefault();
                           var data = $("#editForm").serializeArray();
                           data.push({name: 'action', value: 'saveform'});
                           $.post(
                               'ajaxhandler.php',
                               data,
                               function(htmlReturn) {
                                   $("#editFormBlock").html( '' ); // clear edit form out
                                },
                                'HTML'
                                );
                       });
                   });
                </script>
                <?php
            }
            ?>
        </div>

<?php

$tbl_name2="fanswer"; // Switch to table "forum_answer"
$sql2 = "SELECT * FROM $tbl_name2 WHERE question_id='$id'";
$result2 = mysqli_query($conn, $sql2);
$row_cnt = mysqli_num_rows($result2);

if ($row_cnt > 0) {
    ?>
    <h3>Replies:</h3>
    <div id="replies">

    <?php
    while($rows = mysqli_fetch_array($result2)) {
    ?>
        <p id="dates"><?php echo $rows['a_datetime']; ?></p>
        <div id="reply">
        <b><p><?php echo $rows['a_username']; ?></p></b>
        <?php
        // The Regular Expression filter
        $reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";

        // The Text you want to filter for urls
        $text = htmlspecialchars($rows['a_answer']);

        // Check if there is a url in the text
        if(preg_match($reg_exUrl, $text, $url)) {
            $url = preg_replace("/^http:/i", "https:", $url);

            // make the urls hyper links
            echo preg_replace($reg_exUrl, '<a title="Opening this link will take you to a new page" alt="External Link Deleted" target="_blank" href="'.$url[0].'" rel="nofollow">'.$url[0].'</a>', $text);

        } else {
            ?>
            <p><?php echo htmlspecialchars($rows['a_answer']); ?></p>
            <?php
        }
        ?>
        </div>
        <?php
    }
} else {
    ?>
    <div id="answers">
        <p style="color: red;">There doesn't seem to be anything here</p>
    <?php
}

$sql3 = "SELECT view FROM $tbl_name WHERE id='$id'";
$result3 = mysqli_query($conn, $sql3);
$rows = mysqli_fetch_array($result3);
$view = $rows['view'];

// if have no counter value set counter = 1
if(empty($view)) {
    $view = 1;
    $sql4 = "INSERT INTO $tbl_name(view) VALUES('$view') WHERE id='$id'";
    $result4 = mysqli_query($conn, $sql4);
}

// count more value
$addview = $view+1;
$sql5 = "update $tbl_name set view='$addview' WHERE id='$id'";
$result5 = mysqli_query($conn, $sql5);
mysqli_close($conn);
?>
    </div>
    <h3>Post A Reply:</h3>
    <form name="form1" method="post" action="add-answer" autocomplete="off">
    <label>Reply: </label>
<?php
if ($locked == 1) {
    echo '<textarea name="a_answer" id="a_answer" style="width: 800px;" readonly> This topic is locked! </textarea><br>';
} else if ($_SESSION['logged_in'] != true) {
    echo '<textarea name="a_answer" id="a_answer" style="width: 800px;" readonly>⛔ You must login to reply! ⛔</textarea><br>';
} else {
    echo '<textarea name="a_answer" id="a_answer" maxlength="300" required style="width: 800px;"></textarea><br>
    <div class="g-recaptcha" data-sitekey="6LdrxD4UAAAAACAaVAR6U9BjOEDC9-j4QaOzBsFh"></div>
    <input type="submit" name="submit" value="Submit">
    <input type="reset" name="reset" value="Reset">';
}
?>
    <input name="id" type="hidden" value="<?php echo $id; ?>">
    </form>
    </div>
</body>

ajaxhandler.php:

<?php

session_start();

$detail = $_SESSION['detail'];
$id = $_SESSION['id'];

if (!empty($_POST['action'])) {
    if ($_POST['action'] == 'editform') {
        ?>

        <style>
            #post, #editPostButton {
                display: none;
            }

            #saveButton {
                border: none; outline: 0; background-color: #D8D8D8; margin-left: -5px;
            }
        </style>

        <form id="editForm">
            <textarea name="detail"><?php echo $detail; ?></textarea><br>
            <input type="button" id="saveButton" value="Save">
        </form>
        <?php
    }
    if ($_POST['action'] == 'saveform') {
        // do save process to db
        // echo out a new static post html block

        $host = "host"; // Host name 
        $user = "username"; // Mysql username 
        $password = "password"; // Mysql password 
        $db_name = "database"; // Database name 
        $tbl_name = "fquestions"; // Table name 

        // Connect to server and select databse.
        $conn = mysqli_connect($host, $user, $password)or die("cannot connect"); 
        mysqli_select_db($conn, $db_name)or die("cannot select DB");

        $sql = "UPDATE $tbl_name SET detail = '$detail' WHERE id=$id";
        $result = mysqli_query($conn, $sql);
    }
}
?>
TheWelshManc
  • 495
  • 3
  • 13

1 Answers1

1

Two ways you could do the toggling of an edit form.

  1. Load in more html (sub parts, not whole html documents) with ajax calls, and replace existing elements with the new html chunks based on actions. Click the edit button, it calls ajax to 'get the form block', and then it replaces some slot on the page with it. Submitting the form, tosses that form, and replaces it with the new static text block. This is generally a cleaner way to handle it.

  2. Have all the relevant bits in the html DOM on first load of the php script. Have many parts hidden. Then clicking certain buttons, or doing actions shows/hides elements based on those actions. This is easier, but not as clean, as all your form submit elements and actions, as well as the original static parts, are all in the HTML on every general page load.

An example of loading in a edit form on edit-button click, and swapping content blocks:

Basic static HTML framework (from first load of main.php):

<p id="post">[the original post html here]</p>

<?php if ($editPost == true) { /* dont bother if they have no edit rights */?>
<input type="button" id="editPostButton" value="Edit" data-postId="<?php echo $postId;?>">
<div id="editFormBlock"></div>
<?php }?>

Script area (jquery required):

<script language="Javascript" type="text/javascript">
$(document).ready(function() {

    // for clicking on the edit button, to grab the edit form
    $("#editPostButton").on('click',function(e){
        e.preventDefault();
        $.post(
            'ajaxhandler.php',
            { action: 'editform', postid: $(this).data('postId') },
            function(htmlReturn){
                $("#editFormBlock").html( htmlReturn ); // replace editForm content
            },
            'HTML'
        );
    });

    // for clicking the save button for a edit form
    // using .on so it catches dynamically added content
    $("#editFormBlock").on('click',"#saveButton",function(e){
        e.preventDefault();
        var data = $("#editForm").serializeArray();
            data.push({name: 'action', value: 'saveform'});
        $.post(
            'ajaxhandler.php',
            data,
            function(htmlReturn){
                $("#post").html( htmlReturn ); // replace static post content
                $("#editFormBlock").html( '' ); // clear edit form out
            },
            'HTML'
        );
    });

});
</script>

The ajaxhandler.php:

// Have blocks that pertain to the $_POST['action']
if (!empty($_POST['action'])) {
    if ($_POST['action'] == 'editform') {

        // do a database select on using the postId
        // grab the data you wish to use in the edit form

        // build a form and echo it out for the ajax return
        echo '
        <form id="editForm">
            <input type="hidden" name="postId" value="'. $row['id'] .'">
            <textarea name="detail">'. $row['detail'] .'</textarea>
            <input type="button" id="saveButton" value="Save">
        </form>
        ';
    }
    if ($_POST['action'] == 'saveform') {

        // put your "save to database" code here
        // that uses $_POST['postId'], $_POST['detail'] etc

        // after saving, grab a fresh copy of the post
        // and then echo out a new static html #post content
        echo htmlspecialchars($row['detail']);
    }
}

I hope this was clear enough to understand to get a foothold on what you wish to do. There is a lot more you can do, with an extra errorBlock to show errors, and handling of results. You can even push in some animations too. Endless possibilities.

NOTE: I should warn you though, that this is all based off your example, where you are showing just one post, and one edit form. This uses "ID"s, which must be unique on the page. If you are planning on pouring many posts on ONE page, you will need to adjust everything to use classes and enumerated ID's to keep the unique.

IncredibleHat
  • 4,000
  • 4
  • 15
  • 27
  • Yeah for now I am trying to just edit the main post, the replies are a whole other level – TheWelshManc Feb 28 '18 at 19:47
  • Also might I add your answer is a little confusing for me as someone who hasn't used AJAX before. I don't know how to update the text of my post in my database. – TheWelshManc Feb 28 '18 at 20:47
  • Sorry. I assumed you had all the database and processing end working since you were using standard form submission and html building. AJAX is simply submitting the form (or a button press to get the form). All the database edit/save is handled pretty much the same using $_POST vars of appropriateness (under the `saveform` php block). You showed no example code of your db handling, so I thought you only needed help on the HTML juggle. – IncredibleHat Feb 28 '18 at 21:02
  • Before I was just using the UPDATE sql function to update the text but now that doesn't work – TheWelshManc Feb 28 '18 at 21:06
  • Should still work. Just make sure the form field names match the $_POST['varname'] you use in the sql statement building. Since ajax is sending the form data as POST vars like a normal form would. – IncredibleHat Feb 28 '18 at 21:10
  • I got it to display the text in the textarea but when I click save it doesn't seem to update the db and display the edited text – TheWelshManc Feb 28 '18 at 21:12
  • I've updated the original question to help a little bit – TheWelshManc Feb 28 '18 at 21:29
  • I see the issue... you are overwriting `$detail` with the _SESSION value. Instead of using the `$_POST['detail']` when updating the database. Also, you excluded the 'rebuild the post text from new data' bit. – IncredibleHat Feb 28 '18 at 21:37
  • the detail is the bit where it says id="post" just above the first if statement on $editPost I tried doing $_POST['post']; but that didn't work. – TheWelshManc Feb 28 '18 at 21:41
  • Change `UPDATE $tbl_name SET detail = '$detail' WHERE id=$id` to `UPDATE $tbl_name SET detail = '{$_POST['detail']}' WHERE id=$id` ... I also tweaked some things in my answer to cater to your original `

    ` ...

    – IncredibleHat Feb 28 '18 at 21:46
  • Didn't work. I had it all working before adding in AJAX and having the page refresh but I'd like it without to look more professional but I might just give up as I have spent so long on it. – TheWelshManc Feb 28 '18 at 21:55
  • What you are attempting is doable. There are just a lot of moving pieces to align. Naming, using the right var in the right place. It gets easier, trust me. I'd suggest at this point, you can toss the question and fiddle around with it more. Maybe get it to a point where you need additional help and then create a new specific question. What you have is so broad, and as changed so much since the start, its gone off topic (and amazed someone didn't close it already). ;) – IncredibleHat Feb 28 '18 at 21:57
  • 1
    Looking back at your example, I looked at other examples to help me understand and so far I have got a working prototype. – TheWelshManc Mar 01 '18 at 16:04
  • 1
    Yay! It only gets more exciting from there, glad you got a foothold on the situation, and can now focus on cleanup and refining it to your liking :) – IncredibleHat Mar 01 '18 at 16:08