You are currently browsing the monthly archive for June 2010.

In the past couple weeks, I have been working on the Easy Tabs v5. I have completely rewritten the script to make it more generic. The objective is to accomodate various layouts, including SP 2007 Web Part pages, SP 2010 Web Part pages, and wiki pages. I am also taking this opportunity to include some of the options mentioned here (see the comments).

My script is in good shape, but still has a couple issues, linked in particular to wiki pages and Microsoft bugs. Today I sent the latest draft to the readers who have volunteered to test drive the new version.

Also, I am preparing another gift for you: I recently built a variation of the Easy Tabs for a group at Hewlett-Packard, and the manager has agreed to make the code public. I’ll publish it a month or two, after I make it compatible with SP 2010. This variation allows multiple Web Parts under a same tab, which makes it suitable for dashboards for example.

Remember to subscribe to my RSS feed if you are interested in the latest updates!

For the record, the current Easy Tabs script for SP 2007 is available here:
http://www.pathtosharepoint.com/sharepoint-user-toolkit/default.aspx

This series assumes that you are familiar with the “HTML Calculated Column” . 

Part I: fallback to SP 2007
Part II: edit in SharePoint Designer
Part III: deal with individual Web Parts
Part IV: brute force 

At the end of part III, we were left with this question: how do I know when I need to run the Text to HTML script? 

In this post I’ll provide an easy answer: I don’t know. Updates to the page can come from the asynchronous load of a calendar view,  the asynchronous update of a list view, expanding grouped items, a response to a Web service call, etc.

Not knowing when or where updates happen, my only solution is to scan the content of the page at regular intervals. Not the most elegant or performant choice, but a bulletproof approach that will cover all cases.

My sample code:

 
<script type="text/javascript">

// Copyright (c) 2010 Christophe Humbert - Path to SharePoint

// Find all Web Parts in the page
var listWP=[],calWP=[],divs=document.getElementById("MSO_ContentTable").getElementsByTagName("div");
var count=divs.length;
for (i=0;i<count;i++) {
try {
if (divs[i].id.indexOf("WebPartWPQ")==0){
if (divs[i].innerHTML.indexOf("ViewDefault_CalendarView")>=0) {
// Calendars
calWP.push(divs[i].id);
}
else {
// Other Web Parts
listWP.push(divs[i].id);
}
}
}
catch(e){}
}

function TextToHTML(NodeSet, HTMLregexp) {
var CellContent = "";
var i=0;
while (i < NodeSet.length){
try {
CellContent = NodeSet[i].innerText || NodeSet[i].textContent;
if (HTMLregexp.test(CellContent)) {NodeSet[i].innerHTML = CellContent;}
}
catch(err){}
i=i+1;
}
}

var regexpA = new RegExp("\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");

var WP = new Object;

function UpdateWP() {
if (calWP.length>0){
for (i=0;i<calWP.length;i++) {
WP=document.getElementById(calWP[i]);
if (WP.innerHTML.indexOf("&lt\;")>=0) {TextToHTML(WP.getElementsByTagName("a"),regexpA);}
}
}
if (listWP.length>0){
for (i=0;i<listWP.length;i++) {
WP=document.getElementById(listWP[i]);
if (WP.innerHTML.indexOf("&lt\;")>=0) {TextToHTML(WP.getElementsByTagName("td"),regexpTD);}
}
}
// Check every 200 ms, forever
setTimeout("UpdateWP()",200);
}
UpdateWP();

</script>

The beginning of the script is taken from part III.

Note that I have included a quick check – if the Web Part doesn’t contain any “<” character then there’s no need to run the full Text to HTML function.

The 200 ms interval is a trade off between refresh needs (we hope that the naked eye won’t even notice the HTML strings) and browser performance. For IE 6, you may have to increase this number.

Like the other articles in this series, consider this sample script as experimental and handle with care.

In the next episodes, we’ll try to be more subtle, and provide optimized routines to address specific situations.

This series assumes that you are familiar with the “HTML Calculated Column” .

Part I: fallback to SP 2007
Part II: edit in SharePoint Designer
Part III: deal with individual Web Parts

My current Text to HTML script, written for SharePoint 2007, works as follows:

  1. find all hyperlinks (A tags) on the page
  2. if a tag contains an HTML string, convert it to actual HTML
  3. find all cells (TD tags) on the page
  4. if a tag contains an HTML string, convert it to actual HTML

I played with some more efficient scripts, but my tests showed that there was so little to gain that it was not worth the trouble.

