Tracking SharePoint Popular Items Accessed through JavaScript

Applies to: SharePoint 2013+

A while back I wrote an AngularJS app running in SharePoint 2013 and using lists as the backing store for some components. Without getting into the reasons this particular architecture was chosen, let’s look at an issue that came up.

The client asked us to show the popular items. There is a standard web part for this, but you can also query the search API directly by sorting by ViewsLifeTime:descending which is what we did so that we could display it in a custom Angular directive. No problem! Right?

It wasn’t until some time later that the client asked about the results we were displaying. The most “popular” items appeared to be the ones they had had trouble with behind the scenes and didn’t match their expectations about what users would be viewing.

Unpopular

When you view a list item (dispform.aspx?id=X) this view is tracked in SharePoint’s Usage Analytics (assuming you’ve configured this correctly). It’s this information that is used by search to determine an item’s popularity.

Unfortunately, it turns out pulling items from the REST API triggers no such view event. This seems obvious in retrospect, but until we really thought about it, usage tracking is just one of those magical behind the scenes things SharePoint does and we just assumed it would work.

This explains the results the client was seeing. The items they were having trouble with are the ones they were viewing directly (outside of the Angular app). While this wasn’t a ton of traffic, it was far more than any other list item was getting since they were only being viewed via the REST API inside a custom application. Ugh.

Fortunately, the fix for this isn’t too complicated, it’s just not very obvious.

Spoofing Item Views in JavaScript

You can log a View event using the SP.Analytics.AnalyticsUsageEntry.logAnalyticsEvent2 method. I had trouble finding any helpful documentation on this method or what the parameters should be. Fortunately, after some experimentation (and patience as the entries are not immediately available), I got it working.

Here’s the basic JS code which you can then adapt and make smarter:

For instance, I adapted the above into an AngularJS service and wrapped the call to get the site Id and user into a promise so that I only had to pull that once in my app, but all of that is up to you.

One nice thing about doing this manually is you can control when it fires. For instance, you might want to only log usage during reads but not during edits or exclude administrative accounts, etc.

That’s it! Now your custom interface can participate in the internal popularity contest!

Taking Advantage of the Loading Indicator in the SharePoint Framework

Applies to SharePoint Framework (SPFx)

When making SharePoint Framework (SPFx) client side webparts, it’s common to load some data from somewhere else and then display it on the screen. Even if that data is just coming from a local list these requests are performed asynchronously and you should indicate to a user that the operation may take some time. The easiest way to do this is through the loading indicator. Here’s how it looks by default:

Default Indicator

Did you know that you can easily show/hide this indicator and even customize the text? You can even decide where it’s displayed. WOWEE!

To show the Loading Indicator you can simply call this.context.statusRenderer.displayLoadingIndicator where the this refers to your BaseClientSideWebPart. This method takes 2 parameters.

The first parameter is the element where you want the loading indicator to be displayed. Typically if you are calling this from the main render method in your webpart, you’ll just specify this.domElement. However, you can easily specify any other element (see below for an example). Just be aware that the default styles are currently pretty large.

The second parameter is the text you want to display between Loading and

Loading indicator with some custom text:

Custom Text

this.context.statusRenderer.displayLoadingIndicator(this.domElement,"Some Stuff");

Loading indicator inside a custom element with custom text:

Custom Text - Inline

this.domElement.innerHTML = `
  <div class="${styles.loadingIndicator}">
    <div class="${styles.row}">
      <div class="${styles.container}">
        <span class="ms-font-xl">Critical Information:</span>
        <div class="${styles.specialbox}" id="myspecialbox">
        </div>
        <span class="ms-font-xl">Static text, wowee!</span>
      </div>
    </div>
  </div>`;

//Show the loading indicator inside an element
this.context.statusRenderer.displayLoadingIndicator(document.getElementById("myspecialbox"),"Some Stuff");

Hiding the Loading Indicator:

this.context.statusRenderer.clearLoadingIndicator(this.domElement);

You can find a sample project here: https://github.com/thechriskent/spfxLoadingIndicator

