Ответ Аджая от 1 августа 2014 года хорош, но требует немного большего объяснения.Причина невозможности закрыть диалог проста.Функции безопасности межсайтовых сценариев современных браузеров запрещают несколько вещей, одной из которых является использование window.frameElement из рамочного окна.Это свойство доступно только для чтения в объекте окна, и ему присваивается значение null (или в IE оно фактически выдает исключение при попытке доступа к нему).Обычные обработчики событий Cancel в модальном диалоговом окне завершаются вызовом window.frameElement.cancelPopup ().Это не удастся, конечно.Обычный обработчик Save, где Save работал на стороне сервера, приводит к тому, что SharePoint отправляет обратно одну строку в качестве документа замены, который представляет собой скриптлет для вызова window.frameElement.commitPopup ().Это также не сработает, и это реальная боль, которую нужно преодолеть, потому что страница была перезагружена, и нет сценария для обработки чего-либо.XSS не даст нам доступ к DOM в рамке с вызывающей страницы.
Для того, чтобы междоменная форма работала без проблем, вам нужно добавить скрипт как на страницу, которая открывает диалог, так и на рамку.стр.На странице, которая открывает диалоговое окно, вы устанавливаете прослушиватель сообщений в соответствии с предложением Ajay.На странице формы в рамке вам нужно что-то вроде следующего:
(function() {
$(document).ready(function() {
var frameElement = null;
// Try/catch to overcome IE Access Denied exception on window.frameElement
try {
frameElement = window.frameElement;
} catch (Exception) {}
// Determine that the page is hosted in a dialog from a different domain
if (window.parent && !frameElement) {
// Set the correct height for #s4-workspace
var frameHeight = $(window).height();
var ribbonHeight = $('#s4-ribbonrow').height();
$('#s4-workspace').height(frameHeight - ribbonHeight);
// Finds the Save and Cancel buttons and hijacks the onclick
function applyClickHandlers(theDocument) {
$(theDocument).find('input[value="Cancel"]').removeAttr('onclick').on('click', doTheClose);
$(theDocument).find('a[id="Ribbon.ListForm.Edit.Commit.Cancel-Large"]').removeAttr('onclick').removeAttr('href').on('click', doTheClose);
$(theDocument).find('input[value="Save"]').removeAttr('onclick').on('click', doTheCommit);
$(theDocument).find('a[id="Ribbon.ListForm.Edit.Commit.Publish-Large"]').removeAttr('onclick').removeAttr('href').on('click', doTheCommit);
}
// Function to perform onclick for Cancel
function doTheClose(evt) {
evt.preventDefault();
parent.postMessage('Cancel', '*');
}
// Function to perform onclick for Save
function doTheCommit(evt) {
evt.preventDefault();
if (!PreSaveItem()) return false;
var targetName = $('input[value="Save"]').attr('name');
var oldOnSubmit = WebForm_OnSubmit;
WebForm_OnSubmit = function() {
var retVal = oldOnSubmit.call(this);
if (retVal) {
var theForm = $('#aspnetForm');
// not sure whether following line is needed,
// but doesn't hurt
$('#__EVENTTARGET').val(targetName);
var formData = new FormData(theForm[0]);
$.ajax(
{
url: theForm.attr('action'),
data: formData,
cache: false,
contentType: false,
processData: false,
method: 'POST',
type: 'POST', // For jQuery < 1.9
success: function(data, status, transport) {
console.log(arguments);
// hijack the response if it's just script to
// commit the popup (which will break)
if (data.startsWith('<script') &&
data.indexOf('.commitPopup()') > -1)
{
parent.postMessage('OK', '*');
return;
}
// popup not being committed, so actually
// submit the form and replace the page.
theForm.submit();
}
}).fail(function() {
console.log('Ajax post failed.');
console.log(arguments);
});
}
return false;
}
WebForm_DoPostBackWithOptions(
new WebForm_PostBackOptions(targetName,
"",
true,
"",
"",
false,
true)
);
WebForm_OnSubmit = oldOnSubmit;
}
applyClickHandlers(document);
}
});
})();
В этом решении используется библиотека jQuery, которая широко используется нашей организацией.Это наш предпочтительный каркас (выбранный мной).Я уверен, что кто-то очень умный мог бы переписать это без этой зависимости, но это хорошая отправная точка.Я надеюсь, что кто-то найдет это полезным, поскольку он представляет собой хорошую двухдневную работу.Некоторые вещи, на которые следует обратить внимание:
SharePoint выполняет обратную передачу всех событий на странице, включая перевод страницы в режим редактирования.В связи с этим более целесообразно отлавливать определенные нажатия кнопок, как на форме, так и на ленте, а не переопределять целиком, например, глобальную функцию WebForm_OnSubmit.Мы кратко переопределяем это при нажатии кнопки «Сохранить», а затем устанавливаем его обратно.
При любом событии нажатия кнопки «Сохранить» мы отменяем нормальное размещение формы и заменяем его идентичным запросом POST с использованием AJAX.Это позволяет нам отказаться от возвращенного скриптлета, когда форма была успешно размещена.Когда отправка формы не удалась, возможно, из-за пустых обязательных значений, мы просто публикуем форму правильно, чтобы позволить странице обновляться.Это нормально, так как форма не будет обработана.Более ранняя версия этого решения взяла полученный HTML-документ и заменила все содержимое страницы, но Internet Explorer это не нравится.
API FormData позволяет опубликовать форму как multipart-mime .Этот API имеет, по крайней мере, базовую поддержку во всех современных браузерах, и есть обходные пути для старых.
Еще одна вещь, которая, по-видимому, не работает в междоменном диалоговом окне, - это прокрутка окна контента.По какой-то причине высота не установлена правильно в div с идентификатором s4-workspace, поэтому мы также установили это в решении.
РЕДАКТИРОВАТЬ: Почти забыл.Вам также может понадобиться добавить этот элемент управления на страницу ASPX в рамке, что можно сделать с помощью SharePoint Designer: