An jQuery, Ajax, JSON and PHP CMS problem

Let me start off describing the problem. I’m creating a blog for my website using Ajax, JSON and PHP so the user(s) won’t have the page reload every time it is save. I have it working except it doesn’t recognize carriage returns.

If I enter the following :
one
two
three
I get this
onetwothree
when I expect
one
two
three

The funny thing is it works in straight php.
Here’s the code:

index.php
  require_once 'lib/includes/utilities.inc.php';
  
  use website_project\blog\Page;
  
  $stmt = $blog->read();
  require_once 'lib/includes/header.inc.php';
  ?>
  
  <?php
 while ($row = $stmt->fetch()) {
     if ($row->sticky === 'yes') {
         $final_date = new DateTime($row->date_updated, new DateTimeZone('America/Detroit'));
         ?>
         <article id="blog" class="container blogArticle">
 
             <h1 class="title" contenteditable="true" data-id="<?php echo $row->id; ?>"><?php echo $row->title; ?></h1>
             <p class="author">by <?php echo $blog->getUsername($row->creator_id); ?> created on <?php echo $final_date->format("F j, Y"); ?></p>       
             <hr>
             <p class="content" contenteditable="true" data-id="<?php echo $row->id; ?>"><?php echo nl2br($row->content); ?></p>
             <hr>
         </article>
     <?php } ?>
 <?php } ?>
 <?php
 require_once 'lib/includes/footer.inc.php';

cms.js

  $(function () {
      var $blog = $('#blog');
      
      function update(myData) {
          
          $.ajax({
              type: "post",
              url: "forumsAjax.php",
              data: myData,
             success: function (info) {
                 console.log(info);
             }, 
             error: function (request, status, error) {
                 output(request, status, error); // Not for production use:
             }
         }); // End of Ajax function:
         
     } // End of update function:
     
     $blog.on("focusout", function (event) {
 
         var article = event.target,
                 id = $(article).data('id'),
                 title = $(article).siblings('h1').text(),
                 content = $(article).siblings('p.content').text();
 
         if ($(article).hasClass('title')) {
             title = $(article).text();
         }
         if ($(article).hasClass('content')) {
             content = $(article).text();
         }
        
        var params = { id: id, title: title, content: content };
        var myData = jQuery.param(params);
        
        console.log(myData);
        
        update(myData);
 
     }); // End of focusout function:
     
 }); // End of Document Ready Function;

forumsAjax.php

  <?php
  require_once 'lib/includes/utilities.inc.php';
  
  /* Makes is so we don't have to decode the json coming from JQuery */
  header('Content-type: application/json');
  
  $data['id'] = filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT);
  $data['title'] = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
  $data['content'] = filter_input(INPUT_POST, 'content', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
 
 $result = $blog->update($data);
 
 if ($result) {
     $output = json_encode(['result' => "success"]);
     output($output);
 }
 
 /* If there is an error then change the error to the proper code and output the */
 /* error message via Ajax /JQuery.                                              */
 function error($output, $code = 500) {
   http_response_code($code);  
   echo $output;
 }
 
 /* If everything validates OK then send success message to Ajax/jQuery */
 function output($output) {
   http_response_code(200);
   echo $output;
 }

Any help would be greatly appreciated and I can post more code if needed. I’ve tried solving this on my own, but when I do a Google search I get these crazy scripts that in order to have carriage returns. There has to be an easier fix than doing that.

Are the newlines present in the view-source (which the rendered view would not display as newlines)?
If you don’t want to convert the newlines into br tags you could try wrapping the text in pre tags.

What I’m confused about is some people mention json_encode as a method on how to get carriage returns (Which I’m pretty sure I’m doing), but yet don’t say anything on how to implement it. Frustrating to say the least. I’ve tried converting newlines to br with no joy also.

How are you converting the new lines?

Did you see this thread? How do I keep user-entered carriage returns in a text field? - #9 by Helen_W_Lee

Scott

I was told that it was proper to give the solution to the problem, so that others who might have the same problem can fix it faster.

Well after spending about a day on this problem I finally came up with the solution. I noticed that since I was using contenteditable=“true” in a p tag that it would give me a div br div tags, so I did a internet search that way.

I found this for the answer:

$(function () {
      var $blog = $('#blog');
  
      function update(myData) {
  
          $.ajax({
              type: "post",
              url: "forumsAjax.php",
              data: myData,
             success: function (info) {
                 console.log(info);
             },
             error: function (request, status, error) {
                 output(request, status, error); // Not for production use:
             }
         }); // End of Ajax function:
 
     } // End of update function:
      
     /* This is the function(s) that solves the carriage return/new line problem */
     $('p.content[contenteditable="true"]').keypress(function (event) {
 
         if (event.which != 13)
             return true;
 
         var docFragment = document.createDocumentFragment();
 
         //add a new line
         var newEle = document.createTextNode('\n');
         docFragment.appendChild(newEle);
 
         //add the br, or p, or something else
         newEle = document.createElement('br');
         docFragment.appendChild(newEle);
 
         //make the br replace selection
         var range = window.getSelection().getRangeAt(0);
         range.deleteContents();
         range.insertNode(docFragment);
 
         //create a new range
         range = document.createRange();
         range.setStartAfter(newEle);
         range.collapse(true);
 
         //make the cursor there
         var sel = window.getSelection();
         sel.removeAllRanges();
         sel.addRange(range);
 
         return false;
     });
 
     $blog.on("focusout", function (event) {
 
         var article = event.target,
                 id = $(article).data('id'),
                 title = $(article).siblings('h1').text(),
                 content = $(article).siblings('p.content').text();
 
         if ($(article).hasClass('title')) {
             title = $(article).text();
         }
         if ($(article).hasClass('content')) {
             content = $(article).text();
         }
 
 
 
         var params = {id: id, title: title, content: content};
 
         var myData = jQuery.param(params);
 
         console.log(myData);
 
         update(myData);
 
     }); // End of focusout function:
 
 }); // End of Document Ready Function;

I have to say that I would not had in a million years come up with this solution, but I was always told that it was proper to give the solution. Just paying it forward… :grinning:

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.