Як змусити 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);
    });
  });
});

Відповіді:


293

З груп Google :

Перед кожним спеціальним символом використовуйте дві косої риски.

Зворотний косий рядок у селекторі jQuery дозволяє уникнути наступного символу. Але вам потрібні два з них, тому що зворотна косої риси також є символом втечі для рядків 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.


4
Цікаво, що таке раціоналізація для того, щоб вимагати від розробника цього робити, схоже, простий набір евристики в jQuery вирішив би цю проблему, оскільки в ІД немає нічого поганого з періодами в них ...
Джейсон Бантінг,

5
Якщо вам не довелося бігти, як би ви запитали елемент з ідентифікаційною адресою та станом класу (за умови, що якщо ви знаєте ідентифікатор, ви не додаєте багато, вказавши клас, але він все одно повинен бути дійсним, я б подумайте)?
бдук

12
З цієї причини в самому CSS ви також повинні уникати крапки в ідентифікаторі. Все, що робить jQuery, вимагає дотримуватися правил, встановлених CSS.
bdukes

6
Ви також можете вибрати ім'я замість ідентифікатора. Наприклад, $ ('[name = "Address.Country"]')
Funka

25

Ви не можете використовувати селектор jQuery id, якщо ідентифікатор містить пробіли. Використовуйте селектор атрибутів:

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

Якщо можливо, вкажіть і тип елемента:

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

Я вважаю за краще робити це таким чином, ніж використовувати символи втечі .... Очевидно, найкращим способом вирішення не є використання періодів в ідентифікаторі.
GordonB

Пробіли не допускаються в ідентифікаторах, навіть у більш ліберальному прийнятті символів HTML5. stackoverflow.com/questions/70579/…
Джей Бланшард

Правда, але чи вони дозволені чи ні, не має значення для бідного соку, який застряг, додаючи перев'язку вікон у погано написаний веб-додаток, розгорнутий наприкінці 90-х.
Елліот Нельсон

4
для роботи повинні бути лапки: `$ (" div [id = '"+ змінна +"'] ")" або `$ (" div [id = 'foo bar'] ")`
olga

Як сказав @olga, відповідь вже не є законною. Зокрема, ви отримаєте повідомлення про помилку "Неприхована помилка: Помилка синтаксису, нерозпізнаний вираз: 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 (/(:|\.| evidence| снимки)/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.
Функа

4

Це задокументовано в документах селекторів jQuery :

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

Коротше кажучи, префікс .з \\наступним чином:

$("#Address\\.Country")

Чому .в моєму посвідченні не працює?

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

Якщо втекти як \\., точка буде розглядатися як звичайний текст без особливого значення, що відповідає ідентифікатору, який ви бажаєте <div id="Address.Country">.

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

Чому 2 \\?

Як зазначається у відповіді на бдуки, є причина, що нам потрібні 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

Додаткова інформація: Перевірте цю проблему № 2403 ASP.NET MVC .

Поки проблема не виправлена, я використовую свої власні методи розширення, такі як Html.TextBoxFixed тощо, які просто замінюють крапки підкресленнями в атрибуті id (а не в атрибуті імені), так що ви використовуєте 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;
}

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 виберіть елемент з особливими символами

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.