Friday, March 27, 2015

Folding map effect using Oridomi

Half gob smacked I’ll just throw out one more post today. I’ve discovered Oridomi today. In a matter of minutes, I was able to add a cool feature to my page.


First, I added a static Google Map image to my page using the Google Map API for position and markers.

var customShapes = [];
<img src="https://maps.googleapis.com/maps/api/staticmap?center=59.273544,11.096837&zoom=15&size=600x400&markers=color:blue%7C59.273544,11.096837&maptype=hybrid" />
Then I put this image inside a div element that when executed folds the map up like a… yes, map ;)


Check out the code…
var customShapes = [];

var oriDomi = new OriDomi('.myoridommi', {
    vPanels: 5,     // number of panels when folding left or right (vertically oriented)
    hPanels: 3,     // number of panels when folding top or bottom
    speed: 3200,  // folding duration in ms
    ripple: 2,     // backwards ripple effect when animating
    shadingIntesity: .5,    // lessen the shading effect
    perspective: 800,   // smaller values exaggerate 3D distortion
    maxAngle: 40,    // keep the user's folds within a range of -40 to 40 degrees
    shading: 'soft' // change the shading type
});
var unfolded = false;
function effect() {
  //  unfolded ? jQuery(".myoridommi").hide() : jQuery(".myoridommi").slideToggle(500);
    unfolded ? oriDomi.foldUp() : oriDomi.unfold();
    unfolded = !unfolded;
}
effect();
document.getElementById('CanvasLoc').addEventListener('click', effect);
...
...

Fetching blogger posts using ajax.

For my showcase webpage, I wanted to show some of my blog posts as a demo. Now getting hold of rss-content is fairly easy in an rss-reader; but as JavaScript objects – not so much.

I came across different pieces and put them together in a solution that gave me a limited number of blog posts as JavaScript objects using ajax and the blogger API.



In the following snippet, I fetch the data using ajax and handle the response building an array of blog posts. Please see my inline comments...

var customShapes = [];

// First I need a container holding the data in a structured way. As I render the content, I traverse through the array handling each object
var blogPosts = [];
...
// As the query will change in different scenarios I keep part of the query string as an argument in the function call.
loadBlogPostAndRender('alt=json-in-script&start-index=1');
...
...
function loadBlogPostAndRender(posts) {

    $.ajax({
        url: 'http://www.someBloggerBlogUrl/feeds/posts/default?' + posts, // The blog url and the variable specifying the query arguments
        type: 'get',  
        dataType: "jsonp", // It is VERY important that you use jsonp and not json to get around cross site scripting restrictions
        success: function (data) {
            try {
                var posturl = ""; // Initiating variables
                var postcontent = "";
                var postCat = "";
                // Traversing the responce handling each post
                for (var i = 0; i < data.feed.entry.length; i++) {
                    // Getting the post url
                    for (var j = 0; j < data.feed.entry[i].link.length; j++) {
                        if (data.feed.entry[i].link[j].rel == "alternate") {
                            posturl = data.feed.entry[i].link[j].href;
                            break;
                        }
                    }
                    // Fetch tags from the blog post
                    for (var k = 0; k < data.feed.entry[i].category.length; k++) {
                        postCat = data.feed.entry[i].category[k].term + " ";
                    }
                    // Fetching the content
                    if ("content" in data.feed.entry[i]) {
                        postcontent = data.feed.entry[i].content.$t;
                    } else if ("summary" in data.feed.entry[i]) {
                        postcontent = data.feed.entry[i].summary.$t;
                    } else {
                        postcontent = "";
                    }
                    // As I want to show any image from the blog post as well, I look for the first image linked up to the blog post.
                    var imgUrl = "";
                    try {
                        imgUrl = $(data.feed.entry[i].content.$t).find('img:first').attr('src');
                    } catch (error) {
                        imgUrl = "http://foo.com/missingimage.png"; // If there is no image, I keep a placeholder backup
                    }
                    // As I only need part of the blog post, I use regular expressions to filter the content and substring to limit the length.
                    var re = /<\S[^>]*>/g;
                    postcontent = postcontent.replace(re, "");
                    //reduce postcontent to 200 characters
                    if (postcontent.length > 200) {
                        postcontent = postcontent.substring(0, 400);
                    }
                    // Getting the title and publication date.
                    var posttitle = data.feed.entry[i].title.$t;
                    var postdate = data.feed.entry[i].published.$t;
                    // I'm done and add the content as an object on to the array.
                    blogPosts.push({ bUrl: posturl, bTitle: posttitle, bContent: postcontent, bDate: postdate, bCategory: postCat, bImgUrl: imgUrl });
                }
            } catch (e) {

            }
        },
        error: function () {
            //        writeErrorMessage("blogCanvas");
        },
        complete: function () {
            // When the request is complete it is time to render the content. 
            listAll(blogPosts);
            // In order to start the next request with a clean slate, I empty the array.
            blogPosts = [];
        }
    });
}
...
...
...

Execute Canvas rendering based on scroll event.

I have been showing animations using canvas in several blog posts lately and implemented a lot of this in my own homepage. Now, if you are doing animations you need to plan how the animations should execute so that the user does not miss the whole show. :)


