Friday, February 17, 2012

JQuery Sortable and VisualForce

So todays topic of discussion is how to use the sortable method of JQuery within a VisualForce page to display and allow users to update the specic order of the records. I am going to cover this in it's most generic form and what you choose to do with it is up to your imagination. I was recently asked to create an interface for users to view a list of projects by department and provide them the ability to move these projects around based on priority etc and then update the list order. So our finshed result was very detailed lists with status icons for such things approved, priority level, color coded based on department and so on.

So lets get started. In your development account, the products object should already have an existing set of generic product records. So for the purposes of this tutorial I decided to go ahead and what was there, but you can use any existing or custom object of your choosing.

First thing we are going to do is add a new custom field to the object, I choose to name mine "sort order" and set the field type to number. Next lets create a new Apex class and name it ProductSort. In the Apex class lets go ahead and query the Product object and return a list ordering it by our new field which at the moment contains no data. Your code should look similar to this:

public  class ProductSort {
public list  p;
public Product2[] getp() {
 p=[Select Id,Name, sort_order__c From Product2  Order by sort_order__c];
 return p;
}
}


Next lets create a new VisualForce page (I just named mine Sort) and add a few references to the JQuery and JQuery UI libraries hosted on on Google. Then we are going to setup the JQuery Sortable list and embed an apex:repeat wthin it.



 



 


 

  • {!prod.Name}

