Replacing CKEditor on the Fly While Enabling Save Button Using jQuery

I was working on a project yesterday when I encountered the need to have DIVs change into text editors upon double-click. It was fairly easy since I was using CKEditor as a rich-text editor and there was an example on the CKEditor website on how to do that. The DIV to be replaced by CKEditor looks like this:

[html]
<div class="editable">
<h3>Part 1</h3>
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras et ipsum quis mi
semper accumsan. Integer pretium dui id massa. Suspendisse in nisl sit amet urna
rutrum imperdiet. Nulla eu tellus. Donec ante nisi, ullamcorper quis, fringilla
nec, sagittis eleifend, pede. Nulla commodo interdum massa. Donec id metus. Fusce
eu ipsum. Suspendisse auctor. Phasellus fermentum porttitor risus.
</p>
</div>
[/html]

While the script on the demo page looks like this:

[javascript]
window.onload = function()
{
// Listen to the double click event.
if ( window.addEventListener )
document.body.addEventListener( ‘dblclick’, onDoubleClick, false );
else if ( window.attachEvent )
document.body.attachEvent( ‘ondblclick’, onDoubleClick );
};

function onDoubleClick( ev )
{
// Get the element which fired the event. This is not necessarily the
// element to which the event has been attached.
var element = ev.target || ev.srcElement;
// Find out the div that holds this element.
var name;
do
{
element = element.parentNode;
}
while ( element && ( name = element.nodeName.toLowerCase() ) && ( name != ‘div’ || element.className.indexOf( ‘editable’ ) == -1 ) && name != ‘body’ )
if ( name == ‘div’ && element.className.indexOf( ‘editable’ ) != -1 )
replaceDiv( element );
}
var editor;
function replaceDiv( div )
{
if ( editor )
editor.destroy();
editor = CKEDITOR.replace( div );
}
[/javascript]

I have to say that the code works well. But the project that I’m doing uses jQuery, so I had to convert the above script to utilize it. Please take note that this project uses the included jQuery adapter.

The downside of the code above is that the Save button only works if it is inside a FORM element. If the CKEditor is not within a form, then the Save button will be disabled automatically. So after knowing this, many of you, including me, will just wrap the whole div inside a form and try to test out the Save button.

[html highlight=”1,12″]
<form action="actionpage" method="post">
<div class="editable">
<h3>Part 1</h3>
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras et ipsum quis mi
semper accumsan. Integer pretium dui id massa. Suspendisse in nisl sit amet urna
rutrum imperdiet. Nulla eu tellus. Donec ante nisi, ullamcorper quis, fringilla
nec, sagittis eleifend, pede. Nulla commodo interdum massa. Donec id metus. Fusce
eu ipsum. Suspendisse auctor. Phasellus fermentum porttitor risus.
</p>
</div>
</form>
[/html]

To our surprise, the button is still disabled! After a few seconds of pondering, we will find out that the culprit lies within our HTML code. Come to think of it, according to the documentation, CKEditor works like a textarea inside our form and just submit the contents of our editor as such. Also, the Save button works just like a Submit button, which in turn, pass the content of our CKEditor to the form. But wait, we don’t have a textarea! Yes, if you used the HTML code above, our CKEditor was a div and not a textarea, so logically, a form cannot submit the value from a div, which in turn, makes our Save button disabled.

Some of you probably opted to replace the DIV from your HTML to a textarea but figured out it would defeat the purpose of editing on the fly. Others probably will hack into the CKEditor to create a new Save button that will do everything that they wanted to! But I thought, why not just change the DOM of the document so a textarea could be inserted to the form, then just replace the textarea into CKEditor instead of the div. Well, I think it was a better idea instead of creating a new plugin. Here’s a how I did it:

[javascript]
/** Here are the global variables **/
var ceditor; //This is for our CKEditor editor
var divcontent=""; //This will save the contents of our div (Not really necessary, just for illustration purposes)

//I wanted it to execute after the DOM is ready.
$(document).ready(function(){
//Handle the doubleclick event for the div
$(".editable").dblclick(function(){

//Destroy first our editor if it exists
if(ceditor)
{
$(ceditor).ckeditorGet().destroy();
}

divcontent = $(this).html(); //Save the content of our div (Stored it in a variable just for clarity)

//Insert the textarea inside the div with the contents of our div as it’s value
$(this).html("<textarea name=’txtArea’>"+divcontent+"");

//Time to replace the textarea to a CKEditor editor
//Notice that it’s not using the jQuery adapter’s method since it doesn’t modify the textarea’s value upon submission of the form
//It’s better to use the native CKEditor in this case
ceditor =  CKEDITOR.replace($(this).children("textarea").get(0));
});
});
[/javascript]

Works fine for me, the Save button is now enabled and can submit the form just fine. If we double-click on another div, the previously edited div retains the modified text on the DOM. So what if if we want to cancel the editing of a div by double-clicking outside the editor and upon canceling, rolls back to the previous value of the div? Fairly easy, especially if all you have to do is copy-paste:

[javascript]
/** Here are the global variables **/
var ceditor; //This is for our CKEditor editor
var ceditor_container; //Saves the container of our editor (DIV).
var divcontent=""; //This will save the contents of our div

