Me gustaría mostrar las sugerencias en una tabla, funciona pero arroja un error JS al pasar el mouse sobre el encabezado de la tabla estática. ¿Cómo puedo solucionar esto? Funciona perfectamente de lo contrario.

enter image description here

Pasos de error:

enter image description here

Nota: solía funcionar en jquery 1.10.4 pero arroja un error cuando intenté actualizar a 1.12.4

Versión de trabajo (en 1.10.4): https://jsfiddle.net/sajjansarkar/bq526h67/1/

Error al lanzar la versión (en 1.12.4): https://jsfiddle.net/sajjansarkar/L52u064j/2/

HTML:

<div id="project-label">Select a project (type "s" for a start):</div>
<input id="project">
<input type="hidden" id="project-id">
<p id="project-description"></p>

JS:

$(function() {
  //random json values
  var projects =  [{ id: 1, value: "Thomas", cp: 134 }, { id: 65, value: "Richard", cp: 1743 }, { id: 235, value: "Harold", cp: 7342 }, { id: 78, value: "Santa Maria", cp: 787 }, { id: 75, value: "Gunner", cp: 788 }, { id: 124, value: "Shad", cp: 124 }, { id: 1233, value: "Aziz", cp: 3544 }, { id: 244, value: "Buet", cp: 7847 }];



  // define UI behavior methods

  function _renderMenu(ul, items) {
    var self = this;
    //table definitions
    ul.append("<table border=1><thead><tr><th>ID#</th><th>Name</th><th>Cool&nbsp;Points</th></tr></thead><tbody></tbody></table>");
    $.each(items, function(index, item) {
      self._renderItemData(ul, ul.find("table tbody"), item);
    });
  }

  function _renderItemData(ul, table, item) {
    return this._renderItem(table, item).data("ui-autocomplete-item", item);
  };

  function _renderItem(table, item) {
    return $("<tr class='ui-menu-item' role='presentation'></tr>")
      //.data( "item.autocomplete", item )
      .append("<td >" + item.id + "</td>" + "<td>" + item.value + "</td>" + "<td>" + item.cp + "</td>")
      .appendTo(table);
  };



  // create the autocomplete
  var autocomplete = $("#project").autocomplete({
    minLength: 1,
    source: projects
  });

  // get a handle on it's UI view
  var autocomplete_handle = autocomplete.data("ui-autocomplete");

  //overriding jquery-ui.autocomplete .js functions
  autocomplete_handle._renderMenu = _renderMenu;
  autocomplete_handle._renderItemData = _renderItemData;
  autocomplete_handle._renderItem = _renderItem;

});
0
Sajjan Sarkar 19 ene. 2018 a las 22:47

3 respuestas

La mejor respuesta

[ACTUALIZACIÓN] Solución de trabajo basada en el código de Twisty y la sugerencia de Lambrusco:

  • Hice el encabezado como "elemento" completo (con objeto de respaldo) en el widget, entonces el controlador arrow tiene un "elemento" para procesar cuando se enfoca en él.
  • Y agregué una propiedad de identificación en el objeto de encabezado para permitir que el renderizador lo represente de manera diferente.
  • También cambié el código para que sea DIV/CSS basado en la cuadrícula en lugar de verdadero TABLEs, con cada "fila" siendo un LI apropiado para que no tengamos el desorden completo de las tablas dentro de {{X3} } etiquetas.

Código de trabajo:

$(function() {
  //random json values
  var projects = [{../*commented for brevity*/..}];

  $.widget("custom.tablecomplete", $.ui.autocomplete, {
    _create: function() {
      this._super();
      this.widget().menu("option", "items", "> li:not(.ui-autocomplete-header)");
    },
    _renderMenu(ul, items) {
      var self = this;
      ul.addClass("container");

      let header = {
        id: "IP",
        value: "VALUE",
        cp: "CP",
        isheader: true
      };
      self._renderItemData(ul, header);
      $.each(items, function(index, item) {
        self._renderItemData(ul, item);
      });

    },
    _renderItemData(ul, item) {
      return this._renderItem(ul, item).data("ui-autocomplete-item", item);
    },
    _renderItem(ul, item) {
      var $li = $("<li class='ui-menu-item' role='presentation'></li>");
      if (item.isheader)
        $li = $("<li class='ui-autocomplete-header' role='presentation'  style='font-weight:bold !important;'></li>");
      var $content = "<div class='row ui-menu-item-wrapper'>" + "<div class='col-xs-3'>" + item.id + "</div>" + "<div class='col-xs-5'>" + item.value + "</div>" + "<div class='col-xs-3'>" + item.cp + "</div>" + "</div>";
      $li.html($content);


      return $li.appendTo(ul);
    }

  });



  // create the autocomplete
  var autocomplete = $("#project").tablecomplete({
    minLength: 1,
    source: projects,
  });

  // get a handle on it's UI view
  var autocomplete_handle = autocomplete.data("ui-autocomplete");
});

