您的位置:首页 > 移动开发 > IOS开发

Integrate the CKEditor as html editor into iOS application

2012-07-28 14:25 615 查看
In short, it is very easy to integrate the CKEditor into the iOS application and make it work for you.  In this document, I will introduce:
how to embed CKEditor into your iOS application, how to customize the toolbar icons of the CKEditor, how to set html content to CKEditor and how to get its html content, how to resize CKEditor frame in fly and how to disable the default inputAccessoryView
of UIWebView which annoys the user with the default toolbar with "Previous" and "Next" buttons.  

 
Here is my screenshot on the CKEditor on my iOS application

 


Here are my steps on how to do it.

 
1.  Please download the latest version of the CKEditor.  What the version I used is CKEditor_3.6.4 from the url: http://download.cksource.com/CKEditor/CKEditor/CKEditor%203.6.4/ckeditor_3.6.4.zip  

2. Add the CKEditor source files into your project. 

In my project Libraries group, I create a new group "CKEditor" and then right click on this group and select "Add Files to 'myproject' ", in the file browser dialog, I choose the ckeditor_3.6.4 folder to involve all the files into my project.

 
After added source files into the project, please make sure all the js files are moved into Copy Bundle Resources section in Build Phases to avoid the
[WARN]warning: no rule to process file '$(PROJECT_DIR)/EndPlay/ckeditor_3.6.4/ckeditor/ckeditor_basic.js' of type sourcecode.javascript for architecture i386
 
Here are my steps to do:
In the Project Navigator, click the Project  to show the TARGETS item in the right side view.  Click the your project name in the TARGETS, then click the Build Phases tab.  In the down list view of Compile Sources, please drag and drop all the
js files into the Copy Bundle Resources section.
 

3.  Refine or create a html file to embed CKEditor into html body, and customize the toolbar icons of CKEditor.

 In my application, to speed up, I just copy and rename the readonly.html to "ckeditorIPad.html" and "ckeditorIPhone.html".   And changed the default text in editor as below in these html files:

<textarea
id="editor1"name="editor1"cols="80"rows="10">{*CKEditor
HTML BODY*}</textarea>
 
This change will be easy for me to fill the user text into editor later. 

 
Customize the toolbar to fit for your use and organize the position of toolbar differently for iPhone and iPad because the screen size different, that is why I have two separate html files.

To customize the toolbar, the key is to init  the icon set in the CKEDITOR.config.  such as I initialized a simple icon set:
    CKEDITOR.config.toolbar_Abstract =
        [ [
'Source', '-',
'FontSize', '-',
'TextColor', 'BGColor',
'-', 'Bold',
'Italic', 'Underline',
'-', 'PasteText',
'-', 'Subscript','Superscript',
'-', 'JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock',
'-', 'Undo',
'Redo', '-',
'Link', 'Unlink' ] ];
 
When initialized the CKEditor instance, we can user this icon set with the keyword 'Abstract':
                
var editor1 = CKEDITOR.replace(
'editor1', {
                                              filebrowseBrowseUrl:null,
                                              filebrowserUploadUrl:null,
                                              height:'300px',
                                               width:'100%',
                                              toolbar:'Abstract',
                                              resize_enabled:true
                                              } );
 
Here is the example code of my customized html file:
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!--
Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or
http://ckeditor.com/license
-->
<html
xmlns="http://www.w3.org/1999/xhtml">
<head>
   
<title>Read-only State — CKEditor Sample</title>
   
<meta content="text/html; charset=utf-8"http-equiv="content-type"
/>
   
<script type="text/javascript"src="ckeditor.js"></script>
   
<script src="sample.js"type="text/javascript"></script>
   
<link href="sample.css"rel="stylesheet"type="text/css"
/>
   
<script type="text/javascript">
   
//<![CDATA[
 
var editor;
    CKEDITOR.config.toolbar_Abstract =
        [
         [
'Source', '-',
'FontSize', '-',
'TextColor', 'BGColor',
'-', 'Bold',
'Italic', 'Underline',
'-', 'PasteText',
'-', 'Subscript','Superscript',
'-', 'JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock',
'-', 'Undo',
'Redo', '-',
'Link', 'Unlink' ]
         ];
