Entries in code (110)

Friday
May252012

SharePoint in a single page, now with List Item edit

 

Here's the latest screenshot from this project on http://spaspa.codeplex.com

 

 

I've put in buttons that allows you to edit a list item, and that drops the item into edit mode.

Here I'm modifying the Title field.  When you hit Save, it will commit the changes back to SharePoint.

Twitter Bootstrap UI turns out to be really good at guessing screen sizes and adapt.  Here's the page in landscape mode.

image

Saturday
Apr212012

SPSPerth 2012 Update

This is my first time in Perth!  Hello Perthites!

I even took a train to Cottesloe beach - a very nice beach, I watched the sunset and did what any geek would do, I checked in the Indian Ocean.

I will update this post with links after the sessions. In the mean time, you can reference my current collection of articles on these topics regarding REST, custom service, and Knockout

http://johnliu.net/rest/

Downloads

Reference

Make sure you follow Matt Menezes
http://spmatt.wordpress.com/

He's a regular at Perth user group circles and knows a lot about Knockout.  I think he is slotted in for a future session in the upcoming months - don't miss it!

Tuesday
Mar272012

InfoPath - disabling backspace key in browser form

How to disable the backspace key using Javascript/jQuery for an InfoPath browser form in SharePoint 2010.

 

The problem

One really troubling problem with almost all web solutions is how the Backspace key works.  By default, it tells your browser to go back to the previous page in history.

If you are just browsing around on your Intranet, this is probably not a big deal - firstly, you wouldn't be pressing backspace unless you actually wanted to go back.  Secondly, if you did indeed made a mistake and pressed the backspace key, you'd just undo that action by clicking the forward button, or navigate to another link.  No problem.

 

When you are filling in a form on the browser though, such as through InfoPath, suddenly the backspace key is a big deal.  You users may be using the backspace key to delete text that they are in the middle of entering.  And if they didn't have a textbox focused, the backspace key is sent to the browser form, and suddenly you have a problem.  The form disappeared, and you have lost information.

 

InfoPath is quite smart - it remembers which view you are supposed to be on, and when you navigate to an outdated browser historical view of the form - Form Server will automatically redirect you forward to show you the correct form you are supposed to be viewing.  This is good, at least in the navigation sense.  So the only remaining problem is the lost data - your user may have had a whole page filled out and this mistake has just cleared their form.  Not good.

 

Enter Javascript

So, the plan is simple:

  1. Inject javascript to the existing browser form
  2. Listen to keydown event for a backspace key (keycode 8)
  3. Eat the event and stop it from propagation, so the browser don't see it

Using jQuery, you'll need this simple function.

 

function document_keydown(e) {
    if (e.keyCode == 8 && e.target.tagName != "INPUT") {

        // letting us know we've ate a backspace key
        SP.UI.Notify.addNotification('Ate a backspace key, hew!', false);

        // cancel backspace navigation
        e.preventDefault();
        e.stopImmediatePropagation();
        return false;
    }
};

$(document).keydown(document_keydown);

 

Injecting Javascript in modal dialog

 

If you are using SharePoint 2010's modal dialog to show InfoPath in a modal popup, it's slightly trickier.

 

// grab a reference to the modal window object in SharePoint
var w = SP.UI.ModalDialog.showModalDialog(options);

if (w) {
    // get the modal window's iFrame element
    var f = w.get_frameElement();

    // watch frame's readyState change - when page load is complete, re-attach keydown event
    // on the new document       
    f.onreadystatechange = function(e) {
        if (f.readyState == 'complete') {
            var fwin = f.contentWindow || f.contentDocument;
            $(fwin.document).keydown(document_keydown);
        }
    };
}

Result

 

nom-nom-nom backspace keys.

image

 

Note, because the Javascript catches the keypress event at the document level.  If your user still has focus on the input (textbox) level, the event will not be stopped - so your user still will be able to backspace when they are using a textbox.

Wednesday
Mar212012

AUSPC 2012 summary

I had an awesome time presenting Building your own custom REST Services and consuming them with jQuery AJAX in the Australian SharePoint Conference 2012.  A big thank you to the developers that came and geeked out with me for an hour on a Wednesday afternoon.

Notes