You might want to kick off the animation on a click, or even on a long page – start the animation once the user scrolls down to the animations position. There would be little use in an animation if the show were over when the user gets to it, right?

Now, you can hook on to the browsers events using the window object or the document object. The click event I’ve already covered in this post. For the scroll event you need to grab the window object.

The easiest way to do this is to use JQuery and extend the scroll event. In this example I’ve added a delay before kicking of the animation.

I’ve also calculated the position the user should scroll to before firing the event handler.
var target = $("#mainSectionFootprint").offset().top - 400,
    timeout = null;

$(window).scroll(function () {
    if (!timeout) {
        timeout = setTimeout(function () {
            clearTimeout(timeout);
            timeout = null;
            if ($(window).scrollTop() >= target) {
                startFootLoop();
            }
        }, 250);
    }
});

Friday, March 20, 2015

Resizing your canvas drawings properly using repaint

This post will be a short one attending a problem I briefly touched upon in my previous post on animation using canvas. We live in a "mobile first" world and need to pay attention to responsive designing.



Try as you might resizing your canvas using CSS you are in for a disappointing surprise. Especially if you are rendering text, it will look all chunky and broken. My solution to this problem is to calculate a factor value based on the window and canvas width. Using this value, I can multiply it with all xes and ys and lengths and widths and so on and keep the relative positions all these shapes have to each other.
var ic = window.innerWidth / (canvas.width * 1.2) > 1 ? 1 : window.innerWidth / (canvas.width * 1.2);
When adding objects I apply the factor to keep the relative positions.
var customShapes = [];

// Figures - Balls
customShapes.push({ x: ic * (canvas.width / 2 - 58),  minRadius: 0, maxRadius: ic * (3), y: ic * (canvas.height / 4 - 152), borderThickness: ic * (11), borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 2.4 });
customShapes.push({ x: ic * (canvas.width / 2 - 117), minRadius: 0, maxRadius: ic * (3), y: ic * (canvas.height / 4 - 102), borderThickness: ic * (3),  borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 3 });
customShapes.push({ x: ic * (canvas.width / 2 + 43),  minRadius: 0, maxRadius: ic * (3), y: ic * (canvas.height / 4 - 150), borderThickness: ic * (7),  borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 1 });
...
...
...
Now, make sure to use the windows.resize event to kick off the rerendering of your canvas. The result is a world apart from the CSS approach.

Animating objects using HTML5 Canvas

Object animation using JavaScript is fairly simple once you get the hang of it. In the three previous posts I've explained how to render shapes and how to render a series of shapes. To recap some of the steps I've included the part where I create the objects.


Creating classes

I've created a generic shape class called CShape, with a set of basic properties that I find relevant for any of the shapes I'm going to render. This also includes properties relevant to animation. Each property is explained in the comments below.

// Applies to circles, boxes and lines
// X and Y coordinates
// expand (bool) growing (true) or shrinking (false)
// direction - animating going cw or ccw
// speed - animation speed
// borderThickness - border thickness
// borderColor - border color
// color - shape color
// clickZone - clickable zone with pointer cursor
// speed - animation speed
function CShape() {
    this.x = 0;
    this.y = 0;
    this.expand = true;
    this.speed = 0;
    this.borderThickness = 1;
    this.borderColor = "#FFFFFF";
    this.color = "#000000";
    this.delay = false;
    this.runAnimation = false;
}

Further on I've extended the CShape creating another class called CCircle. Here I've added the properties minRaduis and maxRadius as these only apply to circular shapes. The radius values will be used for animating references, growing or shrinking.

CCircle.prototype = new CShape();
CCircle.constructor = CCircle;
// Circle object - prototyped CShape
// Adds min and max radius. 
function CCircle() {
    this.minRadius = 0;
    this.maxRadius = 0;
}

A bit to the side, but indeed relevant to the mission we add a factor for resizing. You might know that resizing a canvas without rerendering the content might give you a poor result, so we'll do a calculation here and multiply all positions and sizes with it. I'll come back to this in a future blog post. Maybe even the next.

var ic = window.innerWidth / (canvas.width * 1.2) > 1 ? 1 : window.innerWidth / (canvas.width * 1.2);

Creating objects

Now I am ready to create some shapes. For this demo I'll create a series of small circles like you can see on my home page. I add them straight away to the array to save some steps, but you can create the objects based on the classes and then add them later if you wish.

var customShapes = [];