You can download the whole project and run it, or just take a look at the main webpart file.

List View Extension Points (CSR)

Applies To: SharePoint 2013, 2016, Office 365

List View Client Side Rendering Primer: 4 of 5

About This Series

This series provides a brief overview of Client Side Rendering for List Views (often referred to as JSLink). Basic extension points and examples are included. The goal of this series is to get developers unfamiliar with this programming model quickly up to speed.

How to Get the Code

The example created using the steps in this series can be found in full as part of the csrShim repository:
https://github.com/thechriskent/csrShim/tree/master/Examples/CSR%20Primer

The full project can be found on GitHub:
https://github.com/thechriskent/csrShim

You can download or clone the repository directly from that site. You can also view the code directly on the site. csrShim is not used in this example and is not required.

In the following examples, we will be targeting on premise SharePoint 2013 using SharePoint Designer 2013.

List View Extension Points

You can override one or more parts of the rendering of your list view. You do not need to specify all the following, but be aware that specifying a single template will use the default render for the other templates (this is different from the OOTB view).

CTX

The CTX object contains all the information about your list view – including all the returned data. This object is provided to the event callback functions and to any template functions.

Although there are many properties (especially when using standard CSR vs csrShim), here are the key properties to pay attention to:

  • CurrentItem
    • This property is only set when passed to the Item template
    • Provides quick access to all properties for the current item
    • Properties match the internal name of the field
    • Properties can sometimes contain periods and therefore these properties cannot be accessed using the standard dot notation
      //Standard Access
      var created = ctx.CurrentItem.Created;
      
      //Access Properties with Periods
      var createdF = ctx.CurrentItem["Created.FriendlyDisplay"];
      
  • firstRow
    • When true, the item is the first item returned
  • lastRow
    • Only available with csrShim!
    • When true, the item is the last item returned
  • Row
    • The array of returned items with their properties
    • These are equivalent to CurrentItem objects
    • This allows access to ALL rows from any template including the Item template
  • FirstRow
    • Available with standard CSR and csrShim with Lists (not feeds/XML)
    • The item ID of the first item returned
  • LastRow
    • Available with standard CSR and csrShim with Lists (not feeds/XML)
    • The item ID of the last item returned
  • ListSchema
    • In standard CSR, contains several properties about the underlying list structure and the view configuration
  • Field
    • Array of the fields returned with the view
    • In standard CSR, several properties (like DisplayName) can be very helpful for dynamic displays. csrShim only provides the Name (internal name).

Event Callbacks

There are 2 events (OnPreRender and OnPostRender) where you can provide callback functions.

OnPreRender

To have a callback function executed BEFORE your templates are applied to the list data, you can specify an anonymous or named function to the OnPreRender property of your CSR object.

The PreRender event can be helpful to declare any necessary SOD dependencies, verify existence of elements, contact additional web service, etc.

(function(){

    var myCSR = {
        BaseViewID: 1,
        ListTemplateType: 100,
        OnPreRender: myFunction
    };

    function myFunction(ctx){
        //Do Stuff
    }
})();

Example

In our HallOfFame.js example from earlier we will add a console message so we know when our rendering is about to start:

    var HallOfFame = {
        BaseViewID: 1,
        ListTemplateType: 100,
        OnPreRender: hofPreRender
    };

    function hofPreRender(ctx){
        if(window.console && window.console.log){
            console.log('Begin Hall Of Fame!');
        }
    }

Here’s what we just did:

  • Line 5 we added a comma to ensure we could add another property
  • Line 6 we added the OnPreRender property and gave it a reference to our function hofPreRender
  • Line 9 this is our callback function
  • Line 10-12 safely logs a message to the console (the checks prevent IE from throwing errors when the console is not visible)

Refreshing the page with the developer tools visible (F12) should show our message. If you don’t see a console message, verify the JS Link property is pointing to the correct page. Also note that console messages logged before the developer tools were open (in IE) will not show and you may need to refresh.

OnPostRender

To have a callback function executed AFTER your templates are applied to the list data, you can specify an anonymous or named function to the OnPostRender property of your CSR object.

