sttf-url-generator — A Chrome/Edge Extension

In the past few days, I created a small Chrome/Edge extension, sttf-url-generator, and published it to both Chrome web store and Edge Add-ons. What this extension does is merely the user sharing use case that is described in the text fragment spec.

With text fragments, browsers may implement an option to ‘Copy URL to here’ when the user opens the context menu on a text selection. The browser can then generate a URL with the text selection appropriately specified, and the recipient of the URL will have the specified text conveniently indicated.

The idea of creating this extension was originated from an internal discussion with my colleagues. As customer engineers, we need to share document links with customers quite often. Quoting the text from the document directly in the email could make the email awfully long, while just sending a link may not help customers quickly locate the information in a long document. We need a better way to share the information so that the customer can get it quickly and accurately.

Text fragment is a perfect solution for this case. It is a new feature supported by browsers natively, and it is available in the latest version of Chrome and Edge. We just need a way to easily generate a url with the text fragment. Browsers might provide such a feature in the future, but before that I hope this extension can help to address the needs.

The implementation of the extension is quite simple and easy, just several lines of javascript. I don’t use any framework or libraries, and purely rely on the DOM when I need to deal with HTML elements. Node and webpack are used simply because I’d like to use eslint to sanitize the code and babel to minimize the js files.

The more interesting part is about packaging and submitting it to Chrome and Edge. To meet the requirements of these stores, I have to consider the permissions required by the extension carefully, create the images and assets, setup a home page with GitHub Pages, and even write a privacy policy by myself. These tasks took more time than the coding itself, but it’s a good experience of bringing an idea to production. I learned a lot from it.

The extension currently consists of 3 functions: copy the generated url, open the generated url in a new tab, and copy the text fragment and the generated url in the markdown format. I think these 3 features are more than enough for a single purpose extension.

Hope you enjoy it.

Exporting SharePoint search result with a custom display template

In my recent project, I got a requirement to export the search result of SharePoint 2013 to a CSV file. Initially, I think it was simple. I could probably extend the search result web part, generate the CSV on the server side and send it to the client. But when I looked at it in detail, I doubted if a search extension web part was a good idea. It could be way too heavy for such a simple requirement. It didn’t fit into our project very well too, because we are trying to leverage the new app model as much as possible, and to limit the server side customization as minimum as possible.

So I decided to explore another way, to use the display template to get the search result and to generate the CSV with JavaScript. Here are then two questions to answer.

  1. Is it possible to get all search result in display template easily?
  2. How to generate a file with JavaScript on the fly and prompt the user to download it?

Fortunately, I managed to figure out the answers of the above two questions. And I will show you how I did it in this post.

First of all, I created a control display template based on the OOTB Default Result template. I wrapped all my JavaScript code in a custom js file, exportresult.js, and uploaded it to the Style Library. I then linked the js in the display template with the following code:

<body>
  <script>
    $includeScript(this.url, "~sitecollection/Style%20Library/export/exportresult.js");
  </script>
...
</body>

I hooked my JavaScript function onto ctx.OnPostRender() so that it could be called after the page is rendered. I also added a button on top of the search result for user to trigger the exporting:

<div style="display: table-cell">
   <a id="idExportSearchResults" href="#">Export Result</a>
</div>

There is almost no useful document regarding to the JavaScript object used in the display template. So I have to try and debug the JavaScript code to figure out where the search result is stored. In the ctx.ListData object, there is a ResultTables array which stores several result tables. Based on my testing, the first item of this array is the search result shown in the search result web part. The 2nd item could be the result for refinement. So I used the following js code to export the result with the required metadata.

var propArray = ["Author", "Created", "ExternalMediaURL", "LastModifiedTime", "Path"];
var exportedResult = new Array();
// Get only the required the managed properties.
ctx.ListData.ResultTables[0].ResultRows.forEach(function (row) {
   var obj = new Object;
   for (var i = 0; i < propArray.length; i++) {
     obj[propArray[i]] = row[propArray[i]] ? row[propArray[i]] : "";
   }
   exportedResult.push(obj)
});

Finally, I need a way to export the data to a file with JavaScript. I actually found a very helpful post here. All credit of the way I used following goes to this post. The following code shows the idea.

var showSave;
// Only works with IE10 or later.
if (window.Blob && navigator.msSaveBlob) {
  showSave = function (data, name, mimeType) {
    resultBlob = new Blob([data], { type: mimeType });
    navigator.msSaveBlob(resultBlob, name);
  }
}

With all the above, I can fulfill the requirement now. The code only works for IE10 and later. It could be extended to support other browsers. If you are interested in extending the code, feel free to fork it on Github.