// Figures - Balls
customShapes.push({ x: ic * (canvas.width / 2 - 58),  minRadius: 0, maxRadius: ic * (3), y: ic * (canvas.height / 4 - 152), borderThickness: ic * (11), borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 2.4 });
customShapes.push({ x: ic * (canvas.width / 2 - 117), minRadius: 0, maxRadius: ic * (3), y: ic * (canvas.height / 4 - 102), borderThickness: ic * (3),  borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 3 });
customShapes.push({ x: ic * (canvas.width / 2 + 43),  minRadius: 0, maxRadius: ic * (3), y: ic * (canvas.height / 4 - 150), borderThickness: ic * (7),  borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 1 });
customShapes.push({ x: ic * (canvas.width / 2 + 138), minRadius: 0, maxRadius: ic * (3), y: ic * (canvas.height / 4 - 120), borderThickness: ic * (15), borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 1.4 });
customShapes.push({ x: ic * (canvas.width / 2 + 195), minRadius: 0, maxRadius: ic * (3), y: ic * (canvas.height / 4 + 53),  borderThickness: ic * (10), borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 4 });
customShapes.push({ x: ic * (canvas.width / 2 + 99),  minRadius: 0, maxRadius: ic * (2), y: ic * (canvas.height / 4 + 152), borderThickness: ic * (6),  borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 1.4 });
customShapes.push({ x: ic * (canvas.width / 2 - 75),  minRadius: 0, maxRadius: ic * (2), y: ic * (canvas.height / 4 + 232), borderThickness: ic * (26), borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 2.9 });
customShapes.push({ x: ic * (canvas.width / 4 + 60),  minRadius: 0, maxRadius: ic * (2), y: ic * (canvas.height / 4 + 86),  borderThickness: ic * (12), borderColor: ringBlue, color: ringBlue, runAnimation: !0, speed: 5.4 });

Rendering shapes

Now it is time for some logic. We need a function that can render a circle based on these objects. The function below takes an object, an id and the canvas context as an argument. I choose to send in the context because I want to use the same function rendering on several canvas elements in one page. Other than that the function pretty much does what it says.

// Renders a circle based on a Circle object
function drawCircle(tmpShape, id, renderContext) {
    var tmpCircle = new CCircle();
    tmpCircle = tmpShape;
    var centerY = tmpCircle.y;
    var centerX = tmpCircle.x;
 
// These two lines are relevant to the rendering speed. 
// As long as the minRadius is less than the maxRadius it

// will grow according the the value of the speed property

    if (tmpCircle.minRadius <= tmpCircle.maxRadius) {
        tmpCircle.minRadius = tmpCircle.minRadius + tmpCircle.speed;
    }
    var radius = tmpCircle.minRadius;
    renderContext.fillStyle = tmpCircle.color;
    renderContext.lineWidth = tmpCircle.borderThickness + (tmpCircle.minRadius * 0.01);
    renderContext.strokeStyle = tmpCircle.borderColor;
    renderContext.save();
    renderContext.beginPath();
    renderContext.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
    renderContext.fill();
    renderContext.stroke();
    renderContext.restore();
    }

Animating the shapes

Oki, so now we can draw a circle. Now I'll add two functions. One for running the rendering based on the kind of shape, and one that runs through the array.

// Loops through the custom shape array calling renderShapes on every shape
function animationLoop() {
    var i = customShapes.length;
    while (i-- && i >= 0) {
        var customShape = customShapes[i];
  // Calling the rendering function
        renderShapes(customShape, i, context);
        if (customShapes[20].minRadius >= customShapes[20].maxRadius) {
 //checking if the shape should continue animating in the next iteration 
            keepAminationAlive = false;
        }
    }
    if (keepAminationAlive == true) {
  // if the shape should be reredered, the function is called again
        setTimeout(animationLoop, 50);
    }
}

Now, for each object in the previous function we need to know which kind of shape to render. This is simply done by checking if the object contains one of the unique shape properties applied to the shape object. Since we are only rendering circles in this demo, this is not a problem. However, if your animation is based on several shapes like on my site (www.engvoldsen.net) - you have to tend to this.

// Renders one figure based on the type of figure, testing on figure specific properties. 
function renderShapes(tmpShape, id, renderContext) {
    if (!isEmpty(tmpShape)) {
        // if circle
        if (tmpShape.hasOwnProperty("maxRadius")) {
            if (tmpShape.runAnimation == true) {
                drawCircle(tmpShape, id, renderContext);
            }
        }
            // if line
        else if (tmpShape.hasOwnProperty("length")) {
            if (tmpShape.runAnimation == true) {
                drawLine(tmpShape, renderContext);
            }
        }
            // if box
        else if (tmpShape.hasOwnProperty('width')) {
            drawBox(tmpShape, renderContext);
        } else
            return;
    }
}

Kicking of the animationLoop should give you a decent animation experience ;)

Rendering shapes in Canvas using objects

In a previous blog post (Painting using Canvas and JS), I explained how to paint a figure using canvas. I explained how to paint the figure inside a single function by setting coordinates and calling stroke and fill. In the following post, (Create an interactive HTML5 Canvas using event handlers.) I presented the clickable area as an object. In this, post I am going to start up by combining the two like the snippet below.



I create an object called CustFigure. It has X and Y values and a height and width. This is all we need in order to place it in the grid and to get the size of the figure, say a box.
 
 var CustFigure = function (x, y, height, width, label ) {
    this.x = x;
    this.y = y;
    this.height = height;
    this.width = width;
    this.label = label;
    };
 
function DrawShape(Shape){
    var rectWidth = Shape.width;
    var rectHeight = Shape.height;
    var rectX = Shape.x;
    var rectY = Shape.y;

    renderContext.beginPath();
    renderContext.fillRect(rectX, rectY, rectWidth, rectHeight);
}