The PostRender event can be helpful to attach events or run any other code dependent on your HTML being in place.

(function(){

    var myCSR = {
        BaseViewID: 1,
        ListTemplateType: 100,
        OnPostRender: myFunction
    };

    function myFunction(ctx){
        //Do Stuff
    }
})();

Example

In our HallOfFame.js example from earlier we will add another console message so we know when our rendering is all done:

var HallOfFame = {
        BaseViewID: 1,
        ListTemplateType: 100,
        OnPreRender: hofPreRender,
        OnPostRender: hofPostRender
    };

    function hofPreRender(ctx){
        if(window.console && window.console.log){
            console.log('Begin Hall Of Fame!');
        }
    }

    function hofPostRender(ctx){
        if(window.console && window.console.log){
            console.log('Finished Hall Of Fame!');
        }
    }

Here’s what we just did:

  • Line 6 we added a comma to ensure we could add another property
  • Line 7 we added the OnPostRender property and gave it a reference to our function hofPostRender
  • Line 16 this is our callback function
  • Line 17-19 safely logs a message to the console (the checks prevent IE from throwing errors when the console is not visible)

Refreshing the page with the developer tools visible (F12) should show both our PreRender and PostRender messages in the proper order.

Templates

There are several templates that can be specified using the Templates property of your CSR object. You can specify simple strings, “magic” strings, and full functions that return a string.

(function(){

    var myCSR = {
        BaseViewID: 1,
        ListTemplateType: 100,
        Templates: {
            Header: "
<div>I'm the Header!</div>
",
            Item:   "
<div>I'm an Item!</div>
",
            Footer: "
<div>I'm the Footer!</div>
"
        }
    };

})();

Available Templates

  • Header
  • Item
  • Fields
  • Footer

Note – The Footer template is often misused to close any open tags from the header or item templates. This will result in invalid HTML. Although most modern browsers will auto close these open items for you, this may cause hard to track down display issues! The Footer template is rendered inside a div element outside the hierarchy of the Header and Item templates and is designed for standalone paging. It can be used for other things, but it is separate from anything generated in the other templates.

Magic Strings

In the most basic forms, templates can be specified as simple strings (as in the example above). Additionally, when specified as strings you can use special notation to have “magic strings” resolved automatically.

(function(){

    var myCSR = {
        BaseViewID: 1,
        ListTemplateType: 100,
        Templates: {
            Header: "
<div>My BaseViewID is <#=ctx.BaseViewID#></div>
"
        }
    };

})();

The format is to include <#=ctx. Before the name of the property and followed by #>

In nearly every case you will be better supplying a function to the template properties (even for simple strings) since this will give you more flexibility, better readability, and easier extensibility.

Functions

You can specify anonymous or named functions (named functions are best practice coding) to each of the template properties. These functions will be provided with the CTX object as the parameter.

(function(){

    var myCSR = {
        BaseViewID: 1,
        ListTemplateType: 100,
        Templates: {
            Header: myFunction
        }
    };

    function myFunction(ctx){
        //Do Stuff
    }
})();

Example Header

Although it would be better to use an external stylesheet, for this simple example we will be declaring an inline style block to set our CSS for the rest of the list view. We will do this in the header. Additionally, we’d like to show a title box.

    var HallOfFame = {
        BaseViewID: 1,
        ListTemplateType: 100,
        OnPreRender: hofPreRender,
        Templates: {
            Header: hofHeader
        },
        OnPostRender: hofPostRender
    };

    function hofHeader(ctx){
        var styles = '
<style type="text/css">' +
                     '.halloffame{' +
                     ' text-align:center;' +
                     ' width:504px;}' +
                     '.halloffame div{'+
                     ' box-sizing:border-box;}' +
                     '.hof-header{' +
                     ' font-size:18px;' +
                     ' font-weight:bold;' +
                     ' border:solid black 4px;' +
                     ' padding:6px;}' +
                     '.hof-items{' +
                     ' border-right:solid black 4px;}' +
                     '.hof-items:after{' +
                     ' clear:both;' +
                     ' content:"";' +
                     ' display:block;}' +
                     '.hof-item{' +
                     ' float:left;' +
                     ' width:125px;' +
                     ' border-left:solid black 4px;' +
                     ' border-bottom:solid black 4px;' +
                     ' height:100px;}' +
                     '.hof-item div{' +
                     ' color:black;' +
                     ' font-weight:bold;' +
                     ' font-size:15px;}' +
                     '.hof-item:hover{' +
                     ' filter:brightness(75%);}' +
                     '.hof-footer{' +
                     ' border:solid black 4px;' +
                     ' border-top:none;' +
                     ' padding:3px;' +
                     ' font-size:10px;}' +
                     '</style>

';
        var header = '
<div class="halloffame">
<div class="hof-header">- Hall of Fame -</div>
<div class="hof-items">';
        return styles + header;
    }

