TypeScript and SharePoint - definition files

 

One of TypeScript's strengths is that you can use the ability to define Interfaces to produce Type Definition files for JavaScript.  These interface definitions provides an IDE (like Visual Studio) with a lot more type information at compile time regarding how to use a certain JavaScript object.

A large repository of definition files are at: https://github.com/borisyankov/DefinitelyTyped

Why is this related to SharePoint?  Well, javascript files provided in SharePoint are actually quite rich in meta data and could potentially be used to reverse engineer the TypeScript Definition Files. 

Without further delay...

  • Here's my TypeScript program
  • which will generate a JavaScript program
  • which will parse and read SP's JavaScript objects
  • which will produce TypeScript definition results

 

TypeScript code

 

module tools {

    export function findReturnType(o: any): string {

        // return;
        if (/return\s*;/gi.test(o)) return ": void";

        // no return
        if (!/return/gi.test(o)) return ": void";

        // return 1.1; return 1;
        if (/return\s*\d+(\.\d+)?;/gi.test(o)) return ": number";

        // return "xx";
        if (/return\s*"[^"]*?"\s*;/gi.test(o)) return ": string";

        // return 'xx';
        if (/return\s*'[^']*?'\s*;/gi.test(o)) return ": string";

        // return something;
        if (/return\s*[^;]+?;/gi.test(o)) return ": any";

        // don't know
        return ": any";
    }

    export function toClass(o: any): string {
        var isClass = o["__class"] == true;
        var typeName = o["__typeName"];

        var results = "interface " + typeName + "{\n";

        for (var member in o) {

            if (member.match(/\$|__/)) continue;

            var m = o[member];
            if (typeof (m) == "function") {
                var match = /function\s*(\(.*?\))/gi.exec(m);
                if (match) {
                    results += "function " + member + match[1] + findReturnType(m) + ";\n";
                }
            }
            else {
                results += "" + member + " : " + typeof (m) + ";\n";
            }
        }

        results += "}\n";

        return results;

    }

    export function toEnum(o: any): string {

        var typeName = o["__typeName"];
        var results = "interface " + typeName + "{\n";

        for (var member in o) {

            if (member.match(/\$|__/)) continue;

            var m = o[member];
            if (typeof (m) == "function") {
                continue;
            }
            else {
                results += "" + member + " : " + typeof (m) + ";\n";
            }
        }

        results += "}\n";
        return results;
    }

    export function toTypeScript(o: any): string {
        var isClass = o["__class"] == true;
        var isNamespace = o["__namespace"] == true;
        var isEnum = o["__enum"] == true;

        if (isClass) {
            return toClass(o);
        }
        if (isEnum) {
            return toEnum(o);
        }
        return "";
    }
}

 

What does this do?

 

When you run this code in the SharePoint browser console, you'd get this:

image

Which is nearly a usable TypeScript definition file. 

There are still a bunch of clean up to do, since this is a really basic list:

  • You will need to clean up the interface name. 
  • If you want, improve the arguments list, a number of the arguments are actually optional.
  • Remove zIndexStep and zIndexStart - which are properties in SP.UI.ModalDialog but aren't for public use.
  • Remove bind function - that's from jQuery

 

Here's another example, with enum's defined in SP.UI

image

 

Summary

In this quick blog article, I talked about using a TypeScript program to read the javascript object, and infer TypeScript definitions.  Since TypeScript contains far more information that isn't available in JavaScript, there will still be need to manually tweak the output.

Eventually, I hope we'll arrive at a place where we have fully documented TypeScript definitions for SharePoint available. 

Charlie Holland has started such a work, and it is available on https://github.com/chaholl/TypeScriptDefinitions/

http://www.chaholl.com/archive/2013/02/18/a-collection-of-typescript-definition-files-for-sharepoint-2013-et-al.aspx

Example uses of SPServices, JavaScript and SharePoint

 

I wanted to write about spservices.codeplex.com from Marc D Anderson - we've found ourselves using this really special library time and again across different projects to talk back to SharePoint quickly.

 

Starting Workflows

Here's a page from one of our Process Wiki articles.

image

 

  • We have a special "Contributor-only" webpart on the right. 
  • It shows the various workflow status' on the current page, as traffic light bubbles. 
  • The "Certify Process Page" calls a javascript function that calls StartWorkflow via SPServices.
  • The workflow is a Nintex workflow and triggers a significant multi-stage approval process.  But you can use StartWorkflow to start SharePoint workflows as well.

 

Getting List data, lots of list data

Here's our task list, represented as a taskboard.

