Archive for Uncategorized

Sharepoint 2010 RTE Image Picker for the Ribbon

// July 29th, 2010 // No Comments » // Uncategorized

Our current project required us to make a few changes to the OOTB Asset Picker dialog. Within this dialog there is the common “Look in” pane which isnt easily customized. We required the dialog to only show certain document libraries in which only png, jpeg or gif files may be viewed. Additionally we customized the picker to be launched from the ribbon and place the returned image within the rich text editor.

This all would not have been possible without the help of Karine Bosch’s Post on Custom Dialogs.

The following is a screenshot of the end product:

The page is invoked from a custom ribbon control however this only makes a call to our custom AssetPicker dialog. The source code (elements.xml) provides a split button control which invokes the picker for both replacing and inserting images. This ribbon control element (elements.xml) replaces the OOTB “Insert Image” control, however can be customized to add the default “From Address” and “From Computer” split options at a later stage.

The LaunchPicker method in the xml file invokes the OpenDialog method which in our project has been created as an extension to jQuery. However this need not be the case. Its merely a function which calls the SP.UI.ModalDialog.showModalDialog() method with a bunch of options. Note the callback method which is specified in the LaunchPicker method. This method is called once the image has been selected; this is known as the “callback method”. Careful that you only pass “replace” or “insert” to the LaunchPicker method.

Right lets move onto the AssetPicker itself. The .aspx is pretty much the simple part simply with a method which allows the user to choose the right image and invoke the callback method. It uses a repeater control to populate the images datasource.

The code-behind features several enhancements including a paging function. The repeater control provides us with the datasource of all the images found within the choosen folder or document library itself. Note: We have used a custom document library basetemplate and populate our treeview with these document libraries. This is where you may customize the code to search for Document Libraries or Image Libraries only. Be careful not to include generic lists as the code searches for files only.

Once the image has been chosen, the pickerCallBack callback method is fired as shown in javascript file. This in turn may replace or insert an image using the InsertRTEImage or ReplaceRTEImage depending on the options you passed to the launchpicker method.

The source files are attached.

Sharepoint 2010 Ribbon Control and Rich Text Editor

// July 26th, 2010 // No Comments » // Uncategorized

Im currently lucky enough to be working on the 2nd largest Sharepoint 2010 deployment in the world currently! It really has been a wonderful opportunity to be exposed to some of the new Sharepoint 2010 functionalities as well as interfaces, API’s, SDK etc.

One of the latest modules for the eBackPack project is the media library ribbon control, a control which manipulates the way our users will upload images to Sharepoint.

The OOTB functionality allows users to upload images from multiple sources namely:

1) From Sharepoint
2) From Computer
3) From Address

We needed new functionality to be able to upload images using a silverlight control (activex prevents our users using Firefox which is a big problem for the 70,000 odd users!). The silverlight control also checks for banned words which wasnt available to us. The key functionality here is:

1) Replace the existing “Upload Picture” split button with ours

2) Call the Upload Image Dialog

3) Instantiate the callback method which inserts the image back into the Rich Text Editor

First up, we need to create a new module in Visual Studio 2010. This is the module which act as a replacement button for OOTB “Upload Picture” split button. Im not going to go through doing this as this is basic VS2010 functionality. The new elements.xml file is as below:

 XML |  copy code |? 
01
02
<?xml version="1.0" encoding="utf-8"?>
03
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
04
  <CustomAction
05
 Id="Ribbon.Image.Image.Edit.ReplacementButton"
06
 Location="CommandUI.Ribbon"
07
 Rights ="EditListItems" >
08
    <CommandUIExtension>
09
      <CommandUIDefinitions>
10
<CommandUIDefinition
11
          Location="Ribbon.EditingTools.CPInsert.Media.Image">
12
          <SplitButton
13
                  Id="Ribbon.EditingTools.CPInsert.Media.Image.ReplacementButton"
14
                  Alt="$Resources:core,ButInsertImageAlt;"
15
                  Command="InsertImage"
16
                  CommandMenuOpen="InsertImageMenuOpen"
17
                  CommandMenuClose="InsertImageMenuClose"
18
                  Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-176" Image16by16Left="-224"
19
                  Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-192" Image32by32Left="-448"
20
                  LabelText="Insert Image"
