Why and how to create Microsoft Office Minibar with jQuery and CSS3

May 23, 2010

Although many will argue that Microsoft products are an example of a good design, Minibar was one of design refreshments that came out with the Office 2007. It is a variation of a toolbar that exposes context-related functionality. In case of MS Word, context is a text selection. Since Minibar always pops up near the mouse pointer it enables users to quickly perform actions related to a selection.

Check out demo

So how it works? When user makes a selection in input field Minibar pops up, semi-transparent, above the selection. When user hovers the Minibar it fades out. It disappears when user clicks anywhere in the input field or performs an action by clicking on a Minibar button.

Quite simple Minibar will be shown in this tutorial – it has only bold, underline, italic, and link buttons.

<textarea id="description" rows="8" cols="50"></textarea>
<div id="menu">
    <a href="#" id="bold">b</a>
    <a href="#" id="italic">i</a>
    <a href="#" id="underline">u</a>
    <a href="#" id="link">Link</a>
</div>

We need to make Minibar semi-transparent initially, and solid-color on hover.

#menu {padding:5px; background-color:#f5f5f5;
       background-color:rgba(245, 245, 245, 0.6);
       display:none; position:absolute; top:0px; left:0px; overflow:hidden;
       border:solid 1px #929292; border-radius:3px; -moz-border-radius:3px;
       -webit-border-radius:3px; box-shadow: 5px 5px 5px #888;
       -moz-box-shadow: 1px 1px 3px #555; -webkit-box-shadow: 5px 5px 5px #888;}
#menu:hover {background-color:rgba(245, 245, 245, 1);}

Fade it in and out

To be able to control Minibar position we will need to track the mouse position and use x an y coordinate to set top and left properties of its container. To show Minibar upon selection we will use .select() event, where its container will be faded in at the specific location. We also need to handle .mousedown() event in order to fade the Minibar out when user click somewhere else.

$(document).ready(function() {
    var mouseX = 0;
    var mouseY = 0;

    $("#description").mousemove(function(e) {
        // track mouse position
        mouseX = e.pageX;
        mouseY = e.pageY;
    });
    
    // Fade out the menu on any click
    $("#description").mousedown(function() {
        $("#menu").fadeOut("1000");
    });

    $("#description").select(function() {
        // get the mouse position an show the menu
        $("#menu").css("top", mouseY - 30)
            .css("left", mouseX + 10).fadeIn("1000");
    });
});

Handling clicks

Now when we know how to handle fading in and out, we can add some functionality. If we want to make a selection bold, we can wrap it with <strong> and </strong> tags (of course, it can be done with span element and some CSS but for the purpose of this tutorial I will wrap selection with tags).

function wrapText(startText, endText){
    // Get the text before the selection
    var before = $("#description").val().substring(0, $("#description").caret().start);
    
    // Get the text after the selection
    var after = $("#description").val().substring($("#description").caret().end, $("#description").val().length);
    
    // merge text before the selection, a selection wrapped with inserted text and a text after the selection
    $("#description").val(before + startText + $("#description").caret().text + endText + after);
}

This function, which relies on jCaret plugin wraps the selection with tags and merge it with text before and after the selection. Quite simple, when you have useful plugin such as jCaret. We only need to handle click events for each Minibar button.

$("#bold").click(function() {
    wrapText("<strong>", "</strong>");
    $("#menu").fadeOut("1000");
});

$("#italic").click(function() {
    wrapText("<em>", "</em>");
    $("#menu").fadeOut("1000");
});

$("#underline").click(function() {
    wrapText("<u>", "</u>");
    $("#menu").fadeOut("1000");
});

$("#link").click(function() {
    var url = prompt("Enter URL", "http://");
    if (url != null)
        wrapText("<a href='" + url + "'>", "</a>");
    $("#menu").fadeOut("1000");
});

Handling click events for bold, italic and underline actions is more than simple. We just call wrapText() function, pass it appropriate start and end tags and fade Minibar out. Handling click for link button is a bit different – we first need to prompt users to enter URL and then pass the URL inside opening tag.

Check out demo

Conclusion

As a regular Word user I am so used to this small toolbar and I am missing it on the web. I would really like to see it as a feature in WYSIWYG editors such as TinyMCE. It can also be a part of comment/contact forms. In order to play around with it more I will add it to my comment form as a part of the current blog realign.

