¿Cómo consigo jQuery para seleccionar elementos con a. (punto) en su identificación?

172

Dadas las siguientes clases y método de acción del controlador:

public School
{
  public Int32 ID { get; set; }
  publig String Name { get; set; }
  public Address Address { get; set; }
}

public class Address
{
  public string Street1 { get; set; }
  public string City { get; set; }
  public String ZipCode { get; set; }
  public String State { get; set; }
  public String Country { get; set; }
}

[Authorize(Roles = "SchoolEditor")]
[AcceptVerbs(HttpVerbs.Post)]
public SchoolResponse Edit(Int32 id, FormCollection form)
{
  School school = GetSchoolFromRepository(id);

  UpdateModel(school, form);

  return new SchoolResponse() { School = school };
}

Y la siguiente forma:

<form method="post">
  School: <%= Html.TextBox("Name") %><br />
  Street: <%= Html.TextBox("Address.Street") %><br />
  City:  <%= Html.TextBox("Address.City") %><br />
  Zip Code: <%= Html.TextBox("Address.ZipCode") %><br />
  Sate: <select id="Address.State"></select><br />
  Country: <select id="Address.Country"></select><br />
</form>

Puedo actualizar tanto la instancia de la escuela como el miembro de la dirección de la escuela. ¡Esto es bastante bueno! ¡Gracias al equipo ASP.NET MVC!

Sin embargo, ¿cómo uso jQuery para seleccionar la lista desplegable para poder completarla previamente? Me doy cuenta de que podría hacer este lado del servidor, pero habrá otros elementos dinámicos en la página que afectarán la lista.

Lo siguiente es lo que tengo hasta ahora, y no funciona ya que los selectores no parecen coincidir con los ID:

$(function() {
  $.getJSON("/Location/GetCountryList", null, function(data) {
    $("#Address.Country").fillSelect(data);
  });
  $("#Address.Country").change(function() {
    $.getJSON("/Location/GetRegionsForCountry", { country: $(this).val() }, function(data) {
      $("#Address.State").fillSelect(data);
    });
  });
});
Doug Wilson
fuente

Respuestas:

293

De Grupos de Google :

Use dos barras invertidas antes de cada personaje especial.

Una barra invertida en un selector jQuery escapa al siguiente carácter. Pero necesita dos porque la barra diagonal inversa también es el carácter de escape para las cadenas de JavaScript. La primera barra diagonal inversa escapa a la segunda, dándole una barra diagonal inversa real en su cadena, que luego escapa al siguiente carácter para jQuery.

Entonces, supongo que estás mirando

$(function() {
  $.getJSON("/Location/GetCountryList", null, function(data) {
    $("#Address\\.Country").fillSelect(data);
  });
  $("#Address\\.Country").change(function() {
    $.getJSON("/Location/GetRegionsForCountry", { country: $(this).val() }, function(data) {
      $("#Address\\.State").fillSelect(data);
    });
  });
});

Consulte también ¿Cómo selecciono un elemento por una ID que tiene caracteres utilizados en notación CSS? en las preguntas frecuentes de jQuery.

bdukes
fuente
44
Me pregunto cuál es la racionalización para requerir que el desarrollador haga esto, parece que un simple conjunto de heurísticas dentro de jQuery resolvería este problema, ya que no hay nada de malo en las ID con puntos en ellas ...
Jason Bunting
55
Si no tuviera que escapar, ¿cómo consultaría un elemento con la dirección de ID y el estado de la clase? (Concediendo que si conoce la ID no está agregando mucho al especificar la clase, pero aún así debería ser válida, me gustaría pensar)?
bdukes
12
Por esa razón, en CSS mismo, también debes escapar de un punto en una ID. Todo lo que jQuery está haciendo es exigirle que siga las reglas establecidas por CSS.
bdukes
66
También puede seleccionar por nombre en lugar de ID. Por ejemplo, $ ('[name = "Address.Country"]')
Funka
25

No puede usar un selector de id jQuery si el id contiene espacios. Use un selector de atributos:

$('[id=foo bar]').show();

Si es posible, especifique también el tipo de elemento:

$('div[id=foo bar]').show();
Elliot Nelson
fuente
Prefiero hacerlo de esta manera que usar los caracteres de escape ... Obviamente, la mejor solución es no usar puntos en la identificación.
GordonB
Los espacios no están permitidos en las identificaciones, ni siquiera en la aceptación más liberal de caracteres de HTML5. stackoverflow.com/questions/70579/…
Jay Blanchard
Es cierto, pero si están permitidos o no, no le importa a la pobre savia que se ha quedado atascada agregando escaparatismo a una aplicación web mal escrita implementada a fines de los 90.
Elliot Nelson
44
debe haber quates para poder funcionar: `$ (" div [id = '"+ variable +"'] ")` o `$ (" div [id = 'foo bar'] ")`
olga
Como dijo @olga, la respuesta ya no es legal. Específicamente, recibirá un mensaje de error "Error no detectado: error de sintaxis, expresión no reconocida: div [id = foo bar]"
James Moore
13

Escápelo por Jquery:

function escapeSelector(s){
    return s.replace( /(:|\.|\[|\])/g, "\\$1" );
}

ejemplo de uso:

e.find('option[value='+escapeSelector(val)+']')

Más información aquí .


fuente
2
La solución según los documentos de jQuery es agregar solo un "\" (barra oblicua). alert (escapeSelector ("some.id")); saldrá como algunos \ .id. Así que supongo que la expresión regular de reemplazo debería haber sido s.replace (/(:|\.|[|font>)/g, "\\\\ $ 1");
Arun
Tengo el mismo problema, ¿por qué nadie más ve esto?
TruthOf42
9

