2012-09-30 31 views
43

Estoy usando Twitter Bootstrap con Jquery. Quiero utilizar la función TYPEAHEAD para un área de texto, que tengo que trabajar muy fácilmente. Pero también lo necesito para permitir selección múltiple.Twitter bootstrap typeahead valores múltiples?

Con esto quiero decir, después de seleccionar una palabra de la función de autocompletar, me lleva de vuelta a textarea con un espacio extra después y luego, si comienzo a escribir nuevamente, me ofrece volver a hacerlo.

Aquí hay una papelera JS: http://jsbin.com/ewubuk/1/edit (Nada especial en el interior).

¿Existe una solución fácil para permitir la selección múltiple con typeahead? Si es así, ¿cómo?

Gracias de antemano.

Respuesta

87

Editar Ya había un tirón al respecto: https://github.com/twitter/bootstrap/pull/2007


usted puede acercarse a la conducta deseada mediante el uso de un proxy para la escritura siguiente: Demo (jsfiddle)

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

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

creo que el método updater es para este tipo de cosas, solo devuelve lo que se mostrará.


O si realmente quiere que todo sea en el mismo elemento de entrada, que tendría que anular más métodos para que sólo coincide con el elemento mecanografiado actualmente: 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>' 
     }) 
    } 
}); 

Este uno no es una prueba idiota, porque tienes que escribir al final, después del personaje especial.

+0

Eso es perfecto. ¡Gracias! – denislexic

+1

¡Increíble, hombre! Exactamente lo que necesitaba. –

+0

¡Muchas gracias! –

1

Supongo que podría editar el complemento para permitir selecciones múltiples (simplemente no cierre el menú desplegable) y agregue los valores seleccionados separados por comas. El único problema que veo es que no sabes cuándo cerrar el menú desplegable.

12

Este es un excelente sustituto de cajas de selección:

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

(Si se utiliza la versión de múltiples valores.)

+2

Solo una nota, los autores de typeahead han declarado que nunca planean agregar esta característica. En realidad, recomiendan usar Select2 en este caso también. https://github.com/twitter/typeahead.js/issues/135 – andrewtweber

1

No parece que la respuesta más común que trabajar más con la última typeahead, entonces ofrezco lo siguiente.

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: Al darse cuenta el código anterior tenía demasiado material extra, reducido a un ejemplo de trabajo mínima.

This es lo que se publicó anteriormente ..

Cuestiones relacionadas