Archive

Posts Tagged ‘js’

SharePoint 2010: Fixing the MSDN Contextual Tab Web Part Walkthrough

July 31st, 2010 Buta 2 comments

I haven’t had much opportunity to work with SharePoint 2010 in the past few months. However, I did get to try out the MSDN walkthrough for creating a custom web part with contextual ribbon tab recently. You can find the article here: http://msdn.microsoft.com/en-us/library/ff407578.aspx

In a nutshell, what’s supposed to happen is when you click on the web part, there will be a custom tab that appears in the Ribbon. It all works great for the first instance of the custom web part you place onto a page, but if you try adding a second instance of the web part, your page blows up!

You’ll get the following error:
Item has already been added. Key in dictionary: ‘Ribbon.CustomContextualTabGroup’ Key being added: ‘Ribbon.CustomContextualTabGroup’

:-/ … looks like there wasn’t much QA done for the walkthrough. Anyways, to make a short story shorter… I posted a question on the TechNet forums and Dallas Tester from MS did get back to me with a bunch of suggestions.

Here are the changes you can make to allow for multiple instances of the custom web part to appear on the page without everything blowing up.

Make the following modifications to the ContextualTabWebPart class.

Add the global ‘_added’ bool and OnInit event handler:

static bool _added = false;

protected override void OnInit(EventArgs e)
{
 base.OnInit(e);
 _added = false;
}

Since we no longer have to get the unique component ID in the delay script, I changed DelayScript into a private string:

private string delayScript = @"
 function _addCustomPageComponent()
 {
  for (var i = 0; i < g_customWebPartIds.length; i++)
  {
    SP.Ribbon.PageManager.get_instance().addPageComponent(new ContextualTabWebPart.CustomPageComponent(g_customWebPartIds[i]));
  }
 }

 function _registerCustomPageComponent()
 {
  SP.SOD.registerSod(""CustomContextualTabPageComponent.js"", ""/_layouts/CustomContextualTabPageComponent.js"");
  var isDefined = ""undefined"";
  try
  {
   isDefined = typeof(ContextualTabWebPart.CustomPageComponent);
  }
  catch(e)
  {
  }
  EnsureScript(""CustomContextualTabPageComponent.js"",isDefined, _addCustomPageComponent);
 }
 SP.SOD.executeOrDelayUntilScriptLoaded(_registerCustomPageComponent, ""sp.ribbon.js"");";

Modify the OnPreRender event handler:

protected override void OnPreRender(EventArgs e)
{
 base.OnPreRender(e);

 ClientScriptManager csm = this.Page.ClientScript;
 string componentId = SPRibbon.GetWebPartPageComponentId(this); // the unique component id 

 // if this is the first instance of the custom web part,
 //we need to add the contextual tab to the ribbon
 if (!_added)
 {
  this.AddContextualTab();
  _added = true;
 }

 // we need to create an array which will store the IDs of all instances of our custom web part
 csm.RegisterClientScriptBlock(
  this.GetType(), "DeclareCustomWebPartArray", "var g_customWebPartIds = new Array();", true);

 // add this webpart's ID to our array
 csm.RegisterClientScriptBlock(
  this.GetType(), "AddCustomWebPartId" + componentId, "g_customWebPartIds.push('" + componentId + "');", true);

 csm.RegisterClientScriptBlock(this.GetType(), "ContextualTabWebPart", this.delayScript, true);
}

If you want to verify that the correct web part is trigger the Ribbon commands, you can modify the ‘handleCommand‘ method in ‘CustomContextualTabPageComponent.js

handleCommand: function ContextualTabWebPart_CustomPageComponent$handleCommand(commandId, properties, sequence) {
 if (commandId === 'CustomContextualTab.HelloWorldCommand') {
  alert(this._webPartPageComponentId + ' says: Hello, world!');
 }
 if (commandId === 'CustomContextualTab.GoodbyeWorldCommand') {
  alert(this._webPartPageComponentId + ' says: Good-bye, world!');
 }
}

Here’s a ZIP file of the entire solution in case you’re too lazy to make the modifications yourself. :-)

Microsoft announces Internet Explorer 9 at PDC

November 20th, 2009 Buta Comments

Microsoft has announced they’re busy working away on the next version of Internet Explorer. Some of the more interesting things included:

  • Much better JavaScript performance! IE8 was a nice first step at improving JS performance on IE but still woefully behind the JS profilers and JIT compilers of Firefox, Safari, et al. Early builds of IE9 are already 4 times faster in the SunSpider benchmark than that of IE8 and putting it about par with Firefox 3.5.
  • CSS Level 3! Again early builds apparently are able to pass the majority of the CSS3 Selectors Testsuite, 41 out of 43. Of course, Firefox 3.5 and Safari 4 already completely pass this test. IE8 only passed 22 of these tests by the way.

Where’s more HTML5?

Microsoft was very non-committal about this. They made a good start in IE8 with things like DOM storage, cross document messaging (XDM) and have a built in JSON API, but where’s <video> or more importantly <canvas>?

It’s a promising start for Microsoft with news about IE9′s JS performance and CSS3 compliance. Here’s hoping to Microsoft finding time to implement some of the HTML elements that competitors have already integrated into their browsers. Don’t need IE10 to STILL be playing catch-up.