Как получить jQuery для выбора элементов с помощью. (точка) в их удостоверение личности?

172

Даны следующие классы и метод действия контроллера:

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

И следующая форма:

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

Я могу обновить как экземпляр школы, так и адрес участника школы. Это довольно мило! Спасибо команде ASP.NET MVC!

Тем не менее, как я могу использовать jQuery, чтобы выбрать выпадающий список, чтобы я мог предварительно заполнить его? Я понимаю, что могу сделать это на стороне сервера, но на странице будут другие динамические элементы, влияющие на список.

Вот что у меня есть, и оно не работает, так как селекторы не соответствуют идентификаторам:

$(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);
    });
  });
});
Дуг Уилсон
источник
learn.jquery.com/using-jquery-core/faq/…
Кристоф Русси

Ответы:

293

Из групп Google :

Используйте две обратные косые черты перед каждым специальным символом.

Обратная косая черта в селекторе jQuery экранирует следующий символ. Но вам нужно два из них, потому что обратный слеш также является escape-символом для строк JavaScript. Первая обратная косая черта экранируется от второй, давая вам одну реальную обратную косую черту в вашей строке, которая затем экранирует следующий символ для jQuery.

Итак, я думаю, вы смотрите на

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

Также ознакомьтесь с разделом Как выбрать элемент по идентификатору, в котором есть символы, используемые в нотации CSS? на jQuery FAQ.

bdukes
источник
4
Интересно, каково обоснование того, что разработчик должен сделать это, кажется, что простой набор эвристик в jQuery решил бы эту проблему, поскольку нет ничего плохого в ID с точками в них ...
Джейсон Бантинг
5
Если вам не нужно было убегать, как бы вы запросили элемент с идентификатором Address и классом State (при условии, что если вы знаете ID, вы не добавляете много, указав класс, но он все равно должен быть действительным, я бы считать)?
bdukes
12
По этой причине в самом CSS вы также должны избегать точки в идентификаторе. Все, что делает jQuery, требует от вас соблюдения правил, установленных CSS.
bdukes
6
Вы также можете выбрать по имени вместо ID. Например, $ ('[name = "Address.Country"]')
Funka
25

Вы не можете использовать селектор идентификатора jQuery, если идентификатор содержит пробелы. Используйте селектор атрибута:

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

Если возможно, укажите также тип элемента:

$('div[id=foo bar]').show();
Эллиот Нельсон
источник
Я предпочитаю делать это таким образом, чем использовать escape-символы .... Очевидно, что лучший обходной путь - не использовать точки в id.
GordonB
Пробелы не допускаются в идентификаторах, даже в более либеральном восприятии символов в HTML5. stackoverflow.com/questions/70579/…
Джей Бланшар
Да, но неважно, разрешены они или нет, для бедного человека, который застрял, добавив оформление витрин в плохо написанное веб-приложение, развернутое в конце 90-х годов.
Эллиот Нельсон
4
для работы должны быть кавычки: `$ (" div [id = '"+ variable +"'] ")` или `$ (" div [id = 'foo bar'] ")`
olga
Как сказала @olga, ответ больше не является законным. В частности, вы получите сообщение об ошибке «Uncaught Error: синтаксическая ошибка, нераспознанное выражение: div [id = foo bar]»
Джеймс Мур
13

Побег это для Jquery:

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

пример использования:

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

больше информации здесь .


источник
2
Решение в соответствии с документами jQuery заключается в добавлении только одного "\" (косая черта). Оповещение (escapeSelector ( "some.id")); будет выводить как некоторые \ .id. Поэтому я думаю, что регулярное выражение замены должно было быть s.replace (/(:|\.|[|])/g, "\\\\ $ 1");
Арун
У меня та же проблема, почему никто другой не видит это?
TruthOf42
9

Кандидат на выпуск ASP.NET MVC, который был только что выпущен, исправил эту проблему, теперь он заменяет точки подчеркиванием для атрибута ID.

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

Оказывает

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

