SharePoint SPWidgets v2.5.2 Released (bug fixes)

Tags

, , , ,

Over the weekend, I released SPWidgets (purtuga.github.io/SPWidgets) version 2.5.2. SPWidgets, if you are not familiar with it, is a set of developer JavaScript widgets meant to create customizations for a SharePoint environment.  It currently includes a People Picker, Filter Panel, Kanban Board Widget, Date Field and an Upload Widget.

Whats New

This latest version provides mostly bug fixes based on user reports as well as refinements I identified while continuing to improve the MyBoard Single page Application (a SharePoint Kanban Task Manager). The full change log can be found in Github (here).

Automated Testing Framework

In addition, and in an effort to improve code and release quality (as well as time), I have started the process of adding Unit Test cases to this library. I have worked with a few different types of testing frameworks (Mocha, QUnit, Chai, Sinon) but wanted to try a new one, so I went with Jasmine.  Its still early for me to judge it among the others, but the one thing I can say looks promising is that ti includes everything I need in one package (Assertions, HTTP mocks, ajax support, etc).  The setup into a web page was simple, however, getting it incorporated into the Grunt build process was a little tricky and at times frustrating – I think mainly because I needed to setup requireJS (a client side library) into the build system (a “server” side setup).  The good thing with these types of tools are that once its setup – its (for the most part) hands off.

I have added some test cases already and my goal is to continue to increase code coverage with it. I have even started to collect SharePoint API responses that will be used for mocking up the calls that several of the widgets make to the SharePoint APIs.

So that’s what’s going on… SPWidgts v2.5.2 provides bug fixes and lays the foundation for starting to add unit test cases.

SharePoint SPWidgets Converted to AMD Modules

Tags

, , ,

SPWidgets – purtuga.github.io/SPWidgets – is a project I started back in 2012 when I started to take advantage of the SharePoint platform to build custom web solutions for the teams I worked with. It initially served as a place to gather reusable User Interface (UI) components that could be quickly applied to multiple projects – similar to jQuery UI (it’s design was inspired by jQuery UI). It has since grown to also include reusable utilities as well as SharePoint API methods – each self contained and again reusable across solutions.

I have now taken the self-contained reusable concept a step further and converted all files in the project to Asynchronous Module Definitions (AMD). If you have not yet learned how to use AMD and break up your projects code into modules, I suggest you take the time as it will forever change the way you design software – in a positive way. I think that anyone would agree that working with small pieces of code is much better than to try and navigate through a 5000+ line script file.

Why

I’m a big proponent of modules and now use requireJS for just about all web development. SPWidgets was already broken up into individual files – each providing self contained functionality, so the move to AMD was not a difficult one for me. The move benefits the development of this library as well as anyone else wanting to use these modules without having to include the entire library into their projects. This was another big motivation for the move. When building SharePoint web apps, I want to keep them as small as possible, and AMD modules allow me to do that so that only the modules I referenced as dependencies will be compiled into the final file.

Build Process Updated as Well

I also took this opportunity to convert the build process to use Grunt, which was something that was way past due – this project was still using the cumbersome Ant system. Because SPWidgets is a jQuery library used by others (yes, there are a few out there – I think), the build process “compiles” the final single file just as it did before (look in the “dist” folder). The move to AMD should be transparent to existing users of this library – all widgets and utilities should continue to be exposed as they were before and with the same input signatures.

Support for Bower Package Manager

In the process of converting all code to AMD and re-factoring the Demo showcase page, which I also use for development, I also introduced support for Bower to help manage the project’s dependencies and also allow others to list SPWidgets as one of their dependencies.

Conclusion

Having SPWidgets broken up into AMD modules provides the most flexibility for advanced development while at the same time, through the use of the build process, continue to allow for the single jQuery library to be generated. In one of my next posts I will demonstrate how to build a quick SharePoint web app that utilizes a few of the modules available in SPWidgets.

How to render a SharePoint page in IE using EDGE mode without changing the master page

Tags

, ,

So you are running the latest version of Internet Explorer and you’re thinking: I should get good performance and better User Experience when accessing a SharePoint site. After all, Microsoft® has done allot of work to bring that browser closer to being standards compliant. Wrong!

SharePoint’s User Interface (UI) is a creature of habit. It’s coded to target specific versions of Internet Explorer (IE), which makes me think some group at the company is stuck in the early 2000’s. If you take a look at SharePoint 2010 page source, you will see this meta tag in the section:


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