Here’s what we just did:

  • Line 7 we added a Templates property
  • Line 8 we added a Header property to our Templates object and gave it a reference to our hofHeader function
  • Line 19 this is our template function
  • Lines 20-54 is a massive string to define our style block
  • Line 55 this is our actual HTML. We begin with a wrapper div (that we don’t close in this template) with a class of halloffame since this allows us to target our CSS classes very specifically. We also provide a div to hold our title text
  • Line 56 we return the combined styles and header strings

When you refresh the page now you will get this monstrosity:

lve01

Example Item

We’d like to show each of the items as a box showing the Title and the picture of the Person field. Additionally, we’d like to color the box based on the value of the Color field. When someone clicks on a box, they should be taken to the user’s profile page.

    var HallOfFame = {
        BaseViewID: 1,
        ListTemplateType: 100,
        OnPreRender: hofPreRender,
        Templates: {
            Header: hofHeader,
            Item: hofItem
        },
        OnPostRender: hofPostRender
    };

    function hofItem(ctx){
        var sip = ctx.CurrentItem.Person[0].sip;
        var photoUrl = '/_layouts/15/images/PersonPlaceholder.96x96x32.png';
        if(ctx.CurrentItem.Person[0].picture){
            photoUrl = ctx.CurrentItem.Person[0].picture;
        }
        var photo = '/_layouts/15/userphoto.aspx?accountname=' + sip + '&size=L&url=' + photoUrl;
        var userUrl = _spPageContextInfo.siteServerRelativeUrl + '/_layouts/15/userdisp.aspx?ID=' + ctx.CurrentItem.Person[0].id;                           

        var item = '<a href="' + userUrl + '">' +
                   '
<div class="hof-item" style="background-color:' + ctx.CurrentItem.Color + ';">' +
                   '
<div>' + ctx.CurrentItem.Title + '</div>
' +
                   '  <img style="max-height:72px;max-width:72px;" src="' + photo + '"/>' +
                   '</div>
' +
                   '</a>';
        if(ctx.ListData.LastRow == ctx.CurrentItem.ID){
            var closures = '</div>
</div>
';
            return item + closures;
        } else {
            return item;
        }
    }

Here’s what we just did:

  • Line 9 we added an Item property to our Templates object and gave it a reference to our hofItem function
  • Line 60 this is our template function
  • Lines 61-66 is the building of the profile picture image.
    • In standard CSR, a person field is returned as an array of objects with additional properties about a person. One of those properties is the picture property which is the URL to the profile picture for a given user.
    • If a user does not have a profile picture, this property is not included
    • So, we ensure that if the picture is not available we use the standard person placeholder image instead
    • Additionally, if your My Site web application is hosted at a different domain (even sub domain) users using machines not joined to the domain (IE iPads) may be prompted to log in for each profile picture you display.
    • So, instead of using the profile picture directly, we use the userphoto.aspx page to provide us the picture without leaving the domain
  • Line 67 builds the URL to the user profile page using the user id property
  • Lines 69-74 builds our actual HTML for each item.
    • We wrap everything in a link to the user profile
    • We use an inline style to set the background-color to the choice field
      • This is not a good idea and is only used as an obvious example, generally you should not directly incorporate values into markup like this. It would be easy to break simply by adding a choice for a color that is not one of the named HTML colors.
    • Line 67 checks if this item is the last item returned
      • In csrShim we could simply check ctx.CurrentItem.lastRow
      • If this is the last item, we close the wrapper divs left open in the header template and return those after the item.
      • This is necessary since the Footer template will be in a different div and leaving open HTML tags can cause display issues
    • If this wasn’t the last item, we just return the basic item box in line 80

