4

I have searched a lot, but did not find anything useful, so I just ask. The context is Rails 2.3.x, the usual javascript libraries. I would like to reach the following:

  1. I would like to have something similar to <%= text_field_with_auto_complete :recipe, :name %> but on text editors: <%= text_editor_with_auto_complete :recipe, :description, '\w+\:\w+' %>
  2. It should be customizable (best by a reg-expression) when to start auto-complete. So instead of starting for the whole contents, I would like to start on \w+\:\w+ which means: start calling auto-complete when a string is entered that starts with non-space characters followed by a ':' sign which is followed by non-space characters.
  3. The replacement should be done only on the string that matches the reg-expression of course.

Do you know any solution that could be adapted to my needs?

mliebelt
  • 15,345
  • 7
  • 55
  • 92

2 Answers2

3

The answer of abstraktor gave me a good starting point, but there were some missing parts. So I developed an example on github: jquery-autocomplete-inner

Here is the complete source code of the example (no HTML), and some explanation:

$().ready(function() {
// search only, if the regexp matches
var cities = [
    "Amsterdam", "Stuttgart", "Singapore", "Madrid", "Barcelona", "Hamburg",
    "Esslingen", "Berlin", "Frankfurt", "Essingen", "Straßburg", "London",
    "Hannover", "Weil am Rhein", "Tuttlingen", "München", "Marsaille", "Paris",
    "Manchester", "Rome", "Neapel", "New York", "Brasil", "Rio de Janeiro"
];
// Defines for the example the match to take which is any word (with Umlauts!!).
function _leftMatch(string, area) {
    return string.substring(0, area.selectionStart).match(/[\wäöüÄÖÜß]+$/)
}

function _setCursorPosition(area, pos) {
    if (area.setSelectionRange) {
        area.setSelectionRange(pos, pos);
    } else if (area.createTextRange) {
        var range = area.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
    }
}

$("#citites").autocomplete({
    position: { my : "right top", at: "right bottom" },
    source: function(request, response) {
        var str = _leftMatch(request.term, $("#citites")[0]);
        str = (str != null) ? str[0] : "";
        response($.ui.autocomplete.filter(
                cities, str));
    },
    //minLength: 2,  // does have no effect, regexpression is used instead
    focus: function() {
        // prevent value inserted on focus
        return false;
    },
    // Insert the match inside the ui element at the current position by replacing the matching substring
    select: function(event, ui) {
        //alert("completing "+ui.item.value);},
        var m = _leftMatch(this.value, this)[0];
        var beg = this.value.substring(0, this.selectionStart - m.length);
        this.value = beg + ui.item.value + this.value.substring(this.selectionStart, this.value.length);
        var pos = beg.length + ui.item.value.length;
        _setCursorPosition(this, pos);
        return false;
    },
    search:function(event, ui) {
        var m = _leftMatch(this.value, this);
        return (m != null )
    }
});
})
  • First the data of the examples, some cities (mostly German)
  • A helper function to extract the matching substring left from the cursor, named _leftMatch
  • A helper function copied mostly from jQuery Set Cursor Position in Text Area
  • Then in the usage of autocomplete the following points:
    • Search only when the substring (_leftMatch) before the cursor position matches the defined regexpression (in my example /[\wäöüÄÖÜß]+$/ --> all german work characters).
    • Filter the source things by using the request - response variation and filtering there by the substring (as in the other examples of autocomplete with multiple values
    • Replace the matching substring with the selection from the user and ensure that the cursor is positioned right after that.

If you want to take a look, download the zip-file from the GitHup repository and start the local example under examples/cities-local.html.

Community
  • 1
  • 1
mliebelt
  • 15,345
  • 7
  • 55
  • 92
1

What about using jquery ui autocomplete with custom search function. Assuming that your text-area's id is #birds:

// search only, if the regexp matches
$("#birds").autocomplete({
  source: "/birds/search",
  minLength: 2,
  select: function( event, ui ) {alert("completing "+ui.item.value);}
  search:function(){/\W:\w+$/.test($(ui.item.value).val())}
  })

Now you just still have to implement that search on server side...Perhaps you could adapt the search later on, to only transfer the word instead of the whole textarea value...

abstraktor
  • 955
  • 9
  • 20
  • Wow, I will give that a try. I will need some time, and I hope, I can fill the holes for me (does not know enough about JAvaScript). But looks very promising, thank's a lot. – mliebelt Mar 28 '11 at 07:42
  • well, if you want to develop an application, that uses javascript and jquery, you should have done some tutorials with it. Just try out [jquerys tutorial page](http://docs.jquery.com/Tutorials) and you'll see it's no rocket science :) – abstraktor Mar 28 '11 at 14:35
  • I now tried your example, and had some problems with it. The line beginning with select: should end with ',', and I need a first argument (local or remote data) for the call to autocomplete. The I have added arguments event and ui to the function bound to search. But even then I get an error that ui.item is undefined. The minLength seems to work, because when I set a breakpoint inside search, this is only triggered after entering the second character. So I'm stuck now. The path seems the right one, but there is much left for me to do. – mliebelt Apr 01 '11 at 19:38
  • After some time, I found now solutions of all the questions I had: added focus: .. return false; implemented the select function so that the selection is placed at the cursor; found a solution to position the cursor correct. The code looks a lot different now :-) – mliebelt Apr 07 '11 at 15:28