//I wanted it to execute after the DOM is ready.
$(document).ready(function(){
//Stop bubbling of event, so the handler for double-clicking the body doesn’t executed
event.stopPropagation();

//Handle the doubleclick event for the div
$(".editable").dblclick(function(){

//Destroy first our editor if it exists then rollback the previous value of our div
if(ceditor)
{
$(ceditor).ckeditorGet().destroy();
$(ceditor_container).html(divcontent);
}

divcontent = $(this).html(); //Save the content of our div so we can rollback later

//Insert the textarea inside the div with the contents of our div as it’s value
$(this).html("<textarea name=’txtArea’>"+divcontent+"");

//Time to replace the textarea to a CKEditor editor
ceditor =  CKEDITOR.replace($(this).children("textarea").get(0));

//Save the div container for retrieval later
ceditor_container = $(this);
});

//Handle double-click from anywhere on the page.
$("body").dblclick(function(){
//Destroy the editor and rollback the previous value
if(ceditor)
{
$(ceditor).ckeditorGet().destroy();
ceditor = null; //Set it to null since upon the destroying the CKEditor, the value of the variable is not destroyed (not destroyed by reference)
$(ceditor_container).html(divcontent);
}
});
});
[/javascript]

What do you think about the code? I hastily modified the code from the project I was working on, like variable names, etc. Notify me if you found some errors.

jQuery Mobile: The Next Big Thing Comes in Minified Package

Introduction

For the seasoned web developer, there’s no denying it, jQuery is one of the best and widely used JavaScript framework aside from ExtJS, Dojo, MooTools and Google Web Toolkit to name a few. According to BuiltWith.com, at the time of this writing, jQuery is the top JavaScript framework used with 44.01% of websites using it. With the Top 1 Million Websites indexed by BuiltWith.com, it is used by approximately 44.82% of internet websites, solidifying its stature as the best JS Framework in the world. And if you are curious, the 2nd most used JavaScript Library used is Facebook for Websites with a usage of 15.11%. Such a huge difference in numbers, it’s a landslide victory for jQuery. Combined with its ease of use, small memory footprint, cross-browser compatibility and its popularity, it’s no surprise that it is the ideal JS library for noobs and pros alike.

With the popularity of mobile computing, suddenly mobile browser shares skyrocketed from a small minority to an indispensable business consideration for major companies. Back then, mobile browsers were just a simple browser, very limited compared to mainstream desktop browsers. All they’re capable of doing is display WAP sites and simple HTML websites. Mobile browsers which can run WMLScripts were considered advanced then. As the mobile devices level-up, so are their capabilities. Smartphones in general, gained mainstream popularity, arguably because of the iPhone in 2007. As the devices gain more processing power, so are the possibilities that it can achieve. These phones are capable of displaying full websites instead of the usual stripped-down version of the page. They behave more of a mini-netbook with phone features.

jQuery Mobile

Enter JavaScript. Web developers wanted to incorporate JavaScript into their mobile websites since smartphones are now capable to do so. From simple client-side form validation to some jaw-dropping transition animations, the more interactive a site is, the more visitors it is likely to attract. With this in mind, it’s inevitable that JS is sure to stay in the mobile market. Like the desktop browser, it needs a JavaScript library to make development easier and more feature-rich. Here comes jQuery Mobile, a framework built on top of the already stable jQuery library. According to the jQuery Mobile overview, it can be described as:

Delivering top-of-the-line JavaScript in a unified User Interface that works across the most-used smartphone web browsers and tablet form factors.

Although the said framework only targets only smartphone and tablet web browsers, as long as the HTML mark-up is semantically correct, it will silently and discretely fallback to a plain HTML page. Probably the best feature of the library is transforming the differently-rendered pages from different mobile web browsers into a uniform, familiar touch-friendly user-interface.

Plain mobile webpage
Plain mobile webpage.
Mobile webpage with jQuery Mobile
Mobile webpage with jQuery Mobile

The images above shows the difference in terms of rendering of a single webpage using an old mobile browser and a smartphone. We can notice a large difference in terms of style when viewing a website when jQuery Mobile is capable of running. And by simple analogy, we can say that customers and visitors alike are more likely to visit a mobile website that has better visual eye-candy, and therefore the website will get more traffic. We can also notice that the one with the framework is ergonomically-designed for touch-enabled phones. Notice the iPhonesque  design of the page? It almost blends seamlessly with the designs of the iPhone and Android interface, so users are almost familiar with it.

But why?

So what’s the point of using the framework when not all mobile phone is supported? Well for one thing, you aren’t given any kind of disadvantage if you use the framework. Let’s assume that most of your visitors who visit your site through mobile web browsers uses smartphones. When they see your site, they will be shown a clean, touch-optimized page designed especially for their devices’ capabilities. But when a visitor visits your site using a non-compatible mobile web browser, they would simply be shown a plain mobile webpage with almost no difference in content with your touch-friendly page. The good thing in here is that you won’t need to change any of your HTML code to suit these browsers. As I’ve said before, it falls back discretely to plain HTML when the browser used cannot run JavaScript. It’s a win-win situation for you!

I therefore conclude

jQuery Mobile is still in its alpha stage, meaning it shouldn’t be used for production websites, but rather for testing purposes only. As of this writing, the current version is 1.0 alpha 4.1. It’s still a bit far for a stable release, heck it’s not even on beta yet. But based on user responses, feedback is quite good. A few bugs are found and sprout everyday, but results are promising. Since it was built on top of the full jQuery framework, in my personal opinion, I think it is safe to use it for production on desktop websites. Yes, it runs perfectly on desktop browsers too! Your desktop websites inherits a few touch capabilities such as dragging the page to scroll down, cool huh? But as of now, we have to keep an eye on its development, and I’m sure we’ll still be surprised in what it can do. Next time, I’ll probably make a simple tutorial on how to incorporate jQuery Mobile in your pages, as if it wasn’t on the official documentation yet.