When you build a custom WCF Service using the CKS template, it is deployed to a subfolder the web front end's ISAPI folder, which, in turn, is mapped to the site's /_vti_bin/ folder.

image

 

It appears that in my earlier attempt to create an incomplete version of the REST service template item, I interfered with how CKS's templates worked - and correct features for deploying the WCF service is no longer being included in the package.  While existing items were updated and deployed, the new WCF service that I was creating wasn't being deployed to the ISAPI folder.

I've removed the REST template item from my Visual Studio .NET environment, and voila - the WCF services deployed nicely once again.

So that's one mystery resolved.  Now I scratch my head about how to fix my VS.NET REST template item.

 

Downloads

Thursday
Feb232012

Knockout binding formatters for date and currency

 

Dependency

  • Requires Knockout
  • jQuery (for setting text())
  • ASP.NET (for the formatting functions).

 

ko.bindingHandlers.date = {
    update: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor(), allBindings = allBindingsAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(value);
       
        var d = "";
        if (valueUnwrapped) {
            var m = /Date\([\d+-]+\)/gi.exec(valueUnwrapped);
            if (m) {
                d = String.format("{0:dd/MM/yyyy}", eval("new " + m[0]));
            }
        }       
        $(element).text(d);   
    }
};
ko.bindingHandlers.money = {
    update: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor(), allBindings = allBindingsAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(value);
       
        var m = "";
        if (valueUnwrapped) {       
            m = parseInt(valueUnwrapped);
            if (m) {
                m = String.format("{0:n0}", m);
            }
        }       
        $(element).text(m);   
    }
};

Usage:

 

  • data-bind="money: myMoney"
  • data-bind="date: myDate"

 

Note:

Dates are converted from ASP.NET's date format: \/Date(1000+1000)\/

Tuesday
Feb212012

SSPUG retrospective: Creating Knockout user experiences in SharePoint with JavaScript

 

I had an absolute blast presenting Knockout, AJAX, jQuery, SP2010 REST services, and spservices tonight at the February 2012 Sydney SharePoint user group.

The turn out was awesome, and I want to thank you guys for the great questions and the awesome attention for listening me talk about this stuff, with great excitement, for 1.5 hours.

This is what we built, not bad, in 90 minutes ;-)

image

 

Great questions:

Why do you need to call ko.utils.unwrapObservable for the key function? 

This is actually pretty important, and I didn't explain it very well until I thought about it afterwards.

The reason is that I believe Knockout is actually building a dependency graph when you use knockout expressions and compute functions.  If you use data.Id() - you will actually set up a dependency chain between the knockout viewmodel and the key function.  I can't imagine it would be disastrously bad - since you don't bind the key function to the UI, but it is an unnecessary performance hit.

 

 

What do you do with the formatting?

The easiest way, I think, is to build a compute function and then return the value you want in the right format you wanted it.  Knockout itself doesn't contain formatting functions, and I think it will probably be implemented as an separate plugin.

ASP.NET's built in JavaScript, which is available in SharePoint, contains a lot of formatting functions for rendering both currency and dates. 

A separate, slightly prettier technique, is to add additional binding handlers (aka, the text:, html:, value: expressions), and create a new binding expression that also does formatting.  In my projects, I've used

  • money: MyCurrency
  • date: MyDate

These are one-way binding, because I'm lazy, but you can make them two-way as well if you want to handle the parsing.

 

Downloads

 

Next Presentations

No idea, but I plan to be presenting this for the rest of the year in the various SharePoint Saturdays, so bring your colleagues for a exciting session on a very cool, new technique.

Friday
Feb032012

SharePoint - JavaScript current page context info

Quick blog. On every SharePoint page there's a javascript context variable:

 _spPageContextInfo 
{
webServerRelativeUrl : "/ProjectWeb",
webLanguage : 1033,
currentLanguage : 1033,
webUIVersion : 4,
pageListId : "{c1d7b89f-f07b-4e2e-b89c-76c315831d59}",
pageItemId : 5,
userId : 68,
alertsEnabled : true,
siteServerRelativeUrl : "/",
allowSilverlightPrompt : "True"
}
So if you are on /ProjectWeb/Pages/default.aspx
_spPageContextInfo.pageListId;   // list guid for Pages
_spPageContextInfo.pageItemId; // ID for listitem

 