// This call is sending the object to the function DrawShape(), rendering the shape.
DrawShape(CustFigure);
If you want to render many shapes, you can take the following approach. Create an array as a container for all your figures and push each instance of CustFigure in it.
var custFigures = [];

var custFigure1 = new CustFigure(10, 10, 75+10, 75+10, " Hello Nerd!");
custFigures.push(custFigure1);
var custFigure2 = new CustFigure(20, 20, 75+20, 75+20, " Hello Nerd!");
custFigures.push(custFigure2);
var custFigure3 = new CustFigure(30, 30, 75+30, 75+30, " Hello Nerd!");
custFigures.push(custFigure3);
Now, calling the function renderLoop, we render all the shapes in the array.
// Loops through the custom shape array calling DrawShape on every shape
function renderLoop() {
    var i = custFigures.length;
    while (i-- && i >= 0) {
        var customShape = custFigures[i];
        DrawShape(customShape, i, context);
    }
}

Wednesday, January 7, 2015

Create an interactive HTML5 Canvas using event handlers.

You can use HTML5 Canvas as an alternative approach designing info graphics, branding graphics etc. Using the example in my previous blog post, I will add a clickable area on the canvas and use a JavaScript event handler to execute some logic.

This is the result of the previous example. I want to pop an alert Box when clicking inside the logo.


I need to create an object reflecting the coordinates I want my clickable zone to have. I’m also throwing in an id/name.

    var CustFigure = function (x, y, height, width, name ) {
    this.x = x;
    this.y = y;
    this.height = height;
    this.width = width;
    this.name = name;
    };

In this case I just create a global Array that I can pop the objects on to.  

    var custFigures = [];

At some point (I choose to include it in the function drawing the logo) we create the object with the desired coordinates and push it on to the array.

    var custFigure = new CustFigure(50, 50, 75+50, 75+50, " Hello Nerd!");
    custFigures.push(custFigure);

Now, for the final section; adding the logic to the canvas click event handler.  

   $('#xpCanvasWeb').click(function (e) {
    //Picking up the cursor coordinates
    var clickedX = e.pageX - this.offsetLeft;
    var clickedY = e.pageY - this.offsetTop;
    //You might have more than one clickable zone in your canvas. 
    //We run through the array and compare the coordinates.
    for (var i = 0; i < custFigures.length; i++) {

        if (clickedX > custFigures[i].x
            && clickedX < custFigures[i].width
            && clickedY > custFigures[i].y
            && clickedY < custFigures[i].height) {
            var name = custFigures[i].name;
            //When matching we fire of the alert box.
            alert("You clicked X=" + clickedX + " and Y=" + clickedY + name);
        }
    }
   });

The result should look something like the box below.



Tuesday, January 6, 2015

Painting using Canvas and JS.

Lately I've been playing around with HTML5 and Canvas trying to render icons and graphics without the use of image files. This blog post is simply showing how to render the HTML5 logo using only code.
First up, we create a HTML5 canvas-tag where our logo will live. I’ll add some simple CSS to it for good measure, creating a circular form for our logo. We make sure to call our function rendering the logo as the page is loaded.

<canvas id="xpCanvasWeb" class="testblock" width="175" height="175"></canvas>

<style type="text/css">
.testblock {
    background: none repeat scroll 0 0 #2a2a2e;
    border: 1px solid #2a2a2e;
    border-radius: 115px;
    margin: 10px;
}
</style>


Now, for the rendering-function, please see my inline code. My approach towards this is to paint the logo in «layers», starting with the background and adding on layer by layer until the logo is complete. By using semi-transparent colors, we get the desired 3D-effect.

function xpCanvasWeb() {
    // We grab the canvas and context.
    var c = document.getElementById("xpCanvasWeb");
    var ctx = c.getContext("2d");

   //Adding color and filling a rect as background
    ctx.fillStyle = "#2a2a2e";
    ctx.fillRect(0, 0, 175, 175);

   // We want to be able to move our logo about without too much fuss, so we declare an x and y variable and add it in the rendering code.
   var x = 60;
   var y = 50;
   //We set the line width to 1 px.
   ctx.lineWidth = 1;

   //We begin by declaring the start of a path and setting the fill style.
   ctx.beginPath();
   ctx.fillStyle = "#E34C26";
   //Then we move into position and start drawing
   //Fig left
   ctx.moveTo(x, y);
   ctx.lineTo(x + 5, y + 57);
   ctx.lineTo(x + 28, y + 63);
   ctx.lineTo(x + 51, y + 57);
   ctx.lineTo(x + 56, y + 0);
   ctx.lineTo(x, y);
   ctx.fill();

   //Fig center
   ctx.beginPath();
   ctx.fillStyle = "#F06529";
   ctx.moveTo(x + 28, y + 4);
   ctx.lineTo(x + 28, y + 58);
   ctx.lineTo(x + 47, y + 53);
   ctx.lineTo(x + 51, y + 5);
   ctx.lineTo(x + 28, y + 5);
   ctx.fill();

   //Fig right
   ctx.beginPath();
   ctx.fillStyle = "rgba(255, 255, 255, 0.6)";
   ctx.moveTo(x + 46, y + 12);
   ctx.lineTo(x + 10, y + 12);
   ctx.lineTo(x + 12, y + 33);
   ctx.lineTo(x + 35, y + 33);
   ctx.lineTo(x + 35, y + 42);
   ctx.lineTo(x + 28, y + 45);
   ctx.lineTo(x + 21, y + 43);
   ctx.lineTo(x + 20, y + 37);
   ctx.lineTo(x + 13, y + 37);
   ctx.lineTo(x + 13, y + 48);
   ctx.lineTo(x + 28, y + 52);
   ctx.lineTo(x + 43, y + 48);
   ctx.lineTo(x + 45, y + 26);
   ctx.lineTo(x + 19, y + 26);
   ctx.lineTo(x + 19, y + 20);
   ctx.lineTo(x + 45, y + 20);
   ctx.lineTo(x + 45, + 12);
   ctx.fill();
}


