How to Save and Retrieve Contenteditable Data

How to save and retrieve contenteditable data

Use a client-side language, such as JavaScript (or best, jQuery), to manage whether the input boxes could be edited.

Use AJAX to grab the field data and fire it off to a PHP file, which would stick the data in your database.

Here is a very simplified example of using jQuery to manage enabling/disabling the input fields:

jsFiddle Demo

$('.editable').prop('disabled',true);

$('.editbutt').click(function(){
var num = $(this).attr('id').split('-')[1];
$('#edit-'+num).prop('disabled',false).focus();
});

$('.editable').blur(function(){
var myTxt = $(this).val();
$.ajax({
type: 'post',
url: 'some_php_file.php',
data: 'varname=' +myTxt+ '&anothervar=' +moreTxt
});
});

PHP file: some_php_file.php

<?php 
$myVar = $_POST['varname'];
$secondVar = $_POST['anothervar'];
//Now, do what you want with the data in the vars

Using AJAX is quite easy. I gave a very brief example of what it would look like. Don't look in the HTML or jQuery for the moreTxt variable -- I added that to show how you would add a second var of data to the ajax.

Here are some basic examples to bring you up to speed on ajax:

AJAX request callback using jQuery


There is no short path to learning jQuery or AJAX. Read the examples and experiment.

You can find some excellent, free jQuery tutorials here:

http://thenewboston.com

http://phpacademy.org


UPDATE EDIT:

To respond to your comment inquiry:

To send data from a DIV to a PHP file, first you need an event that triggers the code. As you mentioned, on an input field, this can be the blur() event, which triggers when you leave a field. On a <select>, it can be the change() event, which triggers when you choose a selection. But on a DIV... well, the user cannot interact with a div, right? The trigger must be something that the user does, such as clicking a button.

