Как получить доступ к ClientID из ServerControl во внешнем JavaScript

На данный момент, если я использую JavaScript в своих проектах SharePoint, я добавляю код в файл *.ascx, в блок <script type="text/javascript"></script> и создаю для каждого элемента переменную для ClientID.

Например:

var test = '<%= TextBox1.ClientID %>';

Теперь я хотел бы добавить внешний JavaScript в свои проекты и вставить туда код. Но как я мог получить доступ к ClientID? Во внешнем JavaScript я не могу использовать <%= TextBox1.ClientID %>. Я нашел это: ссылка на серверные элементы управления во внешнем файле но я не понимаю, как это должно работать. Было бы здорово, если бы кто-нибудь объяснил мне, как получить доступ к идентификаторам.

Кстати, почему это:

<script type="text/javascript">
    var ClientIDs = {
        test1   : '<%= TextBox1.ClientID %>',
        test2   : '<%= TextBox2.ClientID %>'
        }

    function SetButtonStatus() {    
            alert($(ClientIDs.test1).value);
        }
</script>

не работает, сообщение не будет отображаться?

Гретц

Редактировать 1:

Хорошо, я могу просто использовать textBox1 в своем внешнем скрипте? Я сделал это так, это в моем файле *.ascx:

<script type="text/javascript">
    var ClientIDs = {
        textBox1:    '<%= textBox1.ClientID %>',
        textBox2:    '<%= textBox2.ClientID %>'
    }
</script>

В моем внешнем скрипте у меня есть только функция для проверки:

function test () {
alert($(ClientIDs.textBox1).val();
}

Я также проверил это с "#" +. Каждый раз, когда выполняется test(), я получаю следующую ошибку:

"document.getElementById(...)" is null or not an object

Изменить 2: я пропустил ) в предупреждении. Но теперь я получаю сообщение о том, что переменная не определена. Если я использую: $('#' + ClientIDs.SumbitSearch).val(), я просто получаю текст, а не идентификатор своего элемента управления.

Редактировать 3: На данный момент я использую:

<script type="text/javascript">
    var ClientIDs = {
        test1 :    '<%= TextBox1.ClientID %>',
        test2 :    '<%= TextBox2.ClientID %>'
    }

    function test() {
       alert($('#' + ClientIDs.test1).attr("id")));
    }
</script>

В моем файле *.ascx это работает. Мне так не нравится... Во внешнем JS не работает, ссылки не работают. Если у кого-то есть другие идеи, которые будут работать с .net 3.5, было бы неплохо, если бы он дал мне знать.


person Andre Hofmeister    schedule 24.10.2011    source источник
comment
Я бы не стал определять переменные JS в вашем файле ASCX: страница может включать несколько элементов управления (или несколько экземпляров одного и того же элемента управления). Если каждый элемент управления определяет var ClientID, они будут конфликтовать друг с другом (проклятое глобальное пространство имен JS!). Если вы разрешаете своему файлу .ASPX только определять JS-переменную, по крайней мере, вы знаете, что у вас будет только одна переменная на странице.   -  person mikemanne    schedule 24.10.2011
comment
На самом деле, я определяю переменную JS вручную. Я нашел небольшой инструмент, который автоматически создает ClientIDs ссылка. Но я не могу получить доступ к переменной из моего внешнего JS. Грец.   -  person Andre Hofmeister    schedule 25.10.2011
comment
Я не уверен, что вы имеете в виду, определяя переменную JS вручную, и как это предотвращает конфликты, если один и тот же элемент управления определяет одну и ту же переменную, но включается на страницу несколько раз.   -  person mikemanne    schedule 25.10.2011
comment
...один и тот же контрол определяет один и тот же var... Извините, я не понимаю, в чем проблема? Вы имеете в виду, что если wepart добавляется несколько раз, элементы управления используют один и тот же идентификатор? Я проверил это. Если я использую на одном веб-сайте одну и ту же веб-часть несколько раз, идентификатор элемента управления каждого элемента управления отличается. Веб-часть 1: TextBox1 ID: ..._yyyyyy_ctl00_TextBox1ID Веб-часть 2: TextBox1 ID: ..._xxxxxx_ctl00_TextBox1ID Или вы имеете в виду, что переменная JS, в данном случае ClientIDs, существует более одного раза? Какое ему дело, если идентификаторы ClientID являются частными, а полный код JS находится в файле ascx. Или я это неправильно понял?   -  person Andre Hofmeister    schedule 27.10.2011
comment
Если вы напишите javascript var ClientIDs в своем файле ASCX, а затем включите 2 экземпляра этого элемента управления на страницу, тогда var ClientIDs будут дважды включены в отображаемую страницу. Поскольку переменные JS являются глобальными, два определения ClientID вашей переменной будут конфликтовать. Это либо вызовет ошибки JS, либо, что более вероятно, когда JS получит доступ к ClientID, вы понятия не имеете, какой из них будет использоваться.   -  person mikemanne    schedule 27.10.2011
comment
Я не уверен в JS, я думал, что вары не глобальны. Любое решение этой проблемы? Я не могу использовать clientIDMode="Static, SP2010 работает только с .net 3.5. Грец.   -  person Andre Hofmeister    schedule 28.10.2011
comment
Я что-то вроде JavaScript-программиста среднего уровня, поэтому я не могу сказать вам, какова общепринятая передовая практика для решения этой проблемы с глобальной переменной. Но я знаю, что есть способы справиться с этим. Книга Дугласа Кроуфорда «JavaScript, хорошие стороны» — выдающаяся книга, помогающая избежать ужасных частей JS, использовать хорошие части и разобраться с серой зоной между ними.   -  person mikemanne    schedule 28.10.2011


