Зарегистрируйте js для пользовательского типа поля в SharePoint 2013
-
10-12-2019 - |
Вопрос
У меня есть пользовательский тип поля для SharePoint 2010/2007, но после перехода на SharePoint 2013 я столкнулся с проблемой.
Вот что я определил для "RenderPattern" в fldtypes_myfield.xml
<RenderPattern Name="DisplayPattern">
<HTML><![CDATA[<script type="text/javascript" src="/_layouts/myfield/myjs.js"></script>]]></HTML>
<HTML><![CDATA[<img src="/_layouts/images/myfield/pic.png" onload="myfun()">]]></HTML>
</RenderPattern>
функция myfun() определена в myjs.js, поэтому при загрузке pic.png она будет выполнять функцию.Это прекрасно работает в 2010/2007 и 2010 годах для пользователей SharePoint 2013.
В 2013 году, в разделе пользовательский опыт 2013, когда я просматриваю список, содержащий myfield, он выдает ошибку:
myfun is not defined
Итак, причина очевидна, myjs.js не добавляется на страницу.(Ссылка js верна, скопируйте ссылку в адресную строку, и браузер сможет отобразить ее)
Итак, мой вопрос заключается в следующем: почему myjs.js не зарегистрирован?
Есть какие-нибудь идеи?Заранее благодарю.
Обновить:
Это не работает на странице "ListView", но работает на странице "DisplayForm".Для параметра "CAMLRendering" установлено значение true.На странице "ListView", если вы проверите это поле с помощью инструмента веб-разработчика, html-разметка внутри:
<SCRIPT type=text/javascript src="/_layouts/myfield/myjs.js"></SCRIPT>
<DIV><IMG src="/_layouts/images/myfield/pic.png" onload="myfun()"></DIV>
Запрещает ли SharePoint 2013 загрузку js?
Решение
После отладки я обнаружил, что существует переменная с именем "WPQ2ListData", которая хранит содержимое списка данных, ее формат:
var WPQ2ListData = {
"Row": [{
"ID": "1",
"PermMask": "0x7fffffffffffffff",
"FSObjType": "0",
"Title": "A",
"FileLeafRef": "1_.000",
"Created_x0020_Date.ifnew": "1",
"FileRef": "\u002ftest\u002fLists\u002fRatingList\u002f1_.000",
"File_x0020_Type": "",
"File_x0020_Type.mapapp": "",
"HTML_x0020_File_x0020_Type.File_x0020_Type.mapcon": "",
"HTML_x0020_File_x0020_Type.File_x0020_Type.mapico": "icgen.gif",
"ContentTypeId": "0x01008AD43674D321D3428ACAFC1C3BD2971E",
"MyField": "<script type=\"text/javascript\" src=\"/_layouts/myfield/myjs.js\"></script><img src=\"/_layouts/images/myfield/pic.png\" onload=\"myfun()\">"
}],
"FirstRow": 1,
"LastRow": 1,
"FilterLink": "?",
"ForceNoHierarchy": "1",
"HierarchyHasIndention": ""
}
Обратите внимание на "MyField", в нем есть содержимое, которое должно быть отображено.
На странице "WPQ2ListData" используется в одном месте:
ctx = new ContextInfo();
//other assignments
ctx.ListData = WPQ2ListData;
Затем "ctx" будет передан функции "RenderListView", которая отвечает за рендеринг представления списка.Эта функция определена в "clienttemplates.js".Если вы углубитесь в него, то обнаружите, что он вызовет другую функцию под названием "SPClientRenderer.Render", в этой функции она сгенерирует все html-содержимое для данных списка и вставит его в td (возможно, div) как innerHTML.
var result = SPClientRenderer.RenderCore(renderCtx);
if (result != null && result != '') {
if (node.tagName == "DIV" || node.tagName == "TD") {
if (renderCtx.fHidden)
if (renderCtx.fHidden)
node.innerHTML = result;
}else{
//create div element, and insert result as innerHTML
}
}
Обратите внимание на "node.innerHTML = result", потому что если некоторое строковое содержимое вставлено в один элемент как innerHTML и содержимое содержит код JavaScript, js-код выполняться не будет.И вот почему "myjs.js" не добавляется на страницу! Я думаю, что это одно из больших различий при рендеринге списка в 2010 и 2013 годах, в 2010 году html-данные списка выводятся на страницу напрямую, в то время как в 2013 году они вставляются на страницу динамически.
Решение:
На самом деле, есть еще одно место, которое содержит js-код и может выполнить этот код.В img это "onload" (загрузка).Итак, почему бы нам не зарегистрировать наш js-файл здесь?И после загрузки myjs.js пусть он вызовет myfun()!
var head = document.getElementsByTagName("head")[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '/_layouts/myfield/myjs.js';
script.onload = script.onreadystatechange = function() {
myfun();
};
head.appendChild(script);
И для повышения производительности нам не нужно регистрироваться myjs.js для каждой строки мы должны сначала проверить, существует ли она.