I am calling SP.UI.ModalDialog.showModalDialog() in a javascript function of my Web Part (SharePoint 2010) but the dialog appears for one second, then closes itself.
Originally, I wanted to call a sharepoint page (in Layouts folder) but I am testing with a simple dialog to make sure it isn't an error in my sharepoint page.
In the Web Part, I have a table where each first cell row is a LinkButton. I have set the OnClientClick to call a javascript function :
linkButton.OnClientClick = string.Format("OpenNotationCurveDialog('{0}');",
notation.code);
In the script block of the web part ASCX, I have :
function OpenNotationCurveDialog(notationCode) {
var htmlElement = document.createElement('p');
var helloWorldNode = document.createTextNode('Hello world!');
htmlElement.appendChild(helloWorldNode);
var options = {
title: "Add item",
allowMaximize: true,
showClose: true,
width: 800,
height: 600,
html: htmlElement,
dialogReturnValueCallback: CurveDialog_ClosedCallback
};
SP.UI.ModalDialog.showModalDialog(options);
return false;
}
function CurveDialog_ClosedCallback(result, value) {
console.log('!! CurveDialog_ClosedCallback !!');
}
The function CurveDialog_ClosedCallback is never called.
In the same Web Part, I have added an element to the Web Part menu that calls the javascript function SP.UI.ModalDialog.showModalDialog() : it is working perfectly. I don't understand why it is working when calling showModalDialog() from the menu and not working from the LinkButton client event.
Any idea how to solve this very annoying behavior ?
thx
What probably happens is that the linkbutton performs a postback so that the page reloads, causing the dialog to disappear Try using a simple anchor-tag instead.
Related
hi i'm having a problem with sharepoint web part
so i want to call message box everytime user input is wrong
so for example if user input password more than 15 than there will be message box that says"Password lenght max 15"
when i wrote
Messagebox.show("Password lenght max 15") it works fine,but if i try to fill password more than 15 than it return error that says sharepoint cannot support message box
so i'm wondering if there's a way to use message box in sharepoint
any help will be appreciated
FYI i put the Messagebox.show in my save button click
thank you
sorry if my english are bad
Message box is not supported in ASP.NET Application so similar in Sharepoint.
SharePoint Support MessageDialog.
SP.UI.ModalDialog.showModalDialog(options)
If you want to open through server side, then you need to create JS function and call it through C# or as below
hyperLink.NavigateUrl = "javascript:SP.UI.ModalDialog.ShowPopupDialog('" + url + "')";
You can send proper string as well using options.
This may be old post, but accepted answer does not work too good in Sharepoint 2013, at least for me. Instead, I have to use this script:
<script ID="callMyFunction">
function myFunction() {
var element = document.createElement('div');
element.innerHTML = 'Hello World, I am the dialog content';
var options = {}
options.title = "Name of dialog";
options.width = 400;
options.height = 300;
options.html = element;//MSDN states it should be string, which is wrong. This is supposed to be DOM element
SP.SOD.execute('sp.ui.dialog.js', 'SP.UI.ModalDialog.showModalDialog', options);//This starts function "showModalDialog" after loading "sp.ui.dialog.js", if it was not loaded yet.
}
</script>
and call it from my WebPart like this:
Page.ClientScript.RegisterStartupScript(this.GetType(), "callMyFunction", "myFunction()", true);
If you want to use Ali Murtaza answer, remember to load script below, as it seems to be not loaded by default:
<script type="text/javascript" src="_layouts/15/sp.ui.dialog.js"></script>
I am facing issue with opening a custom portlet in popup window.
Below is the code of opening popup.
LiferayPortletURL documentLibURL = PortletURLFactoryUtil.create(request, "portlet name with WAR name", themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
documentLibURL.setWindowState(LiferayWindowState.POP_UP);
documentLibURL.setPortletMode(PortletMode.VIEW);
AUI().use('aui-dialog', 'aui-io', 'event', 'event-custom', function(A) {
var dialog = new A.Dialog({
width: 800,
height: 500,
title: 'Popup Title',
centered: true,
draggable: true,
modal: true
}).plug(A.Plugin.IO, {uri: '<%= documentLibURL.toString() %>'}).render();
dialog.show();
});
When my portlet is not having any call to local services, portlet is being rendered in popup. But after adding some complex code. Portlet is giving permission error.
"You do not have the roles required to access this portlet."
1) I have also added true in liferay-portlet.xml.
2) I have assigned permissions to guest user for view from control panel.
Please let me know if any changes requires.
Thanks in advance
Local service calls will never generate a permission exception (PrincipalException) but remove services will.
Audit your code that this URL will invoke and see if there are any remove service calls. They are easily distinguished. For example, if it is the User service you're working with a call to UserLocalServiceUtil will never throw a PrincipalException but a call to UserServiceUtil will. Check to see what calls you're making to *ServiceUtil and ensure the user performing the operation has sufficient access.
Which version of liferay your using.
The dialog will not work in liferay 6.2 and also maybe in 6.1, refer the below code.
function popup(url){
AUI().ready(function(A) {
AUI().use('aui-base', function(A) {
Liferay.Util.Window.getWindow(
{
title : "Popup Tile",
uri: url,
dialog: {
cache: false,
modal: true
}
}
).on('hide', function() {
console.log("Modal closed")});
});
});
}
if its correct dont forget to mark it as an answer
just add in your portal-ext.properties the following code and restart the server
layout.show.portlet.access.denied=false
I have a page hosted in 'virtualcasa1' domain opening a modal dialog:
var options = {
title: "Repro",
width: 400,
height: 600,
url: http://domain2:999/sites/blank/_layouts/XDomainTest/XDomainTestTarget.aspx //[1]
//url: http://virtualcasa1/sites/blank/_layouts/XDomainTest/XDomainTestTarget.aspx [2]
};
SP.UI.ModalDialog.showModalDialog(options);
And I have this code to close it:
alert(document.domain);
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, 'Cancelled clicked');
If both are in the same domain (case [2] above), the dialog closes well, no issues.
But - if target page hosted in the dialog (case [1] above), dialog does NOT close :-(
document.domain above shows the correct domain where page exists.
I suspect I'm facing a cross-domain issue here (duh), but how to fix it? Or am I wrong and issue is not XDomain-related?
Thanks much!
HTML5's postMessage is your answer.
https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage
Your parent window that initiates the dialog must have the following javascript:
function listener(event) {
//alert(event.data);
if (event.data == 'Cancel') {
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, 'Cancel clicked');
}
else {
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, event.data);
}
}
if (window.addEventListener) {
addEventListener("message", listener, false)
} else {
attachEvent("onmessage", listener)
}
Javascript for OK and Cancel buttons in your popup:
<input type="button" value="OK" onclick="parent.postMessage('Message to be displayed by the parent', '*');" class="ms-ButtonHeightWidth" />
<input type="button" value="Cancel" onclick="parent.postMessage('Cancel', '*');" class="ms-ButtonHeightWidth" />
Ajay's answer from the 1st of August 2014 is good, but it needs a bit more explanation. The reason for the failure to close the dialog is simple. Cross site scripting security features of modern browsers disallow a few things, one of which is the use of window.frameElement from within the framed window. This is a read-only property on the window object and it becomes set to null (or with IE, it actually throws an exception when you try to access it). The ordinary Cancel event handlers in the modal dialog conclude with a call to window.frameElement.cancelPopup(). This will fail of course. The ordinary Save handler where the Save worked on the server side results in SharePoint sending back a single line as the replacement document, which is a scriptlet to call window.frameElement.commitPopup(). This also will not work, and it's a real pain to overcome because the page has been reloaded and there is no script available to handle anything. XSS won't give us access to the framed DOM from the calling page.
In order to make a cross domain hosted form work seamlessly, you need to add script to both the page that opens the dialog and the framed page. In the page that opens the dialog, you set the message listener as suggested by Ajay. In the framed form page, you need something like below:
(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);
}
});
})();
This solution makes use of the jQuery library, which our organization uses extensively. It is our preferred framework (chosen by me). I'm sure someone very clever could rewrite this without that dependency, but this is a good starting point. I hope someone finds it useful, as it represents a good two days work. Some things to note:
SharePoint does a postback on all sorts of events on the page, including putting the page into edit mode. Because of this, it makes more sense to trap the specific button clicks, both on the form and in the ribbon, rather than wholesale redefinition of, for example, the global WebForm_OnSubmit function. We briefly override that on a Save click and then set it back.
On any Save click event, we defeat the normal posting of the form and replace that with an identical POST request using AJAX. This allows us to discard the returned scriptlet when the form was successfully posted. When the form submission was not successful, perhaps because of blank required values, we just post the form properly to allow the page to be updated. This is fine, since the form will not have been processed. An earlier version of this solution took the resulting HTML document and replaced all of the page contents, but Internet Explorer doesn't like this.
The FormData api allows us to post the form as multipart-mime. This api has at least basic support in all modern browsers, and there are workarounds for older ones.
Another thing that seems to fail in the cross domain hosted dialog is the scrolling of the content window. For whatever reason, the height is not set correctly on the div with id s4-workspace, so we also set that in the solution.
EDIT:
Almost forgot. You may also need to add this control to your framed ASPX page, which can be done with SharePoint Designer:
<WebPartPages:AllowFraming runat="server"/>
I have exactly the same issue - a dialog opening a view page for an item works fine when opened from a site collection on the same web app/domain, but the Close button fails to work when opening the same item from a site collection hosted in a separate web application. I'm assuming it is a cross-domain thing so I've altered the solution to accomodate this restriction, however, I'm not 100% happy about it as it does make the overall solution a little awkward to use from a user-perspective. I've put the issue to one side for now due to project timescales, but I'm still curious as to why. The only things I can think of is the whole cross-domain thing causing it and that maybe it is there by design to prevent XSS security holes.
My Background:
I am new to WatiN, but not new to writing automated Web UI tests. At my new job, we are trying to use WatiN for our Web UI tests (thanks to a few CUIT fails).
I've solved this problem in the past using ArtOfTest.WebAii, by using a Win32 mouse click with a magic number offset from the containing element, but I can't seem to find documentation on how to do that in WatiN and I can't figure it out myself :\
My problem:
This dialog appears and I can't seem to find a way for WatiN to click it.
The dialog has the following markup:
<OBJECT style="FILTER: alpha(opacity=1); WIDTH: 329px; HEIGHT: 100px; mozOpacity: 0.01; opacity: 0.01; mozopacity: 0.01" data="data:application/x-oleobject;base64, <a bunch of data>" width=329 height=100 type=application/x-silverlight-2></OBJECT>
<param name="source" value="/CuteWebUI_Uploader_Resource.axd?type=file&file=silverlight.xap&_ver=634334311861475176"/>
<param name="windowless" value="true" object="" <=""/>
my test code:
[TestMethod]
public void SomeTest()
{
Settings.MakeNewIeInstanceVisible = true;
Settings.AutoStartDialogWatcher = true;
Settings.AutoMoveMousePointerToTopLeft = false;
using (IE ie2 = new IE())
{
ie2.GoTo(URL);
ie2.Link(SomeButtonID).Click();
ie2.Image(AnotherButtonID).FireEvent("onclick");
// some debugging code wrapped around the next user action
// which is clicking on the attach file button
var helper = new DialogHandlerHelper();
using (new UseDialogOnce(ie2.DialogWatcher, helper))
{
Thread.Sleep(1 * 1000); // wait for attach button to be "ready"
// Click button that triggers the dialog that states:
// "file browsing dialog has been blocked"
// "please click here and try again"
//
ie2.Button(FileAttachButtonID).FireEvent("onclick");
}
foreach(string dialogHandler in helper.CandidateDialogHandlers)
{
// nothing prints out here :(
Console.Out.WriteLine(dialogHandler);
}
// debug print out all elements with tagname = object
foreach (Element objectElement in ie2.ElementsWithTag("object"))
{
StringBuilder elementInfo = new StringBuilder();
elementInfo.AppendLine("--------------------------------------------");
elementInfo.AppendLine("element.tagname = " + objectElement.TagName);
elementInfo.AppendLine("element.style = " + objectElement.Style);
elementInfo.AppendLine("element.type = " + objectElement.GetAttributeValue("type"));
elementInfo.AppendLine("element.data = " + objectElement.GetAttributeValue("data"));
elementInfo.AppendLine("--------------------------------------------");
Console.Out.WriteLine(elementInfo.ToString());
// none of these clicks make the dialog go away
objectElement.ClickNoWait();
objectElement.Click();
objectElement.DoubleClick();
objectElement.MouseEnter();
objectElement.MouseDown();
Thread.Sleep(500);
objectElement.MouseUp();
}
// wait to see if dialog disappears after click
Thread.Sleep(300 * 1000);
}
}
Any and all help will be very much appreciated.
Thanks!
Your control is a silverlight component which can't be automated with WatiN. Fortunately this you can combine WatiN and White to get the job done.
Following code is created and published by Leo Bartnik so ALL the credits go to him! Have a look at his blog post here. The following code in the comments:
He used the following versions.
watin-2.0.50.1179.zip from 2011-02-08 http://sourceforge.net/projects/watin/files/WatiN%202.x/2.0%20Final/
white 0.20 Binaries http://white.codeplex.com/releases/view/29694
public void WatiN_and_White_join_forces()
{
// Navigate to your webpage with WatiN
string url = "http://localhost[port#]/WatinWhiteTestLandingPage.aspx";
WatiN.Core.IE watin = new WatiN.Core.IE(url);
watin.Link(Find.ByText("click here)).Click();
// Attach the IE instance used by WatiN to White
InternetExplorerFactory.Plugin();
string title = "[browser title here]"; // will be something like "WatinWhiteHybrid - Internet Explorer provided by ..."
var ie = (InternetExplorerWindow)Application.Attach(watin.ProcessID).GetWindow(title);
White.WebBrowser.Silverlight.SilverlightDocument sl = ie.SilverlightDocument;
// Click the button in the silverlight control using White
sl.Get(SearchCriteria.ByAutomationId("ClickMeId")).Click();
}
btw don't know why the formating of this code is so way off....
So this was my hack solution:
Use Microsoft's Coded UI Test to click on the Silverlight dialog. However, CUIT is inferior to WatiN, so I run my test in WatiN and load CUIT for one, magical, click.
Additionally, I was not able to easily find the Silverlight object using CUIT, so I find the window behind it, find the window's center pixel and force a Microsoft.VisualStudio.TestTools.UITesting.Mouse.Click(). Yes, a hack inside of a hack, I am a very bad person, but I ran out of time and just needed something working.
If anyone has a more elegant solution, please share.
My solution code:
FileUploadDialogHandler helper = new FileUploadDialogHandler(attachmentPath);
using (new UseDialogOnce(ie.DialogWatcher, helper))
{
Thread.Sleep(1 * 1000); // wait for attach button to be "ready"
ie.Button(browseButtonID).FireEvent("onclick");
// When automating a file upload, there is a Silverlight popup in IE that forces an extra click
// before opening the file open dialog. WatiN does not support Silverlight automation
// and the popup element was acting quirky in Microsoft's Coded UI Test, so we find the
// dialog box UNDERNEATH the Silverlight popup and force one, lovely, mouse click.
//===== Entering Coded UI Test land, beware! =====================================
// initialize Coded UI Test
Playback.Initialize();
BrowserWindow.CurrentBrowser = "IE";
Process watinBrowserProcess = Process.GetProcessById(ie.ProcessID);
BrowserWindow cuitBrowser = BrowserWindow.FromProcess(watinBrowserProcess); // attach Coded UI Test to the IE browser WatiN initialized
// get the window underneath the Silverlight popup
UITestControl modalUnderSilverlightPopup = new UITestControl(cuitBrowser.CurrentDocumentWindow);
modalUnderSilverlightPopup.SearchProperties.Add("id", windowElementUnderPopupID);
// get the X and Y pixel center of the window
int centerX = modalUnderSilverlightPopup.BoundingRectangle.X + modalUnderSilverlightPopup.BoundingRectangle.Width / 2;
int centerY = modalUnderSilverlightPopup.BoundingRectangle.Y + modalUnderSilverlightPopup.BoundingRectangle.Height / 2;
// Click!
Mouse.Click(new Point(centerX, centerY));
// Shutdown Coded UI Test
Playback.Cleanup();
//===== End Coded UI Test land, you survived! yay! ============================
}
I have this script below that will call my browse window;
var $dialog = $('<div></div>')
.load('scripts/browsecharges.jsp')
.dialog({
width: 800,
height: 500,
modal: false,
title: 'Browse Charges',
buttons: {
Ok: function() {
$(this).dialog('destroy');
}
},
close: function(event, ui) {
$(this).dialog('destroy').remove();
}
});
$dialog.dialog('open');
This browse window contains a jqgrid in it. At first my jqgrid works fine, I can see the data. But calling this browse window for the second time, my jqgrid will not show anymore. What should I do to open it as many times as I want?
Perhaps you need to call GridUnload prior to creating the grid, to ensure any elements from the previous grid are cleaned up.
I had this problem when a page was load via a .ajax call. The page contained dialogs with grids. On the first call everything worked great, on the second call (loaded another page and then reloaded the page) I would get an empty jqGrid, event though msg.d was clearly being set properly. The answer was when I left the page (loaded another page via .ajx) to destroy and remove the grid ($(this).dialog('destroy').remove()).