Although it works in all major browsers, the code is everything but perfect – it can be optimized and more features can be seen here. Feel free to play with it and if you find any bug, please drop me a line.

Let's discuss this on twitter.

53 Comments

  • Diogo (May 24, 2010)

    One of the most useful tips/posts ever! :D
    This would be great if implemented in forums, blogs, etc

  • MauxWebmaster (May 24, 2010)

    Great post!
    Incredible!
    Very useful!

  • Mike Stokes (May 24, 2010)

    Janko – I love it! It’s so much less obtrusive than a toolbar that is always up. It makes for a much cleaner writing space which I really like as it keeps the creativity focused on what’s important… which for an easily distracted person like me is important :)

  • Saurabh Shah (May 24, 2010)

    This is an amazing tutorial. For sure very handly to use it. Thanks for sharing it.

  • Ahmad Alfy (May 24, 2010)

    Great concept! Would be great if implemented on WYSIWYG editors like TinyMCE!
    Just one note, I think you should replace <b> and <i> with <strong> and <em>!
    I am sure you’re already aware of this :)

  • Janko (May 24, 2010)

    Thanks Ahmad, fixed!

  • Manmohanjit Singh (May 24, 2010)

    Good stuff. Nice job with the CSS3 :)

  • Janko (May 24, 2010)

    Yeah, it’s a nice tool to have, I don’t know why it isn’t supported by wysiwyg editors so far.

  • Jonatan Lundin (May 24, 2010)

    Really interesting idea. Having a "minibar" together with a contentEditable based WYSIWYG- or WYSIWYM-editor would make front end/inline editing of rich content work like a charm! No more pop-ups or clunky editors appearing out of nowhere when you edit content.

    This is definitely something I’ll consider adding to the road map for future versions of WYMeditor.

  • amantur (May 24, 2010)

    this is amazing!

  • sivaranjan (May 24, 2010)

    Your website is incredibly beautiful and useful. I have taken liberty to add this article to my CSS aggregator site. I hope you wont mind that.

  • sojan (May 24, 2010)

    reallyy a great post :)

  • Brian Boatright (May 24, 2010)

    This is a great article and demo. Thanks!

  • wespai (May 25, 2010)

    nice plugin

  • Scott Corgan (May 25, 2010)

    Ohh, put it in WordPress!!

  • enam (May 25, 2010)

    very nice post. Thanks a lot.

  • Marco (May 25, 2010)

    Well done Janko, another great example of an application (part) ported to the web. Although I don’t like/use the minibar at all in Word, I know other people might like it.

    Keep up the great work mate!

  • Arun Prasad (May 25, 2010)

    Wow! I really love jQuery and css3. Great post Janko. I enjoyed reading it. I’m going to implement this in an application that I’m working with.

    Thank you so much for sharing this.

  • Webstandard-Blog (May 25, 2010)

    Awesome Janko, very nice solution! Thx for sharing it!

  • Pau Codina (May 25, 2010)

    Wow!! very useful and creative!

  • Barbara Laird (May 25, 2010)

    Nice! I think I’ll add it to my WordPress comment form.

  • Auré (May 26, 2010)

    Waho… great :)
    I will try to add this to my blog comment form.
    Thanks for sharing dude ;)

  • Janko (May 26, 2010)

    Thanks Auré! Btw, you have really fantastic site.

  • Janko (May 26, 2010)

    I’m glad you like it. It would be really helpful to have it while writing articles :)

  • Janko (May 26, 2010)

    WYMeditor looks nice, it would be good to see how would minibar work with it.

  • Janko (May 26, 2010)

    Anytime :)

  • Auré (May 26, 2010)

    Thanks a lot I appreciate the compliment dude :) (it’s not the definitive version yet I’m optimizing again and again)

  • Bubu (May 26, 2010)

    Hi all.

    Great job Janko ! Very usefull !
    It could be really awsome to have the color gestion (texts and text-backgrounds) ! lol :)

    Bye, cool !

  • Bubu (May 26, 2010)

    I just wanted to add for those who would insert your plugin into a forum, that they have to take care of the real HTML tags you decided to use because hackers could be tempted to write some bad codes you’d insert in a database for example and which would be executed later when you load it orsome other bad things …
    That why all forum use [quote] [bold] etc etc because you don’t have to worry about that. When you read your database, you just use a "strtr()" or "preg_replace()" and that’s all ;)

    (sorry for my english :p)

  • Kevin (May 28, 2010)

    IE6 has issues with demo (just transparency) needs a background color it seems for ie6. Other than that this rocks

  • SJL Web Design (May 28, 2010)

    Great post and code, this is really useful!!

    Thanks.

  • Bernardo (May 28, 2010)

    just beautiful!!!

    Txs.

  • Andy (May 28, 2010)

    Don’t you mean:
    "Although many will argue that Microsoft products *aren’t* an example of good design…"

    ?

  • Mark Freeman (May 28, 2010)

    This would be great for wikis too. And the comment input field of blog pages like this one. :-)

  • SyntaX (May 28, 2010)

    How can I install that in WordPress? Pls. Help!

  • Janko (May 28, 2010)

    Wikis are exactly the types of site where this can be useful, inline edits as well.

  • Janko (May 28, 2010)

    I don’t test my work in IE6 anymore, I don’t even know how my site ugly is in ie6 ;)

  • Janko (May 28, 2010)

    Exactly. I missed that.

  • Theo (May 31, 2010)

    Great idea and article, very useful and well written tutorial. Thanks for sharing!

  • Mike Helton (May 31, 2010)

    I like the idea.

    What I really like is more writing and viewing space.

    Is this available for using in wordpress or a platform similar to that?

    Good post,
    Mike

  • Igor (June 20, 2010)

    Check this approach – http://mini.squiz.net/features/inline-editing
    Way cooler than anything else.

  • Diego (June 23, 2010)

    Nice idea, the only issue is that CSS should be tweaked a little, as it doesn’t work properly on IE. The cause is the ":hover", which, on IE, is supported only on <a> elements.

  • AIK (July 26, 2010)

    Very nice article, UI concepts, code. The only issue: DON’T use HTML as your source data. To see why: in your demo, try to enter <form> … some hacking stuff, like <input type=submit value=submit name=submit> … </form> and then change some arbitrary tag to bold, for example.

    This issue is common for all WYSIWYG HTML editors. A nice solution: use a different mark-up (e.g., Textile).

  • Azeem Michael (September 28, 2010)

    nice work. thanks!

  • Chris Wheeler (October 9, 2010)

    This is one of the best I have seen from you Janko. Keep up the good work and feed us some more quick!

  • Jeff (October 12, 2010)

    Thanks for this. I found it through a link from Smashing Magazine and it’s perfect for what I need.

    Anybody have any thoughts on how to implement this for MULTIPLE text boxes on the page without having to duplicate a lot of code?

  • Edgar (October 13, 2010)

    That’s a great article,
    i just want to know if there is a way to make an undo to any change made with this minibar.

    Regards,

  • Scott Richardson (October 14, 2010)

    Any reason why when I select text in my form textarea, the popup tools appear too far to the right? Almost as if it’s not tracking the mouse coordinates properly?

  • Janko (October 14, 2010)

    Hey Scott, which browser/OS you use? Seems to be working fine in browsers I tested, but there’s always a room for mistake :)

  • Scott Richardson (October 15, 2010)

    OK so it turns out that if your form elements are inside a div that has relative positioning in it, it breaks the popup positioning. Any way to fix this without putting the #menu outside the relative div?

    Scott

  • Adam (October 23, 2010)

    This is a really great article Janko, thanks for sharing this and thanks for the code this will come in very useful!

  • matt (November 18, 2010)

    nice work, just stinks that when you re-highlight your text, you cannot remove the styles applied.

  • Philipp (November 19, 2010)

    to remove styles you could add an extra button with an extra function, something like this

    $("#button").click(function(){
    var markup = $("#text").val();
    var markup = markup.replace(/<\/?[^>]+(>|$)/g, "");
    $("#text").val(markup);
    $("#preview").val(markup);
    }

    this function removes all html elements

    another problem are linebreaks:
    make some breaks in the textfield and mark a word after the linebreaks and try to edit it, in firefox everything is great but in ie it isnt, its counting the wrong number of letters before and after the marked word

    i wonder if there is a better solution than counting the linebreaks and edit the selection