mensajes emergentes dinamicas close bootstrap alertas javascript jquery autocomplete twitter-bootstrap

javascript - emergentes - Extienda el encabezado de bootstrap para tomar un objeto en lugar de una cadena



bootstrap tooltip (3)

Extendí el encabezado de bootstrap para tomar un objeto en lugar de una cadena.
Funciona, pero me gustaría saber que esta es la manera correcta de hacer las cosas.

Gracias.

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


Recomiendo no reescribir el prototipo (que afectaría a todos los lugares donde podría usar el autocompletador, no solo la siguiente función).
Este código debería funcionar:

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/


Además de la respuesta de @AntoJs, aquí hay una versión de Ajax (solo parte ''fuente''):

$(''.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); } } })); } }); }, /* ... */ });

Por cierto: @AntoJs - muchas gracias por su respuesta!


La respuesta de @antonjs no funcionaba para mí y recibía el siguiente error

TypeError: item.substr no es una función

así que con jQuery v2.1.3 y bootstrap3-typeahead.js v3.1.0 el siguiente funciona para mí

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