2012-08-29 61 views
21

我擴展了bootstrap-typeahead以獲取對象而不是字符串。
它的工作原理,但我想知道這是做事情的正確方法。擴展bootstrap-typeahead以獲取對象而不是字符串

謝謝。

參考:
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

以下作品我看不出你是如何甚至還讓遠。當我嘗試運行代碼時,會在'sorter()'方法中引發異常,以嘗試在對象上應用字符串方法。你是否在改變這種方法?或者可能添加功能的對象? – merv

+1

是的,你是對的,因爲我做了其他改變,我沒有發佈..我會在稍後做。謝謝 –

+1

是的,這樣做會很有幫助,因爲'matcher()'和'sorter()'在將'items'傳遞給'render()'方法之前都會改變'items'。此外,API中支持重寫'sorter()',因此不需要在** bootstrap-typeahead.js **源文件中編輯它。 (不是說那就是你正在做的 - 只是指出來) – merv

回答

18

我建議不重寫原型(這將影響所有的地方,你可以使用autocompleter,不僅下面的函數)。
此代碼應工作:

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

演示:http://jsfiddle.net/hyxMh/48/

+0

嗨,我正在嘗試使用您的解決方案,並且由於我使用ajax調用來獲取用戶數據,所以我發現很難將它與您的代碼集成。如果我在外部聲明的getSource中編寫ajax,我找不到如何將查詢傳遞給它的方法。你有這個工作嗎?謝謝 :) –

0

除了@AntoJs回答,這裏是一個Ajax版本(只是 '源' 部分):

$('.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 - 非常感謝您的回答!

0

@ antonjs的答案不是爲我工作,我是收到以下錯誤

類型錯誤:item.substr不是一個函數

與jQuery V2.1.3和bootstrap3-typeahead.js V3

所以.1.0我

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

相關問題