Wednesday, November 27, 2013

Adding media="print" in CSS References in SharePoint 2013 Master Pages

In SharePoint 2013 with Design Manager, we can convert an .html file into a SharePoint 2013 master page. After the conversion, the HTML file and the master page are associated, so that when we edit and save the HTML file, the changes are synced to the associated master page.

Advantage of this approach is that we can focus on designing our site in HTML, CSS, and JavaScript, without having to know much about ASP.NET or the SharePoint specific markup. By using Design Manager to convert an HTML file into a SharePoint master page, it will add required elements, such as controls and content placeholders that are specific to SharePoint, which must be present on the page for SharePoint to correctly render that master page.

Even though it sounds easy, there will be some issues coming in the process. One of such issues I got is adding media="print" property to the CSS references.

In the HTML version of the master page we usually add CSS references as:

<link rel="stylesheet" href="styles/Pages.css" type="text/css" />
<link rel="stylesheet" href="styles/PageLayouts.css" type="text/css" />
<link rel="stylesheet" href="styles/Theme_1.css" type="text/css" id="CssRegistrationTheme" />
<link rel="stylesheet" href="styles/Print.css" type="text/css" media="print" />

In here I have added an id in the third link and media="print" property in the fourth link.

But in the conversion, CSS references will be generated as below in the .master version of the master page.

<SharePoint:CssRegistration name="&lt;% $SPUrl:~sitecollection/_catalogs/masterpage/PRASAD/styles/Pages.css %&gt;" runat="server" after="SharepointCssFile"/>
<SharePoint:CssRegistration name="&lt;% $SPUrl:~sitecollection/_catalogs/masterpage/PRASAD/styles/PageLayouts.css %&gt;" runat="server" after="SharepointCssFile"/>
<SharePoint:CssRegistration name="&lt;% $SPUrl:~sitecollection/_catalogs/masterpage/PRASAD/styles/Theme_1.css %&gt;" runat="server" after="SharepointCssFile"/>
<SharePoint:CssRegistration name="&lt;% $SPUrl:~sitecollection/_catalogs/masterpage/PRASAD/styles/Print.css %&gt;" runat="server" after="SharepointCssFile"/>

We can see that <link> tag is now converted to CssRegistration control. Also, all 4 links are generated in the same way and ID or the media property I added are not there anymore.

How to fix:
We can add the ms-design-css-conversion="no" property in CSS link references in which we don’t need Design Manager to do alterations.

So in my case, CSS references in .html file need to be:

<link rel="stylesheet" href="styles/Pages.css" type="text/css" />
<link rel="stylesheet" href="styles/PageLayouts.css" type="text/css" />
<link rel="stylesheet" href="styles/Theme_1.css" type="text/css" id="CssRegistrationTheme" ms-design-css-conversion="no" />
<link rel="stylesheet" href="styles/Print.css" type="text/css" media="print" ms-design-css-conversion="no" />

Then the generated CSS references in the .master page will be:

<SharePoint:CssRegistration name="&lt;% $SPUrl:~sitecollection/_catalogs/masterpage/PRASAD/styles/Pages.css %&gt;" runat="server" after="SharepointCssFile" />
<SharePoint:CssRegistration name="&lt;% $SPUrl:~sitecollection/_catalogs/masterpage/PRASAD/styles/PageLayouts.css %&gt;" runat="server" after="SharepointCssFile" />
<link rel="stylesheet" href="/_catalogs/masterpage/PRASAD/styles/Theme_1.css" type="text/css" id="CssRegistrationTheme" />
<link rel="stylesheet" href="/_catalogs/masterpage/PRASAD/styles/Print.css" type="text/css" media="print" />

Now the 3rd and 4th references are remain as <link> tags and only the href property value has been changed. The ID and media properties are there as well.

Tuesday, November 26, 2013

JavaScript - Few Things to Know About - Part 2

This is the second article on JavaScript, which talks about examples of the usage of few JavaScript methods.

In JavaScript, functions are objects. A new function object can be created with the function constructor. Invoking the function constructor as a function without using the new operator has the same effect as invoking it as a constructor.

Methods are the actions that can be performed on objects.

Example 1:
The .call method

Calls a function with a given this value and arguments provided individually. .call is used when we want to control the scope that will be used in the function called.

<script type="text/javascript">
    var greet = function (name) {
        alert(this.toUpperCase() + ' ' + name);
    }
    greet('Prasad');
</script>

Calling greet function with the above syntax, using the name ‘Prasad’ as a parameter won’t run correctly. In fact Webpage error details will say "Message: Object doesn't support this property or method".

