Archive for February, 2009

Feb 27

Inspired by my fellow teammate, Justin Grammens, I’ve decided I should say a little about the F1 Web Challenge I am participating in tomorrow.

The F1 Web Challenge is a charity event where teams of developers and designers are paired with a nonprofit and are given 24 hours to build the nonprofit a website. The catch is that pairings aren’t announced before the start of the event and those 24 hours are consecutive. Crazy? Maybe. Fun? Definitely. Worth it? Absolutely.

Last spring I remember seeing some tweets about the event and I thought it was a really cool idea. Having worked for a nonprofit  myself at one point, I knew that they often lack the personnel, funds, and knowhow to pull off a great website themselves. So when the call went out on the local Ruby user’s mailing list, I jumped at the chance and found a spot on the Ruby.mn team.

I’ve been more than impressed with the people on my team. Within weeks of the team forming, we had 2 sponsors; Github and Tightrope Media Systems. Our sponsors really helped push our team up above the rest. With the funds donated by TRMS, we were able to purchase hosting for our team website, hosting for the nonprofit, and team t-shirts. Github provided us with a repository for our team website and the nonprofit. Thanks to Sam Schroeder for talking to Github and thanks to John Reilly for talking to his boss at TRMS.

I couldn’t let John and Sam be the only ones to step up for the team. I assumed the role of t-shirt designer even though I’d never done any t-shirt design before. With some help from one of last year’s team members and some feedback from the group, I was able to put a design together. I was happy with what I was able to come up with and I’m anxious to see how the finished product turned out. At the very least, we’ll look like a team!

It is my plan to tweet, live blog, and take photos throughout the day and night. I’m hoping to make a few posts here tomorrow. Follow me (@jrmehle) and @webchallenge on Twitter. Watch my Flickr stream for photos. FriendFeed aggregates all of the previously mentioned content sources, so that would be a place to watch too. Who knows, I may end up with Ustream account at some point to live-stream the event too. The festivities kick off at 9AM and will run through 9AM on Sunday.

Feb 13

In Part I of the Wysihat tutorial, I went through some simple examples of how to use Wysihat. This time around, I’m going to go through adding a button that prompts for an image URL and inserts the image into the editor. I’ll show how to use CSS to turn the links Wysihat produces into buttons. DecoyMusic launched version 1.1 in early January with a Wyishat-enabled WYSIWYG editor. I’ve encountered several problems which will close out the second half of this series.

As I mentioned in my first tutorial, there are several examples provided in the Wysihat repository. The ‘link selection’ example (found in the examples/ directory) shows you how to go about allowing the user to add links to a piece of selected text. The user first makes a selection, then hits the link button, and is prompted for the URL. The prompt is a standard Javascript prompt, but the code to send the user value back to the editor is up to us. Wysihat doesn’t provide this out of the box. Take a look at that example again. Here is the meat of it.

    var LinkSelection = {
      promptLinkSelection: function() {
        var node = this.selection.getNode();
        if (node.tagName == 'A') {
          if (confirm("Remove link?"))
            this.execCommand('unlink');
        } else {
          var value = prompt("Enter a URL", "http://www.google.com/");
          if (value)
            this.linkSelection(value);
        }
      },
 
      queryLink: function() {
        var node = this.selection.getNode();
        return node ? node.tagName == 'A' : false;
      }
    }
 
    Event.observe(window, 'load', function() {
      var editor = WysiHat.Editor.attach('content');
      var toolbar = new WysiHat.Toolbar(editor);
 
      Object.extend(editor, LinkSelection);
 
      toolbar.addButton(
        { name: 'link', label: "Link" }, function(editor) {
          editor.promptLinkSelection();
      });
    });

We’re using the pseudo-object-oriented nature of Javascript to cram some functionality into LinkSelection which we later on give to an editor through extension. Examine PromptLinkSelection. Ignoring some of the other stuff that is going on there. What it is doing for us is prompting for a value from the user, and then passing it to the linkSelection function of the editor. The rest of the code should look familiar if you read Part I. It sets up the button and adds it to the toolbar. The one exotic looking line is where the prompt function gets added to the editor. All this does is make it trivial to call the PromptLinkSelection function  from a button event further down.