Ответы (4)


Чтобы объяснить и упростить вопрос, на который вы ссылаетесь, все, что они делают, - это устанавливают переменную JavaScript из элемента управления страницы/сервера и считывают эту переменную из внешнего файла JavaScript.

Например, ваш файл *.ascx будет содержать следующий код JavaScript:

var textBox1 = '<%= TextBox1.ClientID %>';

Тогда ваш внешний файл JavaScript может просто ссылаться на переменную textBox1.

Теперь есть другие способы добиться этого. Если вы используете ASP.NET 4, вы можете использовать новое свойство ClientIDMode, чтобы запретить ASP.NET изменять ваши идентификаторы. Если вы не используете ASP.NET 4, вы также можете просто добавить класс CSS к элементам, которые хотите выбрать, и просто изменить селектор jQuery для использования класса (хотя это немного медленнее, чем использование идентификатора).

Наконец, вам нужно будет использовать # при оценке селектора jQuery для идентификатора элемента, так что это будет работать:

alert($('#' + ClientIDs.test1).val());
person wsanville    schedule 24.10.2011
comment
См. мою Редактировать 1:. Спасибо за Ваш ответ. Грец. - person Andre Hofmeister; 24.10.2011
comment
Обновил селектор jQuery, мой был совершенно неправильным. Кроме того, метод val() не values. - person wsanville; 24.10.2011
comment
Проголосуйте за ClientIDMode - я забыл об этом. Это решает проблему .JS/ClientID. Конечно, это добавляет проблему, заключающуюся в том, что каждый элемент управления/страница отвечает за обеспечение уникального именования своих элементов. - person mikemanne; 24.10.2011
comment
Правда, использование clientIDMode="Static" заставляет вас немного подумать/перепроверить заранее. Но для случаев, когда у вас есть только один экземпляр элемента управления, это намного лучше с точки зрения CSS/JS. - person wsanville; 24.10.2011
comment
Хорошо, я попробую с «clientIDMode». Но сейчас я сделаю перерыв. Я дам вам завтра отзыв, если все работает нормально. Грец. - person Andre Hofmeister; 24.10.2011
comment
Метод clientIDMode выглядит хорошо, но как мне выбрать .net 4 Frameworks в качестве основного фреймворка для моего проекта? Я просто мог выбрать 3,5. Я установил Targeting Pack и Runtime. Если я создаю новый проект, фреймворк устанавливается на 4, но в свойствах проекта снова выбирается фреймворк 3.5. Грец. Изменить: Правда ли, что sharepoint 2010 не поддерживает .net 4? ... Итак, метод clientIDMode умирает... - person Andre Hofmeister; 25.10.2011

На странице ASP:

<script>
    var test2 = '<%= TextBox2.ClientID %>'
</script> 

А во внешнем доступе к JavaScript TextBox2 таким образом:

documnet.getelementByid(test2);
person Jahangeer Ahmed    schedule 27.08.2012

Я никогда не находил решения, которое мне нравится, но я реализовал пару обходных путей, которые не являются полностью ужасными:

  • Для кода JS, который должен ссылаться на определенные элементы страницы, определите его в файле .aspx, чтобы у вас был доступ к ‹%= btnFoo.ClientID %>. Эти функции могут вызывать обычные тяжелые функции в вашем файле .js.
  • Определите переменные javascript в файле .aspx для хранения значений ClientID. Функции в вашем файле .js могут ссылаться на эти переменные для получения идентификаторов клиентов. Конечно, эти функции будут корректно работать только на страницах, которые определяют ожидаемые переменные.

Возможно, у других SO'ers будут более элегантные решения этой проблемы - я с нетерпением жду других ответов.

person mikemanne    schedule 24.10.2011
comment
Это правда. Я также не нашел решения, что довольно приятно. Грец. - person Andre Hofmeister; 24.10.2011
comment
Если у вас нет нескольких экземпляров пользовательского элемента управления на странице, самым элегантным решением будет установить clientIDMode="Static" в узле <pages> вашего файла web.config. Это было введено в ASP.NET 4. - person wsanville; 24.10.2011

Использовать явный глобальный параметр.

window.clientId= '‹%= TextBox1.ClientID %>';

это означает, что у вас есть глобальная переменная "cilentId". И тогда вы сможете использовать его везде.

person Sergey    schedule 25.10.2011
comment
Насколько я понимаю, любое использование ключевого слова var в JS - это то же самое, что и применение var к объекту окна (за исключением vars, определенных специально в рамках функции). Возможно мое понимание неверно? - person mikemanne; 25.10.2011