Sort the LinkedIn People You May Know page by Shared Connections

UPDATE: Now available as a Chrome Extension via the Chrome Web Store:
Get the Sort ‘People You May Know’ Chrome Extension


If you’ve ever scrolled through the LinkedIn ‘People You May Know’ page, you may have noticed that the suggested connections are not sorted by the number of Shared Connections you have, despite frequent requests to do so.

As a quick tip, I knocked together a tiny snippet of JS (and some jQuery, which LinkedIn is already loading natively on the page) that will resort the cards in descending order according to the number of shared connections. To run it, simply open your browser console, copy/paste the script and hit ‘Enter’.

var PYMK = [];
$('.pymk-card').each(function() {
 var Markup = $(this)[0].outerHTML;
 var InCommon = parseInt($(this).find('.bt-incommon > .glyph-text').text()) || 0;
 var Person = {InCommon:InCommon, Markup:Markup};
 PYMK.push(Person);
});
PYMK.sort(function(a, b){
 return b.InCommon - a.InCommon;
});
$('.people-cards-list').empty();
var NewPeopleCardsList = '';
$.each(PYMK,function(index,item){
 NewPeopleCardsList += item.Markup;
});
$('.people-cards-list').html(NewPeopleCardsList);

Quick Tip: CorasWorks Variables in your Path References

Now nearly two years old, you have been using CAPS, the CorasWorks API for building solutions in SharePoint, for a while; and hopefully you’re hammering out some pretty slick custom displays. However you keep running into one place you can’t leverage your CorasWorks variables, be it Global Variables or our built-in ones. Namely, how do you centralize your resource files (i.e. JS, CSS, images, etc) and yet still be able to leverage a Global Variable to reference those files?

CAPS has the answer for you: the “GetFileContents” method!

You may say “Wait, that is not right; is it…?” but it is. Normally, you might use a CorasWorks CAPS HTML Viewer to call an HTML file that is the base of your display; and to keep things clean, you reference all your dependent JS, CSS & Image files inside that HTML file. However that means that you have to reference them either via fully-qualified domain names (which then are not portable) or via relative paths, which is not always conducive to centralizing those resources. Well here is the technique…

In your CorasWorks CAPS HTML Viewer, instead of pointing directly to the HTML file (a scenario discussed in a previous blog post), make a call like this:
%SiteURL%/_layouts/CorasWorksApps/CorasWorksApplicationService.ashx?RequestType=GetFileContents&FileUrl=[Your Global Variable]/Folder/YourFile.htm

Then in your HTML file, you can now freely use references like:

<link href="[Your GV]/Folder/YourFile.css" rel="stylesheet"/>
<script src="[Your GV]/Folder/YourFile.js"></script>
<img src="[Your GV]/Folder/YourFile.png" title="Your Image">

This also open up the use of any of the built-in CorasWorks variables or your own Global Variables for anything else in that HTML page (think maybe current Username or Site Title in an <h1> tag). The reason this works is because the contents of the file – in this case, an HTML file – that is being queried via the GetFileContents method is automatically being passed through the CorasWorks variable replacement engine, thus ensuring proper translation/insertion of variable values anywhere within that HTML. And because that HTML includes those resource file URLs, their location is automatically set using those variables.

CorasWorks Global Variables permissions explained

Working within a highly secure environment recently, I had a need to detail out the effective permissions necessary to leverage the CorasWorks Global Variables (GVs) – specifically, the client wanted to understand the absolute minimum permissions needed to leverage the GVs and so I thought it worthwhile to share here.

First, know that when CorasWorks Central Configuration is first enabled on a web application, a custom list entitled “CWActionsGlobalSettings” is created within the selected Central Config site. This list will effectively store the variables in an XML blob, inside a single List Item, that is managed by the GUI that is the Global Variable Manager.

Next – and this is key – the user who creates the first GV must have at least Owner rights on the “CWActionsGlobalSettings” List. This is because upon creation of the first GV, a multi-line text column entitled “CWActionsGlobalSettings” (yes, same name as the List itself) is created within the List and the XML blob is first created, with the first GV present.

Now going forward, only Contribute rights are needed for those that you want to be able to manage GVs, as Contribute provides them insert & edit rights to that special List Item. However, because Contribute rights does not allow a user to add columns to a list, a user with those rights will not be able to create that first GV.

And finally, as is hopefully fairly obvious, any users who you want to be able to read GV values (i.e. if a GV is used in a solution they’re using), end users must have Read rights to the ”CWActionsGlobalSettings” List. The inverse is also true; if a user does not have Read rights to that list, they will not be able to see the GVs, what their value is or use any part of a solution that leverages a GV.

How to “pin” a jQuery UI Dialog in place