This essentially tells Internet Explorer to render the page using the IE 8 rendering engine even if the current version of IE is a more recent one (ex. IE10 or IE11).

SharePoint 2013 is no better. Despite still not using the HTML5 standard header, it instructs IE to render the page using IE10:


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

This is why I always strongly suggest using a non-IE browser when using SharePoint.

In working an issue found by a user of MyBoarda SharePoint task management app that I have a available – I found that the problem was due to the page being rendered in IE8 mode. If I brought up the debugger in IE11 and switched the rending engine to EDGE (latest version), then the issue would not occur. Rather than spending time trying to find a code workaround for this version of IE, something I have decided to stop doing long ago, I instead researched if there is a way to force the MyBoard app page to be rendered using IE EDGE, but at the same time not impact the entire site.

Changing the Master page to include the meta tag to render the page in IE using the latest engine is not an option, since MyBoard is an app whose main feature is that it can be quickly used from any site in a SharePoint (it simply requires it to be placed in a Document Library). It’s also only a single page, thus impacting an entire site for the benefit of only one page is not good. There are also several posts on the web documenting the negative impacts to a SharePoint site if this is done – perhaps the main reason that SharePoint, by default, sets its rendering engine to a specific version of IE.

So what do we do? What options do we have?

Solution

The solution is to use a simple HTML file (I call it my “IE Loader”), which loads with a meta tag that instructs IE to render in EDGE mode, and show the MyBoard app page in that iframe. The reason this works is because IE can only set the rendering engine once per page load. Once set (by the “top” page) it cannot be changed and thus all pages loaded through an iframe are forced to EDGE mode.

Here is the HTML:

This file, named ie.aspx (yes, file extension is, and needs to be, ‘aspx’ instead of ‘html’), can simply be uploaded to a Document Library and it will load the file defined at line 26 (var url) by default.

The JavaScript code simply ensures that the iframe takes up the entire width and height of the browser window, and maintains those dimensions even when window is resized, thus providing the allusion to the user that its actually not in a frame. In addition, it supports providing the URL to the page that should be loaded via the ‘search’ parameter field. Example: the following URL

ie.aspx?/sites/sitename/documents/myCustomPage.aspx

will load the page at /sites/sitename/documents/myCustomPage.aspx in the iframe rendered using the latest version of IE.

A default page to be loaded should be set so that if a user clicks on this file they will not get an alert.

Some caveats and tips:

  • Displaying the page in an iframe means that all links that the user clicks on, will also be displayed on the iframe and potentially breaking form functionally. To get around this, one can further enhance the code above to “break” the iframe if the URL is changed to one that is not the page that was meant to be displayed in an iframe.
  • For non-IE browsers that may access the ie.aspx page, it may be desirable to also break the iframe and just show the intended page directly.
  • If using this workaround on a controlled page, code can be added to that page to detect if IE is being used and if so, whether the ie.aspx page is the one displaying it.

Conclusion
So the solution here will trigger IE to render a single page using the latest version of the browser while leaving the rest of the site intact. This approach also does not require any structural change to a site or the involvement of an IT department to implement. In my current use of it, I have additional code that further integrates the “IE viewer” with the app I have loaded in the iframe.

Grunt – How to Copy Only New Files

Tags

, , , ,

In using Grunt on a large project, I wanted to speed up the build time by only copying files to the staging area that have changed. Unless I missed something, the Grunt Copy plugin always copies all files, regardless if they were changed or not. It does provide hooks that we can use in determining what should be copied, thus I created this small function that does just that using the filter parameter. The function simply compares the time stamp of the FROM file to the TO file, and tells the Copy plugin if it should copy it or not.

The function below can also be found in this GIST:

Usage

In your Gruntfile.js, include the above function before defining your grunt configuration. Then use it in the Copy task as:


grunt.initConfig({

    copy: {
        build: {
            src:    "src/**,
            dest:   "build/",
            expand: true,
            filter: onlyNew(['copy', 'build'])
        }
    }

})

 

The example above will copy files from a the src folder to the build folder, but only if they are newer than those currently in the build folder. Note the use of expand: true, which is necessary in order for this work.

Using a Local Time Stamp File for Destination

I often use the Copy task to copy files over the network to a server – usually a linux mounted directory or a SharePoint document library folder. I call it my deployment task. Both of these types of destinations can be very slow when copying large amounts of files because the Copy task needs to access file information on the destination in order to determine if the file should be copied or not. To get around that performance issue, a second parameter can be given to the onlyNew function – a path to a local file – that will be used as the Destination file to compare time stamps to. That file will be “touched” at the end of the build so that it insures the next time the grunt task is ran, it will be comparing file time stamps against the last run.

