2012-08-29 5 views
21

Ich erweiterte die Bootstrap-Typahead, um ein Objekt anstelle einer Zeichenfolge zu nehmen.
Es funktioniert, aber ich würde gerne wissen, das ist der richtige Weg, um die Dinge zu tun.Erweitern Sie die Bootstrap-TypeAhead, um ein Objekt anstelle einer Zeichenfolge zu nehmen

Danke.

Referenz:
http://twitter.github.com/bootstrap/javascript.html#typeahead http://twitter.github.com/bootstrap/assets/js/bootstrap-typeahead.js

_.extend($.fn.typeahead.Constructor.prototype, { 
    render: function (items) { 
     var that = this; 

     items = $(items).map(function (i, item) { 
      i = $(that.options.item) 
       .attr('data-value', item[that.options.display]) 
       .attr('data-id', item.id); 
      i.find('a').html(that.highlighter(item)); 
      return i[0]; 
     }); 

     items.first().addClass('active'); 
     this.$menu.html(items); 
     return this; 
    }, 
    select: function() { 
     var val = this.$menu.find('.active').attr('data-value'), 
      id = this.$menu.find('.active').attr('data-id'); 
     this.$element 
      .val(this.updater(val, id)) 
      .change(); 
     return this.hide() 
    } 
}); 

return function (element, options) { 
    var getSource = function() { 
      return { 
       id: 2, 
       full_name: 'first_name last_name' 
      }; 
    }; 

    element.typeahead({ 
     minLength: 3, 
     source: getSource, 
     display: 'full_name', 
     sorter: function (items) { 

      var beginswith = [], 
       caseSensitive = [], 
       caseInsensitive = [], 
       item, 
       itemDisplayed; 

      while (item = items.shift()) { 
       itemDisplayed = item[this.options.display]; 
       if (!itemDisplayed.toLowerCase().indexOf(this.query.toLowerCase())) { 
        beginswith.push(item); 
       } else if (~itemDisplayed.indexOf(this.query)) { 
        caseSensitive.push(item); 
       } else { 
        caseInsensitive.push(item); 
       } 
      } 

      return beginswith.concat(caseSensitive, caseInsensitive); 
     }, 
     highlighter: function (item) { 
      var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); 

      return item[this.options.display].replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) { 
       return '<strong>' + match + '</strong>'; 
      }); 
     }, 
     matcher: function (item) { 
      var value = item[this.options.display]; 

      return { 
       value: ~value.toLowerCase().indexOf(this.query.toLowerCase()), 
       id: item.id 
      }; 
     }, 
     updater: function (item, userId) { 
      options.hiddenInputElement.val(userId); 
      return item; 
     } 
    }); 
}; 
+1

ich sehe nicht, wie sind Sie sogar so weit zu bekommen. Wenn ich versuche, Ihren Code auszuführen, wird eine Ausnahme in der 'sort()' - Methode ausgelöst, um zu versuchen, String-Methoden auf Objekte anzuwenden. Änderst du diese Methode? Oder vielleicht Funktionen zu den Objekten hinzufügen? – merv

+1

Ja, du hast Recht, weil ich andere Änderungen vorgenommen habe, die ich noch nicht gepostet habe. Ich werde es später machen. danke –

+1

Ja, das wäre hilfreich, da 'matcher()' und 'sorter()' beide 'Elemente' ändern, bevor sie an die' render() 'Methode übergeben werden. Außerdem wird das Überschreiben von 'sorter()' in der API unterstützt, daher sollte es nicht notwendig sein, das in der ** bootstrap-typeahead.js ** - Quelle zu bearbeiten. (nicht zu sagen, dass Sie das getan haben - nur darauf hinweisend) – merv

Antwort

18

Ich empfehle den Prototyp nicht neu zu schreiben (die alle Orte auswirken würde, wo Sie die Autocompleter nutzen könnten, nicht nur die folgende Funktion).
sollten Dieser Code funktioniert:

var getSource = function() { 

    var users = new Backbone.Collection([ 
     { 
      first_name: 'primo', 
      last_name: 'ultimo', 
      id: 1 
     }, 
     { 
      first_name: 'altro_primo', 
      last_name: 'altro_ultimo', 
      id: 2 
     } 
    ]).models; 

    return _.map(users, function (user) { 
     return { 
      id: user.get('id'), 
      full_name: user.get('first_name') + ' ' + user.get('last_name'), 
      // these functions allows Bootstrap typehead to use this item in places where it was expecting a string 
      toString: function() { 
       return JSON.stringify(this); 
      }, 
      toLowerCase: function() { 
       return this.full_name.toLowerCase(); 
      }, 
      indexOf: function (string) { 
       return String.prototype.indexOf.apply(this.full_name, arguments); 
      }, 
      replace: function (string) { 
       return String.prototype.replace.apply(this.full_name, arguments); 
      } 
     }; 
    }); 
}; 

$('.full_name').typeahead({ 
      minLength: 3, 
      source: getSource(), 
      display: 'full_name', 
      updater: function (itemString) { 
       var item = JSON.parse(itemString); 
       $('.id').val(item.id); 
       return item.full_name; 
      } 
}); 

Demo: http://jsfiddle.net/hyxMh/48/

+0

Hallo, ich versuche, Ihre Lösung zu verwenden, und da ich Ajax-Anruf verwende, um Benutzerdaten zu erhalten, finde ich es schwierig, es mit Ihrem Code zu integrieren.Wenn ich den Ajax in der getSource außerhalb deklariere, kann ich keinen Weg finden, wie ich meine Abfrage an sie weitergeben würde. Hast du eine Arbeit dafür? Vielen Dank :) –

0

Neben @AntoJs beantworten, hier ist eine Ajax-Version (nur 'source' Teil):

$('.full_name').typeahead({ 
    /* ... */ 
    source: function(query,process){ 
    $.ajax({ 
     url: 'your_url_here', 
     data: {term: query, additional_data: 'some_data'}, 
     success: function(data){ 
      process($.map(data, function(user){ 
       return { 
        id: user.id, 
        full_name: user.first_name + ' ' + user.last_name, 
        toString: function() { 
         return JSON.stringify(this); 
        }, 
        toLowerCase: function() { 
         return this.full_name.toLowerCase(); 
        }, 
        indexOf: function (string) { 
         return String.prototype.indexOf.apply(this.full_name, arguments); 
        }, 
        replace: function (string) { 
         return String.prototype.replace.apply(this.full_name, arguments); 
        } 
       } 
      })); 
     } 
    }); 
    }, 
/* ... */ 
}); 

Btw: @AntoJs - vielen Dank für deine Antwort!

0

@ antonjs Antwort nicht für mich gearbeitet und ich war immer die folgenden Fehler

Typeerror: item.substr ist keine Funktion

so mit jQuery v2.1.3 und bootstrap3-typeahead.js v3 .1.0 die folgenden Werke für mich

var getSource = function() { 
 

 
    var users = new Backbone.Collection([ 
 
     { 
 
      first_name: 'primo', 
 
      last_name: 'ultimo', 
 
      id: 1 
 
     }, 
 
     { 
 
      first_name: 'altro_primo', 
 
      last_name: 'altro_ultimo', 
 
      id: 2 
 
     } 
 
    ]).models; 
 

 
    return _.map(users, function (user) { 
 
     return { 
 
      id: user.get('id'), 
 
      full_name: user.get('first_name') + ' ' + user.get('last_name'), 
 
      // these functions allows Bootstrap typehead to use this item in places where it was expecting a string 
 
      toString: function() { 
 
       return JSON.stringify(this); 
 
      }, 
 
      toLowerCase: function() { 
 
       return this.full_name.toLowerCase(); 
 
      }, 
 
      indexOf: function (string) { 
 
       return String.prototype.indexOf.apply(this.full_name, arguments); 
 
      }, 
 
      replace: function (string) { 
 
       return String.prototype.replace.apply(this.full_name, arguments); 
 
      }, 
 
      substr: function(start, len){ 
 
        return this.full_name.substr(start, len); 
 
      } 
 
     }; 
 
    }); 
 
}; 
 

 
$('.full_name').typeahead({ 
 
      minLength: 3, 
 
      source: getSource(), 
 
      display: 'full_name', 
 
      updater: function (itemString) { 
 
       var item = JSON.parse(itemString); 
 
       $('.id').val(item.id); 
 
       return item.full_name; 
 
      } 
 
});

Verwandte Themen