When you refresh the page now things are looking truly amazing:

lve02

Example Footer

We’d like to add some instructions to the bottom to remind people to click on these boxes.

    var HallOfFame = {
        BaseViewID: 1,
        ListTemplateType: 100,
        OnPreRender: hofPreRender,
        Templates: {
            Header: hofHeader,
            Item: hofItem,
            Footer: hofFooter
        },
        OnPostRender: hofPostRender
    };

    function hofFooter(ctx){
        var footer = '
<div class="halloffame">
<div class="hof-footer">Click on a person to learn more</div>
</div>
';
        return footer;
    }

Here’s what we just did:

  • Line 10 we added a Footer property to our Templates object and gave it a reference to our hofFooter function
  • Line 84 this is our template function
  • Line 85 builds standalone HTML to be used as our footer. We provide another wrapper with the halloffame class so that our global styles still get applied. Then we give an unnecessary message encouraging clicks.
  • Line 86 we return the footer

When you refresh the page now you will now be struck at the beauty of our creation:

lve03

Continue?

That’s pretty well everything you need to know about client side rendering with list views. However, the final post in the series provides a quick list of best practices to keep in mind while applying CSR to List Views:

Getting Started (List View CSR)

Applies To: SharePoint 2013, 2016, Office 365

List View Client Side Rendering Primer: 3 of 5

About This Series

This series provides a brief overview of Client Side Rendering for List Views (often referred to as JSLink). Basic extension points and examples are included. The goal of this series is to get developers unfamiliar with this programming model quickly up to speed.

How to Get the Code

The example created using the steps in this series can be found in full as part of the csrShim repository:
https://github.com/thechriskent/csrShim/tree/master/Examples/CSR%20Primer

The full project can be found on GitHub:
https://github.com/thechriskent/csrShim

You can download or clone the repository directly from that site. You can also view the code directly on the site. csrShim is not used in this example and is not required.

In the following examples, we will be targeting on premise SharePoint 2013 using SharePoint Designer 2013.

List Setup

For this example, we will be using a custom list with just 3 columns:

  • Title (Text)
  • Person (User)
  • Color (Choice)

To create the list:

  1. From a site where you have full control or design permissions, using the Site Actions menu (gear) choose Add an App
  2. Choose Custom List
  3. Name the list Hall of Fame and click Create
  4. From Site Contents, hover over the Hall of Fame icon and click the ellipsis to show the panel and choose Settings:
    gs01
  5. Under Columns, click Create column
  6. Give a name of Person and set the type to Person or Group then click OK:
    gs02
  7. Under Columns, click Create column again
  8. Give a name of Color and set the type to Choice (menu to choose from). Replace the choices with Tomato, YellowGreen, DeepSkyBlue, Gold (each on separate lines):
    gs03
  9. Navigate to the Hall of Fame list and add several entries:
    gs04
  10. On a page, choose to Edit and click the Add a Web Part button
  11. Under Apps, choose Hall of Fame
  12. Click Stop Editing

By default, you have a very OOTB view of the list as a table with column headers and not a lot of excitement. So, let’s customize it!

Script Setup