El Release Candidate de ASP.NET MVC que se acaba de lanzar solucionó este problema, ahora reemplaza los puntos con guiones bajos para el atributo ID.

<%= Html.TextBox("Person.FirstName") %>

Renders a

<input type="text" name="Person.FirstName" id="Person_FirstName" />

Para obtener más información, vea las notas de la versión, comenzando en la página 14.

Dale Ragan
fuente
1
No veo cómo esto es una "solución": ¿por qué ASP.NET MVC debe cambiar la ID a algo que jQuery necesita? Creo que jQuery es donde radica el problema, no usando a. en una identificación.
Jason Bunting
77
el punto tiene un significado especial en CSS para identificar / combinar clases, por lo que tenerlo en una ID es problemático. El "problema" no es con jquery.
Funka
4

Esto está documentado en los documentos de jQuery Selectors :

Para utilizar cualquiera de los meta-caracteres (tales como !"#$%&'()*+,./:;<=>?@[\]^`{|}~) como una parte literal de un nombre, hay que escapó con dos barras invertidas con: \\. Por ejemplo, un elemento con id="foo.bar", puede usar el selector $("#foo\\.bar").

En resumen, prefije el .con de la \\siguiente manera:

$("#Address\\.Country")

Por qué no . funciona en mi identificación?

El problema es que .tiene un significado especial, la siguiente cadena se interpreta como un selector de clase. Entonces $('#Address.Country')coincidiría<div id="Address" class="Country"> .

Cuando se escapó como \\., el punto se tratará como texto normal sin un significado especial, que coincida con la ID que desee <div id="Address.Country">.

Esto se aplica a todos los caracteres !"#$%&'()*+,./:;<=>?@[\]^`{|}~que de otro modo tendrían un significado especial como selector en jQuery. Simplemente anteponga \\para tratarlos como texto normal.

¿Por qué 2 \\?

Como se señaló en la respuesta de bdukes, hay una razón por la que necesitamos 2 \caracteres. \escapará al siguiente carácter en JavaScript. Cuando JavaScript interprete la cadena "#Address\.Country", verá que \, interpretarlo significa tomar el siguiente carácter literalmente y eliminarlo cuando se pasa la cadena como argumento a $(). Eso significa que jQuery seguirá viendo la cadena como "#Address.Country".

Ahí es donde \entra el segundo para jugar. El primero le dice a JavaScript que interprete el segundo como un carácter literal (no especial). Esto significa que jQuery verá el segundo y comprenderá que el siguiente . carácter es un carácter literal.

¡Uf! Tal vez podamos visualizar eso.

//    Javascript, the following \ is not special.
//         | 
//         |
//         v    
$("#Address\\.Country");
//          ^ 
//          |
//          |
//      jQuery, the following . is not special.
Jon Surrell
fuente
2

Usar dos barras invertidas está bien, es un trabajo. Pero si está utilizando un nombre dinámico, es decir, un nombre variable, deberá reemplazar los caracteres.

Si no desea cambiar los nombres de sus variables, puede hacer esto:

var variable="namewith.andother";    
var jqueryObj = $(document.getElementById(variable));

y que tienes tu objeto jquery.

Daniel
fuente
0

Solo información adicional: consulte este problema ASP.NET MVC # 2403 .

Hasta que se solucione el problema, uso mis propios métodos de extensión como Html.TextBoxFixed, etc., que simplemente reemplaza los puntos con guiones bajos en el atributo id (no en el atributo de nombre), de modo que use jquery como $ ("# Address_Street") pero en el servidor, es como Address.Street.

El código de muestra sigue:

public static string TextBoxFixed(this HtmlHelper html, string name, string value)
{
    return html.TextBox(name, value, GetIdAttributeObject(name));
}

public static string TextBoxFixed(this HtmlHelper html, string name, string value, object htmlAttributes)
{
    return html.TextBox(name, value, GetIdAttributeObject(name, htmlAttributes));
}

private static IDictionary<string, object> GetIdAttributeObject(string name)
{
    Dictionary<string, object> list = new Dictionary<string, object>(1);
    list["id"] = name.Replace('.', '_');
    return list;
}

private static IDictionary<string, object> GetIdAttributeObject(string name, object baseObject)
{
    Dictionary<string, object> list = new Dictionary<string, object>();
    list.LoadFrom(baseObject);
    list["id"] = name.Replace('.', '_');
    return list;
}
gius
fuente
1
del problema mencionado anteriormente: "UpdateModel () usa un punto porque así es como entran los elementos del formulario. Los elementos del formulario usan un punto porque así es como se especifican en las llamadas de ayuda HTML. Las llamadas de ayuda HTML usan un punto porque así es como ViewData.Eval () funciona. Finalmente, ViewData.Eval () usa un punto porque así es como se separa un objeto y su propiedad en los principales idiomas de .NET Framework. Usar un delimitador que no sea un punto en cualquier punto de esta cadena se rompería el flujo para toda la cadena ".
Simon_Weaver
0

Resolví el problema con la solución dada por jquery docs

Mi funcion:

//funcion to replace special chars in ID of  HTML tag

function jq(myid){


//return "#" + myid.replace( /(:|\.|\[|\]|,)/g, "\\$1" );
return myid.replace( /(:|\.|\[|\]|,)/g, "\\$1" );


}

Nota: elimino el "#" porque en mi código concaté la ID con otro texto

Fuente: Jquery Docs selecciona un elemento con caracteres especiales

Gabriel Molina
fuente