Recently, I wanted to “pin” a jQ UI Dialog in place for an application I was designing – the idea being that the user could open the Dialog (non-modal), drag it to the location on the screen they wanted, then scroll up & down the page and interact with content while having the Dialog pinned in its position, say just inside the top-right corner of the viewport.

Surprisingly, I found very little info on doing so (sorry, no documented jQ UI method) but I didn’t let that stop me. Conceptually, I knew I needed first to add a “pin” button to the Dialog itself – I thought the top-left corner of the title bar would be best – then I needed to combine some jQ that would handle my click events for pinning & unpinning. And before long, I had it…

Click to pin (state is currently unpinned):
UnpinnedDialog

Click to Unpin (state is currently pinned):
PinnedDialog

Here’s what I did to achieve this result…

  1. Initialize your jQ UI Dialog; in this example, mine has an ID of ‘MyJqUiDialog’. As part of creating the Dialog, I’m prepending a button to the Title bar that has stock jQ UI styling plus a custom class called ‘PinDialog’.
    $('#MyJqUiDialog').dialog({
        autoOpen: false,
        modal: false,
        create: function () {
            $('#MyJqUiDialog').parent().children('.ui-dialog-titlebar').prepend('<button class="ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only PinDialog" role="button" aria-disabled="false" title="Pin down"><span class="ui-button-icon-primary ui-icon ui-icon-pin-w"></span></button>');
        }
    });
  2. Add a click handler binding to the ‘PinDialog’ class; upon click, this will toggle the Pin class to ‘DialogPinned’ (which also re-styles the icon as seen in the screenshots above), calculate the current position of an unpinned Dialog, change its CSS position to “fixed” and set its CSS top & left to the current position. In other words, it calculates where in the viewport the Dialog currently is & fixes it there.
    $('.PinDialog').click(function () {
        var CurrentDialogPosition = $(this).closest('.ui-dialog').offset();
        var DialogLeft = CurrentDialogPosition.left - $(window).scrollLeft();
        var DialogTop = CurrentDialogPosition.top - $(window).scrollTop();
        $(this).toggleClass('PinDialog DialogPinned').toggleClass('ui-state-highlight ui-state-default').children().toggleClass('ui-icon-pin-w ui-icon-pin-s').closest('.ui-dialog').css({ 'position': 'fixed', 'top': DialogTop, 'left': DialogLeft });

    });

  3. Add a click handler binding to the ‘DialogPinned’ class; upon click, revert to the previous icon and set the CSS position to absolute while also setting its top & left to its absolution position in the window. This is key as it keeps the Dialog from jumping back to the top of the window if say you had scrolled down the page before unpinning it.
    $('.DialogPinned').click(function () {
        $(this).toggleClass('PinDialog DialogPinned').toggleClass('ui-state-highlight ui-state-default').children().toggleClass('ui-icon-pin-s ui-icon-pin-w').closest('.ui-dialog').css({ 'position': 'absolute', 'top': $(this).closest('.ui-dialog').offset().top, 'left': $(this).closest('.ui-dialog').offset().left });
    });
  4. Finally, I have a little CSS to ensure the Pin/Unpin icon displays as expected within the Dialog title bar
    .ui-dialog-titlebar .PinDialog, .ui-dialog-titlebar .DialogPinned {
        float: left;
        height: 20px;
        margin: 0 5px 0 -10px;
        padding: 1px;
        top: 50%;
        width: 20px;
    }

And there you have it – everything you need to create your own jQuery UI Dialog customization to enable the pinning & unpinning of the Dialog on the screen.

Who Really Needs Custom Forms on SharePoint Anyway

Right about now, a lot of IT decision makers, SharePoint users & developers are all probably thinking the same thing – that somewhere in the halls of the Microsoft campus in Redmond, somehow this idea has taken hold: that no one wants, alas needs, custom web-based forms on SharePoint.

How else do we explain the sudden, if not buried, announcement that not only has InfoPath Forms Services been extended indefinitely on O365 and included for the next release of SharePoint on-premises (i.e. SP2016), but the most promising alternative on the horizon – Forms on SharePoint Lists (FoSL) – has simply been cancelled.

Consider the facts:

  1. A few weeks before the SPC14, Microsoft makes a big announcement that they’re retiring InfoPath. They say InfoPath 2013 will be the last version of InfoPath, InfoPath Forms Services is not committed to indefinite O365 support (i.e. it will only be “supported until further notice”) and, for on-premises, SharePoint Server 2013 (SP2013) will be the last release.
  2. They heavily promote, both before & during, a session at SPC14 entitled “Update on InfoPath and SharePoint Forms – SPC348″, during which four potential alternatives are introduced, of which FoSLs receive the most attention; we actually blogged about this in the immediate aftermath of SPC14.
  3. An InfoPath “funeral” is held at SPC14, and yet very little additional information is released after the conference regarding FoSLs
  4. Then suddenly late on a Friday afternoon (February 6, 2015) – because that’s a great time to get maximum exposure on a major announcement – rather than making a new post, an “Editor’s Note” is added to the original January, 2014 article concerning the end of InfoPath, simply noting “we are also updating the timelines for removal of InfoPath Forms Services components of SharePoint and SharePoint Online.”
  5. In parallel, and not mentioned within any related post during that time, the release of FoSLs on the O365 Roadmap is abruptly moved from “In development” to “Cancelled”, which is succinctly defined as “Previously planned updates that are no longer being developed or are indefinitely delayed.”