Here is an example of a Copy task that uses a local file for comparing time stamps:


grunt.initConfig({
    copy: {
        deploy: {
            src:    "build/**,
            dest:   "//network.mapped.drive/folder",
            expand: true,
            filter: onlyNew(['copy', 'build'], "build/copy.deploy.last.deployed.txt")
        }
    }

})

 
I use this function in several projects to assist with a more efficient build. Perhaps I should create a Grunt plugin out of it, so that it can be better incorporated into a build by defining it as a dependency in the package.js.

Grunt: How to embed the content of files in JavaScript Files

Tags

, , , ,

When working with any project, large or small, I almost always break up the source into different files in order provide clarity and maintain small working components. So you usually find a few different files under the src folder of my projects: JavaScript files, HTML files and CSS files – all of which are then embedded into a single file by the build process.

When I started to work with Grunt, one of the first functions I needed was one that allowed me to embed the content of one file into another. The function works in conjunction with the grunt copy plugin as the ‘process’ option callback function. I needed this when:

– embedding JavaScript files into HTML files
– embedding CSS files into HTML files
– embedding HTML files into other HTML files
– embedding HTML, CSS files into a JavaScript files

The widgets and plugins I create are often used by simply including a script into the page. That JavaScript file includes everything needed to provide the functionally. In the source file, I often have variables defined that will hold the content of other files. For Example: in this code sample, the content of a file called ui-template.html will replace the token show below (inside the quotes):

var uiTemplate = "//BUILD_INCLUDE('./ui-template.html')[asJsString]";

The function recognizes the following tokens:

//BUILD_INCLUDE()
/* BUILD_INCLUDE() */
<!-- BUILD_INCLUDE() -->

Just include these in the various files that need content embedded and then define a grunt copy task that uses this function as the callback to the ‘process’ option. In addition to these tokens, options can be passed along by wrapping them in square-brackets. One the options in the example above is asJsString, which essentially takes the content of the given file and formats it as a JavaScript string – ideal for embedding into JavaScript files. Right now, this is the only option supported. Note that when using it to embed content as a JavaScript string, it is assumed that the content will be embedded within double-quotes, as shown in the example above.

The name of the file to be included can also use normal Grunt template tokens, so you could do something like this:

// BUILD_INCLUDE('<%= buildDir %>/src/file1.js')

Here is the full function code, hosted as a gist at Github:

Usage Example

Here is a full example of how to use this function. Suppose you have the following files:

demo/myPlugin.html
src/myPlugin.js
src/template.html
src/styles.css
Gruntfile.js

The demo/myPlugin.html contains the following:

<script>
    //BUILD_INCLUDE('dist/myPlugin.js')
</script>

The src/myPlugin.js contains the following:

var setup = {
    template: "//BUILD_INCLUDE('src/template.html')[asJsString]",
    styles: "//BUILD_INCLUDE('src/styles.css')[asJsString]"
}; 

The above setup object will have its properties values replaced with the content of files in src/template.html and src/styles.css respectively. Note the use of asJsString option at the end of the build include string.

The Gruntfile.js includes the function below and defines a copy target similar to the following:


// includeFile function is define above this code

grunt.initConfig({
    copy: {
        build: {
            options: {
                expand: true,
                process: includeFile
            },
            files: {
                "src/myPlugin.js": "dist/myPlugin.js",
                "demo/myPlugin.html": "dist/myPlugin.html"
            }
        }
    },
});

Running grunt copy will generate a dist/myPlugin.js that includes both the HTML and the CSS file content assigned to the variables shown above. It will also generate dist/myPlugin.html that also includes the content of the dist/myPlugin.js file.

If wanting to look at a working example of this in a real project, take a look at my jquery.todoList plugin over at github. It uses this approach to build the distribution files.

How to Scope 3rd Party Cascade Style Sheets (CSS) with Grunt

Tags

, , , ,

Every client side web developer or even the occasional advanced user knows what a closure is suppose to do and why it is important to keep all variable within a private scope. Snippets like this are common when working with jQuery:

(function($){
    var myPrivateVariable = 'abc';
    // $ is private here

})(jQuery);

It allows you to code freely inside of the above IIFE (Immediately-Invoked Function Expression) knowing that anything properly declared (with a `var`) inside will not leak out to the global space as this possibly interfere with other logic running on the page.