Violín:

https://jsfiddle.net/sajjansarkar/j7fu060j/

0
Sajjan Sarkar 24 ene. 2018 a las 18:01

Lo arregló con la ayuda del constructor $.widget().

Ejemplo de trabajo: https://jsfiddle.net/Twisty/192m0uyc/2/

Widget

$.widget("custom.tablecomplete", $.ui.autocomplete, {
  _create: function() {
    this._super();
    this.widget().menu("option", "items", "> tr:not(.ui-autocomplete-header)");
  },
  _renderMenu(ul, items) {
    var self = this;
    var $t = $("<table>", {
      border: 1
    }).appendTo(ul);
    $t.append($("<thead>"));
    $t.find("thead").append($("<tr>", {
      class: "ui-autocomplete-header"
    }));
    var $row = $t.find("tr");
    $("<th>").html("ID#").appendTo($row);
    $("<th>").html("Name").appendTo($row);
    $("<th>").html("Cool Point").appendTo($row);
    $("<tbody>").appendTo($t);
    $.each(items, function(index, item) {
      self._renderItemData(ul, $t.find("tbody"), item);
    });
  },
  _renderItemData(ul, table, item) {
    return this._renderItem(table, item).data("ui-autocomplete-item", item);
  },
  _renderItem(table, item) {
    var $row = $("<tr>", {
      class: "ui-menu-item",
      role: "presentation"
    });
    $("<td>").html(item.id).appendTo($row);
    $("<td>").html(item.value).appendTo($row);
    $("<td>").html(item.cp).appendTo($row);
    return $row.appendTo(table);
  }
});

Con el http://jqueryui.com/autocomplete/#categories, podemos anular la representación como quisieras y aprovecha la fuerza del generador de widgets. Esto básicamente ignora el thead ahora como una categoría versus un elemento con el que el usuario podría interactuar. El resto del uso se copia desde $.ui.autocomplete para que funcione igual.

Una advertencia menor, si el usuario presiona , se encuentra thead, generando un error. Esto no impide más acciones y es pasivo.

2
Twisty 19 ene. 2018 a las 21:30

Trataré de responder. Primero, hay diferencias entre las versiones 1.10.4 y 1.12.4 de autocompletar, por lo que no es extraño que se comporten de manera diferente.

En segundo lugar, anula la construcción del menú, pero no anula la selección del menú, por lo que si veremos datos de depuración

        menufocus: function(e, i) {
            var s, n;
            return this.isNewMenu && (this.isNewMenu = !1,
            e.originalEvent && /^mouse/.test(e.originalEvent.type)) ? (this.menu.blur(),
            this.document.one("mousemove", function() {
                t(e.target).trigger(e.originalEvent)
            }),
            void 0) : (n = i.item.data("ui-autocomplete-item"),
            !1 !== this._trigger("focus", e, {
                item: n
            }) && e.originalEvent && /^key/.test(e.originalEvent.type) && this._value(n.value),
            s = i.item.attr("aria-label") || n.value,
            s && t.trim(s).length && (this.liveRegion.children().hide(),
            t("<div>").text(s).appendTo(this.liveRegion)),
            void 0)
        },

La cuerda

s = i.item.attr("aria-label") || n.value

Nos da error, porque como vemos antes

n = i.item.data("ui-autocomplete-item")

Y es indefinido

Puede simplemente verificar su función de enfoque si es encabezado y omitirlo, porque el autocompletado espera que el artículo tenga datos de ítem ui-autocomplete como puede ver.

0
Thelambofgoat 19 ene. 2018 a las 21:06
48348490