// The instanceReady event is fired, when an instance of CKEditor has finished
// its initialization.
CKEDITOR.on(
'instanceReady', function( ev )
    {
      editor = ev.editor;
 
     
// Show this "on" button.
      document.getElementById(
'readOnlyOn' ).style.display = '';
 
     
// Event fired when the readOnly property changes.
      editor.on(
'readOnly', function()
        {
           document.getElementById(
'readOnlyOn' ).style.display =
this.readOnly ? 'none' :
'';
           document.getElementById(
'readOnlyOff' ).style.display =
this.readOnly ? '' :
'none';
        });
    });
 
function toggleReadOnly( isReadOnly )
{
   
// Change the read-only state of the editor.
   
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.editor.html#setReadOnly
    editor.setReadOnly( isReadOnly );
}
 
   
//]]>
   
</script>
 
</head>
<body>
   
<!-- This <div> holds alert messages to be display in the sample page. -->
   
<div id="alerts">
     
<noscript>
       
<p>
          
<strong>CKEditor requires JavaScript to run</strong>. In a browser with no JavaScript
           support, like yours, you should still see the contents (HTML data) and you should
           be able to edit it normally, without a rich editor interface.
       
</p>
     
</noscript>
   
</div>
   
<form action="sample_posteddata.php"method="post">
     
<p>
       
<textarea id="editor1"name="editor1"cols="80"rows="10">{*CKEditor
HTML BODY*}</textarea>
       
           
<script type="text/javascript">
           
//<![CDATA[
       
// Replace the <textarea id="editor1"> with an CKEditor instance.
               
var editor1 = CKEDITOR.replace( 'editor1', {
                                              filebrowseBrowseUrl:null,
                                              filebrowserUploadUrl:null,
                                              height:'300px',
                                               width:'100%',
                                              toolbar:'Abstract',
                                              resize_enabled:true
                                              } );
           
//]]>
           
</script>
     
</p>
   
</form>
 
</body>
</html>
        
 
Later, we will use UIWebview control to load this html file to show the CKEditor.

 

4.  In iOS code, init a UIWebView htmlEditorView to load the CKEditor.

 
-(void) initHtmlEditorView:(NSString*) htmlText withBounds:(CGRect) bounds
{
   
if (self.htmlEditorView ==
nil)
    {
       
self.htmlEditorView = [[UIWebView
alloc] initWithFrame:bounds];
       
self.htmlEditorView.delegate =
self;
       
self.htmlEditorView.autoresizesSubviews =
YES;
 
       
self.htmlEditorView.autoresizingMask =
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
                                           

        [[self
egoTextView] addSubview:self.htmlEditorView];
    }
else
    {
        [self.htmlEditorView
setFrame:bounds];
    }
   
   
NSString* path = [[NSBundle
mainBundle] bundlePath];
   
NSURL* baseURL = [NSURL
fileURLWithPath:path];
   
   
NSString* filePath = nil;
   
   
if (isPad)
    {
        filePath = [[NSBundle
mainBundle] pathForResource:@"ckeditoriPad"
ofType:@"html"];
    }
else
    {
        filePath = [[NSBundle
mainBundle] pathForResource:@"ckeditoriPhone"
ofType:@"html"];
    }
   
   
NSMutableString *templateString = [NSMutableString
stringWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding 
error:nil];
 
    // Fill in the user html text into the CKEditor body.
   
if (htmlText ==
nil || [NSNull
null] == (NSNull*)
htmlText || [htmlText
isEqualToString: @""]))
    {
        [templateString
replaceOccurrencesOfString:@"{*CKEditor HTML BODY*}"
withString:@""
options: NSLiteralSearch
range:NSMakeRange(0,         [templateString
length] - 1)];

    }else
    {
        [templateString
replaceOccurrencesOfString:@"{*CKEditor HTML BODY*}"
withString:htmlText
options: NSLiteralSearch
range:NSMakeRange(0, [templateString
length] - 1)]; 

    }
 
 
   
NSData* htmlData = [templateString dataUsingEncoding:
NSUTF8StringEncoding];
   
   
if (htmlData)
    {
        [self.htmlEditorView
loadData:htmlData
MIMEType:@"text/html"
textEncodingName:@"UTF-8"
baseURL:baseURL];
    }
}
 