Realize that there’s not much difference between creating a <a> tag on a page and creating an <img> tag. They both minimally take a URL and that’s it. We’ve just gone over how to add a button that prompts for a link. Thus, it’s not too much of a stretch to figure out how to make a button to insert an image. Why not just add the function to LinkSelection? The reasons are clear. I won’t go over it here, but there is bound to be some common code between these two very similar tasks that could be factored out. It’s also helpful to know that Wysihat provides us with an insertImage function.

    var LinkSelection = {
      promptImageURLSelection: function() {
        var node = this.selection.getNode();
        if (node.tagName == 'A') {
          if (confirm("Remove link?"))
            this.execCommand('unlink');
        } else {
          var value = prompt("Enter a URL", "http://www.example.com/images/my_image.png");
          if (value)
            this.insertImage(value);
        }
      }
  }

I’ve removed the irrelevant parts here. When you boil it down, the only difference between this and the link selection example is you call insertImage instead of linkSelection. You can use this idea to further extend the editor to your needs. One thing I intend to do eventually is create an embed media button like the blogging engine Wordpress has.

In my introduction to Wysihat, I showed off the basic editor. At that time, I mentioned it is possible to style the links as buttons and I would show you how later. Now is that time!

Basic Wysihat Form

Basic Wysihat Form


<div class="editor_toolbar clearfix">
  <a class="button bold" href="#"><span>Bold</span></a>
  <a class="button underline" href="#"><span>Underline</span></a>
  <a class="button italics" href="#"><span>Italic</span></a>
</div>

Take a look at the HTML that is generated for the toolbar. Not surprisingly, the toolbar is a div and has a class of editor_toolbar. Each button has 2 classes: button and it’s name. This allows you to target all buttons with the same style or each button individually.

DecoyMusic.com WYSIWYG Editor

DecoyMusic.com WYSIWYG Editor

The above screenshot is taken from DecoyMusic.com. This is an example of what you can put together with some CSS. That is the exact same markup as I went over. Let’s take a look at the corresponding CSS. I’m only showing the relevant parts for the editor. I’ll let you explore the clearfix technique as well as how I’ve styled the rest of the page on your own. There would also be a style for each button, but here I’ve only shown bold.

.editor_toolbar {
  background-color:#CCCCCC;
  border-left:1px solid #333333;
  border-right:1px solid #6D6D6D;
  border-top:1px solid #6D6D6D;
  margin-right:1px;
  padding:0.3em;
}
 
.editor_toolbar .button {
 height:16px;
 width:16px;
 overflow:hidden;
 text-indent:-100em;
 cursor:pointer;
 float:left;
 margin-right:0.3em;
 vertical-align:bottom;
}
 
.editor_toolbar .button.bold {
  background:#CCCCCC url(/images/icons/bold.gif) no-repeat scroll 0 0;
}

The toolbar itself is basically a solid block with a background color and a border. I’ve given the bottom and right borders a different color from the other sides so that the editor has a little bit of dimension to it. The next style is where most of the magic happens. The width and height are first set. I’ve used 16 by 16 pixel buttons, so I set mine to 16.

The next two rules are key. They shove the link text that Wysihat inserts by default. You can’t control the contents of the links as they are spit out by Wysihat. A CSS trick to hide text like this is to shove it way off the screen. It’s still in the document, but the stylesheet pushes it so far off the screen, you wouldn’t even see it large resolutions. So, set your overflow to hidden and your text-indent to some very large negative number of ems. The rest of the rules simply add a few nice things like spacing out the buttons and giving us a pointer finger cursor when we hover over the buttons. The final piece is to style each button itself. This is where you specify the button image you want to use. It is actually a background image, but combined with all of the other CSS it behaves as a button.

Keep in mind this is only one way of styling your WYSIWYG buttons. You could also leave the text in place and add some kind of background to give the impression of a button. There are also ways of giving the button hover states which provide feedback for your users.

Wysihat is a somewhat immature project (at release 0.2 at the time of writing). As with early adoption of anything there will be some bugs to deal with. Not to say that it is buggy. The project will mature and gain support; it will get better. You can contribute if you’re a javascript developer. I have no doubts by the time it hits 1.0, 37 Signals and the community will have come up with a fine tool. However, the people that use my site have reported some issues. After initially being loaded, the editor is “locked” and will not allow you to delete text. This is apparently only an issue in Firefox 3. If you first add something, even a space, it’s refreshes itself or something and you can use delete. Do not paste any content copied from a Word document and expect it to look anything like what you copied. It won’t and it’s futile to try to correct it within the editor. I also have one person reporting that the editor hangs and stalls when he is editing a large article. I myself witnessed this on a large piece of content containing several images.