This is mostly it :

# Code in controller
@cache('json_feed', time_expire=60)
def json_feed():
    rows = db().select(db.table_name_all.ALL)
    options = []
    for i, row in enumerate(rows):
        options.append({'option': row.field_name, 'id': row.id})
    from gluon.contrib import simplejson
    return simplejson.dumps({'options': options})


def typeahead_widget(field, value, json_feed=json_feed(), **kwargs):
    input_args = {'_data-provide': 'typeahead', '_autocomplete': 'off'}
    input_args.update(**kwargs)
    return CAT(
        INPUT(
            _type='text',
            _class='string input-xlarge',
            _id='txt_%s_%s' % (field._tablename, field.name),
            _value=value,
            **input_args
        ),
        SELECT(
            _id='%s_%s' % (field._tablename, field.name),
            _name='%s' % (field.name),
            _style='display: none;',
            _multiple='multiple',
            requires=field.requires
        ),
        DIV(
            OL(
                _id='ol_%s_%s' % (field._tablename, field.name),
                _class='typeahead_multiselect'
            ),
            _class='typeahead_multiselect'
        ),
        SCRIPT("""
        $(document).ready(function(){
        var json_feed = $.parseJSON('%(json_feed)s');
        var mapped = {};
        var searchFieldNames = _.debounce(function(query, process) {
                        var labels = []

                        $.each(json_feed.options, function (i, item) {
                            mapped[item.option] = item.id
                            labels.push(item.option)
                            });
                            process(labels);
                        }, 100);
                        // _.debounce() depend on underscore.js
        //make_ol_sortable(); // jquery-sortable seems to be bugged and
leave option with value undefined
        $('#%(txtSearch)s').typeahead({
                minLength: 0,
                items: 30,
                source: function(query, process) {
                    searchFieldNames (query, process);
                    },
                updater: function(item) {
                    $('#%(olSearch)s li span:contains("' + item +
'")').parent().remove();
                    $('#%(olSearch)s').append('<li id="' + mapped[item] +
'" class="typeahead_multiselect_option"><span
class="typeahead_multiselect_option_label">' + item + '</span><a href="#"
class="typeahead_multiselect_close" onclick="$(this).parent().remove();
checkOlEmpty(); redo_select();">x</a></li>');

//$('#%(olSearch)s').sortable().bind('sortupdate',function(){
                    //    redo_select();
                    //});
                    redo_select();
                    checkOlEmpty();
                }
            });

            checkOlEmpty();

        });
        function redo_select() {
            $('select[id="%(selSearch)s"]').empty();
            $('#%(olSearch)s li').each(function(){
                $('#%(selSearch)s').append('<option value="' +
$(this).attr('id') + '" selected="selected">' + $('li[id="' +
$(this).attr('id') + '"] span.typeahead_multiselect_option_label').text() +
'</option>');
            });
        }

        function checkOlEmpty() {
            $('ol.typeahead_multiselect').hide();
            $('ol.typeahead_multiselect').has('li').show();
        };

        function make_ol_sortable(){
            var adjustment;
            $('#%(olSearch)s').sortable({
                  group: 'simple_with_animation',
                  pullPlaceholder: false,
                  // animation on drop
                  onDrop: function  (item, targetContainer, _super) {
                    var clonedItem = $('<li/>').css({height: 0})
                    item.before(clonedItem)
                    clonedItem.animate({'height': item.height()})

                    item.animate(clonedItem.position(), function  () {
                      clonedItem.detach()
                      _super(item)
                    })
                    //redo_select(); // This not working for now there is
option with undefined value that remain once the dragged option is released
that seems a bug
                  },

                  // set item relative to cursor position
                  onDragStart: function ($item, container, _super) {
                    var offset = $item.offset(),
                    pointer = container.rootGroup.pointer

                    adjustment = {
                      left: pointer.left - offset.left,
                      top: pointer.top - offset.top
                    }

                    _super($item, container)
                  },
                  onDrag: function ($item, position) {
                    $item.css({
                      left: position.left - adjustment.left,
                      top: position.top - adjustment.top
                    })
                  }
            });
        }

        """ % {'txtSearch': 'txt_%s_%s' % (field._tablename, field.name),
               'selSearch': '%s_%s' % (field._tablename, field.name),
               'olSearch': 'ol_%s_%s' % (field._tablename, field.name),
               'json_feed': XML(json_feed),
               })
    )

I am not a JS kingpin, so it may contain dumb things... Basically I create
a feed function... And use it in callback in javascript...

I didn't have time to review your code, but I guess it similar...

Hope it helps create a good plugin for web2py community... I really thing
this one is missing, but since it sometime really specific what you need as
an autocomplete I doudt it can address every needs... But on this side
semantic ui seems to have more feature... If we can have plugin for which
you can switch from bs to semantic it could be so nice...

You may grab the whole semantic ui and work offline with it :
https://www.httrack.com/

Richard

On Fri, Feb 12, 2016 at 7:25 AM, <tim.nyb...@conted.ox.ac.uk> wrote:

> I've been thinking about doing this exact thing for a while, so I'll be
> eagerly watching your plugin
>
> On Thursday, 11 February 2016 16:18:28 UTC, Carlos Cesar Caballero wrote:
>>
>> Hi, right now I am working in a plugin with an autocomplete widget using
>> typeahead.js:
>>
>> https://github.com/daxslab/web2py-typeahead
>>
>> Any clues, suggestions, recomendations etc... will be very welcomed.
>>
>> Greetings.
>>
>> --
>> Este mensaje le ha llegado mediante el servicio de correo electronico que
>> ofrece Infomed para respaldar el cumplimiento de las misiones del Sistema
>> Nacional de Salud. La persona que envia este correo asume el compromiso de
>> usar el servicio a tales fines y cumplir con las regulaciones establecidas
>>
>> Infomed: http://www.sld.cu/
>>
>> --
> Resources:
> - http://web2py.com
> - http://web2py.com/book (Documentation)
> - http://github.com/web2py/web2py (Source code)
> - https://code.google.com/p/web2py/issues/list (Report Issues)
> ---
> You received this message because you are subscribed to the Google Groups
> "web2py-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to web2py+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to