-1

I have different content editable in my html file. I have a couple of labels, and a couple of tables with content editable as well.

I want to send the info to a database after user focus out, no buttons to trigger the action.

This is part of my html:

<label id="firstLabel" contenteditable="true">Hello</label>
<table id="firstTable">
  <input type="hidden" name="userId" id="userid" value="<?php echo $userId ?">
  <tr>
     <td id="firstRow" name="firstRow" contenteditable="true">This is first row</td>
  </tr>
</table>
<div class="footer" id="footer" contenteditable="true">Bottom message</div>

I'm new to programming, and I'm trying to figure the best way to get the contenteditable information, and send it to my database. I know I have to use Javascript, Ajax, and send it to a PHP file based on the information I've researched. The PHP part is not a problem for me, but I need a little help with the Javascript and AJAX parts because everything I tried so far has not retrieved any results.

Thank you.

Fquintero
  • 45
  • 9
  • just fyi ~ the `name` attribute is not applicable to `td` elements – Professor Abronsius Oct 11 '21 at 05:56
  • Thanks for the td clarification. If I have my html content going through a while loop, userid always gets the value of 1 (which is the first id in the database). It ignores all other values. – Fquintero Oct 11 '21 at 14:58
  • OK - the question mentioned nothing about a loop and multiple records. Within the `blur` event handler you must therefore use the `event.target` and suitable `parent/child/sibling` type selectors to find the input element that has the userid for that particular record/row. The fact that the first and last contenteditable regions appear to only have the `body` as a `parentNode` makes this task harder for you. jQuery has methods to find the nearest elements based upon some criteria I believe though. If you were to group all of the HTML elements you have shown here into a SPAN it would be easier. – Professor Abronsius Oct 11 '21 at 15:04

2 Answers2

2

It's not an "out of the box" answer, but a skeleton : you can listen for an element lost the focus, ie the user is no more typing in it.

let edit = document.getElementById("firstRow");

edit.addEventListener("blur", function(e) {
  console.log("You can send to php");
  // please have a look here for ajax : https://developer.mozilla.org/fr/docs/Web/Guide/AJAX
});
<label id="firstLabel" contenteditable="true">Hello</label>
<table id="firstTable">
  <input type="hidden" name="userId" id="userid" value="<?php echo $userId ?">
  <tr>
    <td id="firstRow" name="firstRow" contenteditable="true">This is first row</td>
  </tr>
</table>
<div class="footer" id="footer" contenteditable="true">Bottom message</div>
Philippe
  • 1,134
  • 12
  • 22
2

A simple example of how to do this might be to assign a blur event listener bound to all elements that have the contenteditable attribute set and use fetch api to send the AJAX request using a FormData object to your backend PHP script.

const getparent=(e)=>{
  let n=e.target;
  while(n.tagName.toLowerCase()!='span' && n.className!='record'){
    if(n.tagName=='BODY')return false;
    n=n.parentNode;
  }
  return n;
}

document.querySelectorAll('[contenteditable="true"]').forEach(el=>{
  el.addEventListener('blur',function(e){
    let span=getparent(e);
    if( !span )return;

    let fd=new FormData();
        fd.set('userid', span.querySelector('[name="userId"]').value );
        fd.set('text', this.textContent );
        fd.set('id', this.id );

    fetch( 'https://www.example.com', { method:'post', body:fd, mode:'cors' })
      .then( r=>r.text() )
      .then( text=>{
        console.log( 'Do something with returned response: %s',text )
      })
  })
})
.record{
  display:block;
  margin:1rem;
  border:1px solid red;
  padding:1rem;
}
<span class='record'>
  <label id="label-1" contenteditable="true">Hello World</label>
  <table>
    <input type="hidden" name="userId" value="123456789">
    <tr>
       <td id="row-1" name="firstRow" contenteditable="true">This is first row</td>
    </tr>
  </table>
  <div class="footer" contenteditable="true">A message from the Bottom</div>
</span>


<span class='record'>
  <label id="label-2" contenteditable="true">World Hello</label>
  <table>
    <input type="hidden" name="userId" value="987654321">
    <tr>
       <td id="row-2" name="secondRow" contenteditable="true">This is second row</td>
    </tr>
  </table>
  <div class="footer" contenteditable="true">A bottom from the Message</div>
</span>
Professor Abronsius
  • 33,063
  • 5
  • 32
  • 46
  • Thank you both for taking me to the right direction. To Professor Abronsius, how do I pass the hidden value as well? – Fquintero Oct 10 '21 at 17:14
  • That does fundementally change the approach that you might need to take as these `contenteditable` elements are no longer `"standalone"` as is suggested by the `"I want to send the info to a database after user focus out"` comment in the question. Are both `contenteditable` elements to be added individually with the `userid` or should there be only 1 `insert` using ALL pieces of information?? – Professor Abronsius Oct 10 '21 at 21:23
  • If the user changes the firstRow element, I need to send the firstRow value and the userid hidden value as well, so I can do changes in the database. To answer your question, I am looking for contenteditable elements to be added individually with the userid. If I understand well, your second approach might require a button, but I don't need a button, I need to send information to database as soon as user focus out. – Fquintero Oct 10 '21 at 23:16
  • It would be easiest if the `userid` is sent with either of the `contenteditable` elements I'd think - you can decide to ignore at the server level then. – Professor Abronsius Oct 11 '21 at 05:50
  • Professor Abronsius, thank you so much! I learned how parent Nodes work, the span tag and fetching values with AJAX. I greatly appreciate it. Hope this can help others having the same issues like me. – Fquintero Oct 11 '21 at 21:38