Creating Notes://-links in SharePoint 2010's Rich Text Editor (RTE)

by Martin 17. oktober 2011 08:15

I've been working on a project where we have migrated a customer from Lotus Notes to Exchange and SharePoint. On the SharePoint side a requirement arose to be able to link to document in the old Notes database. (Notes-links starts with notes:// in the URL and requires Lotus Notes to be installed on the client to be intepreted correct) We found out, that the Rich Text Editor in SP2010 won't allow notes://-links : they are banned by javascript in core.js (it only allows http, ftp, \\, and similar normal protocols). So, when creating a notes://-link in the RTE you are left with an empty a-tag with no href. No matter what you do! Either the client side javascript removes the link or the serverside when posting (if you manually have created the link in HTML-view).

So, the solution for us was actually not that easy. Some forums on the WWW suggests that you edit your core.js to contain the notes:// protocol in the array of allowed protocols. BUT, this will actually leave you in an unsupported state if you upgrade your farm (SP or CU's). That does not fly. So the solution for us kinda three-fold;

  1. Create an easy way for the editors to cvreate links by "mimicking" the normal RTE "Insert Link" (external) in SharePoint
  2. Create a "redirect service" on the server that transferred the user to Notes
  3. Make sure for max usability to get the user back to page they came from

The way I made the mimicking of the standard RTE "Insert Link" was to

  1. Create a button which was placed the same place as the other "Insert Link" shortcuts.
  2. Create a dialog that displayed the same interface as the standard "Insert Link". This was done by completely copying the existing dialog .aspx and changing a few lines
  3. Make this dialog return a url which was not truncated or cut out by the server side execution.

To create the button, the following Elements.xml was produced:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
               <CustomAction
                             Id="Intranet.CustomActions.NotesLink"
                             Location="CommandUI.Ribbon">
                             <CommandUIExtension>
                                            <CommandUIDefinitions>
                                                          <CommandUIDefinition
                                                                         Location="Ribbon.EditingTools.CPInsert.Links.InsertLink.Link.Menu.Link.Controls._children">
                                                                         <Button 
                                                                                        Id="Intranet.CustomActions.InsertNotesLink"
                                                                                        Command="RTE.RichTextEditor.insertNotesLink"
                                             Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-160" Image16by16Left="-224"
                                                                                        Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-160" Image32by32Left="-448"
                                                                                       Description="Inserts notes://-link"
                                                                                       LabelText="Insert link poiting to Notes"
                                                                                       Sequence="30"
                                                                                       TemplateAlias="o1"
                                                                                       ToolTipTitle="Indsæt notes link tool tip"
                                                                                       ToolTipDescription=""/>
                                                                                                      />
                                                          </CommandUIDefinition>
                                            </CommandUIDefinitions>
                                            <CommandUIHandlers>
                                                          <CommandUIHandler
                                                                         Command="RTE.RichTextEditor.insertNotesLink"
                                                                         CommandAction="javascript:RTE.RichTextEditor.insertNotesLink();"
                                                                         />
                                            </CommandUIHandlers>
                             </CommandUIExtension>
               </CustomAction>
</Elements>

The changes in the aspx where minor (some lines removed for readability, just copy (and rename to customerrtedialog.aspx) the existing rtedialog.aspx and replace the lines validating the protocol with this):

function OkButtonClick()
                                            {
                                                          var arr = new Array();
                                                          var valid = 1;
                                                          if ((document.getElementById(">")) != null)
                                                          {
                                                                         arr[0] = (document.getElementById("")).value;
                                                          }
                                                          if ((document.getElementById("")) != null)
                                                          {
                                                                         arr[1] = "/_layouts/Customer.Intranet/Customer.LotusNotesRedirect.aspx?target=" + encodeURIComponent((document.getElementById("")).value);
                                                          }
                                                          if (document.pageName == "SharePointLink")
                                                          {
                                                                         if (arr[0] == null || typeof(arr[0]) == 'undefined' || arr[0].trim().length == 0 ||
                                                                                       arr[1] == null || typeof(arr[1]) == 'undefined' || arr[1].trim().length == 0)
                                                                         {
                                                                                       alert("You must specify a list and an item.");
                                                                                       valid = false;
                                                                         }
                                                          }
                                                          if (document.pageName == "InsertTable")
                                                          {
                                                                         if (arr[0] < 1 ||
                                                                                        arr[1] < 1 ||
                                                                                       isNaN(Number(arr[0])) ||
                                                                                       isNaN(Number(arr[1])))
                                                                         {
                                                                                       alert("");
                                                                                       valid = 0;
                                                                         }
                                                                         if (valid && arr[0] * arr[1] > 625)
                                                                         {
                                                                                       alert("");
                                                                                       valid = 0;
                                                                         }
                                                          }
                                                          if (document.pageName == "CreateLink")
                                                          {
                                                                         valid = true;
                                                          }
                                                          if (valid)
                                                          {

                                                                         commonModalDialogClose(1 , arr);

                                                                         window.returnValue = arr;
                                                                         window.close();

                                                          }
                                            }

In the masterpage i added an EditMode-panel at the very bottom to reference the following javascript, which extends the existing functionallity. The javascript is put in a seperate .js-file.

RTE.RichTextEditor.insertNotesLink = function () {
               ULSkay: ;
               RTE.SnapshotManager.takeSnapshot();
               RTE.ObjectCommands.insertNotesLink();
               RTE.SnapshotManager.takeSnapshot();
}

RTE.ObjectCommands.insertNotesLink = function () {
               ULSkay: ;
               var $v_0 = RTE.Cursor.get_range();
               if (!$v_0.get_isEditable()) {
                             return;
               }
               if (!$v_0.$EP()) {
                             return;
               }
               var $v_1 = new RTE.InsertNotesLinkDialog();
               $v_1.show();
}


RTE.InsertNotesLinkDialog = function () {
               ULSkay: ;
               this.$85 = Function.createDelegate(this, this.$Dq_0);
}
RTE.InsertNotesLinkDialog.prototype = {

               show: function () {
                             ULSkay: ;
                             var $v_0 = new RTE.InsertLinkDialogArguments();
                             $v_0.allowRelativeLinks = false;
                             $v_0.text = RTE.Cursor.get_range().get_text();
                             RTE.DialogUtility.$5Q('CustomerRteDialog.aspx', 'CreateLink', true, true, $v_0, null, this.$85, false, 400);
               },

               $Dq_0: function ($p0, $p1) {
                             if ($p0 === 1) {
                                            var $v_0 = $p1;
                                            var $v_1 = $v_0[0];
                                            var $v_2 = $v_0[1];
                                            if (RTE.RteUtility.$9H($v_2, false)) {
                                                          var $v_3 = RTE.Cursor.get_range();
                                                          var $v_4 = $v_3.parentElement();
                                                          if (!$v_4) {
                                                                         return;
                                                          }
                                                          var $v_5 = $v_4.ownerDocument.createElement('A');
                                                          $v_5.href = $v_2;
                                                          if ($v_3.isEmpty()) {
                                                                         SP.UI.UIUtility.setInnerText($v_5, ($v_1.trim() !== '') ? $v_1 : $v_2);
                                                                         $v_3.insertBefore($v_5);
                                                          }
                                                          else {
                                                                         if ($v_1.trim() !== '') {
                                                                                       $v_3.replaceHtml($v_1);
                                                                         }
                                                                         $v_3.wrapRange($v_5);
                                                          }
                                                          $v_3.moveToEndOfNode($v_5);
                                                          RTE.Cursor.update();
                                                          RTE.RteUtility.showRibbonTab('Ribbon.Link', 'LinkTab');
                                            }
                             }
               }
}
RTE.InsertNotesLinkDialog.registerClass('RTE.InsertNotesLinkDialog');

What this script does is to prefix the given notes://-link with a valid http-link and encode the querystring (the notes url). When saving the page, SharePoint API won't be the wiser than to allow the url.
When the user clicks the link he/she is taken a to page on the SharePoint server which creates a "javascript-redirect" by using the window.location and setting it to the Notes://-url. After waiting 3 seconds, the user is then taken back to the page they came from (this is while Notes is opening up to show the document the link was pointing to.
ASP.Net code:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Customer.LotusNotesRedirect.aspx.cs" Inherits="Customer.Intranet.LAYOUTS.Customer.Intranet.LotusNotesRedirect" DynamicMasterPageFile="~masterurl/default.master" %>

<asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
<script type="text/javascript" language="JavaScript">
<!--
               function goBack() {
                             history.go(-1);
               }
               window.location = '<asp:Literal ID="uiLitRedirectLocation" runat="server" />';
               setTimeout(goBack, 3000);
//-->
</script>
</asp:Content>

Codebehind:

using System;


namespace Customer.Intranet.LAYOUTS.Customer.Intranet
{
               public partial class LotusNotesRedirect : Microsoft.SharePoint.WebControls.LayoutsPageBase
               {
                             protected void Page_Load(object sender, EventArgs e)
                             {
                                            if (string.IsNullOrEmpty(this.Page.Request["target"]))
                                            {
                                                          Microsoft.SharePoint.Utilities.SPUtility.TransferToErrorPage("Kan ikke omdirigere, da link ikke er angivet i \"target\"-querystring");
                                            }

                                            this.uiLitRedirectLocation.Text = System.Web.HttpUtility.HtmlDecode(this.Page.Request["target"]);
                             }
               }
}

Tags: , , , ,

SP2010

Kommentarer (1) -

oZ
oZ Germany
26-04-2012 18:37:54 #

Hi,

thank you this came to my rescue, even if it didn't match my task at hand it was similar enough to get me starting.

cheers
oZ

Besvar

Tilføj kommentar

  Country flag

biuquote
  • Kommentar
  • Eksempel
Loading

Page List

About

Take a look at my LinkedIn-profile.

DISCALIMER: The content on this blog is in NO way affiliated with my employer. The opinions expressed on this blog are solely my own and in NO way endorsed by my employer.

Recent comments

Comment RSS

Month List