tags:

views:

576

answers:

3

Using jQuery, how can I enable the live insertion of smart quotes while editing text boxes?

+6  A: 

One option is to use the little known of 'q' element.

foo bar<q>quoted area</q>foo bar

then the user agent will do its best to create the best style quotes.

Kent Fredric
Very cool, but too bad it doesn't work in IE. It will be a long time till it's usable.
Darryl Hein
+2  A: 

Assuming you're talking about trying to replace " and ' with smart quotes automatically: it's not necessarily a good idea. Algorithms to choose the right way for the quotes to face are fragile and can easily be fooled. There is a common formula to do with looking at the character before the quote, which is used by programs such as Office. But they often make mistakes, leaving the text worse off than if one hadn't tried. Sometimes, of course, you don't want smart quotes at all (especially on a site like this where we're talking code).

If it's for your own personal typing convenience you could try installing a keyboard layout that allows smart quotes to be typed directly and explicitly.

That said, if you must, here's some code to start with...

<textarea id="foo" rows="6" cols="40"></textarea>

...

function AutoReplacer(element) {
    // List of replacement rules. Note currently with this simplistic code
    // replacements should be the same length as the original text.
    //
    replacements= [
        [' "', ' \u201C'],
        ['("', ' \u201C'],
        ['"', '\u201D']
    ];

    // Only attempt to use replacer behaviour if we can retain the cursor
    // position. Setting value by default moves the cursor to the end of the
    // input, which is too irritating.
    //
    if (getInputSelection(element)!==null) {
        element.onkeyup= function() {
            value= element.value;
            for (var i= 0; i<replacements.length; i++) {
                value= value.split(replacements[i][0]).join(replacements[i][1]);
            }
            if (value!=element.value) {
                var s= getInputSelection(element);
                element.value= value;
                setInputSelection(element, s);
            }
        };
    }
}

// Cross-browser (as much as possible anyway) cursor positioning
//
function getInputSelection(element) {
    if (element.selectionStart!==window.undefined) {
        return [element.selectionStart, element.selectionEnd];
    } else if (document.selection) {
        var BIG= 1000000;
        var range= document.selection.createRange();
        if (range.moveStart===window.undefined)
            return [0, 0];
        var start= -range.moveStart('character', -BIG);
        var end= -range.moveEnd('character', -BIG);
        return [start-1, end-1];
    } else return null;
}
function setInputSelection(element, s) {
    if (element.selectionStart!==window.undefined) {
        element.selectionStart= s[0];
        element.selectionEnd= s[1];
    } else if (document.selection) {
        var range= element.createTextRange();
        range.collapse(true);
        range.moveEnd('character', s[1]);
        range.moveStart('character', s[0]);
        range.select();
    }
}

new AutoReplacer(document.getElementById('foo'));
bobince
+4  A: 

To build on Kent's answer: you can use the q tags, however, most browsers only use the straight quotes by default, and IE doesn't display any quotes.

This is remedied in IE7+ and other browsers by using CSS. Here's what I put in my stylesheets:

q:before {
    content: "\201c";
}
q:after {
    content: "\201d";
}
q q:before {
    content: "\2018";
}
q q:after {
    content: "\2019";
}

First batch is for curly double quotes, second is for curly single quotes (for when you have nested q tags).

This doesn't work in IE6. My normal solution is to set a colour on the q elements, so they stand out. Part of my "f*ck it, that's good enough" strategy for IE6.

DisgruntledGoat
+1 for the colour and the "fck IE, its good enough". I've used colour before and just forgotten.
Kent Fredric