0

I'm using 'contenteditable=true' to enable edits on certain table cells. Now I want to know which of the editable elements on the page have actually been edited by the user, so that I can process the changes.

Although I could probably use event-listeners for this purpose, this approach will be tedious in my case. The page is dynamically generated and it has a variable number of editable elements. I want to avoid having to dynamically add event-listeners for every editable element.

I want to know if the DOM already has a property/flag to indicate whether an element has been updated. If so, I'd like to have a solution along these lines:

var element_123 = document.getElementById("element_id_123");
 var was_edited = element_123.was_edited;

Thank you.

Lelio Faieta
  • 6,457
  • 7
  • 40
  • 74
  • You'll need to listen to the `keyup` and `keydown` events. I couldn't figure out another way. – Dan Jun 13 '18 at 08:19
  • @Spingolini I'm trying to avoid having to write low-level listener code. My question is whether the DOM already keeps track of whether an element was modified or not. I don't need the DOM to tell me what change was made, only whether or not an element was changed. – Anupam Khulbe Jun 13 '18 at 08:21
  • use sessionStorage, set the sessionStorage and compare the string at the time of submission, this way you are using a tiny storage on the client side and not throwing event unusually when someone typing. – Anirudha Gupta Jun 13 '18 at 08:23
  • @Adrian you did not understand my question – Anupam Khulbe Jun 13 '18 at 08:24
  • 1
    You need to do this by yourself. There's no `was_edited`-like attribute. Take a look at this article, it might solve your problem: https://coderwall.com/p/lxl3zw – Dan Jun 13 '18 at 08:28
  • @Spingolini Thanks, that was helpful. I was hoping that DOM would have a generic solution for this though. – Anupam Khulbe Jun 13 '18 at 08:32
  • Sorry, couldn't find anything beyond that ... – Dan Jun 13 '18 at 08:33
  • Does it really make a difference if you write a listener that you attach dynamically or a function that is called by HTML? Work is around the same. – dscham Jun 13 '18 at 08:50
  • @Sens if I do it myself via event listeners, then I'd also need to come up with a naming scheme, so that each editable element gets a unique id. And then I'd need to store the edited element's id in sessionStorage (or somewhere else) for tracking the modified elements. It's definitely feasible, but a DOM-level flag for this would result in a more compact (and less bug-prone) code. – Anupam Khulbe Jun 13 '18 at 08:56
  • @AnupamKhulbe Maybe i got you wrong, i thought the site (and content/DOM) is generated via JS. So creating unique id's would have seemed quite easy. And you could factory the eventlisteners. Code should be relatively clean then. Altough it's still a messy solution anyway. But the whole web is ;) – dscham Jun 14 '18 at 12:41

3 Answers3

0

I don't think there is something like this built into the browser. However, you may use something like this (http://api.jquery.com/delegate/):

$( "#didichange_tbl" ).delegate( "input", "change", function() {
  console.log("table has changed!!");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

 <table id="didichange_tbl">
        <tr>
          <td><input/></td>
        </tr>
        <tr>
          <td><input/></td>
        </tr>
 </table>
11AND2
  • 1,067
  • 7
  • 10
  • Something like this would work, but I'd need to do this at the individual table cells. Doing this at the table level will not allow me to identify which specific cells were updated. Also, with this approach, I'd need to assign a unique id to each table cell and then store that id (in sessionStorage, for example) to indicate that it was updated. This quickly becomes a complicated solution, although it's technically feasible. – Anupam Khulbe Jun 13 '18 at 08:49
  • @11AND2 my suggestion would be using on instead of delegate. check https://stackoverflow.com/questions/22904904/delegate-vs-on-in-jquery – Anirudha Gupta Jun 13 '18 at 10:35
0

I tried a few solutions, the best thing I've found was written by conradgray on the coderwall.com blog: https://coderwall.com/p/lxl3zw. I decided to add the articles contents to a post, in case at some time the original doesn't exist anymore.

This is his solution:

var editable = document.getElementById('text');
editable.addEventListener('input', function() {
    console.log('Hey, somebody changed something in my text!');
});
<div id="text" contenteditable>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec at arcu ac dui eleifend suscipit a ut est. Ut iaculis ut massa non accumsan. Quisque hendrerit nisl at egestas cursus.
</div>
Dan
  • 5,140
  • 2
  • 15
  • 30
0

What you need to do is to set contenteditable only to leaf elements and text nodes and then listen for input event. That way you can extract the exact source of the event.

document.body.addEventListener('keydown', event => {
  console.log(event.target);
});

function addContentEditable(el) {
  if (el.children.length === 0) { el.setAttribute('contenteditable', true) }
  if (el.nodeType === 3) { el.setAttribute('contenteditable', true) }
  [...el.children].forEach(c => {
    addContentEditable(c);
  });
}

addContentEditable(document.body);
<div class="pad">
  <p>Some text</p>
  <p>Some more text<a> and a link</a></p>
  <p>Even <b>more</b> text</p>
</div>
Matus Dubrava
  • 13,637
  • 2
  • 38
  • 54