Internet & Web • iOS • 24:29
New in iOS 5, rich text editing is now available for web content. Get up to speed on the technologies behind rich text editing on the Web, and see how to leverage new features such as keyboard customization. Learn how to build a rich text editor that works great in Safari, and in native applications that use UIWebView.
Speaker: Justin Garcia
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Good morning. I'm Justin Garcia, and I work on the iOS keyboards and text team. And before we get started, I'd like to say thank you. I've had a chance to meet some of you this week, and I've seen some of the amazing things that you guys have been working on, and it's been both inspiring and humbling. So again, thank you. So what are we talking about today? Well, today's about four things. First, today's about getting rid of markup.
No, not for you, for your users. I went to Blogger.com a few days ago and used their rich text editing toolbar. And when you use their rich text editing toolbar, it inserts tags. It's 2011, and end users are still seeing tags. Wikipedia does this too. So today is about getting rid of markup for users. We shouldn't be subjecting people to this.
Well, what are we going to do instead? Well, we're going to build a WYSIWYG editor. But what is it that users want to see, and what is it that users want to edit? What kind of text? Well, they want to edit the kind of text that they see in print books, the kind of text that they read. So topography is important.
Number three, you saw it on Monday in the demo, and you want it in your app. Talking about rich text editing, but we're talking about more than just bold, italic, and underline. We're talking about any arbitrary DOM operation or CSS text effect that you can dream up in your app.
And four, we're talking about a desktop caliber experience. What does that mean? Well, iMovie for iPad, the new Photos app for iPad and iPhone, where you can edit your photos. These are desktop caliber experiences for the iPad. That's what we want to build today. So how are we going to do this? Well, first let's look at some examples from the desktop. These are desktop text editors, and this is what we want to strive towards.
This is Google Docs running in Safari. This is a full-fledged, powerful text editor that coincidentally uses the same technology that we're talking about here today. It uses WebKit's editability features. On top of that, Sandbox by Corellia. And this is a website and blogging tool. Both of these are great examples.
So what's the feature set that we want to have? Well, it all starts, of course, with beautiful typography. We're going to have multi-styled text. Multiple columns, custom backgrounds, anything that you're used to building into your page layouts, we're going to have in our editor. transparency, draggable images, and of course, HTML export. So here's what we're going to build. This is a picture of the native app. And we'll talk about that in the second part of the presentation. The first part will be about building a web application.
So what are the alternatives? What can we use besides WebKit before we get started? Well, Mobile Notes uses a UI text view. This is one option you have on iOS, but it's not very powerful. You can have style text, but you can only have a single style. Of course, it doesn't support HTML, JavaScript, CSS, so the page layouts are very basic. And there's no HTML export.
Second option is to build your own custom text layout engine on iOS that implements the UI text input protocol. I've seen many developers do this using Cortex. But as web developers, you want to leverage What you know to build beautiful page layouts for your customers, instead of learning core text.
So this is what we're going to do. We're going to use the new features in iOS, the new WebKit editing features in iOS, to build this editor. First, we're going to build a web application. And then second, we're going to embed that web application into a UIWebView to build a native app. And both of these are standalone options. So before we dive into the code of the web app, Let me give you a quick demo.
So here it is running in mobile Safari. Two column layout. I place the cursor up in the title, and it has single line enforcement. So I'm hitting Return, and it's just like a single line text field on iOS for those iOS developers out there. And right now, there's only a single control in the toolbar for bold. But we're going to add more in just a moment. Select some text here. All my edits are saved automatically as I enter characters.
[Transcript missing]
So the new content editable DOM attribute in iOS 5, you can add to any element in your document to make it editable. And we'll see that in a moment. You can position the cursor programmatically with window.getSelection. to guide the user through the document. You're gonna use the new exec command on document to perform arbitrary DOM operations in CSS text effects. You're going to validate editing UI with query command enabled.
and you're gonna have print caliber topography with two new CSS attributes, excuse me, two new CSS properties in iOS 5. You can validate and format input using JavaScript event handlers. And we're going to save user edits on key up in my demo using an XML HTTP request. So content editable, what does this look like? It's really simple. You can either add it to the document element to make everything editable, or you can create editable pockets by adding it individually to elements.
We're going to position the selection programmatically to guide the user through the document using the window.getSelection method. Here I am setting it in the editable div that I just created. Here's my toolbar with two extra buttons. Create link and highlight. We'll talk about how to implement those in a moment. And these all use exec command. So here's Bold being implemented using exec command. It's pretty simple. Here's Create Link. And all these exec commands are undoable.
is going to point you to documentation that lists all the exact commands at the end of the presentation. So validating UI. I want a bold button that looks depressed when you're in bold text, and is undepressed when you're not in bold text. How do we do that? Well, we're gonna use query command enabled, and pass it the editing operation that we're interested in.
So I talked about improved typography features in iOS 5. Here's a text example without ligatures and kerning. You can see that the i, the dot over the i, runs into the top of the f. We apply this new CSS property. We get some tightening. We get a ligature for FI. And that's really simple. You just use text rendering optimized legibility.
So what's wrong with this? Well, this is justified text. And in a print book, you'd have hyphenation to improve the spacing between the words and that second line. And we can get that in WebKit using the new CSS auto-hyphenation for English. And here's the finished result. And this is just WebKit hyphens auto. So you may have seen drop caps in the demo. This isn't new to iOS 5. But you might be interested in how I implemented that. You just use the first letters, CSS pseudo element.
So how did I do that single line validation? I kept the title and the date from accepting new lines. I'll just check to see if the element is a title or a date. I verified that the user isn't inserting a new line. It's pretty simple. called that element, or excuse me, I called that function on every key down.
Now you noticed that I reloaded the page and the user edits were saved. How did I do that? Well, there are a couple different ways of doing this. I chose to use an XML HTTP request, and I send the entire source of the document to my PHP file.
And this works pretty well, but You'd like to be able to do this when the user doesn't have an internet connection. You'd like to be able to do this offline. So you should go and check out Alexei's talk this afternoon on HTML5 offline storage if you're interested. So let's dive into the code. So this was my original. I'm going to open up my uneditable document. to quickly add contenteditable equals true to the elements that I'm interested in making editable.
Let me just reload the page. And here we go. Let's add two more editing controls to the toolbar. Let's add Create Link and Highlight. Nice. So here we have two more editing operations. Let's add the exec commands for those. Create link and highlight. Now you've noticed, you may have noticed, that highlight doesn't use exec command highlight. There's no such exec command for highlight. So I've used italic.
And then I'll go into my CSS and change the default style for italic. Let's reload the page. Nice. Let's select San Francisco. And let's highlight. There you go, you get a nice orange highlight. So let's do single line enforcement. Because you notice that if I hit return, I get a carriage return.
I showed you the code earlier. It just verifies that the inserted character isn't a new line. Reload the page. And I'm hitting return, and it's a single line. And you may have noticed that we have some really dirty looking justified text down here. There's huge spaces between these words, spots, Grimeer, and let's fix this with WebKit hyphens auto.
And let's dismiss the keyboard so it doesn't crash. And there it is. It's all cleaned up. Real nice. So what's next? So I've hand-rolled this editor. I wrote my own JavaScript. But if you don't want to do that, there are two very excellent JavaScript editing libraries with cross-browser support, TinyMCE and CKEditor.
and the authors of these two JavaScript libraries have been excellent contributors to WebKit, our open source WebKit engine. So now we're going to embed this web application into a native app, and get this beautiful native experience with a customized editing call-out bar instead of a JavaScript CSS toolbar. So let's do that.
[Transcript missing]
I'm using the native call-out bar. And here are my three editing operations-- bold, highlight, and create link.
So let's talk about how we did this at a high level. So we leveraged the entire web application. We embed it in a UIWebView. And then we extend the system editing menu instead of using a CSS toolbar. And in your native application, you can use native UI widgets, like sliders, to adjust the font size. A native application is going to let you import photos from a user's device, and images can become draggable.
So embedding the web application into a UIWebView is pretty simple. Here I just grabbed my application bundle. I get the index file that you saw us working on in the web application, and I load it into the UIWebView. So now we're going to extend that system editing menu.
So I build a UI menu item. I give it a bold selector. I add this to an array. And then I add, and then I set UI menu controllers menu items property to that array. What's the code for the bold selector look like? How do we perform document.exec command from a WebView, UIWebView, excuse me? Well, we use string by evaluating JavaScript. We pass it arbitrary JavaScript to execute. And then we've got to validate that bold item. Some fields, for instance, might not accept bold. Here's how you do that.
I talked about UI widgets. Here I am using a slider to adjust the font size. I grab the slider, I get its value. I determine a font size on the range, max font size to min font size. And then I set the font size of the body element, again using string by evaluating JavaScript. So importing photos from a user's device. I've added a button to send the user to their iPhoto library. I insert it with this method, insert image. And I build a div around the image, and then I insert it with insert HTML, the insert HTML exec command.
And then I perform that exec command using string by evaluating JavaScript. Now I call insert image from image picker controller did finish picking media with info. I verify that what the user chose was an image and not a movie. I get the image, I write it to file, and then I insert it with the method that I just showed you.
Now, what about draggable images? So first, we perform touch tracking at the app level. Then we send that touch coordinate to the web application, again using string by evaluating JavaScript. In order to find the DOM location where we want to insert the image, we call caret_range for point. We pass it a coordinate.
Then we created a DOM range to create a selection object so that exec command can be performed. We remove the image from its old location using exec command delete, and then we reinsert it using insert HTML. And all of this is undoable, so the user can undo a drag.
So let's look at some of the native app code. Here I am in my UIWebView subclass. And I've implemented Bold, Highlight, and Create Link, and these all perform exec command operations using string by evaluating JavaScript. Create Link is a little trickier, So it calls an operation that I've implemented in my web application called Create Link.
So here I am validating each menu item, bold, highlight, and create link. So for more information on exec commands, check out Mozilla's documentation. And if you don't find what you're looking for there, or on Apple Developer Forums, email Vicki Murley, our Internet and Web Technologies Evangelist. The text processing that we did today was very basic. If you're interested in learning more, you want to check out Doug Davidson's talk this afternoon at 3:15.
Internationalization is a big topic for a text editor. So you're gonna wanna check out Brent's talk tomorrow at 10. And if you're interested in embedding the web application into a UIWebView to build a native app, you want to check out What's New in Cocoa Touch. That's today at 4:30. So we talked about why you should use WebKit-based rich text editing. You learned how to get started, and how to take the next steps. Thank you.