21
                  MenuAlt="$Resources:core,ButInsertImageMenuAlt;"
22
                  Sequence="10"
23
                  TemplateAlias="o1"
24
                  ToolTipTitle="$Resources:core,cui_ButInsertImage;"
25
                  ToolTipDescription="$Resources:core,cui_STT_ButInsertImage;">
26
            <Menu Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Replacement">
27
              <MenuSection
28
                Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.Replacement"
29
                DisplayMode="Menu"
30
                Sequence="10">
31
                <Controls Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.Controls.Replacement">
32
                  <Button
33
                    Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromComputer.Replacement"
34
                    Sequence="10"
35
                    Alt="$Resources:core,ButFromComputerAlt;"
36
                    Command="UploadPictureReplacement"
37
                    LabelText="$Resources:core,ButFromComputer;"
38
                    ToolTipTitle="$Resources:core,cui_STT_title_ButInsertImageFromComputer;"
39
                    ToolTipDescription="$Resources:core,cui_STT_ButInsertImageFromComputer;"/>
40
                  <Button
41
                    Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromMediaLibrary.Replacement"
42
                    Sequence="15"
43
                    Alt="$Resources:core,ButFromAddressAlt;"
44
                    Command="eBackpack.MediaLibrary.Ribbon.PerformInsert"
45
                    LabelText="From Media Library"
46
                    ToolTipTitle="Insert Picture from Media Library"
47
                    ToolTipDescription="Insert a picture from Media Library onto the page"/>
48
                  <Button
49
                    Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromAddress.Replacement"
50
                    Sequence="20"
51
                    Alt="$Resources:core,ButFromAddressAlt;"
52
                    Command="InsertImageWeb"
53
                    LabelText="$Resources:core,ButFromAddress;"
54
                    ToolTipTitle="$Resources:core,cui_STT_title_ButInsertImageFromAddress;"
55
                    ToolTipDescription="$Resources:core,cui_STT_ButInsertImageFromAddress;"/>
56
                  <Button
57
                    Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromSharepoint.Replacement"
58
                    Sequence="25"
59
                    Alt="From Sharepoint"
60
                    Command="InsertImageSharepoint"
61
                    LabelText="From Sharepoint"
62
                    ToolTipTitle="Insert Image from Sharepoint"
63
                    ToolTipDescription="Insert an image using the asset picker tool"/>
64
 
65
                </Controls>
66
              </MenuSection>
67
            </Menu>
68
          </SplitButton>
69
        </CommandUIDefinition>
70
      </CommandUIDefinitions>
71
      <CommandUIHandlers>
72
        <CommandUIHandler
73
            Command="UploadPictureReplacement"
74
            CommandAction= "javascript:
75
        var id='?RootFolder=&amp;DisplayType=uploadimages';        
76
        uploadImageDialog(id);
77
        " />
78
 
79
      </CommandUIHandlers>
80
    </CommandUIExtension>
81
 
82
  </CustomAction>
83
</Elements>
84
 
85

Notes:

1) Line 11: The Location specified is exactly the same as the one listed in the CMDUI.xml file (This is the file which lists the OOTB ribbon controls). This is ensures we replace the ribbon control not create a new one.
2) Line 22: Use the same sequence number to replace the button
3) Line 36: The method name which invokes the javascript. See Line 73

Right, so first thing to remember. Everytime you deploy the feature or change it in any way, you need to clear the cookies/cache. Your changes wont be seen otherwise. That took me about 5 hours of work right there!!

Now, for the javascript. We use the ECMAScript opendialog functionality where we specify our own callback function which will be called one we’re done with the upload functionality (not covered here. this functionality would be part of the dialog you launch).

 Javascript |  copy code |? 
01
02
openDialog: function (params) {
03
            params = $.extend({
04
                id: "",
05
                allowMaximize: true,
06
                showClose: true,
07
                callBackFunction: CallDETCustomDialog
08
            }, params);
09
            var siteurl = SP.PageContextInfo.get_webServerRelativeUrl();
10
            var options = SP.UI.$create_DialogOptions();
11
            if (siteurl == "/") {
12
                options.url = params.url + params.id;
13
            }
14
            else {
15
                options.url = siteurl + params.url + params.id;
16
            }
17
            options.allowMaximize = params.allowMaximize;
18
            options.showClose = params.showClose;
19
            options.width = params.width;
20
            options.height = params.height;
21
            options.dialogReturnValueCallback = params.callBackFunction;
22
            SP.UI.ModalDialog.showModalDialog(options);
23
            //SP.UI.ModalDialog.showWaitScreenWithNoClose();
24
        }
25
 
26
// upload Image Dialog
27
function uploadImageDialog(id) {
28
    $(this).openDialog({
29
        id: id,
30
        url: "/_layouts/DET.eBackPack/FileUpload/BasicUpload.aspx",
31
        callBackFunction: InsertImageUploadedCallback
32
    });
33
}
34
 
35
function InsertImageUploadedCallback(dialogResult, returnValue) {
36
 
37
    if (dialogResult == "OK") {
38
        //Delete any existing content the range contains
39
        RTE.Cursor.get_range().deleteContent();
40
 
41
        //Get a handle on the current range of the cursor inside the RTE
42
        var rng = RTE.Cursor.get_range().$3_0;
43
 
44
        //Create a DOM object representing the image
45
        var d = rng.ownerDocument;
46
        var a = d.createElement("img");
47
        //a.setAttribute("id", uniqueid);
48
        a.setAttribute("src", returnValue);
49
 
50
        //Insert the image into the RTE at the current cursor range position  
51
        SP.UI.UIUtility.insertAfter(a, rng);
52
    }
53
    if (dialogResult == "Replace") {
54
 
55
        var $v_0 = RTE.Cursor.getSelectedImage();
56
        if (!$v_0) {
57
 
58
        }
59
        if ($v_0.complete || $v_0.readyState === 'complete') {
60
            $v_0.setAttribute("src", returnValue);
61
        }
62
 
63
    }
64
}
65
 
66

Notes:

1) Line 27: UploadImageDialog launches our dialog with the appropriate callbackfunction
2) Line 21: Is set to InsertImageUploadedCallback
3) Line 37 – Line 51: Use this to insert a new image into the rich text editor.
4) Line 53 – Line 63: Use this to replace the currently selected image

So once we have this functionality we can now create a new aspx page which would be invoked using this dialog. We called ours “basicupload.aspx”.

Within this page’s OnSave method we implemented some javascript which would then invoke the callback method and pass back the image url to the callback method. This is acheived using the following code:

 Javascript |  copy code |? 
1
2
if(containerState == ContainerState.UploadImages)
3
                                        this.Page.ClientScript.RegisterStartupScript(this.GetType(), "InsertImageUploadedCallback", "commonModalDialogClose('OK', '" + oWeb.Url + "/" + oImageItem.File.Url + "');", true);
4
                                    else
5
                                        this.Page.ClientScript.RegisterStartupScript(this.GetType(), "InsertImageUploadedCallback", "commonModalDialogClose('Replace', '" + oWeb.Url + "/" + oImageItem.File.Url + "');", true);                                
6
 
7

Notes:

The code shown above passes back the uploaded image file url back to the callback method based on whether we are replacing or uploading a new image.

Our Sharepoint 2010 Experience

// June 25th, 2010 // No Comments » // Uncategorized

So one of the projects we’re working on is a grand scale education system. It is billed as one of the largest Sharepoint 2010 deployments in the world currently and the budget stretches in the millions. We’re just glad we’ve got to work with cutting edge technology with some of the best sharepoint arhcitects, sharepoint developers and consultants around!

Although i cannot say much about the project it involves building a large LMS system which allows a potential 1.3 million students to collaborate on homework, with teachers and submit assignments online. It has created such a stir in the industry that Steve Ballmer is officially our executive project sponsor! To hear a bit more about it, check out this video. Make sure you fast forward to 23mins into the video to hear about eBackPack!

Sharepoint 2010: Open Modal Dialog from EditControlBlock

// June 9th, 2010 // No Comments » // Uncategorized

Visual Studio 2010 makes it really easy to create and upload Features. Using these new Features makes it easy to add actions to menus. One of these menus is the Edit Control Block (ECB) or the context menu which appears over an item:

Edit Control Block

Normally we’d use a simple UrlAction and fill the Url with the redirect. However in this case to call the modal, we can do the following:

 XML |  copy code |? 
01
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
02
  <CustomAction Id="ReportConcern" RegistrationType="ContentType" RegistrationId="0x0101009b56d20860764b8090e63b320d78f98c" Location="EditControlBlock" Sequence="107" Title="Report Concern" Description="To report a concern on this item">
03
    <UrlAction Url="javascript:
04
              function CallDETCustomDialog(dialogResult, returnValue) 
05
              {
06
                SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK);
07
              }
08
              var options = {              
09
              url: '{SiteUrl}' + '/_layouts/DET.eBackPack/ReportConcern/ReportConcern.aspx?List={ListId}&amp;ID={ItemId}',
10
              title: 'Report Concern',
11
              allowMaximize: false,
12
              showClose: true,
13
              width: 500,
14
              height: 300,
15
              dialogReturnValueCallback: CallDETCustomDialog };
16
              SP.UI.ModalDialog.showModalDialog(options);" />
17
      </CustomAction>
18
</Elements>

Sharepoint and JQuery Web Services: DeleteList

// June 7th, 2010 // 1 Comment » // Uncategorized

I had a requirement today to be able to perform a delete of a list without having to perform a postback. After a little bit of research and a little bit of fine-tuning i came up with a delete list method (deletelist()). Below is just an example of what can be done with the Lists.asmx webservice provided by Sharepoint. Obviously any Web Service can be used or called as required.

 Javascript |  copy code |? 
01
 
02
function delete_list(listid) {
03
            if (confirm("Are you sure you want to delete this container?") == true) {
04
                var message = listid;
05
                var soapEnv =
06
                "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'> \
07
                    <soapenv:Body> \
08
                        <DeleteList xmlns='http://schemas.microsoft.com/sharepoint/soap/'> \
09
                        <listName>" + listid + "</listName>\
10
                        </DeleteList> \
11
                    </soapenv:Body> \
12
                </soapenv:Envelope>";
13
 
14
                $.ajax({
15
                    url: "_vti_bin/lists.asmx",
16
                    beforeSend: function (xhr) {
17
                        xhr.setRequestHeader("SOAPAction",
18
        "http://schemas.microsoft.com/sharepoint/soap/DeleteList");
19
                    },
20
                    type: "POST",
21
                    dataType: "xml",
22
                    data: soapEnv,
23
                    contentType: "text/xml; charset=\"utf-8\"",
24
                    complete: processResult,
25
                    success: function (j) {
26
                        document.location.reload();
27
                    }
28
                });
29
 
30
            } else {
31
                return false;
32
            }
33
        }
34
        function processResult(xData, status) { 
35
            var resultXml = $(xData.responseXML).find("errorstring").text();
36
            resultXml = $.trim(resultXml);
37
            if (resultXml != "") {
38
                alert(resultXml);
39
            }           
40
        }
41

Forms Designer for Sharepoint Services

// February 14th, 2010 // 2 Comments » // Uncategorized

Many of our clients operate in the small to medium entreprise (SME) and thus either make the investment into Microsoft Office Sharepoint Server (MOSS) whilst many opt for Windows Sharepoint Services (WSS) as a pilot or proof of concept.

The differential always comes down to a couple of deal breakers:

1) The extent that search will play a role in their organisation
2) The role of the automation of business processes within the organisation

When deciding between MOSS and WSS, for most organisations using Sharepoint 2007 as an intranet, it is normally the deal breakers mentioned above which entice them to go MOSS 2007 or WSS 3.0. When WSS 3.0 was released intially back in 2006, the difference between MOSS 2007 and WSS 3.0 was quite obvious. But as each of the above have been implemented, sharepoint services companies have slowly developed small features to make up the ground between the two. Take Stramit’s Masterpage Picker which gives one the masterpage and branding type functionality of MOSS with a simple feature or Bamboo’s Mashpoint allowing WSS to take advantage of BDC-like functionality. Im not saying that WSS with a couple of codeplex features will replicate the functionality of MOSS, things like Excel Services, Information Management Policies, Search and Navigation. But what am i saying is that WSS can provide a very rich interface for intranet and extranet deployments.

With the advent of Microsoft Search Server Express, search has become extremely powerful in WSS allowing organisations to use WSS to search Sharepoint Content, Website Content, Fileshares and Exhange Public folders (no people search which is at times a real make or break). Nonetheless i feel it still provides a rich functionality which makes me think that Infopath Forms Services is the real deal breaker. How many of you have used Sharepoint Designer to manipulate Sharepoint List Forms? Ever added a new column and then had a look if your customized form inherits the new column? Ever tried to create business rules around a form? For everything that Infopath provides us, i find that we suggest MOSS time and time again purely on the basis of automating business process within a organisation.

Many would disagree with the above, and yes, there are many features which MOSS adds where WSS does not compete, and theres no doubt, given a client has the budget, id suggest MOSS everyday. However id still love to have the “why do you suggest MOSS over WSS” discussion with some of our colleagues at Sharepint, especially to cash strapped SME businesses.

The crux of my post

Infopath has an almost complete set of functionality available to browser-enabled Sharepoint forms. The ability to “import” and “export” data from Line of Business Systems, addition of business rules and branding of Forms makes it the only option to publish forms with rich functionality to Sharepoint. Why is it that Infopath is the only player in the Forms department. There are multiple workflow providers, Nintex and Blackpoint to name a few. They make designing more complex workflows slightly easier to the average business user or sharepoint consultant and certainly have helped our clients save many hours in the solution development lifecycle. With the business process automation market almost captured, why is it that there isnt a forms provider who can compete with the Infopath juggernaut?

It would certainly lead me to recommend WSS to many cash-strapped SME’s depending on the price or licensing model and with the strong built-in workflow capability of WSS, it seems a no-brainer…. or maybe not?

Forms Based Authentication (FBA) on SharePoint 2010

// February 2nd, 2010 // No Comments » // Uncategorized

Article on setting up Sharepoint 2010 for Forms Based Authentication

Qantas Australia to use Sharepoint

// February 1st, 2010 // No Comments » // Uncategorized

Its great to see large corporates in Australia switching to Sharepoint

Document Management – Cash Management System

// January 29th, 2010 // No Comments » // Uncategorized

A client of mine is involved in gaming and retail, essentially a ‘club’ where patrons engage in gaming (poker machine) and eateries. They turn over a decent amount of revenue per day which they need to then capture in an excel spreadsheet and physically track the money with a large vault where they store all cash. Revenue is generated by:

Gambling machines
Point of Sale Systems (Eateries, Drinks etc)
Post Office
Gym

and cashiers are responsible for their own monies from the time they are handed money to the end of their shifts when they empty their POS systems. Naturally, like any retail business, there are variances between the POS system and the physical cash amount brought in, which need to be tracked. These are recorded in a list in Sharepoint.

At the beginning of each day, the cash supervisor will create a new spreadsheet (Cash Sheet) which will be used to capture all revenue. He/she will create this new spreadsheet using a content type created which is attached to the physical Microsoft Excel Sheet. He/she will then save this document and check it back into Sharepoint. Documents in this case must be checked out since all changes are then captured within multiple versions of the documents, each version having capability to be rolled back to.

At the end of each shift, cash supervisors then count the cash and do a reconciliation. They then record their findings in the “Cash Sheet”. This requires checking out the document, making changes, saving and checking back in the document. This is repeated 3 times during the day, until finally all shifts are completed.

At the end of the final shift, the cash supervisor then locks the document down, using a “Lock Document” workflow. In this Sharepoint workflow, the permissions are automatically applied by Sharepoint such that all users only have “read-only” access to the documents. This prevents changes to the document once the document has been “locked”.

Below is an image of the dashboard used:

This solved a number of different issues for the business. Some of these are listed below:

- Manual processes that are time consuming and non-value adding
- Increased opportunity for errors due to manual keying and re-keying of data
- Data redundancy as information is entered multiple times on each spreadsheet
- A lack of audit and tracking control:
- system is open to „massaging? of data
- no locking down of daily takes – open to fraud
- spreadsheets are open for editing across all users
- Lack of accountability on variances as there is no current reporting on variance by
person by time
- System does not enforce follow up on variances

The document could not be created

// January 27th, 2010 // No Comments » // Uncategorized

It seems that Office 2010 and Sharepoint 2007 (MOSS 2007 and WSS 3.0) dont play too nicely. Office 2010 is only in beta, so give Microsoft a break ok?

Getting the following error?

“The document could not be created”?

Got Office 2010 installed? im afraid you going to have to revert to Office 2007