By text blocks I mean the sort of text you'd normally use a TEXTAREA to enter - might contain line breaks.
So I have a list of these blocks, all visible on the screen and you can edit them individually, inline.
Well, that's what I want to have, I'm a little stuck on how best to do it.
So imagine there's a block of Lorem Ipsum there. You click an edit button and the text is swapped out for a TEXTAREA populated with the same text. You click Save and it's sent to the server. The textarea disappears and is replaced with the updated text rendered as HTML.
First problem is how to populate the textarea initially - do I grab the HTML and convert it so it's safe for the textarea? Or is it pre-populated at the server end and simply hidden in the interface, and shown on request? Or do I request the server for the HTML of the textarea with the text in it when I want to show the textarea?
And then there's what to do after the form is submitted. Show the contents of the textarea in the HTML block, wbich means encoding the input for HTML? Or ask the server to return the HTML of the block containing the updated text, properly encoded?
Is there a better way?
I would personally let the server deal with everything, the most important thing to avoid XSS vulnerability would be to properly HTML encode the text posted from the textarea before displaying it onscreen.
So you start off with some text. Render it as-is into a textarea, and in a properly HTML encoded form in a block element (this will stop nasty XSS hacks).
When the user clicks the edit button, you hide the block element and show the text area.
When the user clicks the save button, you use ajax to post the textarea's contents to the server. Here you store the raw data, and send back the propely HTML encode version of the data.
When JS receives the response from the ajax post, it updates the block element, hides the texteara and shows the block element again.
Just to re-iterate, dont take the contents of a textarea and smash that straight into the block element - it opens you up to all sorts of nasties.
hey jamie, thanks.
That's the way I was thinking of going. The thing that stopped me was seeing that you have to send the same text twice each time - once encoded for HTML, and again in the TEXTAREA.
Surely just the once - only the textarea content gets sent to the server?
The response (as HTML text) then gets placed (HTML-encoded) into the block element and the textarea
sorry, I meant the same text gets sent twice from the server to the client. Client to server is just the textarea content as you say. The server responds with a DIV containing both the read version of the content in HTML, and the hidden edit version in a textarea, ready to show if the user clicks 'edit' again. It's one response, but it's the same text being sent twice, e.g. This is my text here.another line. This is my text here.another line.
(hand coded just now, I skipped some bits of course, and JS will need to be run to handle the button events and post the form when needed) You see how the note text appears twice? Here it's just a couple of lines, but it might run to a few paragraphs.
Speed isn't a big issue to me here, so I don't mind going this way, but it seemed perhaps less than ideal.
ah I tried to edit my post to add some indending and the textarea close tag broke the form :( guess we're all vulnerable to these pitfalls!
So if you're worried about the content being sent twice in the HTML response, there is no problem populating the textarea from the block element - its the other way round you need to be careful of.
So you could send this HTML:
This is my text here.another line.
and on document ready do something like:
$(function(){ $(;'#editor').val($('.view').html()); });
cheers. I'll go that way. I've added a replace to swap out the BR tags for newlines so the textarea shows them correctly, e.g.
$(function(){ $(;'#editor').val($('.view').html().replace(//g, '\n')); });
I think that should handle all eventualities.
Well I got it working how I want it in the end, it wasn't all that easy though.
I had to use .html to set the textarea content instead of .val:
$(function(){ $('#editor').html($('.view').html().replace(//g, '\n')); });
This is because if there were any chars in the input that had been encoded for HTML, like < or &, then by using .val they came into the textarea encoded, making it hard to edit. By using .html instead the actual characters appear in the textarea instead.
Also I have to make sure that all newline characters are replaced with tags before writing to HTML - otherwise when the JS grabs the HTML to put in the textarea you get double carriage returns in the textarea - one for the BR and another for the \n that was still there.
function replace_newline($string, $replacement = '') { return (string)str_replace(array("\r\n", "\r", "\n"), $replacement, $string); }
// example: $note = replace_newline(htmlentities($note, ENT_COMPAT, 'UTF-8'), '');
It was a bit of an encoding minefield doing it this way - I was previously using xss_clean on the textarea input, and I've had to remove that so things don't get double-encoded. In my set up I'm allowing them to enter anything, and just encoding it when I display it. And filtering it before it goes into the db too of course.
Ere you go DBM nl2br
yeah I think nl2br preserves the newlines, so when I copy to the textarea they get doubled up - newline is a newline and the s become newlines too, so double.
Ah - I didn't understand the issue.
I forgot to explain that I'd tried nl2br first and what went wrong with it.