In SharePoint 2010, things are different: because of asynchronous updates on the page (details here), the script needs to run more often, and performance optimizations will have a significant impact. So I chose a different approach to reduce the size of the loops:

  1. identify all the Web Parts on the page
  2. sort them out, to separate calendar Web Parts from the others
  3. for the calendar Web Parts:
    1. find all hyperlinks (A tags) in the WP
    2. if a tag contains an HTML string, convert it to actual HTML
  4. for the other Web Parts:
    1. find all cells (TD tags) in the WP
    2. if a tag contains an HTML string, convert it to actual HTML
  5. rinse and repeat steps 3 and 4 as needed

The script:


<script type="text/javascript">

// Christophe Humbert - Path to SharePoint

// Find all Web Parts in the page
var listWP=[],calWP=[],divs=document.getElementById("MSO_ContentTable").getElementsByTagName("div");
var count=divs.length;
for (i=0;i<count;i++) {
try {
if (divs[i].id.indexOf("WebPartWPQ")==0){
if (divs[i].innerHTML.indexOf("ViewDefault_CalendarView")>=0) {
// Calendars
calWP.push(divs[i].id);
}
else {
// Other Web Parts
listWP.push(divs[i].id);
}
}
}
catch(e){}
}

// Apply Text to HTML as needed

</script>

The question now is how to “apply the Text to HTML script as needed”. I’ll provide some suggestions in the next episodes. We’ll see in particular that the behavior of calendar views is different from other Web Parts.

A note for the jQuery fans