So 13+ months removed from the news that InfoPath would no longer be updated, Microsoft has giveth then taketh away the only fully web-based form customization tool (FoSLs) they had on their roadmap, maintained the removal of Design View in SharePoint Designer 2013 and then extended the life of InfoPath – though it’s noteworthy that they did not commit to a new release, only an extension of how long & on which platforms the old/last release will be supported. Hardly a strategy any CIO/CTO I know would want to bank on.

It’s here that platforms like CorasWorks provide critical value; our existing Actions framework is a mature capability set, with nearly a decade of evolution behind it. It easily supports customizing which fields appear on a form, the order of those fields, whether or not a field is required or read-only within that form instance, customizing the description or guidance for each field using HTML rich text, triggering Workflows and even executing external service/API calls upon form submission. As the browser landscape has improved – namely IE8, the last major browser to not support HTML5 & CSS3 falls to under 3% usage worldwide – CorasWorks now looks to add even more form customization features to include more options over how forms are laid out visually, leveraging the best free frameworks on the web.

We’ll continue to track this development and the potential impacts it has; but more importantly, we’ll also continue to grow & improve our platform to meet the evolving needs of the SharePoint ecosystem, InfoPath getting a last gasp notwithstanding!

Integrating SharePoint data into Office Apps via CorasWorks API

Yes, it’s that simple! Whether it’s a Task Pane app in Excel, Word, PowerPoint or Project; or a Mail app in Outlook, you can easily leverage CAPS, the CorasWorks API, to integrate SharePoint data into your Office Apps.

Organizations with Office 2013 have limited options when it comes to published Office Store apps that integrate SharePoint data into Office Apps; a quick search of the store for just “SharePoint” and filtered by each Office client shows few choices, most of which are simple Site or Document Library explorers. Instead, wouldn’t it be great if you could be in say Excel and pull down a collection of SharePoint list items, filtered & aggregated across multiple sites, site collections or web apps – with CorasWorks, you can. Building these Apps is quick & easy; anyone with web developer skills (HTML + JS + CSS) can do it.

As Microsoft says:

Task pane apps enable users to see the app for Office side-by-side with an Office document… and supply contextual information and functionality to enhance the document viewing and authoring experience.1

What greater source of “contextual information and functionality” do most Microsoft shops have than SharePoint?

As long as the Office clients are amongst the applications end users leverage most often, integrating business data into that experience – and remember, that integration can be two way – will have great potential. The Office Apps provide for a seamless user experience & without requiring they open a separate browser to copy/paste between; and now with CorasWorks, the functionality of those Apps can be taken to the next level!

1: Overview of apps for Office 2013

Auto-generate PowerPoint decks using CorasWorks

For everything CorasWorks can do – our visual Application Designer, reporting & dashboard wizards, Gantts, maps, grids, calendars, custom forms, workflow, integrating external data, the list goes on – I still have seen even the most savvy business user succumb to the need (or desire) make this same mistake: copy & paste data out of an application and into a PowerPoint presentation. Ugh!

CorasWorks users of the world, know you do not have to fall victim to the same trap. Working with our Services team, we can design & implement a solution that uses the CorasWorks v11 platform to auto-generate PowerPoint decks (PPTX files) in a matter of seconds and even save them directly to a SharePoint Document Library.

The design is almost elegant in its simplicity; you start with a template PPTX file that includes spaces & placeholders for the dynamic content that will be injected. Using the CorasWorks APIs, we can then load almost any data or content into the deck, including:

  • Any data within the local SharePoint farm
  • Any data within remote SharePoint farms
  • Any data within external or line-of-business systems accessible via OLEDB, ODBC, OData/REST service or SOAP web services
  • Aggregations and/or analysis of accessible data
  • Snapshot images of any CorasWorks-generated chart or Gantt
  • Copies of any image file upload to any SharePoint Library

Other key features include the ability to dynamically replicate one or more slides based on data (i.e. one slide per distinct Fiscal Year, one per Project, etc), define & pass-in variables to use in the filename and even generate “read-only” presentations that can be opened in PowerPoint & used for briefing from but cannot be modified (governance anyone…).