5.  Then we need consider how to resize the CKEditor to fit for the htmlEditorView, and how to get the html content from CKEditor.

 
In my application, I have a toolbar view with "Done" button set to the inputAccessoryView of the UIWebView (htmlEditorView).  So in the DoneAction, I just call below statement to get the html content from CKEditor.  "editor.getData()" is the
JS API call.  editor is the global variable of my CKEditor, which is defined in the html file (ckeditoriPhone.html, or ckeditoriPad.html).
 
NSString *html = [self.htmlEditorView
stringByEvaluatingJavaScriptFromString:@"editor.getData();"];
 
To resize the CKEditor window in fly, I implement below method to make its height always fit for the height of its parent view.

-(void) adjustHtmlEditorSize
{
   
NSInteger height = (int)(self.htmlEditorView.frame.size.height);
   
if (height < 320) height =
320;
   
NSString* script = [NSString
stringWithFormat:@"editor.resize( \'100%@\', \'%d\' );",@"%", height];
    [self.htmlEditorView
stringByEvaluatingJavaScriptFromString:script];
}
 
Also you might need consider to refine the sample.css file to change the margin size between the CKEditor and UIWebView.  In my code, I just changed the body's margin and padding as below:
 
body {
   
margin: 0px
0px
0px 0px;
   
padding: 0px
5px
0px 0px;
}
 
p, blockquote, address, form,
pre, dl, h1.samples, h2.samples {
   
margin-bottom:15px;
   
margin-right:5px;
}
 
 

6.  The last thing you might meet as well is the default inputAccessoryView is shown up when you have focus on the CKEditor.

It annoys me to show the toolbar with "Previous" and "Next" buttons, which is nothing related to CKEditor.  So disable it or change its default view to customized view which depends on your need.   



Here is a good document on how to disable the default inputAccessoryView of UIWebView:  http://bjhomer.blogspot.com/2012/03/how-to-hide-inputaccessoryview-of.html
In my code, I referenced BJ's solution to disable the inputAccessoryView by calling below code in
webViewDidFinishLoad:
- (void) webViewDidFinishLoad:(UIWebView *)webView
{
    [self
adjustHtmlEditorSize];
   
if (![self.htmlEditorView
isHidesInputAccessoryView])
    {
        [self.htmlEditorView
hidesInputAccessoryView:YES];
    }
}
 
// Here is the code on the category of UIWebView.

@interface UIWebView (HideInputAccessoryView)
 -(BOOL) isHidesInputAccessoryView;
 -(void) hidesInputAccessoryView:(BOOL)value;
@end
 
 
@implementation UIWebView (HideInputAccessoryView)
 
static
const char *
const hackishFixClassName =
"UIWebBrowserViewMinusAccessoryView";
static
Class hackishFixClass =
Nil;
 
- (UIView *) hackishlyFoundBrowserView {
   
UIScrollView *scrollView = self.scrollView;
   
   
UIView *browserView = nil;
   
for (UIView *subview
in scrollView.subviews) {
       
if ([NSStringFromClass([subview
class]) hasPrefix:@"UIWebBrowserView"]) {
            browserView = subview;
           
break;
        }
    }
   
return browserView;
}
 
- (id)methodReturningNil {
   
return nil;
}
 
- (void)ensureHackishSubclassExistsOfBrowserViewClass:(Class)browserViewClass {
   
if (!hackishFixClass) {
       
id newClass = objc_allocateClassPair(browserViewClass,
hackishFixClassName,
0);
       
IMP nilImp = [self
methodForSelector:@selector(methodReturningNil)];
       
class_addMethod(newClass, @selector(inputAccessoryView), nilImp,
"@@:");
       
objc_registerClassPair(newClass);
       
       
hackishFixClass = newClass;
    }
}
 
- (BOOL) isHidesInputAccessoryView {
   
UIView *browserView = [self
hackishlyFoundBrowserView];
   
return [browserView class] ==
hackishFixClass;
}
 
- (void) hidesInputAccessoryView:(BOOL)value {
   
UIView *browserView = [self
hackishlyFoundBrowserView];
   
if (browserView == nil) {
       
return;
    }
    [self
ensureHackishSubclassExistsOfBrowserViewClass:[browserView
class]];
   
   
if (value) {
       
object_setClass(browserView, hackishFixClass);
    }
   
else {
       
Class normalClass = objc_getClass("UIWebBrowserView");
       
object_setClass(browserView, normalClass);
    }
    [browserView
reloadInputViews];
}
 
@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