So, the user clicks a button -- you can get the content of the DIV using the .html() command. (On input boxes and select controls, you would use .val(), but on DIVs and table cells you must use .html(). Code would look like this:

How to send DIV content after a button clicked:

HTML:

<div class='big_wrapper' contenteditable>
PAGE CONTENT
</div>
<input id="mybutt" type="button" value="Send Data" />

jQuery:

$('#mybutt').click(function(){
var myTxt = $('.big_wrapper').html();
$.ajax({
type: 'post',
url: 'some_php_file.php',
data: 'varname=' +myTxt+ '&anothervar=' +moreTxt
});

});

Getting values from HTML Content Editable, passing those values to Javascript and use AJAX to send to PHP file

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>

Save changes made by content editable on any website

Here's a way you can do this using vanilla JS.

Here's JSFiddle since StackOverflow doesn't allow localStorage to be executed on the website as a security feature.

How it works:

  1. Using window.onload = function() {...}, check if 'content' key
    exists in localStorage
  2. If it does, load the data into <div class="content">
  3. Upon pressing Edit button, contentEditable is toggled
  4. Here you can use any method to save the data. I used content.contentEditable === 'false' to save the innerHTML data to 'content' key.

To Note: localStorage is saved in your browser locally, use databases or anything similar to display edits to all viewers.


// Load content onload if it exists in localStoragewindow.onload = function() { if(localStorage.getItem('content')) {  document.querySelector('.content').innerHTML = localStorage.getItem('content');  }}
let editBtn = document.querySelector('#edit_content');let content = document.querySelector('.content');
editBtn.addEventListener('click', () => { // Toggle contentEditable on button click content.contentEditable = !content.isContentEditable; // If disabled, save text if(content.contentEditable === 'false') { localStorage.setItem('content', content.innerHTML); }});
.content {  border: 1px solid;  padding: 15px;}
<div class="content">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</div><br><button id="edit_content">Edit</button>

Save content of a div contenteditable=true to my db through a form in Rails

You are setting the value the wrong way. You want to set the "post_content" value to the "content" innerHTML.

document.getElemenetById('post_content') = document.getElementById('content').innerHTML;

Also, you should use a hidden input instead of a textarea with display:none.

And lastly, make sure the function is being triggered. I don't think the "onsubmit" callback is properly fireing since form_with intercepts the form submission and does an ajax request.

Personally I'd listen to the input event on the contenteditable element so you don't depend on the form submission:

document.getElementById('content').addEventListener('input', function(ev){
document.getElementById('post_content').value = ev.target.innerHTML;
})

Now everytime you change the contenteditable content you get the input updated instantly.

how to save html contenteditable content as text file

I cleaned up and fixed what you had, here: http://pastebin.com/sJXVvRUB

I think it does what you want. You still have to restyle the link to look like a button, if you want. I've also only tested in Chrome, so it may need other small modifications.

As for your problems and how I fixed them:

  1. I'm not sure I completely understand the "spaces" part of the problem, unless you meant that all consecutive whitespace gets (incorrectly) saved as a single space. That's how HTML renders it, actually. I fixed that by replacing your note = note.replace(" ", ""); with note = note.replace(' ', ' ');. You were replacing non-breaking spaces with nothing. For line breaks, I just escaped the note before saving: escape(note). I also tweaked the calls to replace() to be a bit simpler and more targeted (at least on Chrome).
  2. For controlling the filename, I replaced the form+button with a link so I could use the "download" attribute, documented here: https://developer.mozilla.org/en-US/docs/HTML/Element/a#attr-download (also mostly only supported by Chrome at the moment).

Hope this helps!

contenteditable - JQuery save content just to webpage (as well as adding and removing)

Rather than making td editable you could wrap div inside td and make it editable and assign fixed width and height to div.

 .clEdit {
width: 200px;
/*Try chaging it as per need*/
overflow: hidden;
/* try scroll with more height */
height: 15px;
/*Try chaging it as per need*/
}

Now there are 2 options either allow overflow to be hidden or scroll. You could examine the behavior and select either one. As a user friendly experience you could assign tooltip to div on hover or click so that whenever values inside div are being overflown user could see what are the current values inside.

 $(".clEdit").hover(function(e) {

$(this).prop("title", $(this).html());

});

Yes you could add/delete rows from table without DB if you know the values. id can be calculated from previous id value.

Adding/removing from table does not guarantee DB will be updated you need handle that.

On adding rows you need to bind event for contenteditable as well.

 $("#add").click(function() {
//LOGIC TO ADD ROW TO TABLE

var trRow = "<tr><td>" + ++idFirstCol + "</td><td>" + "SecondColValue" + "</td><td><div class='clEdit'>" + "ThirdColValue" + "</div></td> <td> " + "LastColValue" + " </td></tr>";

$("#ConTable").append(trRow);
$(".clEdit").hover(function(e) {
$(this).prop("title", $(this).html());
});
$(".clEdit").prop('contenteditable', true);
});

You could refer to JSFiddle here. http://jsfiddle.net/8mt6d7bz/

Lmk if that answers your question

contenteditable selected text save and restore

A typical use would be displaying some kind of widget or dialog to accept input from the user (thus potentially destroying the original selection) and restoring the selection after that widget has been hidden. Actually using the functions is quite simple; the biggest danger is trying to save the selection after it has already been destroyed.

Here's a simple example. It displays a text input and overwrites the selection in the editable <div> with the text from that input. Note that this code has support for Internet Explorer <= 8 in the document.selection branches which could be removed now, in 2022:

function saveSelection() {
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
return sel.getRangeAt(0);
}
} else if (document.selection && document.selection.createRange) {
return document.selection.createRange();
}
return null;
}

function restoreSelection(range) {
if (range) {
if (window.getSelection) {
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (document.selection && range.select) {
range.select();
}
}
}

function insertTextAtCursor(text) {
var sel, range, html;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
var textNode = document.createTextNode(text)
range.insertNode(textNode);
sel.removeAllRanges();
range = range.cloneRange();
range.selectNode(textNode);
range.collapse(false);
sel.addRange(range);
}
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.pasteHTML(text);
range.select();
}
}

var selRange;

function displayTextInserter() {
selRange = saveSelection();
document.getElementById("textInserter").style.display = "block";
document.getElementById("textToInsert").focus();
}


function insertText() {
var text = document.getElementById("textToInsert").value;
document.getElementById("textInserter").style.display = "none";
restoreSelection(selRange);
document.getElementById("test").focus();
insertTextAtCursor(text);
}
#textInserter {
display: none;
}
<div id="test" contenteditable="true">Some editable text</div>
<input type="button" unselectable="on" onclick="displayTextInserter();" value="Insert text">
<div id="textInserter">
<input type="text" id="textToInsert">
<input type="button" onclick="insertText()" value="Insert">
</div>

Saving contenteditable data using jquery

Change the "textarea" element to "div" and add contenteditable="true". Then change text.value to text.innerHTML. Is that what you mean? It seems to work for me at this link.

<div id="editor" contentEditable="true" placeholder="Start writing..."></div>
...
[text.innerHTML || text.placeholder], {
...
session.text = text.innerHTML;


Related Topics



Leave a reply



Submit