If you’re interested in learning more about how CorasWorks can help add not just efficiency, but consistency & governance, to your process for generating & delivering PowerPoint presentations, reach out today. Email Steve@CorasWorks.net for more info.

Tokenize Me

While working with a customer recently we wanted to pull items from multiple libraries that were similar in structure to show the current status of documents in an advanced chart.  The results of the data were to be shown in columns stacked by status by library.

How to dynamically retrieve the friendly name of the library from each item being returned in the CAPS response? An easy, yet inelegant, method is to add a text column to the libraries that simply defaults to a hard-coded value with the library’s name when a document is added.  But, why add something if it is not really needed, and what if you are dealing with more than just a few libraries?

XSLT 2.0 to the rescue.  One of the great functions of XSLT 2.0 is the tokenize function.  It is pretty easy to use, yet very powerful for a variety of tasks.  In this scenario I wanted to grab the name of the library from an item using the “FileDirRef” column and I didn’t want to apply a recursive template or such to get to it.  I wanted to keeps things as simple and lightweight as possible.  So here it is:

tokenize(@ows_FileDirRef,‘/’)[last()]

Just tokenize the “@ows_FileDirRef” value from the CAPS response using the “/” as the delimiter and then tell it you want the last value using the predicate filter [last()] on the result.

Happy building!

BYOF – Responsive SharePoint Apps with CorasWorks

BYOF? Bring Your Own Framework – meaning whether it’s Bootstrap, AngularJS, Durandal, Foundation or any other (maybe still-to-be-invented) responsive framework, you can use CorasWorks to accelerate the development & expand the functionality of your responsive apps on SharePoint.

There are three core capabilities that the CorasWorks stack provides that will facilitate creating these richer solutions:

  1. The CorasWorks Application Designer as the base for you content management process. Easily create a site using the App Designer and you’ve got all the built-in capability you need to define, manage & even work through approvals for the content that will flow into your responsive app.
  2. The CorasWorks Application Service (CAPS) as your API for not just your data access but also dynamic HTML generation. Sure the native CSOM or REST API will provide access to raw SharePoint data but only CAPS will give you a single, integrated touch point for all your data needs – including executing multiple queries serially or in parallel – while also providing access to the only XSLT 2.0 processor on SharePoint, for generating your HTML.
  3. caps.js, the javascript library for rapidly building client-side with the CorasWorks API, CAPS.

With these three layers of your application now accounted for – specifically managing the content, accessing the content & building the application itself – you’re well on your way to creating a beautiful, responsive application that will have your users saying “Wow, this doesn’t even look like SharePoint!”

Want proof? Our own CorasWorks Customer Center is built on the Bootstrap framework but the site is running on SharePoint 2010. CAPS is used to drive all the dynamic content on the site, while an App Designer-driven site behind the scenes manages the content submission & curation process.

And of course if you’re looking for a partner to help design and/or build a responsive SharePoint-based solution for you, our Services team can help; just email Steve@CorasWorks.net for more info.

Still using SharePoint 2010? Watch out for polyfills…

Pushing the boundaries of SharePoint is a daily exercise for us here at CorasWorks. When still working in SharePoint 2010 though, all too often, the real limiting factor in designing & building applications is the browser – or more specifically, the Document Mode enforced by the masterpage in SP2010:

<meta http-equiv="X-UA-Compatible" content="IE=8"/>

One way you’ll see some people or companies work around this is by adding polyfills; if you’re unfamiliar with the term, a polyfill is essentially a piece of code or script that ensures (or restores, depending on how you look at it) a piece of functionality the browser should natively support. You can read more about the term here.

A word of caution though; if you add a polyfill into your application, you run the risk of conflicting with the stock SharePoint JS. This is exactly what I observed recently when attempting to use the Modernizr.js and Less.js libraries – they broke the ability to add new web parts to any page. The error I was getting in my browser console pointed to a file named “WPAdder.js” and only stated:

Type mismatch.

My research led me to this blog post by Steve Ottenad, an excellent web designer based (ironically?) in Seattle, WA and not far from the Microsoft campus. His findings confirmed my suspicion and, as soon as the offending JS was removed, I was once again able to add web parts to a page.

One approach I considered, but eventually abandoned in favor of taking a different path altogether, was I could have wrapped my polyfill code inside a script block that only ran if my page was not in Edit Mode. But I didn’t trust SP & IE enough that some other issue wouldn’t crop up in the future.

And lest you think I didn’t consider addressing the “root problem”, there is no shortage of tips, tricks & workarounds for using SharePoint 2010 without the “IE=8″ meta tag – but they involve some pretty heady work around overriding stock SP JS files and modifying key server-side application pages for things like the People Picker. In other words, fodder for a future blog post ;-)