Как использовать JQuery, выбрать элемент по идентификатору и ASP.NET, не помещая ctl00_ везде в коде - PullRequest
5 голосов
/ 05 августа 2009

У меня около 600+ ссылок на код, подобный следующему ...

$("#ctl00_ContentMainPane_eliteUser").html

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

Весь javascript включен в отдельные файлы, поэтому я не могу использовать такой код ...

$("#<%= eliteUser.clientID%>").html

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

Ответы [ 7 ]

8 голосов
/ 05 августа 2009

Как насчет определения функции JavaScript на главной странице, например:

function getContainerId() {
    return "<%=ContentMainPane.ClientID %>";
}

Затем во включенных файлах JavaScript сделайте что-то вроде этого:

$("#" + getContainerId() + "_eliteUser");
3 голосов
/ 05 августа 2009

Один из способов - использовать объект переменных js, который записывается вверху каждой страницы. Ваш внешний js может затем ссылаться на объект настройки с желаемым свойством Таким образом, вы можете изменить идентификатор на ваших aspx-страницах без какого-либо жесткого кодирования во внешних js-файлах.

Затем вы можете предоставить метод materpage или метод base page, который позволяет каждой странице добавлять элементы управления id в список. В этом случае базовый метод должен написать сценарий pageVars вверху каждой страницы.

Рик Страл говорит об этом здесь

Я предпочитаю этот метод, поскольку вы все еще получаете преимущества быстрых селекторов.

1011 * например *

Если вы получите aspx, чтобы написать следующий скрипт.

var pageVars = {
    idList: {
        eliteUser : 'ctl00_ContentMainPane_eliteUser',
        normalUser : 'ctl00_ContentMainPane_normalUser', 
        powerUser : 'ctl00_ContentMainPane_powerUser', 
        .....
    }
};

Тогда в вашем внешнем js

$('#' + pageVars.idList.eliteUser)
$('#' + pageVars.idList.powerUser)....etc
2 голосов
/ 05 августа 2009

Я использовал класс, который расширяет WebControl, чтобы по существу сделать то же самое, что Предложение RedSquare . Я прочитал предложение в этом блоге

/// <summary>
/// Custom Web control that renders two JavaScript functions out into the page 
/// so that defined control IDs can be used to get a reference to HTML DOM elements
/// </summary>
[DefaultProperty("Text")]
[ToolboxData("<{0}:ClientIdHandler runat=\"server\"></{0}:ClientIdHandler>")]
public class ClientIdHandler : WebControl
{
    private StringBuilder _builder = new StringBuilder();

public ClientIdHandler(){}


/// <summary>
/// Renders the ClientID of the control in JavaScript function "clientId" to the specified writer.
/// </summary>
/// <param name="output">A <see cref="Control"/> whose ClientID will be included 
/// in the rendered HTML output.</param>
public void AddControl(Control c)
{
    _builder.AppendFormat("    case '{0}': return '{1}'; break;" + Environment.NewLine, c.ID, c.ClientID);
}

/// <summary>
/// Overrides the Render method to prevent a Start and End <see cref="HtmlTextWriterTag"/>
/// being rendered in the HTML for the control.
/// </summary>
/// <param name="output">A <see cref="HtmlTextWriter"/> that represents 
/// the output stream to render HTML content on the client.</param>
protected override void Render(HtmlTextWriter writer)
{       
    RenderContents(writer);
}


/// <summary>
/// Renders the contents of the control to the specified writer.
/// </summary>
/// <param name="output">A <see cref="HtmlTextWriter"/> that represents 
/// the output stream to render HTML content on the client.</param>
protected override void RenderContents(HtmlTextWriter output)
{
    output.Write("<script type=\"text/javascript\"> " + Environment.NewLine);
    output.Write("function clientId(id) {" + Environment.NewLine);
    output.Write("switch (id) {" + Environment.NewLine);
    output.Write(_builder.ToString());
    output.Write("     }" + Environment.NewLine);
    output.Write("}" + Environment.NewLine);
    output.Write("function getElementByClientId(id) {" + Environment.NewLine);
    output.Write("    return document.getElementById(clientId(id));" + Environment.NewLine);
    output.Write("}" + Environment.NewLine);
    output.Write("</script>" + Environment.NewLine);
}
}

Тогда вы можете использовать в aspx странице или коде позади

 protected override void OnInit(EventArgs e)
    {
        ClientIdHandler clientIds = new ClientIdHandler();
        clientIds.AddControl(myControl);

        this.Controls.Add(clientIds);

        base.OnInit(e);
    }

Что выдаст следующее на странице

<script type="text/javascript"> 
function clientId(id) {
switch (id) {
    case 'myControl': return 'ctl00_Main_myControl'; break;
     }
}
function getElementByClientId(id) {
    return document.getElementById(clientId(id));
}
</script>

Итак, во внешнем файле JavaScript вы можете использовать следующее

// for jQuery selectors
var myControl = $('#' + clientId('myControl'));

// for vanilla JavaScript
 var myControl = getElementByClientId('myControl'));
2 голосов
/ 05 августа 2009

Вы можете сделать что-то вроде этого:

$("input[id*=eliteUser]").html()

Но если у вас есть несколько элементов управления, заканчивающих свои идентификаторы в eliteUser - это не сработает.

1 голос
/ 05 августа 2009

Я использую ScriptManager.RegisterStartupScript , чтобы получить все требуемые идентификаторы клиентов.

  1. Определение переменных javascript в «заголовке» страницы для хранения идентификаторов.
  2. Используйте RegisterStartupScript в Page_Load для назначения значений переменным следующим образом:

string myScript = String.Format ("window.onload = function () {id1 = {0}, id2 = {1}, id3 = {2}}", Control1.ClientID, Control2.ClientID, Control3.ClientID);

ScriptManager.RegisterStartupScript (Page, Page.GetType (), "SomeKey", myScript, true);

1 голос
/ 05 августа 2009

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

0 голосов
/ 05 августа 2009

Это проблема, которая, как я понимаю, решается в следующей версии Visual Studio, однако я понимаю, что это вам не поможет.

То, как мы обращались к этому в нашем проекте, было чем-то вроде этого:

$.extend({
    clientID: function(id) {
        return $("[id$='_" + id + "']");
    }
});

И код, который его использовал:

statusBar = $.clientID("MSS_MESS_LINE_Static")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...