2012-09-30 15 views
43

Sto usando Twitter Bootstrap con Jquery. Voglio usare la funzione TYPEAHEAD per un'area di testo, che ho avuto modo di lavorare molto facilmente. Ma ho anche bisogno di consentire la selezione multipla .Twitter bootstrap typeahead valori multipli?

Con ciò intendo, dopo aver selezionato una parola dal completamento automatico, mi riporta in seguito a un'area di testo con uno spazio in più e quindi se ricomincio a digitare, mi offre di farlo di nuovo.

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

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

Grazie in anticipo.

risposta

87

Modifica C'è già stato un tiro al riguardo: https://github.com/twitter/bootstrap/pull/2007


si può avvicinare il 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 il metodo updater è pensato per questo genere di cose, devi solo restituire ciò che verrà visualizzato.


O se si vuole veramente di tutto per essere nella stessa elemento di input, che avrebbe dovuto sostituire più metodi in modo che corrisponda solo l'elemento attualmente tipizzate: 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 uno non è una prova idiota, perché devi digitare alla fine, dopo il carattere speciale.

+0

Questo è perfetto. Grazie! – denislexic

+1

Fantastico, amico! Esattamente quello di cui avevo bisogno. –

+0

Grazie mille! –

1

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 virgola. L'unico problema che vedo è che non sai quando chiudere il menu a discesa.

12

Questo è un ottimo sostituto per selezionare le caselle:

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

(Se si utilizza la versione multi-valore).

+2

Solo una nota, gli autori di typeahead hanno dichiarato che non hanno mai in programma di aggiungere questa funzione. In realtà anche loro raccomandano l'uso di Select2. https://github.com/twitter/typeahead.js/issues/135 – andrewtweber

1

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

FIDDLE

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) 
       ; 
} 

EDIT: Realizzando il codice precedente aveva troppa roba in più, ho ristretto la scelta a un esempio di lavoro minimo.

This è quello che è stato pubblicato in precedenza ..

Problemi correlati