image

  • This one is completely done with SPServices to get the list items
  • Convert the objects to JSON using SPServices.SPXmlToJson
  • Then binding the objects to UI via KnockoutJS
  • There's JQuery UI's drag and drop in play, so we can change the Task's status by dragging the task across a different column.
  • Update task using SPServices' UpdateItem call.
  • And some nice CSS. 
  • This particular page also runs via SharePoint 2010's OData listdata.svc, but is completely viable with SPServices on SP2007 as well.

 

Getting User Profiles via Search

Here's our People page.

image

 

  • First, get SharePoint to index your people.
  • Use SPServices to call SharePoint search to return a bunch of people, including their picture (one would say, especially their picture).
  • Here I use Knockout to render the pictures.  When clicked, each one opens that user's My Site page.
  • There's a filter box on the top right, as well as "fake" refinements on the left hand side that allows us to re-query SharePoint search for filtered people.
  • One possible idea here would be to use SPServices' User Profile Service support and talk directly to the User Profile service, if you want to skip the search service.

 

Summary

A quick post of 3 recent javascript customizations that heavily used SPServices.  Hope that give you guys a lot of ideas.  Let me know what you guys think.

How to create your Windows 8 Start Button with PowerShell

Before I go on, I have to say I find the Start Menu unnecessary.  There are already many ways to get to your Start Screen:

  • Throw mouse to lower-left corner (with the mouse)
  • Press the Windows key (on your keyboard)
  • Swipe in from the left edge (touch screen)
  • Press the Start button (any device with a hardware start button)

 

That said, Windows is still about choice.  And here's how you can add your own "Start Menu Button"

  1. Create a shortcut.
  2. Type in this:
    powershell.exe -Command "Add-Type -AssemblyName System.Windows.Forms; [Windows.Forms.SendKeys]::SendWait('^({ESC})')"

    (all in one line)
    This sends the Windows key (CTRL-ESC) via Powershell.
    image
  3. Configure the shortcut to run minimized
    image
  4. Change the Icon, I select this icon from the bootux.dll file %SystemRoot%\System32\bootux.dll) 
    image
    (All the icons are white, select them to see what they look like) 
  5. Drag the shortcut and pin it to the task bar, on the far left.
    image
  6. Now you have that familiar Start menu button back.  Click it and you'll get the Start Screen to pop up. 
    image

 

Notes

  • Does not appear to work in Windows RT, but if you have a Surface just hit that start hardware button

XML deserialization - cannot have child contents to be deserialized as an object

Element MyValue from namespace http://schemas.datacontract.org/2004/07/Services cannot have child contents to be deserialized as an object. Please use XmlNode[] to deserialize this pattern of XML.

 

I was playing with DataContractSerializer, and getting this strange error when performing de-serialization (turning XML back into an object of type MyClass).

[DataContract]
public class MyClass
{
    [DataMember]
    public string MyName;

    [DataMember]
    public object MyValue;
}

 

The error message actually is pretty clear about what the issue is, but English is a sucky language.  Let me highlight what the error message is really saying:

Element MyValue from namespace http://schemas.datacontract.org/2004/07/Services cannot have child contents to be deserialized as an object. Please use XmlNode[] to deserialize this pattern of XML.

Read it again:

Element MyValue cannot be deserialized as an object.

 

The deserializer was actually talking about the fact that it can't turn <MyValue>1</MyValue> back into an object of the type Object.

If you change your DataContract to

[DataContract]
public class MyClass
{
    [DataMember]
    public string MyName;

    [DataMember]
    public string MyValue;
}

 

Then the deserializer will be happy.

The SharePoint Pinterest-style Image Library

A picture is worth a thousand words.

 

In the latest version of spaspa.codeplex.com, I created a separate Knockout Template and bind the Images library (BaseTemplateID 851) to it.  Then I inserted a simple jQuery Plugin Wookmark https://github.com/GBKS/Wookmark-jQuery

The end result is that when we have pictures, they are displayed in an awesome layout.

As an added bonus, I'm calculating the thumbnail image from SharePoint, so instead of rendering:

http://spg-dev-jl/PublishingImages/wallpaper_08.jpg

image

Original: 78K

I'm rendering

http://spg-dev-jl/PublishingImages/_w/wallpaper_08_jpg.jpg

image

Thumbnail image generated by SharePoint.  Which is a far smaller file - 16k.

 

Next update, I'll try to resolve those pesky SharePoint users and get the correct user name and picture.  So we don't have Mr. Bill Gates staring back at us! ;-)