Correct syntax to call greet function is:

<script type="text/javascript">
    var greet = function (name) {
        alert(this.toUpperCase() + ' ' + name);
    }
    greet.call('Prasad');
    greet.call('Hello', 'Prasad');
</script>

Output = PRASAD undefined, HELLO Prasad

Calling greet function with .call and with one parameter will not output what we expect. It actually expect two parameters and first of them is called context object which we access using this keyword.

Unlike other languages, in JavaScript this does not refer to the current object. It refers to the execution context and can be set by the caller.

<script type="text/javascript">
  var greet = function (name1, name2) {
    alert(this.toUpperCase() + ' ' + name1 + ' and ' + name2);
  }
  greet.call('Hello', 'Prasad', 'Wick');
</script>

Above function expects 3 parameters and first of them is the context object.


Example 2:
The .apply method

The only difference between the .call and .apply is that .call expects parameters separated by commas (argument list), while .apply expects parameters in an array (single array of arguments).

<script type="text/javascript">
  var greet = function (name1, name2) {
    alert(this.toUpperCase() + ' ' + name1 + ' and ' + name2);
  }

  var names = ['Prasad', 'Wick'];
  greet.call('Hello', names[0], names[1]);
</script>

In this example, instead of passing individual elements in the array as above, we can use .apply to pass the whole array at once as the parameter.

<script type="text/javascript">
  var greet = function (name1, name2) {
    alert(this.toUpperCase() + ' ' + name1 + ' and ' + name2);
  }

  var names = ['Prasad', 'Wick'];
  greet.apply('Hello', names);
</script>

Output (in both cases) = HELLO Prasad and Wick

Example 3:
The .forEach method

.forEach executes the provided function once for each element of the array.

<script type="text/javascript">
    var foo = function () {
        var numbers = [1, 2, 3, 4, 5];
        for (var i = 0; i < numbers.length; i++) {
            document.write (numbers[i] + ', ');
        }
    }
    foo();
</script>

Instead of using a for loop to iterate numbers, we can use .forEach and can pass function as arguments.

<script type="text/javascript">
    var foo = function () {
        var numbers = [1, 2, 3, 4, 5];
        numbers.forEach(function (value) {
            document.write(value + ', ');
        });
    }
    foo();
</script>

Output (in both cases) =1,2,3,4,5,

Example 4:
The .filter method

Creates a new array with all elements that pass the condition implemented by the provided function

<script type="text/javascript">
    var foo = function () {
        var numbers = [1, 2, 3, 4, 5];
        numbers.forEach(function (value) {
            if (value > 3) {
                document.write(value + ', ');
            }
        });
    }
    foo();
</script>

Instead of using a if condition to filter out numbers, we can use .filter for the purpose.

<script type="text/javascript">
    var foo = function () {
        var numbers = [1, 2, 3, 4, 5];
        numbers
        .filter(function (value) {
            return value > 3
        })
        .forEach(function (value) {
            document.write(value + ', ');
        });
    }
    foo();
</script>

Output (in both cases) = 4,5,

Example 5:
The .reduce method

Apply a function once for each element present in the array as to reduce it to a single value. The value returned by .reduce will be the last callback invocation.

<script type="text/javascript">
    var foo = function () {
        var numbers = [1, 2, 3, 4, 5];
        var total = 0;
        numbers.forEach(function (value) {
            total += value;
        });
        document.write(total);
    }
    foo();
</script>

We can use .reduce to perform the looping and totaling both.

<script type="text/javascript">
    var foo = function () {
        var numbers = [1, 2, 3, 4, 5];
        document.write(
            numbers.reduce(function (a, b) { return a + b; })
        );
    }
    foo();
</script>

Another example of using .filter and .reduce to total-up numbers in an array, in which the numbers should be greater than 5:

<script type="text/javascript">
  var foo = function () {
    var numbers = [10, 2, 12, 14, 3];
    var greaterThan5 = function (num) { return num > 5; }
    var addTwo = function (num1, num2) { return num1 + num2; }
    var result = numbers
                 .filter(greaterThan5)
                 .reduce(addTwo);
    document.write(result);
  }
  foo();
</script>


Note that some of the above methods are not supported in all the browsers. You can find the compatibility table here:

List of the JavaScript objects, along with their methods and properties in MSN and MSDN:

List of the JavaScript methods in MSN and MSDN:

Here you can find two others posts on JavaScript:

Thanks Venkat Subramaniam for the great session!