阿賈伊的回答
https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage
發起的對話必須有以下的javascript你的父窗口2014年8月1日是好的,但它需要更多的解釋。未能關閉對話框的原因很簡單。現代瀏覽器的跨站點腳本安全功能不允許使用一些東西,其中之一是在框架窗口內使用window.frameElement。這是窗口對象的只讀屬性,它被設置爲null(或者用IE,當你試圖訪問它時,它實際上會引發異常)。模態對話框中的普通的Cancel事件處理程序以對window.frameElement.cancelPopup()的調用結束。這當然會失敗。 Save在服務器端工作的普通保存處理程序導致SharePoint將單行作爲替換文檔發送回來,該替換文檔是調用window.frameElement.commitPopup()的scriptlet。這也是行不通的,這是一個真正的痛苦,因爲頁面已經被重新加載,並且沒有腳本可用於處理任何事情。 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函數。我們簡單地覆蓋保存點擊,然後將其設置回來。
在任何保存點擊事件中,我們打敗了表單的正常發佈,並使用AJAX將其替換爲相同的POST請求。這使我們能夠在表單成功發佈時放棄返回的scriptlet。當表單提交不成功時,可能是因爲需要空白值,我們只是正確發佈表單以允許更新頁面。這很好,因爲表單不會被處理。此解決方案的早期版本將生成的HTML文檔替換爲所有頁面內容,但Internet Explorer不喜歡這樣。
FormData API允許我們post the form as multipart-mime。這個api至少在所有現代瀏覽器中都有基本的支持,並且對於較老的瀏覽器有解決方法。
在跨域託管對話框中似乎失敗的另一件事是滾動內容窗口。無論出於何種原因,使用id s4-workspace的div的高度設置不正確,因此我們也在解決方案中設置了該高度。編輯: 差點忘了。您可能還需要將此控件添加到您的框架ASPX頁面,它可以與SharePoint設計來完成:
< WebPartPages:AllowFraming RUNAT =「服務器」/>