Thursday, 26 February 2015

ShaerPoint 2013: How do I change the picture (source) for an image at runtime?

An image can easily be converted into a 'clickable' image with some simple html manipulation - put the image in an anchor tag.

I have added two images (First.ico and Second.ico) to the Style Library/images of my site collection. I also have jQuery referenced in my masterpage.

Here is the html:

<a href="" onclick="changeImage()"><img id="favourite" ></img></a>

Changing the image is just as easy:

First, lets set an initial source value:

jQuery(window).load(function () {
   $("#favourite").attr("src", "/Style%20Library/Images/First.ico");
})

Then, implement the changeImage function to switch images:

function changeImage() {
if ($("#favourite").attr("src") == "/Style%20Library/Images/First.ico")
{
$("#favourite").attr("src", "/Style%20Library/Images/Second.ico");
}
else
{
$("#favourite").attr("src", "/Style%20Library/Images/First.ico");
}
}

Wednesday, 25 February 2015

SharePoint 2013: How do I reference a html 'source' file from another site collection in a Content Editor Web Part?

Content Editor Web Parts are fantastic for rendering content, but there is small problem if you want to reference a file (through a ContentLink) on another site collection - you are not allowed to! Cross-site scripting is not a good thing.

This problem becomes apparent when you have a 'source' site collection that will host all the html/js files and you want all other site collections to reference this (single) source of truth.

There are a few options available to resolve the problem.
1. Copy all the JS/Html files to each site collection and reference them locally. (Easy, but it will create a maintenance nightmare if you have lots of site collections).
2. Enable Anonymous access to the 'source' site collection. (Easy, but not a great solution)
3. Install Content Link Web Part from Codeplex. (Better, but requires a Farm Solution)
4. Move the link from the ContentLink to the Content in the webpart.
The key to resolving the problem is nested CDATA tags.

In my project, we were using AngularJS, so used ng-include to point to my source file.

Here is my sample from the elements.xml for my page Module:

<AllUsersWebPart WebPartOrder="0" WebPartZoneID="RowLeft">
<![CDATA[
<WebPart xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/WebPart/v2">
  <Title />
  <FrameType>None</FrameType>
  <Description></Description>
  <IsIncluded>true</IsIncluded>
  <ZoneID>RightRow</ZoneID>
  <PartOrder>0</PartOrder>
  <FrameState>Normal</FrameState>
  <Height />
  <Width />
  <AllowRemove>false</AllowRemove>
  <AllowZoneChange>false</AllowZoneChange>
  <AllowMinimize>false</AllowMinimize>
  <AllowConnect>false</AllowConnect>
  <AllowEdit>false</AllowEdit>
  <AllowHide>false</AllowHide>
  <IsVisible>true</IsVisible>
  <DetailLink />
  <HelpLink />
  <HelpMode>Modeless</HelpMode>
  <Dir>Default</Dir>
  <PartImageSmall />
  <MissingAssembly>Cannot import this Web Part.</MissingAssembly>
  <PartImageLarge>/_layouts/15/images/mscontl.gif</PartImageLarge>
  <IsIncludedFilter />
  <Assembly>Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
  <TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName>
  <ContentLink xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor" />
  <Content xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor"><![CDATA[
<div id="description" ng-include="src='/Style Library/html/MyModule.html'" ></div>
  ]]]]><![CDATA[>
  </Content>
  <PartStorage xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor" />
</WebPart>
]]>
</AllUsersWebPart>

The key with nested CDATA is to close the root tags immediately once the nested tags are used and create a new CDATA tag immediately afterwards.


Wednesday, 11 February 2015

Sharepoint 2013: Why is my deployed dll not in the GAC?

I have created a new SharePoint wsp and it has been successfully deployed, but when I searched for the compiled component in the GAC, it was nowhere to be seen. Huh?

The simple solution is that the GAC is .net 1.0 - 3.5 is not the same as the GAC in .net 4.0+.

The old GAC is the trusted location c:\windows\assembly
The new GAC resides in c:\windows\microsoft.net\assembly

It was there after all - it helps when you look for the file in the right place.

Wednesday, 4 February 2015

PowerShell: How do I open a reference without locking it?

I was recently writing a C# dll to the invoked in PowerShell. As I tested the PowerShell script, I found that the dll was being locked and any re-compiles from Visual Studio were being rejected.

I used the following code to resolve the problem:

$bytesCommon = [System.IO.File]::ReadAllBytes("c:\folder\driver.dll")
$loadResultCommon = [System.Reflection.Assembly]::Load($bytesCommon)

Monday, 2 February 2015

PowerShell: How do I append data to an existing file in SharePoint with a new line and quotes?

A recent proejct required the injection of some runtime data in my require js configuration file. The following code allowed me to inject the new values into the file.

$site = Get-SPSite "http://mysite"

$file = $site.RootWeb.GetFile("/Style Library/myfile.js")

if (($file -ne $null) -and ($file.Exists -eq $true))
{
$binaryAsIs = $file.OpenBinary()

$asciiEncoding = New-Object -TypeName System.Text.UTF8Encoding
$asIs = $asciiEncoding.GetString($binaryAsIs)

        # This is the text to append to the top.
        # `r`n will create a crlf (new line)
        # $([char]34) will embed a double quote in the text

$new = "// Here is some next text `r`n //and here is text in $([char]34)quotes([char]34)`r`n"
$newFile = $new + $asIs

$binaryToBe = $asciiEncoding.GetBytes($newFile)

$file.CheckOut()
$file.SaveBinary($binaryToBe)
$file.CheckIn("")
$file.Publish("")
}

$site.Dispose()