Create an Impressive Content Editing System with jQuery and PHP

It’s been a while since we had a good development tutorial, so let’s reawaken the tradition again and have some coding fun today! I’m going to show you how to use jQuery and PHP to build a content editing system that will allow you or your client to easily edit .html pages visually.

If this sounds like something you’re interested in, read on. I hope you’ll enjoy it!

How It’s Going to Work

Of course, the first thing to do is set up a plan for how we’re going to make this happen. Here’s what I’m thinking:

  • We’ll use PHP’s file_get_contents() to load the selected HTML file into a textarea.
  • In order to keep the system secure, we’ll limit editing capabilites to an array of files that we know are OK to edit.
  • We can then traverse and edit the file contents with jQuery and the open source WYSIWYM editor WYM Editor.

Our file structure is going to be really simple – just admin.php, the wymeditor package and jquery together in the demo directory. You’re welcome to check out the demo and download the files before you get started:

DownloadDemo

The PHP

We’re going to need a few things in the PHP file. First, we’ve got to have our HTML structure ready to drop the dynamic stuff into. That’s going to look like this:

< !DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
<head>
	<script type='text/javascript' src='jquery/jquery.min.js'></script>
	<script type='text/javascript' src='jquery/wymeditor/jquery.wymeditor.pack.js'></script>
	<script type='text/javascript'>/*we'll put our custom js here*/</script>
</head>

<body>
	<ul><!--Navigation will go here --></ul>
	<form id="editor" method="post" action="<?php $_SERVER['PHP_SELF']; ?>">
		<h2>Site Editor</h2>
	</form>


</body>
</html>

Now we’ll create an associative array where the keys are handles and the values are filenames. What this does is help keep us far out of the way of an RFI attack, since the includable files are limited to only what’s inside the array. File accessing commands and GET variables are a very dangerous combination, so we’ve got to be extra wary of that. Once the array is ready, we’re going to loop through it and create a link for each editable page so that when the user clicks on it, a GET request will be sent and that page will be loaded. We’ll worry about loading the content in a minute, for now let’s just take care of the links (this goes between the two ul tags):

< ?php
$editable_pages = array(
	'home' => 'index.html',
	'about' => 'about.html',
	'services' => 'services.html',
	'contact' => 'contact.html'
);

foreach($editable_pages as $page){
	echo "<li><a href='?page=" .$page. "'>" .$page. "</a></li>\n";
}
?>