The figure shows how the layers build up the logo for each time we call beginPath, add coordinates and call fill again.

Friday, July 4, 2014

Using parameters in XSLT

If you've read some of my previous posts, you've seen examples of using parameters when calling templates.
I earlier wrote about assigning XML structures to variables. Now we are going to use a variable as parameter for a template call.

Create the variable and send it as a parameter to your template of choice:

  <!-- Given a structure like this one... -->  
  <xsl:variable name="someVariable">  
  <record>  
  <artist sex="female">Madonna</artist>  
  <title>Like a prair</title>  
  </record>  
  </xsl:variable>  
  <xsl:call-template name="targetTemplate">  
  <xsl:with-param name="string" select="$someVariable" />  
  <xsl:with-param name="attributeString" select="$someVariable/@sex"/>  
 </xsl:call-template name="targetTemplate">  
 </xsl:template>   

Grab the variable and do something that makes sense. ;)

 <xsl:template name="targetTemplate">  
  <xsl:param name="string"/>  
  <xsl:param name="attributeString"/>  
  <!-- do something -->  
  <xsl:if test="contains($attributeString, 'female')">  
   <xsl:value-of select="$string">  
  </xsl:if>  
 </xsl:template>  

Note that the variable can change its name, but the name in the "with-param" and "param" tags must match.

Happy coding! 

Thursday, June 26, 2014

Set the logo of all sites in a SharePoint 2013 site collection using PowerShell - Flash post

If you want to quickly set the site logo of a complete SharePoint 2013 site collection, enter the following:

(get-spsite http://YourSiteCollectionURL).AllWebs | foreach {$_.SiteLogoUrl = “/relative/path/to/companylogo.png”; $_.Update()}

Thats all :)

Wednesday, June 11, 2014

Open termbased navigation links in new window in SharePoint 2013


Term based navigation has been greatly improved in SharePoint 2013, but sometimes you want to open navigation URLs in a new window. However, the term store does not offer such a property so we'll solve it using JavaScript instead.

In the masterpage element add this script:

script language="JavaScript"

// Adding an entry to _spBodyOnLoadFunctionNames array so the function runs on pageLoad
_spBodyOnLoadFunctionNames.push("rewriteNavigationLinks");

function rewriteNavigationLinks() {
 // collecting anchors
 var anchorArray = document.getElementsByTagName("a");
 for (var x=0; x0) 
  {
   oldUrl = anchorArray[x].outerHTML;
   // adding target attribute
   newUrl = oldUrl.replace(/#targetnewwindow/,'" target="_blank');
   anchorArray[x].outerHTML = newUrl;
  }
 }
}
/script

Then in the term store append "#targetnewwindow" on the link to activate the specific link.

E.g.
http://intranet.foo/somepagename.aspx?pid=000#openinnewwindow

Friday, April 11, 2014

Configuring MySite search center settings for SharePoint 2013


I stumbled over this one the other day and I (luckily) discovered the solution by accident.

When configuring MySite in SharePoint 2013 you are prompted to give up the URL for your search center. Now, if you’ve set up an Enterprise Search Center as I’ve done redirecting you to the correct result pages will fail when doing a search from MySite. Leaving you with an “The page you're looking for doesn't exist”-error. (Yes, another of MS meaningful errors).
The error you’ll discover is that you’ve most likely entered something like http://theUrlFor/MySearchCenter on the MySite configuration, while it should have been http://theUrlFor/MySearchCenter/pages
Problem:
When searching from MySite you get “The page you're looking for doesn't exist”
Reason:
The search URL is wrong and SharePoint cannot find the pages that display the search results.
Solution:
The solution giving you least headache is to use the SharePoint PowerShell and execute the following lines:
$ssa = Get-SPEnterpriseSearchServiceApplication$
ssa.SearchCenterUrl = "http://theUrlFor/MySearchCenter/pages"$
ssa.Update()

 
Cheers,
Morten

Wednesday, September 25, 2013

SharePoint 2013 - Design Manager - Problems connecting to network drive.

I've been working with SharePoint 2013 lately and I came across a problem trying to upload design files for the design manager.

