nodeunit and SharePoint: unit tests in javascript
nodeunit is a (relatively) new test framework for javascript, mainly for node, but it can be run in a browser as well. The most popular framework for testing javascript is Qunit, but I’ll lab with it another time. I found nodeunit tests in moment.js - the best date handling framework for javascript and it worked very well. So first of all, why should we test? The best answer is actually: Life is to short for manual testing (it was actually the slogan at the Google London Test Automation Conference 2007. 
$ in cmssitemanager.js conflicts with $ in jQuery
In SharePoint 2010 if CMSSiteManager.js library is loaded besides jQuery, then much of stuff stops working. The reason is that the dollar sign ($) is used in cmssitemanager.js as well which conflicts with jQuery. Mostly it appears on pages where you load jQuery and have an image library with thumbnails. To avoid this, just replace all $ with jQuery in your custom scripts. A more crazy situation is when avoiding $ isn’t enough. It is when you load jQuery to page head automatically on all pages. The Asset picker (AssetPortalBrowser.aspx) invokes $ itself and gets with jQuery in conflict without you write a single line of custom javascript code. You usually get the following error:
javascript toolkit on text file
Referencing javascript libraries from Content Delivery Networks (CDN) like jQuery can have many benefits. The self-hosted javascript files are on the other hand give you more control. But in one situation it is much better with cdns: the development. Like Marc D Anderson pointed:
I didn’t realize it at the time, but this txt file has become a standard part of my toolkit already. I’ve added it to three client environments just since last week. It’s the A #1 fastest way to get something up and running, even if you know you’re going to host the files locally later.
jQuery mobile and SharePoint
In this post I want to explore how to build a mobile app using jQuery mobile. Recently I discovered two great blog posts about this:
- Building SharePoint web apps using Sencha Touch by Luc Stakenborg
- jQuery mobile and SharePoint by Chris Quick
In my post I’ll use their findings and share some of mine thougts. I’ll focus mostly on how to get started with jQuery mobile and SharePoint. So go ahead and create your jQuery mobile app, just drag’n’drop some controls:
Download it and yout get an “app.html” file and “my.css”. For now ignore my.css. app.html is something like that:
Clone javascript objects
In javascript, if we copy objects or their properties, the reference still remains and by changing the new object the old one is changed, too. To clone or do a clean copy of an object I found a very useful solution by Jan Turoň on StackOverflow:
Object.prototype.clone = function() {
if(this.cloneNode) return this.cloneNode(true);
var copy = this instanceof Array ? \[\] : {};
for(var attr in this) {
if(typeof this\[attr\] == "function" || this\[attr\]==null || !this\[attr\].clone)
copy\[attr\] = this\[attr\];
else if(this\[attr\]==this) copy\[attr\] = copy;
else copy\[attr\] = this\[attr\].clone();
}
return copy;
}
Date.prototype.clone = function() {
var copy = new Date();
copy.setTime(this.getTime());
return copy;
}
Number.prototype.clone =
Boolean.prototype.clone =
String.prototype.clone = function() {
return this;
}
clearInterval in Chrome doesn't work on window blur
If you want to reset all interval jobs when a browser tab is inactive, the best way would be to use clearInterval on window blur. But unfortunately Chrome fires window focus and window blur two times. Here is an embryo to a solution:
var M = window.M || {};
M.counter = 0;
M.focused = true;
M.tick = function() {
if (M.focused) {
console.log("tic tac " + ++M.counter);
}
};
M.start = function(e) {
console.log("starting...");
M.focused = true;
};
M.stop = function(e) {
console.log("stopping...");
M.focused = false;
};
$(window).on({
focus: M.start,
blur: M.stop
});
M.ticker = window.setInterval(M.tick, 1000);
shorthand for jQuery(document).ready
jQuery(document).ready is used very often, why not use the shorthand variant of that?
$(function() {
// Code here
});
moment.js - the best javascript tool for working with dates
Just look at moment.js. Everybody who have worked with dates in javascript are going to love it.
comments from wordpress
Justin Cooney — 2012-03-03
Interesting, I hadn’t heard of moment.js. I’m taking a look at the site right now; it looks to have some very handy functionality for date manipulation!
Anatoly Mironov — 2012-03-03
The great thing with moment.js is e.g. that one can create a date object from asp.net date format like /Date(123543534)/
Kalendae - new javascript utility for calendars
An alternative to jQuery UI datepicker is Kalendae. (MIT License). Highly customizable and no dependencies to other javascript libraries. Here is the highlights:
Kalendae is an attempt to do something that nobody has yet been able to do: make a date picker that doesn’t suck. Kalendae provides the following features:
- Fully portable, no dependencies. No jQuery, no Prototype, no MooTools; just add the script and the stylesheet and you’re good to go.
- Fully and easily skinable. The default theme uses only one image file (a mask for the previous and next buttons), everything else is styled using CSS.
- Supports all modern browsers and IE8.
- Support single day, multiple day, or day range selection.
- Configurable number of months to be displayed at once.
- Can be displayed on the page as an inline widget, or attached to one or more input fields as a popup control.
- Can be attached to any page element, not just named elements.
- Configurable blackouts, defined either as an array of dates or via a callback function
- Output selected dates in a variety of formats
- Leverages moment.js for smart and easy date parsing.
Found through daily.js
fallback for html5 placeholders
Placeholders are very handy in html5, we don’t need to fool with input values. But in SharePoint and IE we must provide fallback for placeholders if we want use them in other browsers. Here is an jQuery extension to do that:
(function ($) {
$.fn.extend({
ensurePlaceholders: function () {
var input = document.createElement('input');
var placeholderSupported = ('placeholder' in input);
if (placeholderSupported) {
return;
}
function setHints(elem) {
var $elem = $(elem);
var value = $elem.val();
if (value == "") {
var placeholder = $elem.attr("placeholder");
$elem.val(placeholder);
$elem.addClass("empty-text");
}
}
function removeHints(elem) {
var $elem = $(elem);
$elem.removeClass("empty-text");
var value = $elem.val();
var placeholder = $elem.attr("placeholder");
if (value == placeholder) {
$elem.val("");
}
}
this.find("\[placeholder\]").each(function() {
setHints(this);
});
this.on("focus", "\[placeholder\]", function(e) {
removeHints(this);
});
this.on("blur", "\[placeholder\]", function(e) {
setHints(this);
});
}
});
})(jQuery);
```Then "ensure placeholders" by running this function on a wrapper element which contains fields with the placeholder attribute:
jQuery("#form-wrapper").ensurePlaceholders();