iGoogle UI for SharePoint – Part Two : Dragging, Dropping, Sorting and Collapsing

iGoogle-Part-Two

Series Content

  1.     Part One – Overview, Concept,  HTML Structure & jQuery Basics
  2.     Part Two – Dragging, Dropping,  Sorting and Collapsing – Current Article
  3.     Part Three – Saving WebPart states using Cookies
  4.     Part Four – Control Adapters
  5.     Part Five – SharePoint 2010 Integration
  6.     Part Six – Bringing it all together
  7.     Bonus – Saving WebPart States using the Client Object Model

Overview

In Part Two we will take the basic html from part one and using some Javascript magic make it into a more compelling and interactive page.  Firstly we will identify the various techniques individually and then put them all together at the end of this post.

Javascript

As mentioned in the previous post, a decision was made to use the jQuery Library with the jQuery UI abstraction layer to provide the functionality for our “iGoogle” interface.  It is using this library that will speed up development and keep everything cross-browser capable.  In our solution we will be using the following effects / methods from the jQuery & jQuery UI library.

We will begin by modifying our script.js file to include a new global object called “iSharePoint“.  This will be our namespace that we will use to contain all of the functionality for our interface.  Within this object we will create a set of functionality that uses the libraries and methods described above.

This method will be called from the jQuery Document Ready function which will ensure all the items are ready to be manipulated before we do anything.

iSharePoint Settings

The settings object we have defined will contain all of the global settings we require to make this item as functional as possible.

There are quite a few settings which I will now explain each in detail:

  • columns – this is the class selector for each of the columns that we would like to be sortable and drag and drop between.
  • zones – these are the unique ID’s of each of the columns. (This is blank because we are going to dynamically populate this based on the DOM contents)
  • widgetSelector – this is the wrapper div of each of our draggable widgets.
  • handleSelector – this is the grab handle class for the div we will use to drag the widget around the page
  • contentSelector – this defines the class of the widget content wrapper which is used for the collapsing and expanding functionality.
  • editSelector – this defines the class of the edit panel wrapper which is used to contain the edit functions.
  • toolboxSelector – this defines the footer toolbox where unwanted or unused widgets can sit out of the way.
  • widgetPlaceholder – this is the name of the class that is assigned to the drag target div so you know where your div will end up.

Bring the Widgets to life

The next part is a little more complicated but we will take each part individually.  We now need to add another method to our global object that we will call “buttonFunctions

To this method we will add first create a new reference to our global object.  This is useful if multiple instances are required as well as if you ever need to rename the global object.  We will then need to create a new variable so we can reference jQuery without using the “$” symbol in noConflict() mode as that symbol it is used by SharePoint’s internal js files and can cause clashes. (Thanks to Chris O’Brien for explaining this here)  We will then create a local reference to the settings only as a shortcut so you don’t need to type “this.settings” every time.

The next step is to define our button click handlers so that each widget has independent click events that can be raised.  One thing to be careful of is what is known as “Event Bubbling“.  This is when, upon clicking on an element in the DOM the event will bubble upwards through to the highest level element which an event the same as the ones you have recently triggered.  To prevent this from happening we need to add a line of code (e.stopPropagation();) which will prevent this from happening.  Below is a skeleton framework of the button click handlers.

As you can see there is quite alot of framework code added to contain the button functionality.

Demo

You can see and example of where we are currently by clicking here for a demo

Button Functions in More Detail

We will now flesh out each of the functions in the method to provide them with some actual functionality starting with the widget toolbox slider at the bottom.

As you can see we have changed line 5 from the alert to

This simple line will enable use to open and close the toolbox at the bottom.  Nice and simple.

The reset button will not be functional at this point as in future posts we will be resetting the cookies and refreshing the page.  At this stage we will simply ask for confirmation of the action and then refresh the page.

 

We have again removed the alert placeholder from the framework above and instead added three lines of code 5-7 which will ask the user to confirm that they want to reset and if they click yes then the page will reload otherwise nothing will happen.  Two down, Three to go.

Next we will add the toggle functionality to the edit toolbar.  This again is another single line but with some nested functions which will be explained.

As you can see we have once again replaced the alert placeholder with the single line.  If we look at the html of a widget we can explain how this works.

What we are trying to do is traverse the DOM to open and close the widget-edit div.  Our starting location is <a class=’edit’>edit</a> which is the first part of the code $j(this).  We then want to get the reference to the current buttons parent only, with a selector of settings.widgetSelector (which in our settings is set to “.widget”).  We then want to find the widget-edit div which is this part of the code find(settings.editSelector) and then we finally ask the code to perform a slideToggle(“slow”).  The slow property creates a nice visible slide.  Alternate values for this can be fast or to not provide a property at all.

So..Whats next.  The next item on the list is the remove functionality.  What we want this to do is remove the widget from the current div that it sits in and place it in the toolbox div.  This div has some specific CSS attached to it which will collapse the whole widget and just show the title bar with no buttons.

This time we are using a similar method to the previous function by traversing the DOM to find the current buttons parent.  However this time we want to take this whole DIV and using the appendTo() method we can attach it to the toolboxSelector div defined in the settings.  Simple!

The final one to do is the collapse button.  This once again is very similar to the edit button but with an extra line afterwards.

Once again you can see that we are getting the reference to the parent and then this time finding the contentSelector to perform the slide toggle on.  Afterwards we are once again getting the parent widget wrapper but this time we are now adding a class via the toggleClass method.  We need to do this so in future posts when we are saving the various states we can easily identify which widgets are minimised.

Thats is it for the button configuration.  We can now delete, open the edit box and toolbox, we can delete a widget from the main view and we can reset the page and force a page refresh.

Demo

To view a demo of where we are so far click here

Adding Drag and Drop functionality

So next up is the nicest piece which is the ability to drag and drop widgets between the columns.  Firstly like we did for the buttons we are going to add another method to our global object that we will call “makeSortable”.  Once again like above we will also add the iSharePoint reference, noConflict and settings references to the top.

To this function we will now add a reference to the jQuery sortable function.  This function takes a set of parameters which will be explained below the code sample.

  • Line 1 : take the reference of the columns from the settings and runs the sortable method on it.
  • Line 2 : this line enables us to connect all columns together so you are able to drag and drop between all instances
  • Line 3 : defines the element that you use to drag and drop
  • Line 4 : defines what the cursor looks like when dragging
  • Line 5 : If set to true, the item will be reverted to its new DOM position with a smooth animation.
  • Line 6 : The class that gets applied to the otherwise white space when you are dragging.
  • Line 7: Self explanitory, forces the placeholder to have a size.
  • Line 8: Time in milliseconds to define when the sorting should start.
  • Line 9: Opacity of the element currently being dragged.

The following lines 10 – 12 and 13-16 are two functions that get run at the start and end fo the dragging process.  The start function is used to change the colour of the columns so that they are highlighted when you drag so you know what the boundaries are.  The stop function reverses this and resets the toolbox and columns back to their previous state.  In future posts we will be using the stop function to save the state of the widgets.

Notifications

You may have noticed by now that there is a div called “Badge” which is displayed in the HTML as a red circle.  This does indeed have a purpose to display the number of items currently in the toolbox.  To do this we once again need to add alittle piece of jQuery magic to bring it all together.

Firstly we need to create a global function which is not in the iSharePoint object.

What this does is count the number of widget divs that are in the toolbox at the bottom using the .Size() method.  The references to the divs are taken from the iSharePoint settings.  All that is needed to do now is to add the updateBadge(); to the ready function.

Then add it to the .remove click event.

And then finally add it to the stop event from the sortable method.

Colour Picker – Edit toolbar

The final piece of this post is to enable the colour of the header to be changed using the toolbox.  To do this we need to add another function to the global iSharePoint object called activateColours which will be used to process the colours.

The Markup for the edit toolbox is as follows:

As you can see this is nothing different from previous code but as you can see there is an LI with a class of each of the colours that you would like to use.  You are also able to put hex colours into the class names and they will work just fine.  The code for the function is shown below:

The first 4 lines should be nothing new as it is the same as previous functions.  The first loop goes through every unordered list on the page with a class of color and sets the background colour of the list item to what is in the class name.  Once all the items have their colour all we need to do is to attach a click handler to each of the list items themselves so they can control their parents header which is what the next loop then does.

Finally we need to add the function to the init function so that it will become active.

Demo

So want to see the whole thing working?  Click here to see the final result of this quite epic blog post.

Summary

In this post we have outlined how to add the various functionality to our page using javascript and the jQuery Libraries.  Next time I will explain how to save the state of the page using Cookies.  I hope this post has been useful and please leave some comments about what you would like to see in future posts.

 

I am the SharePoint Development Lead at ICS Solutions Ltd. As well as broad knowledge in SharePoint 2007, 2010 & 2013 my specialities lie with SharePoint Branding, WebPart Development and JQuery integration.

15 Comments on "iGoogle UI for SharePoint – Part Two : Dragging, Dropping, Sorting and Collapsing"

  1. WarrenR says:

    Hey Chris, Great post … I like the series. Looking forward to the final installment sometime soon? Be nice to see something similar that allows you to arrange items from a list and update the list items based on the final arrangement … :)

  2. Gokul says:

    Great post…Thanks for sharing.
    Looking forward to other posts in this eagerly awaited series..

  3. Brett says:

    Excellent Work, I can’t wait for the next Tutorial.
    It would be awesome if I could get this working for my Intranet at work.
    Keep up the good work!

  4. Marco says:

    Hi Chris,

    Very nice post! Looking forward to the SharePoint integration. I think this is a nice solution for corporate Intranet sites! Hope to read the next parts soon!

  5. Tim Allison says:

    Have you progressed on this project? I beleive it is worth while.

  6. Yes I have. I have been very busy recently so as soon as I get some time I will be releasing the newest blog post. Thanks

  7. Paul Perry says:

    Awesome, just what I’ve been looking for. In one afternoon, I’ve come so far into using jQuery in SharePoint. Really looking forward to the next posts. Cheers!

  8. So glad you enjoyed it. Please view the next in the series to continue on your learning :)

  9. HaAaS says:

    Waw its amazing post and its working fine
    But On each page loading, the widgets reset as the default Html layouts…
    We can fix our new layout after the drag /drop of widgets ?? and don’t change the order if we opened onather pages and comming back to our welcom page ??
    Hope you help me on that issue

  10. BP says:

    Hey, Great Posts, just wanted to know how soon you’ll be releasing the integration into the Sharepoint 2010. We are really getting into gear to put this into our share point environment and would love to implement this functionality.

  11. Andy says:

    So great articles! it’s very useful to me, thanks!

  12. Sundar says:

    Awesome article, Can I use this in my app development?

  13. sagar mantri says:

    Hello Chris,

    You doing wonderful job, this article helps to newbie like me.
    But i need to run this solution in office 365 as sandbox solution.
    But control adapter is only work if its dll in GAC. How we can accomplish in office 365?
    Please your help will prevent my headache.

    Thanks.

  14. sagar mantri says:

    Hello Sir,

    What are the ways for getting WebPartZone without using ControlAdapter?

    I need alternate solution for this:
    WebPartZone wpz = Control as WebPartZone;

    Is any other way?

Got something to say? Go for it!