Special Note

siteServerRelativeUrl will tell you if your site collection is sitting at the root level, or mapped further down.  Fairly useful information for all sorts of mischief.

No idea why alertsEnabled is a useful information.

 

An Example

Say if you want to show the versions page:

var options = {
tite: "Version History",
url: _spPageContextInfo.webServerRelativeUrl + "/_layouts/Versions.aspx?list="+ _spPageContextInfo.pageListId +"&ID="+ _spPageContextInfo.pageItemId,
width: 800,
height: 500,
};
SP.UI.ModalDialog.showModalDialog(options);

 

This will get you the Version History page in a modal popup, without running any additional client context async query.

image

Figure: Version History showing in a modal popup.

Saturday
Oct222011

SharePoint Saturday Melbourne update

I had a pleasure of flying down and presenting at the SharePoint Saturday Melbourne event.  Had a great time, met many new people and presented my talk on Custom Rest Services and jQuery AJAX, hope you guys enjoyed it.

Highlights for the presentation were the number of people that put up their hands saying they will try this in their environment - that was very encouraging - it's all fairly simple when you look at the result in small chunks.  Thank you guys.

 

The links to the PowerPoint presentation and the demo solution are here:

 

Because I ran out of time (sorry), the bits that I missed were:

  • The 3rd service factory in SharePoint 2010 is for the DataService, allowing you to connect any Entity Framework objects directly into a REST service end-point with almost no code.
  • The 3 service factories are not available in SharePoint 2007, this makes writing services VERY COMPLEX and I don't recommend doing it in 2007.  But you are not out of luck, JavaScript can call the 2007 SOAP services, as long as the correct SOAP envelop is formed before the POST call.  Luckily there are awesome people that has done most of this work: http://spservices.codeplex.com/
  • IMPORTANT: I did not explain what the jQuery.ajax's cache: false argument is.  This is very important.  When you call a REST service via a URL, if you do not very the URL/Query string, your browser will return you the same data that it has downloaded previously, and give you a cached copy.  This can be really bad since your service isn't actually called.  jQuery gets around this by appending a random number at the end of the query string, like this:

    image
    ?_=12312123

    This ensures the query string is unique and browser's cache mechanism won't interfere.  HTTP Response code 200 is success.  Rather than 304 which is browser cache.
Tuesday
Oct182011

SSPUG - REST Service and jQuery AJAX

As promised, the PowerPoint and solution files for my session for the Sydney SharePoint User Group October session.

 

Sorry I spelt "Summery" wrong.  I'm sure I copied it from another slide by mistake.

Files

Related Links

For 2007, unfortunately you can't easily do REST, but a lot of the SOAP service wrappers are done by awesome people so you don't have to do it yourself.  Thank Marc.

Saturday
Sep242011

SPSCBR - REST Service and jQuery AJAX

Climbed out of bed at 4am and drove myself and colleague Jumpei on a laughter-filled trip down to Canberra, where we had lots of fun at the SharePoint Saturday Canberra event.

Our best joke along the drive was debating whether Lake George is a real lake.  Our most scary moment was when the car wouldn't start back up after we took a 10min powernap.

 

As promised, my slide deck and a zip file of the VS.NET solution that was shown. 

While the concepts are still fresh you should build a rest service and see how this all works for you.  Enjoy :-)

Special thanks to Ishai Sagi who saved the day with an innovative 2-laptop remote-each other and project via SVG port.

 

Ran out of time, I couldn't cover in more detail...

  • How to pass multiple parameters to REST, via a POST operation - the example is in my script and Rest service, but commented out follow that pattern.
  • jQuery AJAX calls are asynchronous, you can fire 4 requests at the same time and they will run in parallel.  Number of asynchronous calls depends on browser but 4 is a common-minimum.
  • Debugging javascript tips
  • Packaging CSS/JS files in a sandbox solution tips
  • Some consideration and discussions around sandbox solution webpart and quota

 

Files

Related Links

For 2007, unfortunately you can't easily do REST, but a lot of the SOAP service wrappers are done by awesome people so you don't have to do it yourself.  Thank Marc.