2012-08-29 11 views
21

Rozszerzyłem nagłówek typu bootstrap, aby pobrać obiekt zamiast łańcucha.
Działa, ale chciałbym wiedzieć, że jest to właściwy sposób robienia rzeczy.Rozszerzanie nagłówka programu startowego w celu pobrania obiektu zamiast ciągu znaków.

Dzięki.

referencyjny:
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

nie widzę, w jaki sposób są nawet uzyskanie tak daleko. Kiedy próbuję uruchomić twój kod, wyjątek jest wyrzucany w metodzie 'sorter()' do testowania metod łańcucha na obiektach. Czy zmieniłeś tę metodę? A może dodawanie funkcji do obiektów? – merv

+1

tak, masz rację, ponieważ wprowadziłem inne zmiany, których jeszcze nie opublikowałem. Postanowię zrobić to później. dzięki –

+1

Tak, to byłoby pomocne, ponieważ 'matcher()' i 'sorter()' zmieniają 'items' przed przekazaniem go do metody' render() '. Nadpisywanie 'sorter()' jest obsługiwane w API, więc nie powinno być potrzeby edycji tego w źródle ** bootstrap-typeahead.js **. (nie mówiąc, że właśnie to robiłeś - po prostu wskazując) – merv

Odpowiedz

18

polecam nie przepisać prototyp (co wpłynęłoby wszystkie miejsca, w których można użyć autocompleter, nie tylko z następujących funkcji).
Kod ten powinien działać:

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

Witam, próbuję użyć twojego rozwiązania, a ponieważ używam wywołania ajaxowego, aby uzyskać dane użytkowników, trudno jest zintegrować go z twoim kodem.Jeśli piszę ajax w deklaracji getSource na zewnątrz, nie mogę znaleźć sposobu, w jaki mogę przekazać moje zapytanie do niego. Czy masz do tego jakieś zadanie? Dzięki :) –

0

Oprócz @AntoJs odpowiedzieć, tutaj jest ajax wersja (tylko 'źródło' część):

$('.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 - wielkie dzięki za odpowiedź!

0

@ odpowiedź antonjs nie pracował dla mnie, a ja coraz następujący błąd

TypeError: item.substr nie jest funkcją

więc z jQuery v2.1.3 i bootstrap3-typeahead.js v3 .1.0 następujące prace dla mnie

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

Powiązane problemy