This problem occurs when developing directly on Windows Server 2008 R2.

 When mapping the provided link to your computer like explained here (MSDN), you get an error "The network name cannot be found."

As many other problems you'll find when developing on a server this is due to a missing feature. The solution to the problem is enabling "Desktop Experience" feature.

Go to the Server Manager and click on "Features" in the left side tree structure. In the main pane click "Add Feature" and check the "Desktop Experience" box.



Follow the instructions and make sure to save your work because the Server will have to reboot on finish.

When logged in you'll find that mapping the location to your computer will work.

Sunday, September 30, 2012

XPath - the keymaster

As you might already know you won't get anywhere without XPath when working with XSLT. As scary as it might sound (at least I thought it sounded scary), it is no more than the pattern you need to learn to find the information you're looking for. Now you might argue that it can be more complicated than that, but we'll keep it simple in this blog post. We'll use the music XML structure from a previous post.

Let’s see some examples:

  1. <!-- This code will give you a copy of the XML root of the current structure. -->
  2. <xsl:template name="giveMeTheRoot">
  3. <xsl:copy-of select="//"/>
  4. </ xsl:template >
  5.  
  6. <!-- This template will give you a COPY of the current node. That means that you will also get the subnodes of the current nodes as well. -->
  7. <xsl:template name="giveMeTheCurrentNode">
  8. <xsl:copy-of select="."/>
  9. </ xsl:template >
  10.  
  11. <!-- This template will give you the VALUE of the current node. This will give you the ONLY the value of the current element, and ignore any subnode value. -->
  12. <xsl:template name="giveMeTheCurrentNodeValue">
  13. <xsl:value-of select="."/>
  14. </ xsl:template >
  15.  
  16. <!-- For the next example we need to do some changes to the original XML. Let's say we wanted to include the date when the album was released and that we would put this information in an attribute of the record node. That would look something like this. -->
  17. < recordCollection >
  18. <record released="01.01.1982">
  19. <artist>Madonna</artist>
  20. <title>Like a prair</title>
  21. </record>
  22. <record released="01.01.2001">
  23. <artist>Gorillaz</artist>
  24. <title>Gorillaz</title>
  25. </record>
  26.     ...
  27.     ...
  28. </ recordCollection >
  29.  
  30. <!-- This template will return the value of the node attribute called -->
  31. <xsl:template name="giveMeTheCurrentNodesAttribute">
  32. <xsl:value-of select="./record/@released"/>
  33. </ xsl:template >
  34.  
  35. <!-- This example will show how to use XPath to compare values -->
  36. <xsl:template name="compareIwithCounter">
  37. <xsl:if test="$i &gt; $counter">
  38. <xsl:call-template name="test3">
  39. <xsl:with-param name="counter" select="$counter+1"/>
  40. <xsl:with-param name="i" select="$i"/>
  41. </xsl:call-template>
  42. </xsl:if>
  43. </ xsl:template >

XSLT - Recursion

There are a couple of things that make XSLT hard to manage and recursion is indeed one of them. There is just no way of running a traditional for loop. In order to solve this we need either a structure to iterate on, or we can create a template that calls itself with a counter and control number.

If you simply need to iterate on an XML structure, you can do a for-each loop like this:

  1. <xsl:for-each select=".//child::title">
  2. <!-- Do you thing-->
  3. </ xsl:for-each >

However, if you know that you need to iterate on a procedure "i" times, then we need to complicate things a bit.

  1. <xsl:template name="test3">
  2. <xsl:param name="counter"/>
  3. <xsl:param name="i"/>
  4.  
  5. <!--We do our thing...-->
  6. <xsl:copy>
  7. <xsl:text>Hello Nerd!</xsl:text>
  8. </xsl:copy>
  9. <xsl:if test="$i &gt; $counter">
  10. <xsl:call-template name="test3">
  11. <xsl:with-param name="counter" select="$counter+1"/>
  12. <xsl:with-param name="i" select="$i"/>
  13. </xsl:call-template>
  14. </xsl:if>
  15. </ xsl:template >

To call the template we need to provide it with the starting parameters:

  1. <xsl:call-template name="test3">
  2. <xsl:with-param name="counter">0</xsl:with-param>
  3. <xsl:with-param name="i">10</xsl:with-param>
  4. </ xsl:call-template >

Make sure that you take into consideration that the if test checks if the $i is still greater than the $counter variable. If you write greater or equal you will get 10 + 1 runs of the template. Also make sure that the call comes after you've done your magic in the loop. Otherwise you just won't get anything. The template executes line by line, so if you include any code after the template call, it will execute once(!) no matter how many iterations you initially ask for.

Sunday, September 23, 2012

Working with XSLT variables

Working with variables can get you into any kind of delight or trouble. It brings in many scenarios making it tricky in ways you don't experience with other programming languages.

First of all you need to remember that xsl variables are STATIC. That means that you cannot change them once they are set. Also you need to make sure that they are in the correct scope. If you create a variable inside a template, it will only be available inside the template. However, you can create GLOBAL variables outside a template as well.