What about Style Sheets?
Scoping stylesheets is easy if you are the author of that stylesheet and you know exactly what location of your user interface (UI) that style applies to. Stylesheet scoping means defining your selectors to a specific location on the page. That location is simply defined as an additional selector that is prepended to every other selector in the Stylesheet.
Example: let’s say I’m defining a Stylesheet like this:

h1 {
    font-size: 30px;
    color: red;
} 

This would affect all Heading 1 elements on the page. But I need it only to impact the h1 I define inside a `DIV` that has an ID of my_widget. To do that, simply prepend that selector to the rule sets:

#my_widget h1 {
    font-size: 30px;
    color: red;
} 

Ok. What about 3rd Part Libraries, Like jQuery UI and Bootstrap?

What if you’re trying to use a 3rd party UI stylesheet framework and are trying to have those styles only apply to elements inside a specific selector. I came across that need recently when wanting to use a jQuery UI theme inspired by Bootstrap. The app I was creating was going to be inserted into another application (Mingle) and was going to have to play nice with that application’s existing look. I certainly did not want it to interfere with that application’s User Experience (UI). The only answer is to scope all of the styles from the above theme to the container that holds my app.

HTML5 to the Rescue (almost)

HTML5 does have a feature called ‘scoped’ which allows you to use definitions inside HTML elements and have its rules apply only to the children of that element. But unless you are currently (as of this writing) building your code to run on Firefox only, it’s just not an option. There is a jQuery plugin that attempts to pollyfill this feature. But in reading the information on the site, it sounds like it may not be reliable when using the @import directive, which I may need in some occasions.

Grunt Task to the Rescue
Doing this manually is just not efficient so what I needed was a build time grunt task that would parse the stylesheet and insert a prefix to every selector. After trying a few plugins and getting near the point of ‘I’ll just create one myself‘, I found grunt-css-selectors (by Eric Ferraiuolo @ericf) which does the job.

The setup is just like any Grunt plugin.

– install the task

npm install grunt-css-selectors --save -dev

– configure the task (Gruntfile.js)


grunt.initConfig({
    css_selectors: {

        options: {
            mutations: [
                {prefix: ".my-app"}
            ]
        },

        build: {
            files: {
                "build/css/jquery-ui.custom.scoped.css": [
                    'src/css/jquery-ui/jquery-ui.custom.css'
                ]
            }
        }

    }
});

grunt.loadNpmTasks('grunt-css-selectors');

– Run grunt

The configuration above would take the stylesheet located in `src/css/jquery-ui/jquery-ui.custom.css`, prepend the value `.my-app` to every selector and save the new CSS file as `build/css/jquery-ui.custom.scoped.css`. The style rules selectors will look like the following in this new file:

.my-app .ui-button:active,
.my-app .ui-button.ui-state-active {
    background-image: none;
}

Now when, I include the new CSS file on the targeted (Mingle) page, I’m assured that it’s style rules will apply only to the content inside of elements having the `my-app` class and thus not interfering with the remainder of the UI.

How To: Load a Private Version of jQuery with Require.JS

Tags

, , ,

AMD Loaders Rock!

I have been using require.js (an AMD loader) to do allot of client side development and can’t really imagine starting any decent size project (App) without it.  It allows you to break up your code into modules that are loaded along with their dependencies (other modules). This design patters allows for greater code maintainability as well as improve overall application development by abstracting away the dependency loading mechanism (think deep dependencies: module A is depended on Module B, but B is dependent on C, D, E…). The patterns also encourages keeping the global scope clean and ensuring that all variables are defined to only the executing scope – a pattern that everyone should follow – regardless of AMD – so that conflicts with other modules/libraries/frameworks are not introduced.

A Private Version of jQuery

One of the needs I came across in the last week was how to load a specific version of jQuery via require.js and keep that version private. I’m familiar how to do this in a non-AMD way, but I wanted keep to the AMD design pattern. The app I was developing was going to be added to a page that already had jQuery loaded, so I needed to ensure I did not interfere with it or overwrite it. jQuery itself already supports AMD loaders, but even in the instances where it detects an AMD loader on the page, it still adds two variables to the global space: jQuery and $. The answer obviously is to use  jQuery’s noConflict() method.

The documentation over at require.js provides an entire chapter on how to work with jQuery, including how to obtain a private version of it by using jQuery’s noConflict() method, which is the ideal method for when wanting to load jQuery from a CDN.  I was hosting my own copy of jQuery for this project and thus found the approach detailed there to be overkill. As it turns out, there is a simpler (IMO) setup if you are going to host the copy of jQuery: wrap it in a define() statement and immediately call noConflict().  Here is the content of my jquery.js file:

define(function(){

    // jQuery's code here

    return jQuery.noConflict(true);

})

So this includes the jQuery code inside of the module and immediately calls jQuery.noConflict(true), which essentially reverts the jQuery and $ global variables to their prior values (if they were set), thus ensuring I don’t interfere with any other version already loaded on the page.

Like I said: if you are loading jQuery from a CDN or a location where you don’t have control over the file’s content, then the instructions detailed in the require.js documentation should be followed.

What About jQuery Plugins

One thing I realized, as I was implementing the above code, is that most jQuery plugins (mine included) are not AMD aware. I have not tried (will soon), but I think require.js provides a mechanism for handling that as well. And then again: if hosting those locally along with your App, then the following should also work:


define(['jquery'], function(jQuery){

    // jQuery Plugin code here. Example:
    (function($){

        ...

    })(jQuery);

})

 

One of the tasks I took way from this effort was to make my jQuery plugins AMD aware the next time I make a change to them.

 

 

A JSDoc Template to Output SDOCML Files

Tags

, , ,

In one of my recent posts, I wrote about how to create a SDOCML file to extend Aptana (JavaScript IDE) content assist. This is part of my quest to find an IDE that can provide content assist as well as Eclipse’s Java IDE. But creating these files manually is just too cumbersome. What I needed was a way to auto generate these from my code base.

JSDoc To The Rescue

Jsdoc is a great tool if you are developing plugins or libraries that will be used by other people. It runs against your source code, picks up the jsdoc dockets (tokens that describe your functions and variables) and builds up documentation for it – normally in HTML format – essentially generating API documentation for your code. The output of the tool is controlled by a jsdoc template that can be defined on input and whom receives all of the information jsdoc was able to read from your source files.

I’m a big fan of documenting code. I personally think it helps in quickly understanding how to use a piece of code, and prevents wasted time in reading other people’s code just to try and figure out how to use it. JSDoc doclet can be seen all through out my code, thus creating a template that will output that documentation in the format that Aptana needs quickly became a necessity.

The Template

After searching the web for a template that would allow me to produce SDOCML formatted XML files, I found none. So I created my own. The template can be downloaded from github (here) and produces one single file – the SDOCML formatted file ready to be used with Aptana. It’s purpose is to output JavaScript Classes along with its instance and static methods.

Use it like any other JSDoc template, by using the –template input options and pointing to the folder that contains the template (the one with the publish.js file):

jsdoc --template ./jsdoc-sdocml-template/template ./src

There are a few things that this template alters in the output. These were needed in order for the file to be compliant with Aptana’s SDOCML definition. They are:

  • It outputs (currently) only Classes and Namespaces, along with their members
  • JSDoc Module names are stripped from the XML file due to unsupported characters. So something that may be annotated like this – module:widget/computers.Mac – will be output as: Mac
  • Some Type definitions are adjusted so that Aptana can recognize them

So does it work?

In a sense, for simple Classes, yes it does work. But Aptana seems to be very sensitive to the format used on type inference and to the content of the SDOCML files.

Example: Classes attached to namespaces (ie. Object) don’t seem to get recognized:


/** @namespace my */
var my = {};

/**
 * A widget factory
 * @class my.Widget
 */
my.Widget = function(){}

Also, Type inference is not consistent and as detailed in my prior post, Aptana is just too sensitive as to when it show content assist and when it does not. I had high hopes for this solution. The thought of being able to add good content assist to a JavaScript editor by simply dropping in a file is an awesome concept. It avoids depending on editor-dependent conventions that may not match the style of code you are working with.

Maybe I need to give up on Aptana!

What’s Next?

I’m not done yet.  In trying NetBeans IDE recently I found that not every editor has a “drop-in file” concept for augmenting content assist. It (and other IDEs/Editors) do however, have good support for reading and understanding the classic way of building a JavaScript Class:


function Widget() {}

Widget.prototype.getParam = function() {};

Widget.prototype.setParam = function(){};

We all know that in today’s OO JavaScript programing, you are always most likely going to have a Class Constructor instead of defining them the way detailed above. I realize now that what I need is for a JSDoc template that output JavaScript code. Yes, generate code from code. I need the output to simply provide a stub representation of the Classes and Namespaces using the standard “classic’ way of defining these.

