Knockout and SharePoint - Simple Example

Hi All,

As you all know, client side technology is powerful and I am a fan of it. Apart from being fast and no postback is required, it is relatively easy to develop compared to hefty server side code.

However you should keep in mind that your code can be easily tracked and downloaded so if you have sensitive information and logic that needs to be secured then you need to use server side code :) You can do hybrid application though and that is probably the best way to go.

In this example I will show you how easy to get the data out of SharePoint list and display it with a little user interactivity. This web part consists of a user control and it basically displays a land mass comparison in boxes. Most of the times people do not realize how big WA is in comparison to their own country and when they come here they find out that they need 1-2 days to get to the other region.

End result will look like this:



We will be using:
1. jQuery + Knockout 2.1.0 for the awesomeness
2. SPServices to get the data from SharePoint list

The Html:

1
2
3
4
5
6
7
8
9
10
11
12
13
    <select id="LandMassList" name="LandMassList" data-bind="options: LandMass, value: SelectedLandMass , optionsText : 'Country', optionsValue : 'LandMassValue', optionsCaption: 'Please Select..'" ></select>
     
    <br />
    <div id="LandMassLegend">
        <h4>Land Mass Proportion:</h4>
        <div class="LandMassLegendBox" style="background-color:#103A4C" ></div> <div data-bind="text: WesternAustraliaText"></div>
        <div class="LandMassLegendBox" style="background-color:#91B6C6" ></div> <div data-bind="text: SelectedCountry"></div>
        <br />
    </div>
     
    <div id="BigBox" style="height:300px; width: 300px; background-color:#103A4C">
    </div>
</div>

The Javascript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
$(document).ready(function() {
    viewModel.SelectedLandMass = ko.observable();
    viewModel.SelectedCountry = ko.observable();
    viewModel.WesternAustraliaLandMass = ko.observable();
    viewModel.WesternAustraliaText = ko.observable();
    getLandMassData(onGetLandMassDataCompleted);
 
    //Get Western Australia LandMass and Remove it from dropdown
    var WesternAustraliaRecord = ko.utils.arrayFirst(viewModel.LandMass(), function(selectedItem) {
        return selectedItem.Country == "Western Australia";
    });
 
 
    viewModel.WesternAustraliaLandMass(WesternAustraliaRecord.LandMassValue);
    viewModel.WesternAustraliaText("Western Australia - " + addCommas(WesternAustraliaRecord.LandMassValue.toString()) + " square kilometres");
 
    $("#LandMassList").find("option:contains('Western Australia')").remove();
 
    //LandMass Box
    viewModel.SelectedLandMass.subscribe(function(newValue) {
        viewModel.SelectedCountry(null);
        //Empty child box
        $("#BigBox").css("background-color", "#103A4C");
        $("#BigBox").empty();
     
        if (newValue) {
            viewModel.SelectedCountry($("#LandMassList option:selected").text() + " - " + addCommas(newValue) + " square kilometres");
 
            //Calculate ratio
            var sizeRatio = (newValue / viewModel.WesternAustraliaLandMass());
 
            //If smaller
            if (sizeRatio < 1) {
                var boxWidth = Math.round(sizeRatio * $("#BigBox").width());
                var boxHeight = Math.round(sizeRatio * $("#BigBox").height());
 
                var newBox = "<div id='SmallBox' style='height:" + boxHeight + "px; width:" + boxWidth + "px; background-color:#91B6C6'></div>";
                $("#BigBox").append(newBox);
            }
 
            //If greater
            if (sizeRatio > 1) {
                var oppRatio = (viewModel.WesternAustraliaLandMass() / newValue);
                var boxWidth = Math.round(oppRatio * $("#BigBox").width());
                var boxHeight = Math.round(oppRatio * $("#BigBox").height());
 
                //change color of big div
                $("#BigBox").css("background-color", "#91B6C6");
                var newBox = "<div id='SmallBox' style='height:" + boxHeight + "px; width:" + boxWidth + "px; background-color:#103A4C'></div>";
                $("#BigBox").append(newBox);
            }
        }
    });
});
 
function onGetLandMassDataCompleted(list) {
    viewModel.LandMass = ko.observableArray();
    viewModel.LandMass(list);
     
    ko.applyBindings(viewModel);
}
 
function getLandMassData(onComplete) {
    var options = {
        operation: "GetListItems",
        async: false,
        listName: "LandMass",
        CAMLViewFields: "<viewfields> \
                            <fieldref Name='Title'/> \
                            <fieldref Name='LandMass'/>\
                         </ViewFields>",
        CAMLQuery:"<query><orderby><fieldref Name='Title' Ascending='True' /></OrderBy></Query>",
        completefunc: function(xData, status) {
            var list = new Array();
            $(xData.responseXML).SPFilterNode("z:row").each(function() {
                var item = $(this);
                list.push(new LandMassModel(item.attr("ows_Title"),
                                            item.attr("ows_LandMass")));
            });
            onComplete(list);
        }
    };
     
    $().SPServices(options);
}
 
function LandMassModel(country, landMassValue) {
    this.Country = country;
    this.LandMassValue = Math.round(landMassValue);
}
 
function addCommas(nStr) {
    nStr += '';
    var x = nStr.split('.');
    var x1 = x[0];
    var x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}

That's it! How simple that is :)
P.S: I avoid using drawing plugin etc. because for these simple boxes we can just use square div tags ;)

Hope this helps,
Andreas

Comments

Popular posts from this blog

SharePoint 2013 anonymous access add attachments to list item

CRM Plugin - Parent and Child Pipeline