What remains is check the GET variable ‘page’ to see if we’re supposed to load a page, and if there’s a value there to attempt to match it up with an element from our editable files array and load that file’s contents into a textarea. If no page has been specified, we’ll provide instructions on how to use the editor. We also need to wrap all of that in an if statement that executes only if the user is logged in. If you’d like to read about how to set up a login function like that, you’re welcome to check out our previous tutorial on creating a secure login system with PHP. Anyways, here’s the code (this goes just inside of the #editor form):

if( is_logged_in() ){
	/*If a page is specified and it's in our array of editable pages*/
	if(isset($_GET['page']) &amp;amp;&amp;amp; isset($editable_pages[$_GET['page']])){

		/*Get the filename from $editable_pages and the content from that file*/
		$page_content = file_get_contents($editable_pages[$_GET['page']]);

		/*If it worked*/
		if($page_content){
			/*obfuscate any textarea tags that would mess up the display and print content inside a textarea*/
			echo "<textarea name='page-code' id='page-code'>" .str_replace("</textarea>","",$page_content). "<br />";

			/*Now create a save button*/
			echo "<input type='submit' class='submit' id='page-code-save' name='page-code-save' value='save'/>";
		}
		else{
			/*If it didn't work, display an error message*/
			echo "<p>Uh-oh - that page was unable to be accessed. Please try again.</p>";
		}
	}
}

And the last thing we’ll need to do is create a conditional (also after we know the user has been logged in) that will save submitted data from the textarea:

if(!empty($_POST['page-code'])){
	/*Get filename from $editable_pages and update file with new content*/
	$saved_file = file_put_contents($editable_pages[$_GET['page']],$_POST['page-code']);

	/*Display a response based on whether or not the changes were able to be saved*/
	if($saved_file){
		 echo "<h3>Your page was updated successfully!</h3>";
	}
	else{
		 echo "<h3>uh -oh, your changes were unable to be saved.</h3>";
	}
}

Pretty neat, huh? We now have the PHP part working – but who wants to edit a textarea filled with a bunch of code? There’s not much point. That why we need jQuery, so let’s see how it’s going to work.

The jQuery

We’ve already loaded WYMEditor, so that makes our visual display/editing a breeze. We’ve just got to do a bit of go-between work with jQuery to get the editor loaded with the content it needs, and then to return that edited content to the page-code textarea. Of course, you could use another editor – something more lightweight and jQuery based like markItUp! For this tutorial though, WYMEditor is simple and powerful – just what we need.

What we’ll do is initiate the editor and then set up a trigger system so that when the user clicks ‘save’, the modified content will be retrieved from the editor and inserted back into the textarea. We’ll also have to save all the head content and put it back in manually since the editor doesn’t pay any attention to it and won’t return that part of the code. Here’s the script, complete with comments (remember to put this back up at the top inside the script tags):

$(function(){ 
	  /*initiate the editor*/
	  $("#page-code").wymeditor({
		skin: "minimal",
		skinPath: 'wymeditor/skins/minimal/',
		toolsHtml: '',
		classesHtml: ''
	  });

	  /*Create a trigger link to ensure that the textarea is updated before the form is submitted*/
	  $("#page-code-save").hide().after("<a class='submit' id='pseudo-submit'>save</a>");

	  /*When the user clicks 'save': */
	  $("#pseudo-submit").click(function(){
	  	/* Get anything before the body tag (which will be lost by the editor) */
		var before = $("#page-code").text().split("<body>")[0] + "</body><body>";
	  	/* And anything after the body tag */
		var after = "</body>" . $("#page-code").text().split("")[1];
	  	/*And the code inside the wymeditor frame*/
		var code = jQuery.wymeditors(0).xhtml();
	  	/*Now take it all and slap it into the page code textarea*/
		$("#page-code").text(before + code + after);
		/*Submit the form*/
		$("#editor").submit();
		return false;
	  });
});

Update … One More Feature!

A couple of you folks asked about limiting the editing functionality to certain portions of the page, which is definitely a very useful feature. Thanks for suggesting it, Gregor and Patrick – I should’ve included this in my first version. Anyways, as I explained in the comments, the most straightforward way to go about this would probably be to add marker comments (like and ) in the html files that will mark the start and end of the part of the page you want to be editable.

Here’s a modified version of the Javascript code above that will make this work and even continue working in the absence of marker comments (like if you wanted one page to be fully editable and another to be partially editable):

$(function(){
	  /*define your start and ending markers for the editable area*/
	  var startEdit = "<!--start edit area-->";
	  var endEdit = "<!--end edit area-->";

	  /*If those markers are present, grab only the editable content and save the rest to put back in later*/
	  if( $("#page-code").text().indexOf(startEdit) > 0 && $("#page-code").text().indexOf(endEdit)>0 ){
	  	var before = $("#page-code").text().split(startEdit)[0] + startEdit;
	  	var after = endEdit + $("#page-code").text().split(endEdit)[1];
		var editableContent = $("#page-code").text().split(startEdit).pop().split(endEdit)[0];
	  }
	  /*if they aren't, we'll assume the whole page is editable*/
	  else{
		var before = $("#page-code").text().split("<body>").shift() + "</body><body>";
		var after = "</body>" + $("#page-code").text().split("").pop();
		var editableContent = $("#page-code").text().split("").pop();
	  }

	  /*update the textarea with only the editable content*/
	 $("#page-code").text(editableContent);

	  /*load the editor*/
	 $("#page-code").wymeditor({
		skin: "minimal",
		skinPath: 'wymeditor/skins/minimal/',
		toolsHtml: '',
		classesHtml: ''
	  });

	  /*add a trigger link for submitting the form*/
	  $("#page-code-save").hide().after("<a class='submit' id='pseudo-submit'>save</a>");

	  /*when it's clicked, put the code all back together and sumbit the form*/
	  $("#pseudo-submit").click(function(){
		$("#page-code").text(before + jQuery.wymeditors(0).xhtml() + after);
		$("#editor").submit();
		return false;
	  });
});

And that’s it – pretty clean, effective and efficient if you ask me! I’ve implemented the controlled editing feature in the index.html file of the demo, so you can see how it works on that page if you want, and feel free to let me know if you have any questions.

Wrapping Up

And there you go! Of course, there are a billion and 1 ways to accomplish something like this, and in many cases it would be more advantageous just to set the site up with a CMS rather than using a jQuery/PHP system like this. The one we’ve just made, though, is small and fast (besides being degradable and a lot of fun to make!) and will work very well for a smaller static site where a full CMS would be overblown. Again, you’re welcome to check out the demo and/or download a working set of files:

DownloadDemo

Hopefully you’ve enjoyed reading this tutorial as much as I enjoyed writing it, and I’d love to hear your opinions and any thoughts on how it could be improved!

Written By Nick Parsons

Nick is the editor of Webitect and a developer + designer from Houston TX.

56 Comments

  1. Sung

    March 4th, 2010 at 03:47 am

    Were can we download a demo of this tutorial.
    I try to set this up, but it didn’t worked.

  2. Nick Parsons

    March 4th, 2010 at 03:16 pm

    @Sung – Thanks for the suggestion, Sung! I’ve added a demo and downloadable zip file with all the tutorial files in it. I also tweaked a couple things to make the code a bit smarter, more efficient, and less buggy.

    Let me know if you have any questions!

  3. Silviya

    March 7th, 2010 at 10:18 am

    Thanks a lot for this tutorial! It will be very useful for me, since I don’t need a real CMS. There is one thing though – When editing the result in the end is an append of the old vrsion and new one. So if I make 10 differnet edits, ill actually have ten different …s on the page.

  4. HD

    March 7th, 2010 at 10:50 am

    Great :)

  5. Gregor

    March 7th, 2010 at 05:16 pm

    Hi Nick,

    glad I found your tutorial!

    for a long time I search for easy to use html editor and your solution is nearly perfect for my needs! … But, to use this on more complex layout website, it would be better that a container (div ID) could defined as editable only so navigation elements, header, footer,… could be excluded from the editors functionality.

    Do you think this is possible?
    Thanks and kind regards

  6. Dilly

    March 8th, 2010 at 05:14 pm

    Has the Demo been hacked?
    It has offensive content and doesn’t work – it doesn’t save ay edits-you keep on seeing the offensive content whatever you enter (on the ‘services’ and ‘about’ tabs)

  7. Nick Parsons

    March 8th, 2010 at 05:49 pm

    @silviya- I’m glad you like the tut! I’m not sure what you mean about the duplicate content – it seems to be working fine in the demo. If you want to send me the code that isn’t working I’d be happy to help.

    @gregor- Good to hear this idea has helped you out! You’ll be happy to know that it is very easy to limit editing to only certain portions of the page. The trick is to add some comments (like <!–start edit area–> and <!–end edit area–>) on either side of the part of the page you want to be editable, and then just split the code on those comments instead of the body tags like in my example. If you want to see the actual code for that, let me know and I’ll add it to the tutorial. Good luck!

    @Dilly – Very sorry about that, the offensive content has been removed. Hopefully whoever did that will decide to quite being a jerk. Thanks for bring this issue to my attention :)

  8. Patrick

    March 9th, 2010 at 08:06 am

    Hi Nick.

    Tks lot for your script. I’d traying to change the body element by some comments as you suggest… but I always got all the page within the editing area.

    Could you try yourself. Then add your explanation into your tutorial?

    Tks lot by advance.
    Best regards.

  9. Andrew Champ

    March 10th, 2010 at 10:45 pm

    Thanks for sharing. Very useful.

  10. Jared

    March 11th, 2010 at 10:16 am

    Very nice. This could be useful in many ways.

  11. Jan

    March 12th, 2010 at 02:15 am

    Seems like it has been hacked again… :-(

  12. Anja

    May 4th, 2010 at 09:06 am

    Thank you so much for this! Exactly what I was looking for. Works great, too. There’s just one thing…. (no, I’m not Columbo ;-) )
    My editor has no Buttons (for Bold / Italic …).
    I have tried using the commands from WYMeditor Website but it doesn’t work. When I reload the page I see a short flickering of some buttons.
    Do you know what to do?
    THANX again and all the best from Germany!
    Anja

  13. Anja

    May 4th, 2010 at 09:14 am

    Nevermind! I got what I wanted by removing the options (skin…) from your call of wymeditor. Thanks again!

  14. dev

    June 19th, 2010 at 06:08 am

    Hi,

    First of all great tutorial. Thanks very much.

    Just a few thing could you please add a demo? Also the download doesn’t include you updates to editor.php (start marker/end marker). I added it in and updated the index page and it works BUT all the other pages with the marker don’t work. I’m not sure if this is a bug or if its just me. Could you please update you downloaded files so I can compare it with mine.

    Many thanks

  15. dev

    June 19th, 2010 at 06:19 am

    I mean *without* …

    one more thing which I just noticed if I had multiple start/end tags in one page, it only lets me edit one section?

  16. Janosch

    July 21st, 2010 at 10:03 am

    Switching the Editor to FCKEditor would make this CMS mor powerful. Is there an easy way of switching the Editor?

  17. Janosch

    July 21st, 2010 at 10:27 am

    The small CMS is pretty nice. Thanks for sharing with us.

    I would like to use the full set of the editor, like images, lists, …
    can I change this here?

    toolsHtml: ”
    classesHtml: ”

    let me know. I like other editors better: FCKEditor and TinyMCE are easier to handle for my customers than the build in editor.

  18. kreuzritter

    July 21st, 2010 at 01:06 pm

    is really cool but it will be great if could edit also images, not just text

  19. Cory Marsh

    July 22nd, 2010 at 04:52 pm

    This redefines the word impressive.

  20. Dimitris

    August 26th, 2010 at 02:14 pm

    Can you please post an image of how it should look like the final result of the editor?

    I have a suspicion that something did not work well for me :D

  21. cut out people

    December 11th, 2010 at 11:49 am

    This is quality, glad i found this.

  22. Rob Macintosh

    January 15th, 2011 at 07:52 pm

    Awesome stuff – i’ll likely use this as the basis for a custom CMS system. I often have clients wanting to routinely update small and mundane sections of their websites, this will do just the job.

  23. Helen Neely

    August 9th, 2011 at 04:56 am

    I just started working with PHP and JQuery, this seems like a cool way to see the power of the framework.

    Thanks folks for the brilliant job

  24. Mika @ muscle warfare

    August 9th, 2011 at 09:57 am

    For a long time I’ve been looking for uncomplicated to use html editor and your answer is almost just right for my wishes.

    I’ve been trying to modify the body component by some remarks as you propose… however I constantly got the entire page inside the editing spot.

  25. Churro

    August 20th, 2011 at 09:11 am

    Please note that the given script is HIGHLY insecure!!
    By using file_get_contents() this way, any (malicious) page can be included! Be aware!

  26. Qaysar Akbar

    April 11th, 2012 at 08:33 am

    If you are looking for good tutorials please visit http://www.ssdtutorials.com.

    Theirs loads of free and premium tutorials, Sebastian Sulinski is the person who runs the website and he offers loads of free tutorails in basic PHP, OOP and even using PDO database classes to create websites and most of the tutorials on their are free. You can buy the premium tutorials separate or part of a bundle and if you contact him he may even provide a discount code to use when buying.

    Thanks

  27. Dustin

    August 13th, 2013 at 11:09 pm

    Learning HTML is like learning a language. The hard part for me is that even though I understand it, I still have to go back and look at it often because I can’t remember exactly what the code is supposed to be. I’d like to get to the point where I could remember much of it off the top of my head.

What Do You Think?