So the stage is set for the next post on this topic.

 

MyBoard – A SharePoint Task Management App

Tags

,

April 2015: This little app has become very popular and now has its own page – HERE – that includes feature description and a video of it in action. – Paul

Almost a year ago I started to (finally) gain interest in learning Grunt – the Node.js task execution framework most used in building JavaScript projects. I have been a long time user of Ant, mainly because I use the Eclipse IDE, where support for Ant is built in. But as my work with front end web projects increases significantly (I recently accepted a position as a web GUI engineer) the need to become familiar with these type of build tools was essential to ensuring a productive and streamlined workflow. In addition, I wanted to continue working with the SharePoint platform and specifically, attempt to understand how the Ribbon is composed and whether I could create my own plugin for adding custom Ribbon tabs.

For this, I stared to develop a project I call MyBoard – a SharePoint Single Page Application (SPA) that turns any SharePoint list into a list board (Kanban) complete with drag-and-drop and easy access widgets for managing the cards on the board. This is now a fully working “app” (not a SharePoint App) that I am using in several different projects where we needed to manage a list of work items across a small group of people. It’s simple and efficient and all it takes to get it going is uploading one single ASPX page to a document library. Oh, yeah: and it works on SP2010 and 2013 (and probably even SP 2007 if the proper document header is used).

MyBoard - AppIn working this app, I have ended up with several reusable components that I’m sure I’ll take advantage of in future projects. Some of which I’m also thinking of also making available as open source projects on github – along side some of my other projects, including the SharePoint widgets library.

About MyBoard

I like Trello. It’s clean, fast and efficient as it allows you to apply several action on the cards via each card’s menu. With that service as the model, my requirements for MyBoard were the following:

  • simple to setup and configure including support for zero-configuration
  • adaptive of site’s existing data (lists, Document libraries)
  • multi-user support and bookmarkable urls
  • integrated into the site’s look and feel
  • quick actions available from each card

The app works by having the user select the current site’s List to be used in retrieving data for display, along with the list Column that will be used to build the Board. The Column needs to of type Lookup or Choice, so that its values can be used as the Kanban board’s columns.

A little more on these, including what I have learned and where I currently stand with them:

Simple to Install, Setup and Configure

As I already mentioned above, the entire app is contained within a single ASPX file, which includes all needed dependencies include a private version of jQuery – thus there is no issue or conflict with deploying this to a SharePoint site that already uses jQuery. You drop that file into a Document Library and everything else is configured from the app once you click on the file.

This single file is the result of the build process, which uses grunt as the task execution tool. It takes all if the code files, it combines them into one file, minimizes it and finally inserts the code into the ASPX file. In addition, I have a grunt task that also copies the built ASPX file to the document library on SharePoint – essentially “deploying” the app. Grunt tasks were strait forward to setup and there are tons of examples online on how to achieve any task. I did have to write some functions for embedding contents of one file into another, something that I could not find good example on. There are tons of concatenation examples – but I needed to include the content in specific locations. Perhaps I’ll write about that in the future.

The project source, however, is laid out very differently on disk, with several individual files. For development and debugging I have a special ASPX file that loads each file individually so that I can easily use the browser development tools to focus on the set of functionally I’m working with rather than having to browse through a long list of code all in one place.

So this allowed me to become very familiar with Grunt – just as Gulp is starting to gain some ground. I have not tried it, but the approach it uses seems allot more attractive to me: code-over-configuration.  Perhaps that tool is another excuse for me to create a new project where I can apply it.

Adaptive of site’s existing data (lists, Doc libraries)

I wanted the app to be able to use the site’s existing data and not impose a specific format to be followed or predefined structure. The only requirement is that the List or Document Library have a column of type Lookup or Choice, which is needed to build the board. This design makes it feasible to use this app immediately with existing site’s data.

The only portion of this design I am not happy with is how slow the editing of a card is. When editing the card content, the SharePoint list Edit form is shown in in a dialog, thus loading all the bloat that makes up that form. I may implement my own edit form and add some of the features found in Trello (like inline editing, and progressive saving).

Multi-user support

Multi-User support here simply means that updates by others users are near-instantly seen by others whom may also have the card displayed on their board. For this I built a library that provides data persistence between the SharePoint list data and the web application. This layer is so cool (if I can tune my own horn here) that I know use it on all SharePoint projects that needs to get data out of SharePoint lists.