In jQuery, getting all the Web Parts can be done with a single selector:
$(“#MSO_ContentTable div[id^='WebPartWPQ']“)
What you need to understand is that the above line, although shorter than its JavaScript equivalent, will take the same time to execute. So there is no benefit from using jQuery here.

I am considering adding two new options to the Easy Tabs: Full Screen and Print. This is the result of ongoing discussions with Kerri Abraham.

The “Full Screen” option is similar to the usual overlay/lightbox solutions. Only my solution is lighter, and doesn’t require an external library like jQuery for example. Check out the live demo and let me know what you think!

The Print – or Printer Friendly – option is very similar to the Full Screen one, with maybe a couple additions:
- print job automatically launched on click, to print the current tab or all tabs.
- page break after each Web Part.

Let me know if you find these options interesting, and what in your opinion should be the expected behavior.

Update [June 18, 2010]: the live demo now displays a “Printer Friendly” tab. When you click on it, the tab is replaced with a “Back to Page” tab. If you select print preview in your browser, you’ll see a page break before each printed Web Part.

When Kerri contacted me with a technical question about the Easy Tabs, a detail in the screenshot she sent immediately caught my attention: an original way to drive user adoption! I asked her to tell us more about her idea.

Author: Kerri Abraham, Revenue Cycle Sharepoint Coordinator, Mercy Medical Center.

I always worry that my end-user isn’t going to “get it”. I know my staff, they need to be compelled to change, they tend to be timid with new concepts. That stands to reason of course, but it was a concern when I was debating about using the Easy Tabs solution. How do I make sure that they not only see the information, but that they regularly click on the tabs to see the gems hidden underneath? I bait them.

Recently I had an administrative mandate that required a rebuild of my divisional front page, it was dreary anyway and needed it, but I still had other information to display and this new mandate threatened to take up all of the real estate. About the same time I came across Christophe’s Easy Tabs. Wow, what a solution! I was able to build my mandated Communication Board even bigger than I had originally intended and still had plenty of space to add in ‘extravagant’ web parts like a Table of Contents! This was great, but did my staff see the tabs? Would they click them to see the important ‘News’ announcements underneath? Then Mark Miller posted Create a Weather Magnet for a SharePoint Dashboard. The timing was perfect because I had just caught the end of a History channel show on meteorology that stated most of a TV station’s budget goes into weather reporting because they know it is the #1 draw. Now I had my bait.

I placed my extra-sized weather magnet, per Mark’s instructions, in the middle of the tabs, and sent the message out to staff that it was there, with the link and a “Be sure to test it out.”

It took only a few minutes for the accolades and thanks to pour in, more even than from the normal responders, I heard from people who never say anything! Wow, the weather works, and I can be sure that they are checking that area regularly, it’s human nature to click around on things nearby, so I’m sure they are catching the ‘News’ as well!

Okay, so if I use the weather as a draw at my top site, I need new bait for the lower level team sites. I had been sent a comic that was ‘office topic’ related. So when I redid the page to include the Easy Tabs, I added it in a Content Editor Web part as a ‘Humor Me’ tab just to get staff’s attention. But static comics don’t keep them coming back for more. So with a little inspiration from Christophe, through a correspondence we had over the meaning of that ‘Humor Me’ tab, (it even hooked Christophe) I bulked it up to include a Dilbert widget. Exactly the same premise as the weather magnet and just what was needed to keep them clicking!

The Easy Tabs makes the most of front page real estate without that pesky page refresh, without the slightest hint of bogging down performance, and it allows me to provide my end-users with some extras that would normally take up too much space in that prime real estate area. These are the kinds of solutions that drive my sky rocketing end-user adoption. It’s fun and its easy – Easy Tabs that is! Thanks Christophe for your contributions to the Sharepoint community, they really are so very much appreciated!

Proposed by Alexander Bautz, a client side charting solution for SharePoint that relies on the Google Visualization API.

To understand the difference between the Google Chart API and the Google Visualization API, check out this page:
http://code.google.com/apis/charttools/docs/choosing.html

This is a solution for creating charts directly from SharePoint lists using Google Visualization API. The solution is a CEWP-solution and requiring no other than a few script references. All code and data are processed and rendered in the browser. No data is sent to any server.[...] You can pull data from any existing list view (even from personal views – for personal use), or using a custom CAML-query … Read More

via SharePoint JavaScripts

Author: Larry Pfaff, Sr Systems Analyst, Convergys Corp.

Adding The Final Pieces

Can you see the finish line yet? As you remember in Part 1 we reviewed the requirements and expectations of the data. This output needed to be easy to read and use by all end users throughout the entire organization and most of the views returned the desired results.

One advantage of using these views was no additional scripts were required to display data in table format with one column. Once we had a direction, in Part 2, we discussed some of the obstacles and limitations we ran into and how we overcame them. Although we are very close to completion there are still some details to review and modifications to make. For this all to work we will be adding the final parts (scripts) into a Content Editor Web Parts (CEWP).

Create a view – one column
Begin creating a Standard view with the listed options. This should be fairly simple. If you need details for this you may go here.

  • Added one column, which contained all the data for the table layout.
    • Table – (table of data)

  • Select your Sort and Filter options. I set sort to Ascending by Process Total. This allowed the teams who were less compliant to show closer to the top of the view
  • No Group By
  • No Totals - none available
  • Style – tested in all views
  • Item limit – your choice, this one was set at 150

CSS

Add a CEWP above your list view. This will contain the classes and formatting of the table. Be specific in the class names otherwise the formatting would be transferred to other parts of the page.

There are several references available on the net to provide you with more details: HeatherSolomon.com is one of the most commonly used.

Once you have added your CEWP to your list view you can add the CSS below. Initially my styles were off, which cause some formatting conflicts. Thanks Christophe for the style update for the table borders mentioned in Part 1.

<style type="text/css">
table.myboxed, table.myboxed TD, table.myboxed TH {
				border: 1px solid black!important;
				border-collapse: collapse;
				font-size: 10pt;
}
.twidth {
				width: 100px;
}
.comp {
				color: green;
				font-weight: bold;
}
.nc {
				color: maroon;
				font-weight: bold;
}
.e {
				color: orange;
				font-weight: bold;
}
.label {
				font-weight: bold;
}
</style>

HTML Calculated Column

The key script to display the images, color and table layout can be downloaded here with instructions for installation.

Final product looks like this:

Final thoughts

As I sat down to complete this final part in this 3 part series “Case study: course compliance report” I found IE and FF definitely don’t play well together. I also found there are several things I would do differently. With all the pieces placed together the results are astounding, but this is only one of many ways that scripts, intuitiveness and desire can produce outstanding results.

One of the changes I thought about making was to the progress bar. Currently I am in the process of showing both Complete and Exempt on the same bar as one continuous bar like this.

54% 8%

In theory this works. I can replicate it in a regular html table with div tags, but when implemented into a CC I lose either the color or the percent for the % Exempt. Will keep you posted on the progress, but for now I will continue to hack away until I figure it out.

Since the beginning of this article I was inspired to start my own blog at http://sharepointhacker.wordpress.com. Although this blog may never have any new intermediate scripts it will have scripts implemented in real world scenarios, which I feel will provide beneficial learning. For a long time I always considered myself just a hacker, never wrote any original scripts, so I thought. I would always find someone else’s code and tweak it to fit my needs until one day a blogger said to me:

“More than the script we come up with, what is important is the innovative way in which we approach a real world issue”.

Christophe

Thanks again Christophe for your support.

A question I received from Liz:

“I just downloaded your EasyTabs webpart and think it works great.  My question is: how does it work when you have different permissions on different webparts?  Is it security trimmed?”

Good question, and you definitely need to be clear about security implications when you start adding code to your Web pages.

What I explain in the online workshops is that customizations like the Easy Tabs (and most of my other scripts) simply add a presentation layer on top of existing SharePoint pages. As such:
- all the underlying SharePoint functionalities are maintained (in particular security and audience).
- the customization is non-destructive; if you decide to remove it later, you’ll be back to your initial SharePoint page.
- this approach follows a standard Web design pattern known as “progressive enhancement”. If for some reason the script cannot run in the browser, the user can still access the page content.

SocialVibe


Categories

I’m on Twitter!

Follow

Get every new post delivered to your Inbox.

Join 182 other followers