Domanda Twitter bootstrap typeahead valori multipli?


Sto usando Twitter Bootstrap con Jquery. Voglio usare il TYPEAHEAD funzione per una textarea, che ho avuto modo di lavorare molto facilmente. Ma ho anche bisogno che lo permetta selezione multipla.

Con ciò intendo, dopo aver selezionato una parola dal completamento automatico, mi riporta in seguito alla textarea con uno spazio in più e poi, se ricomincio a scrivere, mi offre di farlo di nuovo.

Ecco un cestino JS: http://jsbin.com/ewubuk/1/edit (Niente di speciale dentro).

C'è una soluzione facile per consentire la selezione multipla con typeahead? Se sì, come?

Grazie in anticipo.


44
2017-09-30 16:18


origine


risposte:


modificare C'era già un vantaggio in questo: https://github.com/twitter/bootstrap/pull/2007


È possibile avvicinarsi al comportamento desiderato utilizzando un proxy per il typeahead: Demo (jsfiddle)

var $myTextarea = $('#myTextarea');

$('.typeahead').typeahead({
    source: source,
    updater: function(item) {
        $myTextarea.append(item, ' ');
        return '';
    }
});

Penso che la updater il metodo è pensato per questo genere di cose, devi solo restituire ciò che verrà visualizzato.


O se vuoi davvero che tutto sia nello stesso elemento di input, dovresti sovrascrivere più metodi in modo che corrisponda solo all'elemento tipizzato correntemente: Demo (jsfiddle)

function extractor(query) {
    var result = /([^,]+)$/.exec(query);
    if(result && result[1])
        return result[1].trim();
    return '';
}

$('.typeahead').typeahead({
    source: source,
    updater: function(item) {
        return this.$element.val().replace(/[^,]*$/,'')+item+',';
    },
    matcher: function (item) {
      var tquery = extractor(this.query);
      if(!tquery) return false;
      return ~item.toLowerCase().indexOf(tquery.toLowerCase())
    },
    highlighter: function (item) {
      var query = extractor(this.query).replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
        return '<strong>' + match + '</strong>'
      })
    }
});

Questo non è una prova idiota, perché devi digitare alla fine, dopo il carattere speciale.


88
2017-09-30 17:39



Questo è un eccellente sostituto per le scatole selezionate:

http://ivaynberg.github.io/select2/

(Se si utilizza la versione multi-valore.)


12
2017-07-17 12:18



La risposta migliore non sembra più funzionare con l'ultima typeahead, quindi offro quanto segue

VIOLINO

function MultiTypeahead(id, data, trigger, vertAdjustMenu)
{
    trigger = (undefined !== trigger) ? trigger : '';
    var validChars = /^[a-zA-Z]+$/;


    function extractor(query)
    {
        var result = (new RegExp('([^,; \r\n]+)$')).exec(query);
        if(result && result[1])
            return result[1].trim();
        return '';
    }

    var lastUpper = false;
    function strMatcher(id, strs) 
    {
        return function findMatches(q, sync, async) 
        {
            var pos = $(id).caret('pos');
            q = (0 < pos) ? extractor(q.substring(0, pos)) : '';

            if (q.length <= trigger.length)
                return;

            if (trigger.length)
            {
                if(trigger != q.substr(0, trigger.length))
                    return;

                q = q.substr(trigger.length);
            }

            if (!q.match(validChars))
                return;

            var firstChar = q.substr(0, 1);
            lastUpper = (firstChar === firstChar.toUpperCase() && firstChar !== firstChar.toLowerCase());

            var cpos = $(id).caret('position');
            $(id).parent().find('.tt-menu').css('left', cpos.left + 'px');
            if (vertAdjustMenu)
                $(id).parent().find('.tt-menu').css('top', (cpos.top + cpos.height) + 'px');

            var matches = [];
            var matches = [], substrRegex = new RegExp(q, 'i');
            $.each(strs, function(i, str) 
            {
                if (str.length > q.length && substrRegex.test(str))
                    matches.push(str);
            });

            if (!matches.length)
                return;

            sync(matches);
        };
    };

    var lastVal = '';
    var lastPos = 0;
    function beforeReplace(event, data)
    {
        lastVal = $(id).val();
        lastPos = $(id).caret('pos');
        return true;
    }

    function onReplace(event, data)
    {            
        if (!data || !data.length)
            return;

        if (!lastVal.length)
            return;

        var root = lastVal.substr(0, lastPos);
        var post = lastVal.substr(lastPos);

        var typed = extractor(root);
        if (!lastUpper && typed.length >= root.length && 0 >= post.length)
            return;

        var str = root.substr(0, root.length - typed.length);

        str += lastUpper ? (data.substr(0, 1).toUpperCase() + data.substr(1)) : data;
        var cursorPos = str.length;

        str += post;

        $(id).val(str);
        $(id).caret('pos', cursorPos);      
    }

    this.typeahead = 
        $(id).typeahead({hint: false, highlight: false}, {'limit': 5, 'source': strMatcher(id, data)})
                .on('typeahead:beforeselect', beforeReplace)
                .on('typeahead:beforeautocomplete', beforeReplace)
                .on('typeahead:beforecursorchange', beforeReplace)
                .on('typeahead:selected', function(event,data){setTimeout(function(){ onReplace(event, data); }, 0);})
                .on('typeahead:autocompleted', onReplace)
                .on('typeahead:cursorchange', onReplace)
                ;
}

MODIFICARE: Rendendomi conto che il codice precedente aveva troppe cose in più, l'ho ristretto a un esempio di lavoro minimo.

Questo è ciò che è stato precedentemente pubblicato ..


3
2017-10-17 15:15



Immagino che potresti modificare il plug-in per consentire selezioni multiple (solo non chiudere il menu a discesa) e aggiungere i valori selezionati separati da una virgola. L'unico problema che vedo è che non sai quando chiudere il menu a discesa.


1
2017-09-30 16:58



Sono in ritardo per la festa, ma questo è quello che mi è venuto in mente per Bootstrap v4. Richiede anche d3 (dato che non ho molta familiarità con jQuery).

Puoi vedere un esempio in esecuzione a http://sumneuron.gitlab.io/multitags/ enter image description here

Ha alcune funzioni utili, è scritto in modo chiaro, e dovrebbe portare a chiunque lo trovi bene. Soprattutto se sei sempre curioso di sapere come viene implementato il tagging.

enter image description here

Il codice è disponibile all'indirizzo https://gitlab.com/SumNeuron/multitags/pipelines

La logica è approssimativamente la seguente:

if keydown in [enter, ","]:
    // logic of function "doneTyping" 
    text = parse(text) // get text from textarea and grab latest value
    if text is valid:
        renderTag(text) // put the text in a tag element
        updateHiddenForm(text) // update the hidden form to include the tag
    else:
        notifyUserOfInvalidTag(text) // alert user
else:
    // logic of function "stillTyping" 
    suggest = bloodhoundSearch(text) // use twitter typeahead
    updateSuggestionBox(suggest) // display results from typeahead

0
2018-04-01 18:56