It uses the GetListItemsSinceToken API operation and depends on Knockout.js and it’s Observables to achieve its automatic insertion and removal of items from the query result as well as the notification of any bound listeners. You use it the same as SPServices GetListItems, but you get back a Promise that resolves with a Knockout observable array containing the list item matching the defined filter. From that point forward the query continues to check the list for changes on the query used on input and reflects that on the results array if any are found – which in turn are reflected on the UI if the Observable Array is bound to the UI (presentation/view). This library also provides a custom binding called SPField that handles the display of sharepoint data – including the format of it (like lookup, Date Values, etc.).

I’m considering releasing this library as open source via github. The code is pretty solid right now, but I need to spend some time documenting the external API and provide some usage examples – maybe even a sample app.

In addition to having constantly updated data displayed on the board, the app also needed to support the ability for the user to “preserve” the setup, so that they did not have to create it on every page visit. This is supported with two approaches:

Predefined Board Setups

An administrator (one having write permissions to the folder where the MyBoard ASPX file is stored) can create boards and then save them as predefined setups. These show up on the Ribbon menu, under the ‘Board’ button:

MyBoard - pre-defined

Stateful URLs

This is a very common approach with SPAs – using the hash portion of the URL to represent the “page” the user is visiting – also called routes.  MyBoard uses the Sammy.js library to achieve this functionality and thus any user can create and configure a Board and then bookmark the page. As they configure the board, the URL is updated to “maintain state” and thus will recreate the view once loaded again. This also makes it ideal to send the url to others, if wanting to share information. Here is an example of such a URL:

/MyBoard.aspx#!/v/Tasks/Task+Status/Status[matchType]=Eq&Status[logicalType]=Or&Status[values][]=Completed

Integrated into the site’s look and feel

This is a work in progress, but the primary thing I wanted to accomplish was to utilize the Ribbon to provide navigation and controls for this app. With time, I’ll look to also use the styles used to brand the given site so that the entire apps feels integrated.

Customizations of the Ribbon are well covered now a days in blog posts, which is done through declarative XML. This is the official and supported way of doing it. But this does not mean it’s the only way. I thought: there has to be a way to create these via JavaScript from a client side script – after all, the entire Ribbon is made up of HTML, CSS and JavaScript. After much searching of the web and debugging of the various ribbon JavaScript files, I have been able to come up with a library that allows you to create your own custom ribbons – or to clarify: add tabs to the OOB SharePoint ribbon. The screen capture above shows the MyBoard Ribbon created with this library.

It does not support all the possible controls that the Ribbon can provide – a vast and rich set. Currently I have support for large buttons, small buttons (usually stacked vertically), Flyout Menus (pop out menu with buttons) and Flyout Areas (my own creation – a pop out are that can be used to display anything). All of this in a client side JavaScript library that frees you from having to use the declarative XML approach and place files on the server side. I am currently using it with SharePoint online O365) as well as SharePoint 2010 on premises.

This is yet another library that I’m thinking making available as open source via github. For the most part, much like the data persistence library, the code is pretty solid. The documentation effort, however will be significant and will delay when I make this available (I don’t like to release a half-baked library :) ).

Quick actions available from each card

Having to open each card just to make a small changes, like setting a value in a column is overkill. Simple tasks like that should be possible right from the card menu – just like Trello. So each cards menu (currently) supports:

  • assigning users to the card
  • email the card
  • showing the cards direct URL

MyBoard - quick actions

Other actions that are In the backlog and will be implemented sometime in the near future are:

  • set categories (labels)
  • subscribe to alerts
  • ability to set any single value columns (those of type Lookup or Choice)

Most of these action are possible only after the user configures the board, which once created, allows the user to set which of the selected list columns will support the action (ex.: which column should be used as the card Assignee, which column should be used for labels, etc.)

So what am I going to do with this app?

Right now I’m keeping this app private and using it in a few projects. I was thinking about converting it to a SharePoint App, but I’m not a VisualStudio person and with my ever decreasing focus on building tools/apps on SharePoint, not sure that will happen (Ps. Would love for Microsoft to support packaging SharePoint apps outside being forced to use their own toolset). The thought of putting up for sale has crossed my mind. Nothing outrageous, but a small fee. But perhaps in the end, I might make available a free “closed source” limited functionality version with an option to license the full version. That last option may be the one I ultimately pursue. It will give the opportunity/excuse to convert this project to use Require.JS and split up the code into modules. Once they are in place, using a (Grunt) build task that creates both versions will be fairly strait forward.

If you have made it this far in reading, let me know what you think I should do it. Do you think there is a market for a paid version?