Looking at the page you can see we have include statements to the JQuery and UI libraries, one to the Cupertino theme Style sheet(You can choose an existing theme or roll your own) and some minimal list styling. Next we have our function to intialize the sortable list based on the DOM Id of the object (#sortable). Within the <ul> tags we have an apex:repeat to display the list of products that we queried. If you look carefuly we are settting the id of each <li> to the record Id of the products, we are going to use this next to update the sort order within the product record.

Now if we take a look at the page you should see something simular to this:

You should be able to drag the products up and down within the list.

Now lets go ahead and tie into the Sortable method and update our sort order. There are alot of different ways you can go about this. For instance you could kick off an update routine within your Apex class, you could use a button on the page and allow the users to update all of the records at one time after they have finished getting all of the records sorted the way they want, and so on.

We are going to use Ajax to update the entire list each time a user changes the postion of a product. First we are going to add our includes to the Ajax libraries on our VisualForce page. Then on the update method of the sortable function we are going to iterate through our list and update the sort order id relative to its order within the array. You may also notice that there is a call to toggle within the script. I just created a div to provide feedback to the user that the list was updating and to please wait.

 
 


In this example we realy do not care what the previous sort order was and so we are just re-ordering the records each time. If you were filtering records out etc and wanted to just update the order of certain records while maintaining the exiting ones, you would just save the existing order into an array and then use that collection of values durring the update process. You can also add touchable events to the list which would provide the same functionality to users on an IPad or other touch based device.

Monday, February 13, 2012

Customize CKEditor on Force.com Part 2

So if you followed along in Part One, you should now have a Visual Force page with CKEditor and the full tool bar. Clicking on the image icon should display the default image dialog with the ability to browse your force.com documents and select and image to insert into the editor window. Now lets discuss what it is going to take to be able to upload images from within the dialog window.

Before we get started let me just say that there are a few quirks with this method that I have coded around while I figure out how to address the issue. While not the exact interface I would like to see, until I dig in a little deeper into customizing dialog elements within CKEditor it will have to do.


Step 1: Modifying the CKEditor Image Dialog

If you happen to have taken a look at the original FCKEditor files included with the package we installed in the first post. You may have noticed that what they did was use customize the image upload page using an IFrame to the FileUpload Visual Force page. Then using a bit of Javascript you can pass the image URL back to your Image Tab in the editor. We are going to do the same thing here, however with the new CKEditor all the dialogs are built with Javascript files so unlike the FCK version there is not actually an HTML page to modify. Some of you may have experience in creating custom plug-ins for CK and may have a better way to approach this, but with a limited amount of time available I choose to move on using this method.

So here is what we have to do. We have to remove the current elements on the Upload Dialog Tab and replace them with our own IFrame element. Navigate to the CKEditor folder you unzipped previously. (Since I don't feel like spending the time to modify the minified version of the Js code the next step is completely optional. If you want to modify the minified version have at it.) Under the _Source folder drill down into the  /plugins/image/dialogs directory and copy the image.js file. Next you are going to paste this file in the ckeditor/plugins/image/dialogs folder and overwrite the minified version that currently exists.

Now open this file in your favorite JS editor and locate the section of code that builds the upload tab dialog. It is identified by the section of code that reads id : 'Upload'


In the above code you will see the element definitions for the file upload control and the send to server button. We are going to remove these elements and replace them with an HTML element that contains the IFrame to the FileUpload VF page. You can either comment out the existing elements or just remove them completely so that your upload section looks like this.

 
{
  id : 'Upload',
  hidden : false,
  //filebrowser : 'uploadButton',
  label : editor.lang.image.upload,
  elements :
   [
    {
     type: 'html',
     id: 'upl1',
     html: ''
   }
  ]
 },

Save the js file and then navigate back up to the root of CKEditor. Select all the files and folder and re-zip the contents naming the file ckeditor.zip as we did in the first post. Now go in and update the static resource file with the new version we just created.

Step 2: Update the FileUpload Page

As I stated in the beginning, the upload tab is supposed to pass back the URL of the image that was uploaded back to the info dialog. I am still trying to get this to work. Since the IFrame is opened within the contents of the upload dialog tab you should be able to do something like parent.CKEDITOR.tools.callFunction(2, fileUrl); from the fileupload VF page but it is kicking an error that I still need to investigate. I also noticed that the when adding multiple images, the IFrame is caching the previous content so for now I have added a reset button.

Open up the FileUpload page and comment out the JS line parent.SetUrl( fileUrl ) ;. Next we are going to add a reset button to clear the form.


 


    
    
    
        
    
    
    
        
        
    



That's it. Navigate to your Ckeditor page and test the image uploader.  If you hit the OK button, an alert will pop-up letting you know that the URL value for the image was not received. Just ignore and hit the browse server button to select your image.

I will post an update as soon as I get the issue resolved. Along with passing back the URL, I think you should be able to use an IFrame element within the upload dialog instead of the html element. The benefit I believe is that you can handle the cache and refresh issue within the dialog code instead of using a reset button.

Last thing I would suggest is that you modify the CKEditor config.js to customize the toolbar removing items that are not needed.

Sunday, February 12, 2012

Customize CKEditor on Force.com

While building a Blog application within Force.com, I ran into an issue with the default Rich Text editor. How do Authors browse and add images? So I did what any other developer does, I went to Google to find out if anyone else has posted a solution.  Back in the day when FORTRAN was a required course for engineering students I had a professor who made a comment that has stuck with me for over 20 years. He said “He said a good programmer will never assume he is the first to run into a particular issue. Use the resources you have at your disposal to find out if a solution already exists “. Of course I am paraphrasing, but I think you get the gist of it. 

Anyway, enough reminiscing, I began my search and low and behold I found an article with some sample code posted on how to achieve file uploading and browsing using FCKEditor(Link). Downloaded the code and sure enough, with a few tweaks I was able to browse existing documents within our Salesforce environment and upload new images from my computer.  After a few days of testing I noticed issues with FCK while using different browsers(Paste from Word in IE and so on). This led me down the path of abandoning the older FCK for the latest version of CKEditor.  So first thing I had to do is figure out how to get at the full functionality of CK within my Visual Force page and I came across a blog post on Mac’sCloud where he discusses replacing the default Rich Text control with a customizable version of CKEditor. Pretty straightforward and easy to implement. So now we have access to all the features of CKEditor, next step is to connect up the file browsing and file uploading functionality from the FCKEditor we had originally gotten to work.

So lets get started.

Step 1:
First lets install the package from Appiphony into our developer account located here: Install Link. This will install the SiteBrowser and FileUpload VF pages and corresponding Apex class files, along with a Document Utility Apex class and a couple of static resources that we are not going to use since we are going to modify the code to work with CKEditor.
Step 2:
Next we are going to download the latest zip version of CKEditor http://ckeditor.com/ (Was currently 3.6.2 at the time of this post.). Go ahead and unzip the contents onto your local drive and navigate to the ckeditor folder. At this point lets go ahead and zip the contents and then upload as a new static resource within our force.com site. While inside the ckeditor folder select all the files and directors and choose send to compressed(zipped) folder from within Windows or you can use what ever zip application you normally  use and then rename the file ckeditor.zip. From within your developer account navigate to setup/develop/static resources and click the new button.

Enter ckeditor for the Name and then click browse and select the zip file we just created(ckedtor.zip). Switch the Cache control drop down from private to public and click save.

Step 3:
Now lets create a Visual Force page and test verify that the CKEditor displays properly. I have created a test Object and added a New Rich Text field to the object for the purposes of this demo, but you can use what ever object and Rich Text field you like. From the develop menu, select pages and create a new Visual Force page(I called mine ckeditor for example). Now go in and edit the VF page adding script references to the CKEditor static resource and the JQuery library. Within the apex form tags we are going to add an input text area and set the style class to ckeditor(we are going to change this later) and set richtext to false. Your final page should look similar to this except for the standard controller and inputtext value.


Go ahead and save your page modifications and navigate to the page /apex/ckeditor to see if what we have. Hey look at that now we have the full CK toolbar. All this is detailed out in Mac Anderson's blog linked earlier in the article.


OK, so before anyone starts posting comments like "I already now how to do this but it still won't let me browse my images or upload anything." Just hold tight, we are getting there. If you click on the image icon you should see a pop up that looks like this which is missing the browse button along with the upload tab.

Step 4: Connecting up the SiteFileBrowser.
After you have confirmed that the CKeditor is working, lets go ahead and connect up the SiteFileBrowser Visual Force Page that we installed with the Appiphony package. First we are going to add a bit of JS code to the VF page and set the configuration options for CKEditor for the filebrowserBrowseURL and filebrowserImageBrowseURL pointing them to the SiteFileBrowser VF page.


Because of differences between the old FCKeditor and CKEditor we need to make a modification to the SiteFileBrowser page. Open up the SFB page in edit mode and modify the line within the SelectFile JS function from "window.opener.SetURL(fileURL);" to read "window.opener.CKEDITOR.tools.callFunction(2, fileUrl);". This mod is needed to allow the file browser page to pass back the URL to the CK Image Dialog. We also need to remove the styleClass="ckeditor" from the inputtextarea tag, if not the page will throw a JS error attempting to initialize the editor instance twice.

Go ahead and save the modification and now lets go ahead and navigate back to our VF page. Now when you click on the image icon you should see a "Browse Server" button next to the URL field on the image info Dialog screen.

Hey look at that. Click the button and it should open up a VF page allowing you to search the document directories and select an existing image(You need to check the externally available image check box for them to appear in the list). Click on an image and the window should close and populate the URL field in the above dialog. Select the green OK button and there you go, now able to browse and select existing images.

Step 5: Adding a save button.

On your VF page we need to add a save button as well as some Javascript to get the editor contents.

 

Because there are a quite a few modifications needed to CKEditor to configure the file upload functionality. I am going to cover those in the next post. Stay Tuned.