To use the JS Link property of the XSLTListView web part we added in the steps above (step 11), we’ll need a JavaScript file to point to.

  1. Open your site in SharePoint Designer
  2. Using the All Files navigation option, open a Document Library (generally, the Style Library is a great location for these types of resources)
  3. In the File dropdown choose JavaScript:
    gs05
  4. Name the file js
  5. Return to the page (in the browser) where you added the web part
  6. Edit the page and using the dropdown on the web part choose Edit Web Part
  7. In the web part tool pane, expand the Miscellaneous section
  8. In the JS Link box, Provide the path (You can use SPURLs) to the JavaScript file we created earlier then click OK:
    gs06
  9. Nothing will happen (we haven’t provided any code yet). Click Stop Editing on the page
  10. Return to SharePoint Designer and Right-Click on the HallOfFame.js file and choose Edit File in Advanced Mode
  11. Enter the code from the CSR Boilerplate Code below

CSR Boilerplate Code

(function(){

    var HallOfFame = {
        BaseViewID: 1,
        ListTemplateType: 100
    };

    SP.SOD.executeFunc('clienttemplates.js','SPClientTemplates',function(){
        SPClientTemplates.TemplateManager.RegisterTemplateOverrides(HallOfFame);
    });

})()

The above code is simply boilerplate for the extension points we will fill in below. Here is what this code currently does:

  • Line 1 is the declaration of an immediately invoked function expression (IFFE) that will ensure our code will not be placed in the global namespace. This convention should always be used with JS Link files.
  • Lines 3-6 is the beginning of our template object. Soon we will be adding more properties to help determine how the list is formatted. For now, we’ve specified the BaseViewID and the ListTemplateType which is how we target the Custom List (type 100) so that SharePoint knows what data to provide us.
  • Line 8 uses a Script On Demand (SOD) method to only call our function once the clienttemplates.js file has loaded and the SPClientTemplates object is ready to be used. This is essential to prevent our script from executing before SharePoint is ready.
  • Line 9 registers our template object with the SharePoint CSR engine

Refreshing at this point will still not apply anything since we did not provide any Templates just yet.

Continue?

Everything is in place for us to provide some actual CSR templates, but in order to do so we need to understand what templates are even available and how to use them. So, check out the next post in this series:

jsMessage Basic Example

Applies To: Construct 2, jQuery, jsMessage

In my last post, Introducing jsMessage for Construct 2, I gave a brief overview of my C2 Plugin jsMessage. jsMessage enables sending and receiving messages in Construct 2 through jQuery events. You can read more in that post, but the basic idea is the ability to communicate to a Construct 2 game through the Browser. The license is free for everybody and attribution isn’t required.

In this post, I’m going to walk through the jsMessageTest Basic game to show you exactly how it works. You can also download it over on CodePlex if you’d like to follow along.

“Game” Overview

When you first run the project not much is going to happen. You’ll see a big red message that says “Nothing Yet…” – once you’ve successfully sent a message the contents will be displayed here.

InitialScreen

This is a very simple game project with just a few assets and only a small set of standard objects (Touch, Sprite, Browser, Particles, Text and Text Box). The only custom object is the jsMessage object. This was added to the project like any other object and can be found in the Web section (assuming you’ve installed it):

jsMessageInsertNewObject

Receiving Messages in Construct 2

The Event Sheet

jsMessage provides 2 conditions for receiving messages. The first one, Message Received, fires every time a message is received. In our game we are using it to set the text of the txtRecevied object (the big red text). We are also outputting additional information to the console. This helps illustrate several of jsMessage’s expressions but is not something you’d normally do outside of debugging. Here’s what this section of the Event Sheet looks like:

EventSheet-MessageReceived

Using the Log in console action of the built-in Browser object, we output information about the received message. The jsMessage.MessageRaw expression provides the full message string. The jsMessage.Command expression provides only the first part of the message before any values (known as the command). The jsMessage.ValueCount provides the total count of values passed (additional strings after the command separated by the Value Separator Property).

Finally, there’s a For Loop that outputs each of the message’s values (if there were any) by using the jsMessage.Value() expression.

Client-Side

Let’s give it a go. For all of the client-side examples we’re just going to type the jQuery commands directly into the console. So go ahead and run the project and open the Dev Tools (Just hit F-12 in Chrome) and switch to the console. Type the following:

$(document).trigger('CKjsMessageSend','Hello World');

Once you hit enter, your screen should look like this:

HelloWorld

You can see the txtReceived object had its text set to the message and the console has all the log messages we expected (Raw & Command are equal in this case and the Value Count is 0).

Now try sending this:

$(document).trigger('CKjsMessageSend','DoThing|Turds|Sunshine');

DoThing

You’ll see the txtReceived object gets the full message just like before, but if you look in the console you’ll see some differences. We can now see our Command is DoThing and that we have 2 values: Value 0 is Turds and Value 1 is Sunshine. Of course, we are assuming the use of the default separator (The separator is customizable so it’s always a good idea to use the Separator Events to determine what that is before sending/receiving messages on the client).

Responding to Commands in Construct 2

The Event Sheet

Another condition provided by jsMessage is Command Received. This condition lets you specify the command to listen for. This is what we’re doing in the Turtle section of the Event Sheet:

TurtleCommand

We are listening for the command, “Turtle”. When it’s received we move a turtle sprite across the screen using a Bullet behavior (There are also a couple of conditions to reset the turtle once it leaves the screen).

Client-Side

Here’s how we trigger this command from the console:

$(document).trigger('CKjsMessageSend','Turtle');

Turtle

Look at that cute turtle! LOOK AT IT!

You can see everything works just like any standard condition (Note that the console also provides us all the extra information because both the Command “Turtle” Received and Message Received conditions are firing).

Responding to Commands with Values in Construct 2

The Event Sheet

Commands are just messages which means they can also have attached values. This can be seen in the Explosions section of the Event Sheet:

ExplosionsCommand

We are listening for the command, “Explode”, but we’ve added some additional conditions to ensure that there is an included value (jsMessage.ValueCount = 1) and that that value is an integer greater than 0 (int(jsMessage.Value(0)) > 0).

Once the above conditions are met,we use a For Loop to create the number of explosions (particle objects) as specified by the passed value (with a max of 10 cause let’s not get crazy!).

Client-Side

Here’s how we trigger this command from the console:

$(document).trigger('CKjsMessageSend','Explode|7');

Explode

GLORIOUS EXPLOSIONS!

Sending Messages from Construct 2

The Event Sheet

jsMessage provides a single Action, Send Message, that is really easy to use. You just provide the message as a parameter and it’ll take care of it:

SendEventSheet

All we’re doing above is treating the icon sprite like a button by responding to a tap (or click). We flash the button to give some feedback to the user that they tapped it and then call the Send Message action with the text of the txtboxSend object. Of course, nothing is going to happen if nobody is listening on the other side…

Client-Side

To receive messages from Construct 2 you will need to register to respond to the appropriate jQuery event. Here’s an extremely simple response that just writes the sent message out to the console:

$(document).on('CKjsMessageReceive',function(e,m){console.log(m);});

To test, just write something in the text box and click the button:

SendMessage

 

Sending Messages with Values from Construct 2

The Event Sheet

To send messages with values from your game you’ll build your messages using the same format as above. You can see an example of this in the Responding to Requests section of the Event Sheet:

RespondingToRequests

 

When we get the command, “FPS?”, we use the Send Message action to send a custom message built by concatenating a command, “FPS”, the separator using the jsMessage.Separator expression and the C2 value, fps. We could have just typed the default separator but since this is a customizable property it’s always better to use the jsMessage.Separator expression.

Client-Side

To test this one, we need a slightly more elaborate response function:

$(document).on('CKjsMessageReceive',function(e,m){console.log('Client-Side Message Received!');var parts=m.split('|');console.log('Command Received: '+parts[0]);for(var v=1; v<parts.length;v++){console.log('Value Received: '+parts[v]);}});

I’ve kept it to one line above so that it can be easily pasted in the console, but here’s what it looks like where it’s a little more readable:

$(document).on('CKjsMessageReceive',function(e,m){
    console.log('Client-Side Message Received!');
    var parts = m.split('|');
    console.log('Command Received: ' + parts[0]);
    for(var v = 1; v < parts.length; v++){
        console.log('Value Received: ' + parts[v]);
    }
});

SendMessagesWithValuesWhen we send the “FPS?” message to the game it responds with the fps information. Our client-side response just outputs the C2 message right back to the console. I’ve hard-coded the default separator in this example, but you’ll want to use the Separator Events beforehand to ensure you know what the separator is before receiving/sending messages from the client.

 

Be sure to check out the full documentation for more details. Stay tuned for an upcoming post where I’ll show you an actual use case for this plugin. WOWEE!

jQuery OuterHTML

Applies To: jQuery 1.0+

Often in debugging I’d like to pull back the full HTML for an object and take a look at it. The html() method is great for a lot of things, but it’s limited to just the inner HTML and often doesn’t contain the stuff I’m looking for. So here’s a helper function I wrote that gives you back the full HTML as a string:

function fullHTML(jQueryElem) {
	var fullH = jQueryElem.wrap('<div>').parent().html();
	jQueryElem.unwrap();
	return fullH;
}

All it does is perform a temporary wrap around whatever jQuery Element you pass in, grab it’s parent (which is now the Div we just wrapped it in) and grab the parent’s inner HTML (which is of course the full HTML of our object). Then we just unwrap it in line 3 and return the string in line 4.

You can call it like this (this code just writes it out to the console):

console.log(fullHTML($('#myobjectID')));

It’s quick and easy and I use it in development all the time. Hopefully it helps you too.

Use SPServices in Nintex Forms 2010

Applies to: SharePoint 2010, SPServices, Nintex Forms 2010

Marc D Anderson’s SPServices (jQuery for SharePoint Web Services) can save you a ton of time and make your SharePoint sites more responsive and dynamic with very little effort. Nintex can really beef up your workflows and/or your forms. So it makes a lot of sense to bring these together!

Recently I was tasked with pulling some user profile information to display on a Nintex Form that was being used to launch a site workflow. Unfortunately, there is no way to run workflow code before showing the initial form; so all of those great Nintex Workflow Actions were unavailable to me. Fortunately, SPServices allows easy querying of the User Profile Service directly from client side script.

Nintex Forms uses a copy of the jQuery library that you can access through NWF$. So just adding SPServices to your form’s page won’t work, but since jQuery is already there it’s fairly simple to get it all hooked up.

The first thing to do is to get the appropriate version of SPServices. The version of SPServices you use depends on the version of jQuery in use. To figure out what version of jQuery Nintex Forms is using you’ll need to temporarily add some custom JavaScript to your form.

To add JavaScript to Nintex Forms, from the Form editor click the Settings button in the Ribbon and then expand the Custom JavaScript section at the bottom:

FormJavascript

You can take advantage of NWF$ here. Simply add the following to the box and click Save:

console.log(NWF$().jquery);

Open the F12 Developer tools and preview your form. In the Console you should see the version of jQuery being used by Nintex Forms. For us it was 1.6.1. So we should be fine using the latest version of SPServices.

You’ll need to download the SPServices library. Since SPServices uses an IIFE to extend the jQuery object, we’ll need to make a slight adjustment to instead extend the NWF$ object. This is actually really easy. Open up the minified version of SPServices (the one with the .min at the end of the file name) and go all the way to the very end where you’ll see (jQuery);

Just replace the jQuery portion with NWF$ and save with a different name (maybe put an NF.min.js on the end). It’ll look something like this:

SPServicesCode

Then just upload it somewhere in your site collection (The Style Library is generally the best place).

To reference that file go back to the Nintex Form editor and click that Settings button again and expand the Advanced section. Scroll down to the Custom JavaScript Includes section and add the address of the script you just uploaded (If you have multiple JavaScript Includes you just put one on each line):

SPServicesInclude

Press Save and that’s it! You can now access SPServices to do whatever fancy magic you need!

To make sure it worked, scroll back down to that Custom JavaScript section of the Form Settings dialog and add the following code:

NWF$(document).ready(function(){
     console.log(NWF$().SPServices.Version());
});

Then just make sure those F12 developer tools are open and preview the form again. You’ll see the version of SPServices logged out to the console.