Special Thank You

I have asked a set of folks who are much more involved with SharePoint than I am, to evaluate this app and received some feedback – specifically from Stefan Bauer (@StfBauer, blog at http://www.n8d.at/blog/). His UI/UX constructive feedback was outstanding and although I have not yet followed up on all of his feedback, I will at some point in the future.

I also have to give kudos to Daniel Walker (@spevilgenius, blog at http://spevilgenius.blogspot.com/ ), whose blog post on how to create Ribbon tabs and buttons via JavaScript helped and inspired me kick start the Ribbon library I reference above.

Whats New in v2.3 of SPWidgets – SharePoint Client Side Widgets

Tags

, , ,

Its been a long time since I tagged a new version of SPWidgets. Too Long. I really should not wait so long between versions, specially when I was making changes all along.  Most of the changes done were in response to issues opened on github as well as in support of a side project I have going called MyBoard. More on that project is forthcoming on a separate post.

This version does not introduce any new widgets, but rather builds upon those that currently make up the library.  If you are a current user of SPWidgets, I don’t foresee any issues with upgrading.  Version 2.3 can be downloaded here: https://github.com/purtuga/SPWidgets/archive/v2.3.zip

The library, both the regular and minified version, is located in the plugin directory.

Are you currently using SPWidgets? If so, drop a comment below to let me know which widget(s).

Enjoy!

Change Log

People Picker Widget:

  1. Support for defining a token that represent current user (ex. [ME]), which translates to caml value <UserID/>
  2. Introduce input option that allows user to control the container where the autocomplete results will be displayed.
  3. Allow user to override jQuery UI’s Autocomplete widget minLength option. See issue #20
  4. BUG: Picker does not handle un-resolved users. See issue #21
  5. Allow input options to be set globally for this widget
  6. BUG: getSeleted does not work. Switch statement does not have ‘getselected’ in lowercase, thus it never matches. See issue #15
  7. BUG: When input element already has a value set, init of widget fails. See issue #14
  8. Support for other types of accounts like groups. Possible values are: [None | User | DistributionList | SecurityGroup | SharePointGroup | All]
  9. BUG: When used on a element that has z-index set suggestions show behind the input element.

Filter Panel Widget

  1. Display columns of Type ‘Attachments’, as a YES/NO dropdown. Column is of type of Boolean.
  2. Remove the focus on the first element when a reset is done.
  3. Does not support a column of Type Choice with Multiple values. Internal type is ‘MultiChoice’
  4. BUG: Created and Modified columns do not display the time picker – only date.

Board Widget

  1. New method to return a list of available columns for the board. Such method will be useful when wanting to create custom UI’s for showing/hiding board Columns.
  2. BUG: if an item is changed by someone else so that it no longers appears in the board being displayed, the Board State column total number of items is not updated to reflect the number of item under it.
  3. Enhancement to include a new input option that will display the board with fixed height colummns. Similar to how Trello works today: All column bodies are fixed height and user is able to scroll through each column’s content independently.
  4. Make each Column Title be “attached” to the column content. In other words, remove the spacing between them. (Feedback provided by Stefan)
  5. Enhance the Headers so that the title of the Column is Left justified and the Number of items is Right justified. (Feedback provided by Stefan)
  6. Change code so that the Column picker button is NOT automatically displayed when calls include visible columns. Options should be driven by developer.
  7. SPShowBoard(“setVisible”) should support a keyword of ‘all’, allowing the developer to automatically make all columns visible. This could also be an empty array ([]).
  8. Consider removing the ui-widget-content class from the container that holds the board columns. Some styles of jQuery UI have a background that throws off the styles between headers and body of kanban
  9. When making all column equal height, use ‘min-height’ instead of height css attribute.
  10. Change the Column selector “all/none” button to use jquery UI icon ‘ui-icon-radio-off’ instead of the current checkbox.

Upload Widget

  1. BUG: Post upload page (if checking is needed) fails to display for SP sites in non-English locale. See issue #16
  2. BUG: Widgets does not work on SP2007. See issue #9.
  3. fillTemplate() utility seems to use a redundant regex [\{\{\}\}]. Reported by Alexey with Issue #10

Date and Time Widget

  1. Support an ‘inline’ option that allows you to display the widget on a page at all times. With inline, the use of an input field should be optional by the user.
  2. BUG: When Allow Multiples is set and field is setup to display only date (no time), removing selected dates does not work.

 

Follow

Get every new post delivered to your Inbox.

Join 32 other followers