SharePoint Modal Dialog from HTML

The problem

The SharePoint SP.UI.ModalDialog namespace enables you to open a Modal Dialog by specifiying either a URL to load inside the dialog, either a string containing the HTML to display in the dialog.

Wait… the second option won’t work. What the documentation says about the html parameter is: “A string that contains the HTML of the page that appears in the dialog”.

So the following piece of code should open a modal dialog with the “Hello world” mention:

In fact it won’t do anything. No error and no dialog. I think you will agree that the documentation is wrong on this point. The html parameter is not a string containing HTML, it is a DOM Element that will be displayed in the Modal Dialog. And you know what? That makes sense. Specifying an HTML string would have been restrictive especially when dealing with events.

Here is a full working version of our “Hello world” example:

Nice!!! Wait a minute… You should see two drawbacks in this solution:

  • The content of the dialog is displayed before opening the dialog
  • It works only one time. The dialog cannot be opened multiple times without refreshing the page.

The first point could be easily forgotten, it’s easy to hide the element on the parent page with a “display: none” and remove it after opening the dialog.
The second problem is a lot more interesting because it gives us a clue about the Modal Dialog’s mecanism. When the dialog is opened the DOM Element specified by the HTML parameter is not copied. The element is nothing more than removed from its parent container, then added to the dialog content.

Cool isn’t it?

The solution

One solution would be to create the DOM elements in memory with document.createElement but that’s painful and not easy to maintain. My solution is the following:

  • Put the markup of the dialog into a script block which won’t be rendered or interpreted by the browser thanks to a type=”text/html” attribute
  • Create a DOM Element in memory with jQuery with the markup specified in the script block
  • Attaching events in memory thanks to jQuery
  • Opening the Modal Dialog with the DOM Element created in memory

Here is a working example:

Note : your script block MUST contain only ONE root element. The jQuery call $($(‘#DialogMarkup’).html()) will take all the nodes of the markup block into account but the statement “return dialogElement.get(0)” returns only the first one. That’s the reason why I put a single div around my controls.

The final result is very simple. When you click on the “Open Dialog” button a SharePoint Modal Dialog is opened and displays a text box. When you click on the “Submit” button after entering content into the text box, the dialog is closed and your text is displayed by the opening page.

SharePoint Well Known Fields / Content Types Id

I’m used to post about specific scenarios and their resolution. Here I’m posting a sort of note to myself because I always forgot where is located this list of SharePoint built in fields ID and Content Types ID.

The list of Fields ID : Microsoft.SharePoint.SPBuiltInFieldId
The list of Content Types ID : Microsoft.SharePoint.SPBuiltInContentTypeId

So if you want to get the user who created an item you can use the following code :

Ajax File Upload Workaround in SharePoint 2010

Today I decided to post about a feature I developed this week. I’m currently working on a Social Project hosted on SharePoint 2010 and we are developing a WebPart to Post your status and share an optional image.

The WebPart must display an input file field to choose the picture to share and a preview must be displayed to the user before he decides to post his status. We are trying to avoid as much as possible PostBacks to offer an improved user experience.

The problem : How to post an input file dynamically without refreshing the entire page ?

My first idea was : with an Ajax call of course ! Unfortunately to do this you have to use the File API added to the DOM in HTML5, but guess what? Internet Explorer does not support this.

The workaround : posting the ASP .Net form into a hidden frame. The frame returns the image, then a script extracts it from the frame’s DOM and insert it into a container in the main page. Thanks to this only the frame is reloaded, this is transparent to the user.

The image is not saved in the server, all the operations occurs in memory, the goal is only to display a preview of the image. Of course you can modify my sample to save the image server side.

Downloading the solution

You can download the entire solution here : download solution.

You should be able to compile it without doing anything else but if you want to deploy it on your SharePoint environment you will have to sign-it with your key.

Step 1 – The project

Creates a new Empty SharePoint Project with Visual Studio, I choosed “Wawawum.DynamicUpload”. If you don’t already have JQuery deployed in your environment you can reuse my project “Wawawum.JQuery” and include it into your solution.

Then add a Visual WebPart “ImagePreviewWebPart” and add it to the Default Feature if it is not already included.

Map the “Layouts” folder to your project and add a new Application Page “PreviewImage.aspx” into it.

SolutionTree

Your project tree should be like the screenshot above. Now we just have to fill the blanks Smile

Step 2 – The UserControl

Let’s create our controls that will post the image and display the preview. Add the following lines to your “ImagePreviewWebPartUserControl.ascx”:

This code is pretty straight forward but here is the goal of the controls:

  • ImageInput : the form field which will contains the path to the file to upload
  • ImagePreviewSubmit : the form button which submits the ASP .Net form into the iframe
  • ImagePreviewLoadingContainer : the div which displays a “Loading” message and image
  • ImagePreviewContainer : this div contains the preview of the image
  • ImagePreviewUploadFrame : the frame in which the form is posted. Using this iframe avoids the entire page to be reloaded when uploading the file.

Step 3 – Few lines of JavaScript

Now we need some JavaScript to post the ASP .Net form into the frame and retrieved the content of the frame to display it in the correct container. Add the following JavaScript block in the ImagePreviewWebPartUserControl after the HTML Controls.









































































Here are the main points of this script:

  • initImagePreview (line 7) : binds events to the controls. Notice that I used ASP .Net Inline Server Tags into my JavaScript to get the client ids of each controls. By using HTML Controls with the runat=’server’ attribute I’m sure to avoid conflicts when adding two instances of the same WebPart in a page.
  • imagePreview_onPreviewLinkClick (line 22) : called when the preview button is clicked. This function posts the ASP .Net form in the iframe. We have to modify the target and action attributes of the form to do that. The original values of these attributes are saved before posting and restored after.
  • imagePreview_onFrameLoaded (line 48) : called when the iframe is loaded. This function retrieves the img element generated by the browser (I tested it in Internet Explorer and Chrome and the code generated is compatible). Then this element is extracted from the frame DOM and added to the div “ImagePreviewContainer”.
  • ImagePreviewEventsArgs (line 63) : object used to pass the controls to the event handlers. The action field contains the server-relative URL of the Application Page which returns the Image.

Step 4 – Code behind

Almost all the code of the User Control is in the ASCX file but we need to set one attribute in the code-behind. So edit the code-behind of the ImagePreviewWebPartUserControl and add the following lines:












This code set a unique name to the iframe to avoid conflicts when multiple instances of the WebPart are added to the page.

Step 5 – The Application Page

The goal of this page is to receive the image posted by the UserControl, resize it and return it to display the preview image into the iframe. It is important to notice that it does not return some HTML but an Image, thus the content type of the response header will be “image/jpeg”.

Open the code behind of the “PreviewImage.aspx” page and here is what it should look like :




































































































































































































This code is very simple. The posted file is retrieved thanks to the Request.Files collection of HttpPostedFile. The file’s content type and size are checked, then in the Render method override the image is resized and written to the response.

Step 6 – Disable Message Authentication Check on the Application Page

The last thing we have to modify is the ASPX page. We need to set the “EnableViewStateMac” attribute of the Page directive to “false” to avoid the “This Page has been modified since you opened it. You must open the page again” error message.

In fact the PreviewImage page receives its form data from another page. In this data is included the ViewState of the WebPart page which causes this error. That’s the reason why we have to disable the message authentication check.

Step 7 – Build and Deploy

Finished. We just have to build the solution and deploy it. Then add the WebPart to a WebPart page and you should obtain this result :

Dynamic-image-preview-1

Yes I know there is no design here. But that’s not the point of this article right? If you browse for a picture and click on preview you should see the loading message then the preview :

Dynamic-image-preview-2

And the most important part is the preview displayed without refreshing the entire page.

Conclusion

We can’t really say that there is no postback here because the ASP .Net form is actually posted in the iframe but this is transparent to the user. A lot of JQuery plugins that use the File API of HTML5 fall-back to this method when Internet Explorer is the client.

So I thought interesting to demonstrate how to implement it in a SharePoint environment in spite of the fact that there is not really any SharePoint code here. You can reuse this code as-is but I strongly recommend you to add some validation logic, security and error handling.

I hope it helps you and feel free to comment.

How to maximize a Modal Dialog in JavaScript?

The problem

Modal Dialogs in SharePoint 2010 are a really good feature. Moreover you can easily create your own dialogs and open them with just few lines of JavaScript :

Ok that’s cool, you can specify the size of the dialog, if the user can maximize it, close it and a lot of others things. But sometimes it can be interesting to let the dialog control some of these options. This is a very common scenario:

  • You are developing several application pages
  • These pages are opened in Modal Dialogs
  • The Dialogs are opened thanks to a User Control. A property of the User Control contains the URL of the application page to open.

Ok now you have developed an application page which contains a lot of content and you would prefer to maxmize the Dialog when opening it. Of course you can modify your User Control to use the showMaximized option when opening the dialog. But why the application page itself wouldn’t be able to maximize the dialog?

Let’s see how to that.

The solution

The main problem here is to get a reference on the actual dialog object. The JavaScript function showModalDialog returns this object but it is difficult to access it from the dialog. Fortunately there is a JavaScript function to do that (yes it is):

Now you can do a lot of things with this object. And of course one of these thing is calling internal functions that shouldn’t be called by non-Microsoft developers 🙂 So if you want to maximize the dialog when opening it you can use this code:

Yes the $z function switches the state of the dialog from “normal” to “maximized”. The $S_0 variable is set to true when the dialog is already maximized. Checking if this is the case avoids from switching the state of the dialog at each page refresh.

Of course you should be aware of the risks of using such a code since these functions are not documented and are subject to change without notice.

SharePoint 2010 Modal Dialog JavaScript internal functions

SharePoint 2010 Modal Dialog Basics

I have probably already worked with the Dialog Framework in a SharePoint 2010 environment. These dialogs are a very interesting feature that I really love. They can be used for a lot of things and of course you can create your owns dialogs to display data or ask for user input.

In this post I will describe briefly the basic functions that are documented on the MSDN and which enables you to work with Modal Dialogs. In a second part I will explain the usage of internal JavaScript functions that are not supposed to be called by custom code. You must be aware that these functions are not documented, ultimately your code should not use these functions because future updates could break down your custom features. But sometimes you need to go beyond the provided API when you have

Opening a Modal Dialog

Let’s begin with the easier and most useful part : opening a new Modal Dialog. For testing purpose I advise you to create an ASPX page inheriting from the default Master Page on a blank Team Site. Then you can add this code directly in a script block in the Main ContentPlaceHolder:

 I won’t go further in details about the different options available because you can now see the whole list on MSDN :

Rating does not work

Today I’m working on the new Ratings feature of SharePoint 2010. I think I had the same issue than everybody when enabling it for the first time : the ratings don’t refresh.

I enabled the Ratings on a Custom List and rate two items for testing purpose. And guess what? The blue stars are not showing!

So I read some blogs which speak about the “Social Rating Synchronization” timer job that must be runned to aggregate the ratings. Actually here is the description of the “Social Rating Synchronization Job”:

Timer Job to synchronize rating values between Social Database and Content database

And here is the description of the “Social Data Maintenance Job” (another timer job):

Aggregates social tags and ratings and cleans the social data change log.

So I think this is clear. You have to run these two jobs if you want to see your ratings refreshing. 

Resetting Windows 8

This is my first post about Windows 8 and you can’t imagine at which point I am excited about this new product of Microsoft. My first impression of this preview is very good. So I decided to write about the History feature but I am totally unable to clear the settings I’ve just play with it. My first idea was to format and reinstall Windows but I search a “Reset” option and guess what? It exists. So let’s look this feature.

Opening the Control Panel

First step is opening the Control Panel. I’m discovering the product while writing these lines so I don’t know what is the most efficient way to open the Control Panel. Personally I use the Windows key on my keyboard then I tap “Recovery”. You can notice that the search box automatically appears when tapping a text with the keyboard. In the right search pane I select “Settings” to display items of the Control Panel. The first result is the good one.

Windows 8 Recovery - Control Panel

Update: the easy way to access the reset feature

You can reset your computer directly from the Metro UI. To do this, open the Control Panel from the Metro UI, then select the General Section. You will find a Reset option. By the way you can notice that the green bar of the recovery tool is more adapted to the Metro UI than in Desktop Mode.

 Reset your computer Metro UI

The Recovery Window

In the Recovery Windows you can now select the “Reset” option. What this feature does exactly? It enables you to delete all your personal stuff. Thanks to this you can easily reset your computer before selling it for example. This option is easier than formatting and reinstalling your computer. Nonetheless I’m wondering if this feature is secure or not? It would be interesting to check what files are exactly deleted.

Windows 8 Recovery - Recovery Window

Recovery Tool

 Then a Metro style Window asks from which drive you want to remove the files. You can choose between the disk where Windows is installed or all drives. I wish we can choose specific drives.

Windows 8 Recovery - Recovery Tool

Then another screen asks you for a confirmation. The PC is now restarting. Notice : you must have the installation media in order to perform this operation.

Conclusion

In my case the operation does not perform well since I needed to format and reinstall the system which refused to boot after the restart. I don’t retry and assume this is a bug of this preview on my environment. We can be sure that Microsoft will fix this in the next releases.

My first impression about this feature was pretty good but finally I think it will be used only by few users. I mean, you need the installation media to perform a reset and it takes the same amount of time than totally reinstalling the system with a USB key (10 minutes in my case). I think this feature would be great if the installation media wasn’t asked.

 

Get SPListItem from URL

Hi Guys! Today I decided to post a snippet of code that I find very useful.

This code retrieves a SPListItem from an absolute URL. The item can be associated to a document or not and the URL can be a display form or not. The main interest of such a code is to retrieve the item associated to an URL returned by the search engine for example.

The good thing is that it works with documents that does not have a IFilter associated. JPEG files for example are not fully indexed by the search engine. The content of the file is not read, only metadata are indexed unless you installed a IFilter supporting JPEG files. The side effect is the url returned by the search engine : this is the display form URL of the file, not the URL of the file itself. So this code handle this case and can be used in such a context.

SharePoint 2010 does not support FR-CA (local 3084)

I discover yesterday what I think is an important issue for users living in Canada and speaking French (like me by the way).

When a Language Pack is installed on a SharePoint 2010 Farm, the browser language is detected by the SharePoint sites on which MUI is enabled. To detect the user language, SharePoint inspects the HTTP request which contains the header “Accept-Language”. The value of this header can be configured in the Options of your browser. Talking about Internet Explorer you have to open “Internet Options” –> “Languages”.

Thus, if you install the French Language Pack and if your browser is configured to accept Fr-Fr (French – France), your SharePoint site will be displayed in French even with a site created in English.

So what’s the problem? This detection does not work with the locale “Fr-Ca” (French – Canada). It seems that SharePoint displays the correct default language only if the locale set in the browser matches exactly the locale of the SharePoint Language Pack. Of course there is only one French Language Pack and its locale is Fr-Fr.
This is very annoying for french users since the SharePoint sites will be displayed in English by default. They have to switch manually to French.

Fortunately the workaround is pretty simple : add the Fr-Fr locale in the languages of your browser. You can set it in second position after Fr-Ca. Of course you will have to deploy this setting to the users 🙂

Ribbon Customization – Refreshing Changes

I’m working these days on a project which require to customize the SharePoint Ribbon. I apply the practice of using the existing items of the CMLDUI.XML file and that works great.

Nonetheless I always have the same problem : refreshing my changes. I was unable to see my changes on Internet Explorer. I was able to see only the first version of my deployment. Even deleting the temporary internet files didn’t work for me. My solution was to use Google Chrome and deleting its cache every time I deployed a new version of my package.

Today I noticed that Internet Explorer doesn’t delete all the files in its temporary folder when you use the “Internet Options” window. So you have to open your temporary internet files folder and delete all the files yourself. Et voilà, your changes are now displayed.

Another solution : you can delete the files beginning by “commandui.ashx” in your temporary internet files folder. This way you keep your Internet cache and you refresh only your ribbon customizations.