Для получения дополнительной информации см. Примечания к выпуску, начиная со страницы 14.

Дейл Раган
источник
1
Я не вижу, как это «исправить» - зачем ASP.NET MVC менять идентификатор на то, что нужно jQuery? Я думаю, что проблема в jQuery, а не в использовании. в удостоверении личности.
Джейсон Бантинг
7
точка имеет особое значение в CSS для идентификации / объединения классов, поэтому наличие ее в идентификаторе является проблематичным. «Проблема» не в jquery.
Funka
4

Это задокументировано в документации по jQuery Selectors :

Для того, чтобы использовать любого из мета-символы (например , как !"#$%&'()*+,./:;<=>?@[\]^`{|}~) , как буквальная часть имени, он должен быть экранирован с двойной косой чертой: \\. Например, элемент с id="foo.bar", может использовать селектор $("#foo\\.bar").

Короче говоря, префикс .с \\следующим:

$("#Address\\.Country")

Почему не .работает в моем удостоверении личности?

Проблема в том, что это .имеет особое значение, следующая строка интерпретируется как селектор класса. Так $('#Address.Country')бы совпало <div id="Address" class="Country">.

Если экранировать как \\., точка будет обрабатываться как обычный текст без особого значения, соответствующего желаемому идентификатору <div id="Address.Country">.

Это относится ко всем символам, !"#$%&'()*+,./:;<=>?@[\]^`{|}~которые в противном случае имели бы особое значение как селектор в jQuery. Просто приготовьтесь \\относиться к ним как к обычному тексту.

Почему 2 \\?

Как отмечается в ответе bdukes, есть причина, по которой нам нужно 2 \символа. \будет избегать следующего символа в JavaScript. Например, когда JavaScript интерпретирует строку "#Address\.Country", он увидит \, что интерпретировать его будет означать, что он возьмет следующий символ буквально и удалит его, когда строка будет передана в качестве аргумента $(). Это означает, что jQuery все равно будет видеть строку как "#Address.Country".

Вот тут и \приходит второй, чтобы играть. Первый говорит JavaScript интерпретировать второй как буквальный (не специальный) символ. Это означает, что второй будет замечен jQuery и поймет, что следующий . символ является буквальным символом.

Уф! Может быть, мы можем визуализировать это.

//    Javascript, the following \ is not special.
//         | 
//         |
//         v    
$("#Address\\.Country");
//          ^ 
//          |
//          |
//      jQuery, the following . is not special.
Джон Суррелл
источник
2

Используя две обратные косые черты, это нормально, это работает. Но если вы используете динамическое имя, я имею в виду имя переменной, вам нужно будет заменить символы.

Если вы не хотите менять имена переменных, вы можете сделать это:

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

и чем у вас есть объект jquery.

Даниил
источник
0

Просто дополнительная информация: проверьте этот ASP.NET MVC выпуск № 2403 .

Пока проблема не устранена, я использую свои собственные методы расширения, такие как Html.TextBoxFixed и т. Д., Которые просто заменяют точки подчеркиванием в атрибуте id (не в атрибуте name), так что вы используете jquery, как $ ("# Address_Street") но на сервере это похоже на Address.Street.

Пример кода следующий:

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
источник
1
из вышеупомянутой проблемы: «UpdateModel () использует точку, потому что так поступают элементы формы. Элементы формы используют точку, потому что именно так они указаны в вызовах помощника HTML. В вызовах помощника HTML используется точка, потому что это как ViewData.Eval () работает. Наконец, ViewData.Eval () использует точку, потому что именно так человек разделяет объект и его свойство в основных языках .NET Framework. Использование разделителя, отличного от точки, в любой точке этой цепочки приведет к разрыву поток для всей цепи ".
Simon_Weaver
0

Я решил проблему с помощью JQuery Docs

Моя функция:

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

function jq(myid){


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


}

Примечание: я удаляю "#", потому что в моем коде я соединяю идентификатор с другим текстом

Шрифт: Jquery Docs выбирает элемент с особенными символами

Габриэль Молина
источник