Now on to the code examples. This post is using the XML example from an earlier post on XML and XSLT.

  1. <!-- The following example creates variables in different ways. -->
  2.  
  3. <!-- This variable is a simple string, hardcoded inside the variable node. -->
  4. <xsl:variable name="myString">
  5. <xsl:text>Hello Nerd!</xsl:text>
  6. </ xsl:variable >
  7. <!-- In order to print the variable we do a simple value-of call. -->
  8. <xsl:value-of select="$myString"/>

This will give us the following output:

Hello Nerd!

  1. <!-- The next variable is created by looking up the artist 'Michael Jackson' in the example XML, and assigning the record title as value to the variable. -->
  2. <xsl:variable name="myArtistAlbum" select="//record/title[../artist='Michael Jackson']"/>
  3. <!-- In order to print the variable we do a simple value-of call. -->
  4. <xsl:value-of select="$myArtistAlbum"/>

This will give us the following output:

Bad

  1. <!-- Sometimes we need to load an intire XML structure into a variable. The following exmaple loads a document by using the document() function and the filepath(./music/recordCollection.xml) as an argument. On load we set the xml files root node as the root node in the variable. -->
  2. <xsl:variable name="allArtists" select="document('./music/recordCollection.xml')/recordCollection"/>

When getting the output from this variable, we can do it in two ways.

  1. <!-- The following code gives us a result similar to the previous example. -->
  2. <xsl:value-of select="ext:node-set($myArtist)//record/title[../artist='Michael Jackson']"/>

This will give us the following output:

Bad

  1. <!-- The following example simply outputs the XML as it is inside the variable. -->
  2. <!-- <xsl:copy-of select="ext:node-set($finData)"/> -->

This will give us the following output:

  1. < recordCollection >
  2. <record>
  3. <artist>Madonna</artist>
  4. <title>Like a prair</title>
  5. </record>
  6. <record>
  7. <artist>Gorillaz</artist>
  8. <title>Gorillaz</title>
  9. </record>
  10. <record>
  11. <artist>Madcon</artist>
  12. <title>Beggin</title>
  13. </record>
  14. <record>
  15. <artist>Michael Jackson</artist>
  16. <title>Bad</title>
  17. </record>
  18. <record>
  19. <artist>Queen</artist>
  20. <title>Jazz</title>
  21. </record>
  22. <record>
  23. <artist>Muse</artist>
  24. <title>The Resistance</title>
  25. </record>
  26. <record>
  27. <artist>Duffy</artist>
  28. <title>Rockferry</title>
  29. </record>
  30. </ recordCollection >
  31.  
  32. <!-- Next up we create a new variable containing an XML structure. We want to create a subset of the original XML containing only titles inside a root node. -->
  33.  
  34. <xsl:variable name="titleCollection">
  35. <titleCol>
  36. <xsl:for-each select=".//child::title">
  37. <xsl:copy-of select="."/>
  38. </xsl:for-each>
  39. </titleCol>
  40. </ xsl:variable >
  41.  
  42. <!-- Now when running the copy-of call we get the new XML structure printed out in the result. -->
  43. <xsl:copy-of select="ext:node-set($titleCollection)"/>

OutPut:

  1. < titleCol >
  2. <title>Like a prair</title>
  3. <title>Gorillaz</title>
  4. <title>Beggin</title>
  5. <title>Bad</title>
  6. <title>Jazz</title>
  7. <title>The Resistance</title>
  8. <title>Rockferry</title>
  9. </ titleCol >

Friday, September 7, 2012

Structuring the XML output.

Note: This post will be used as reference for several posts on XSLT.

If you just want to do a simple transformation where you do the same thing over and over again when a template hits, you don't really need to call templates.

Say you have a long list of records (the music kind) and you want to extract the ones by Michael Jackson, you can simply perform an if-statement inside the template.

  1. <!-- Given a structure like this one... -->
  2. < recordCollection >
  3. <record>
  4. <artist>Madonna</artist>
  5. <title>Like a prair</title>
  6. </record>
  7. <record>
  8. <artist>Gorillaz</artist>
  9. <title>Gorillaz</title>
  10. </record>
  11. <record>
  12. <artist>Madcon</artist>
  13. <title>Beggin</title>
  14. </record>
  15. <record>
  16. <artist>Michael Jackson</artist>
  17. <title>Bad</title>
  18. </record>
  19. <record>
  20. <artist>Queen</artist>
  21. <title>Jazz</title>
  22. </record>
  23. <record>
  24. <artist>Muse</artist>
  25. <title>The Resistance</title>
  26. </record>
  27. <record>
  28. <artist>Duffy</artist>
  29. <title>Rockferry</title>
  30. </record>
  31. </ recordCollection >
  32.  
  33. <!-- Then you would want to have a simple template handling all records and filtering out the ones matching the artist you look for and list the artists name and album. -->
  34.  
  35. <xsl:template match="record">
  36. <xsl:if test="./artist='Michael Jackson'">
  37. Artist: <xsl:value-of select="./artist" />
  38. Album: <xsl:value-of select="./title" />
  39. </xsl:if>
  40. </ xsl:template >

Tuesday, August 7, 2012

How to create an XSLT template

This is the second post in my flash post series on XSLT. We'll start off with some simple examples and move up to advanced as we get the most important components in place.

   1:  <-- The most basic thing you should know about is how to create and call a template. 
   2:  A template is a procedure that is executed when a certain criteria is met. 
   3:  That we will come back to.
   4:   -->
   5:   
   6:  <!-- First off is the template. A template is the most basic element in an XSLT sheet.
   7:  This perticular template targets the XML root node, but gives no output.-->
   8:   
   9:    <xsl:template match="/">
  10:    </xsl:template>
  11:   
  12:  <!-- The following template targets any node and attribute, 
  13:  but gives no output.-->
  14:   
  15:      <xsl:template match="@* | node()">
  16:      </xsl:template>
  17:    
  18:  <!--Now, for the first two, they are executed no matter how the source is structured. 
  19:  The next two act a little differently. While the one matching "title" is executed 
  20:  whenever the engine finds a title node, the template named "mySpecialTemplate" 
  21:  is executed ONLY when called. For this example I'm basically calling it from 
  22:  inside the first template to show how it is done. A template can be called from 
  23:  inside any template at any time.-->
  24:    
  25:  <!-- This template targets all nodes of the type title -->
  26:   
  27:      <xsl:template match="title">
  28:          <xsl:call-template name="mySpecialTemplate" />
  29:      </xsl:template>
  30:    
  31:  <!-- This template has a name and is executed on command -->
  32:   
  33:      <xsl:template name="mySpecialTemplate">
  34:      </xsl:template>


Sunday, August 5, 2012

XSLT transformations with .Net

How the transformation works with .Net.

Using .Net and C# you can do XSL transformations using XslCompiledTransform(). As input to the XSLT engine we use an XSLT sheet, settings (optional), parameters (optional), an XML source and the output path.

Note: Please note that if you need to use XSLT 2.0 or XPath 2.0 you should use a third party XSLT engine.

   1:  // C# code - using .Net 4.0
   2:   
   3:  // We want to enable document() functions and script() inside the XSLT code. 
          In order to allow this in using .Net we include this in the settings. 
          This gives us a bit more power as far as .Net XSLT support goes.
   4:  var settings = new XsltSettings(true, true);
   5:   
   6:  // This is the XSLT engine object
   7:  var xslTransform = new XslCompiledTransform();
   8:   
   9:  // We load the XSLT and settings to the engine.
  10:  xslTransform.Load(XSLTSheetPath, settings, new XmlUrlResolver());
  11:   
  12:  // As there is no way of generating e.g. date objects inside XSLT 1.0 
          (the only one supported by .Net) we do this outside the code and include 
          it as a parameter.
  13:  // Argument list (Params)
  14:  var xslArg = new XsltArgumentList();
  15:  // Grabbing current DateTime
  16:  DateTime time = DateTime.Now;
  17:  // Create a parameter which represents the current date and time.
  18:  xslArg.AddParam("date", "", time.ToString("s"));

Now, as we create the result file we want the transformed output to populate, we apply the source XML, 
arguments (params) and XML writer to the XSLT engines Transform() function. This is when/where the 
transforation is performed and the end of any C#/.Net involvement for now.


   1:  // Transform the file.
   2:  using (XmlWriter w = XmlWriter.Create(XMLResultPath))
   3:  {
   4:      xslTransform.Transform(XMLSourcePath, xslArg, w);
   5:  }
   6:   
   7:  // The entire transforming class could look like this:
   8:  using System;
   9:  using System.Diagnostics;
  10:  using System.Globalization;
  11:  using System.Xml;
  12:  using System.Xml.Xsl;
  13:   
  14:  namespace XSLTGenerator
  15:  {
  16:      class XMLTransformer
  17:      {
  18:          public void TransformXmlUsingXSLT(string XMLSourcePath, 
                   string XSLTSheetPath, string XSDSchemaPath, string XMLResultPath)
  19:          {
  20:              try
  21:              {
  22:                  // Creating settings to enable document() and script()
  23:                  var settings = new XsltSettings(true, true);
  24:   
  25:                  var xslTransform = new XslCompiledTransform();
  26:   
  27:                  // Load XSLT stylesheet
  28:                  xslTransform.Load(XSLTSheetPath, settings, new XmlUrlResolver());
  29:   
  30:                  // Create the XsltArgumentList.
  31:                  var xslArg = new XsltArgumentList();
  32:                  
  33:                  DateTime time = DateTime.Now;
  34:                  
  35:                  // Create a parameter which represents the current date and time.
  36:                  xslArg.AddParam("date", "", time.ToString("s"));
  37:                  // Create a parameter for GUID
  38:                  xslArg.AddParam("id", "", new Guid().ToString());
  39:   
  40:                  // Transform the file.
  41:                  using (XmlWriter w = XmlWriter.Create(XMLResultPath))
  42:                  {
  43:                      xslTransform.Transform(XMLSourcePath, xslArg, w);
  44:                  }
  45:              }
  46:              catch (Exception e)
  47:              {
  48:                  Debug.WriteLine(e.Message);
  49:              }
  50:          }
  51:      }
  52:  }

The next entry will create some basic building blocks