listdata.svc vs CSOM for retrieving and manipulation of list items
What is better and where and when… I’ll try to find out.. This post will be updated soon. Take a look at this so far: http://sharepoint.stackexchange.com/questions/23209/sharepoint-2010-javascript-client-object-model-cross-site-collections
String.format for javascript
sprintf is actually the best javascript implementation of sprintf (string.format). But wait, shouldn’t it be some more .NET-like stuff in SharePoint environment? Indeed there is! (Well, not only in SP, but ASP.NET) String.format(“Hello {0}”, “world”) does exactly the same thing as on server side. Wow, it opens for many opportunities, e.g. in jQuery tmpl:
String.format validates arguments, and if all is OK, it invokes another function String._toFormattedString:
function String$_toFormattedString(useLocale, args) {
var result = '';
var format = args\[0\];
for (var i=0;;) {
var open = format.indexOf('{', i);
var close = format.indexOf('}', i);
if ((open < 0) && (close < 0)) {
result += format.slice(i);
break;
}
if ((close > 0) && ((close < open) || (open < 0))) {
if (format.charAt(close + 1) !== '}') {
throw Error.argument('format', Sys.Res.stringFormatBraceMismatch);
}
result += format.slice(i, close + 1);
i = close + 2;
continue;
}
result += format.slice(i, open);
i = open + 1;
if (format.charAt(i) === '{') {
result += '{';
i++;
continue;
}
if (close < 0) throw Error.argument('format', Sys.Res.stringFormatBraceMismatch);
var brace = format.substring(i, close);
var colonIndex = brace.indexOf(':');
var argNumber = parseInt((colonIndex < 0)? brace : brace.substring(0, colonIndex), 10) + 1;
if (isNaN(argNumber)) throw Error.argument('format', Sys.Res.stringFormatInvalid);
var argFormat = (colonIndex < 0)? '' : brace.substring(colonIndex + 1);
var arg = args\[argNumber\];
if (typeof(arg) === "undefined" || arg === null) {
arg = '';
}
if (arg.toFormattedString) {
result += arg.toFormattedString(argFormat);
}
else if (useLocale && arg.localeFormat) {
result += arg.localeFormat(argFormat);
}
else if (arg.format) {
result += arg.format(argFormat);
}
else
result += arg.toString();
i = close + 1;
}
return result;
}By the way, take a look at summary part of String.format:
Batch remove
To add items to a list in bulk, or remove them in bulk. Well to do that you can use SPLinq, Server Object Model and … web.ProcessBatchData, which is the most effective. I did an experiment today. I created 1000 tasks in my task list three times and removed all items in three different ways and took time. First I put 1000 items with ajax and listdata.svc:
function pad(n) {
if (n >= 10000) return n;
if (n >= 1000) return '0' + n;
if (n >= 100) return '00' + n;
if (n >= 10) return '000' + n;
return '0000' + n;
}
var s;
var counter = 0;
var title = "task "
function foo() {
counter++;
if (counter > 10000) {
window.clearInterval(s);
}
else {
var value = {};
value.title = title + pad(counter);
createNewTask(value);
}
}
s = setInterval(foo, 200);Then I ran three different scenarios. Here is the resut for VMWare machine Windows Server 2008 R2, 4GB RAM, SharePoint 2010 SP1:
use two different versions of jQuery on the same page
jQuery is very popular. The chance that you’ll get two or more jQuery files loaded on the same page is very high. As long as it doesn’t conflict, it is fine. But what if there are differences, and another version of jQuery destroys your functionality. To solve it we can ensure that we invoke “our”, the right version of jQuery. To do so, create a pointer to your jQuery:
var myJq = jQuery.noConfict();So if you can, avoid invoking $ or jQuery directly. Here is the original example from jQuery forum:
this.data in jQuery tmpl
In jQuery tmpl we can render properties with {{= SomeProperty }}. Here is an example:
<script type="text/javascript">
Writer = function (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
Writer.prototype = {
getFullName: function () {
return this.firstName + " " + this.lastName;
}
};
$(document).ready(function () {
var writers = \[\];
writers.push(new Writer("Gennady", "Ajgi"));
writers.push(new Writer("Mišši", "Şeşpĕl"));
writers.push(new Writer("Ille", "Tuktaš"));
writers.push(new Writer("Kĕştenttin", "Ivanov"));
$("#tmpl").tmpl(writers).appendTo("#writers");
});
</script>
<script id="tmpl" type="text/html">
<li>
{{= firstName }} {{= lastName }}
</li>
</script>
<div id="writers"></div>It will render like:
- Gennady Ajgi
- Mišši Şeşpĕl
- Ille Tuktaš
- Kĕştenttin Ivanov
But what if we want to access the object itself, not one of the properties. Say, you want to pass the object from the array into a js function as a parameter to decide how it will be rendered, or if you want show a “calculated” property. The key word is…: this.data. this.data has the current object. After it has been rendered, we can access this object with $(this).tmplItem().data.
format javascript date in ISO 8601
There is a solution in StackOverflow:
/* use a function for the exact format desired... */
function ISODateString(d){
function pad(n){return n<10 ? '0'+n : n}
return d.getUTCFullYear()+'-'
+ pad(d.getUTCMonth()+1)+'-'
+ pad(d.getUTCDate())+'T'
+ pad(d.getUTCHours())+':'
+ pad(d.getUTCMinutes())+':'
+ pad(d.getUTCSeconds())+'Z'}
var d = new Date();
print(ISODateString(d)); // prints something like 2009-09-28T19:03:12Z
But there is already a function for this: toISOString, it came with ecmascript 5. Unfortunately, not all browsers support this, to solve this problem, we can provide our own prototype function for Date if it doesn’t exist:
javascript Module pattern
Want organize your js code in a kind of namespaces, or modules, then use the module pattern. I’ll take the dummy example for getting the current anchor. Let’s look how it would be if the prototype based approach is used:
var Contoso.Utils = function() {};
Contoso.Utils.prototype = {
getCurrentAnchor: function() {
var url = window.location;
var anchor=url.hash; //anchor with the # character
var anchor2=url.hash.substring(1); //anchor without the # character
return anchor2;
}
};
var util = new Contoso.Utils();
var anchor = util.getCurrentAnchor();
```The [prototype pattern](http://weblogs.asp.net/dwahlin/archive/2011/08/01/techniques-strategies-and-patterns-for-structuring-javascript-code-the-prototype-pattern.aspx) reminds the classic object oriented programming. Now, how would it look in the module pattern:
var Contoso = Contoso || {}; Contoso.Utils = function() { //private var invokeCounter = 0; var logInvokeCounter = function() { invokeCounter++; console.log(“invoked: " + invokeCounter + " times”); } //public return { getCurrentAnchor: function() { var url = window.location; var anchor=url.hash; //anchor with the # character var anchor2=url.hash.substring(1); //anchor without the # character logInvokeCounter(); return anchor2; } } }(); var anchor = Contoso.Utils.getCurrentAnchor();
Get the current anchor in javascript
To get the current anchor, we can use hash property::
var url = window.location;
var anchor=url.hash; //anchor with the # character
var anchor2=url.hash.substring(1); //anchor without the # character
Pass arguments from/to Modal Dialog
To pass arguments from a ModalDialog is easy. Provide some buttons and invoke close function:
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, someValue);The first argument is result, it is a enumeration with three alternatives: cancel, invalid and OK. The value you pass back to the main window can be a simple string, or a complex javascript object. In this example I’ll create a html element which is hidden (id=“modal-form” class=“s4-die”):
<div id="modal-form" class="s4-die">
<input type="text" class="todo-text"/><br/>
<input type="button" value="save"
onclick="SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, {title: 'Johannes', property: $(this).siblings('.todo-text')});"/>
</div>Then we get the hidden html element and pass it as options to Modal Dialog, provide a callback (cb).
Get current user and handle a success callback
In my previous post I needed the accound id of the current user for posting new list items. To retrieve the id, we can push this to the client from the code behind, or get the current user using Client Object Model. To provide a more generic way we can write a js function which get the current user. But we must even provide some callback functionality, otherwise we don’t know if the operation was successful or not. Let’s be inspired by success and error properties in $.ajax: