Category Archives: Techniques

Truncating Text in your Interface

If you’re going to offer your content on multiple-sized screens, at some stage you have to accept you’ve run out of space. Then content, particularly headings may need to be truncated.

If you do, try not to be like these guys:

Americas Cup Truncation

Good luck picking which of the finals you want to replay.

And the fix? How about flipping the title to show the important information first.

Determining native size of a SWF (and code to embed it in SharePoint)

Currently working on a Sharepoint reference site that collates a number of Captivate demonstrations. To make the site look presentable it’s necessary to preset the size of each Captivate demo. But how do you know what the native size is so you can determine the appropriate aspect ratio?

Here’s my way.

(1) Download SWFTools

This is a collection of useful little programs for creating and manipulating SWFs. For our purposes the one we want to use is SWFDUMP (read the doco here)

Download Link.

These executables are (on Windows) installed by default in a folder under C:Program Files. To be able to use open a CMD window and navigate to the new folder.

(2) Run SWFDUMP

Once downloaded run the following command to get the required default info.

SWFDUMP -e "path to your SWF"

Easiest way to do the above is type the first part of the command in a CMD window, and when you get to enter the SWF details just drag your SWF file into the window. It will automatically determine the full pathname and add it to your command.

What this generates is the standard HTML embed code, which includes the all important sizes. For example here’s the output when run on my Windows XP work machine.

<OBJECT CLASSID="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
 WIDTH="1153"
 HEIGHT="895"
 CODEBASE="http://active.macromedia.com/flash5/cabs/swflash.cab#version=10,0,0,0">
  <PARAM NAME="MOVIE" VALUE="pathtoCreateProposal.swf">
  <PARAM NAME="PLAY" VALUE="true">
  <PARAM NAME="LOOP" VALUE="true">
  <PARAM NAME="QUALITY" VALUE="high">
  <PARAM NAME="ALLOWSCRIPTACCESS" VALUE="always">
<EMBED SRC="pathtoCreateProposal.swf" WIDTH="1153" HEIGHT="895"
   PLAY="true" ALIGN="" LOOP="true" QUALITY="high"
   TYPE="application/x-shockwave-flash"
   ALLOWSCRIPTACCESS="always"
   PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer">
  </EMBED>
</OBJECT>

Note: You can cut to the chase and retrieve just the size info with the following commands.

SWFDUMP -X "path to your SWF"
SWFDUMP -Y "path to your SWF"

But that’s more typing.

A more useful suggestion if wanting to use this HTML code, save it to a text file to make it easier to cut&paste:

SWFDUMP -e "path to your SWF" > code.txt

(3) Adjust the native sizes to fit the required space

For me all the demonstrations need to be presented at a fixed 650px width. So I need to calculate the required height that keeps the same aspect ratio as the native SWF but at 650px wide.

Simple bit of maths to determine:

RequiredX = 650
RequiredY = CurrentY * (RequiredX/CurrentX)

So for the above example:

RequiredX = 650
RequiredY = 895 * (650/1153) = 505 (with a bit of rounding)

Sorted.

Customising Sharepoint 2007 lists with jQuery

This article explains how you can use jQuery with Sharepoint 2007 to customise how your lists appear on your site. With jQuery we will:

  • highlight specific columns or rows based on values
  • change the default “no records” message, and
  • change the default “add item” message.

Although it’s not envisaged you’ll need to do all three in every list you deliver!

Getting started

To get started first add the required list to your page.  Use the standard list webpart and customise as best you can within the webpart itself:

  • set which columns to present
  • set the order to display the columns
  • set the default appearance (or not) of the toolbar

We’ll use jQuery to interrogate that default view and customise as required.

Once the list is ready, next is to add jQuery to the page. Add a Content Editor webpart, use the Source Editor and add the required link:

<script src="/path/to/jquery-1.9.1.min.js"></script>

We always upload a local copy to our server (because a lot of our internal audience do not have internet access), but you could just link to jQuery on the interwebs.  This article provides the link and an explanation of when/why to use this approach.

Highlight specific columns or rows

This is easy to achieve using the jQuery Filter() function.  We’ll simply search for matching items and then add styling to highlight them.

First step is to update your view so that the value you want to highlight/select is included in the data displayed. jQuery can only work on it if it appears on the page. Ans since list data appears in a table, it will then be searchable within a <td> cell:

<script>
$("td").filter(function() { 
    return $(this).text() == 'Value to Match'; 
    })
    .css("color", "red");
</script>

Alternatively/preferably, when you match your required value apply a defined style (in a separate stylesheet) to it rather than manually making style changes:

<style>
  .highlighted {
       background-color: #ccc;
       color : red;
  }
</style>

...............

<script>
$("td").filter(function() { 
    return $(this).text() == 'Value to Match'; 
    })
    .addClass("highlighted");
</script>

But what if you want to highlight the entire row that matches the selected value, not just the value itself? With jQuery that’s simple, using the .closest() function:

<script>
$("td").filter(function() { 
    return $(this).text() == 'Value to Match'; 
    })
    .closest ("tr")
    .addClass("highlighted");
</script>

Since you’ll need to add a content editor webpart to include the required highlight script, consider adding visible text to that webpart that explains to the user what the highlighting represents.

The result:
highlight-beforeBefore (active and inactive records not differentiated)

highlight-afterAfter (inactive records highlighted with explanation below list)

Change the default Add Item message

Now let’s clean up the standard list option of “Add Item” that presents when you use the summary toolbar:

link-before 

The standard message is a bit vague.  To change it we’ll use the Filter() to search for the “Add Item” anchor text and change to something smarter:

<script>
$("a").filter (function() {
    return $(this).text() == 'Add new item';
    })
    .text("Add yourself to our database");
</script>

The result:

link-after

Change the default “No records” message

The issue with the standard “No records” message is not only is it not very friendly, it also expects you to have the full toolbar visible.

empty-list-before

Notice how the instructions talks of the ‘New’ button above, but that is only available if using the Full Toolbar. Something we rarely do since it adds a heap of confusing features for settings, etc.

To fix we can use the same approach as for the add item link: search for the standard text and replace with something more appropriate. To do so you can use the filter() function as above.

Problem here is the standard text is quite long (and will change if the list name changes). So a better solution would let us just match a key snippet of the standard text (eg “no items to show”) and let us then update the full text. The jQuery selector to match partial text is :contains() but this will surprise you in its result:

<script>
   $("td:contains('no items to show')")
      .css("background-color", "red");
</script>

Issue is :contains() will match not just the TD we’re after, but every TD that contains that TD. Since Sharepoint 2007 goes to town with tables, that’s a lot of TDs changing colour.

Getting around this issue is not simple (as this Stack Overflow question explains). However logically we know the TD we’re after is at the bottom of the tree (ie no child nodes other than text) so let’s use that to filter our matches. Again, Stack Overflow can help: http://stackoverflow.com/questions/743957/how-to-get-elements-which-have-no-children-but-may-have-text. Leading us to the following solution:

<script>
$("td:not(:has(*)):contains('no items to show')")
   .text("No items to show");
</script>

The result:

empty-list-after

Conclusion

This article shows some simple jQuery technicques to improve the appearance of lists in Sharepoint 2007. No promises are made that these are the most efficient methods, but they work. Show us the improved methods in the comments.

Centering an image in IOS

Just been struggling to update flagSter to support the new iPhone5 screen. Issue was horizontally centering the flag image when in landscape mode. This was because the screen width varies between iPhone and iPhone5 when in that orientation.

Quickest/easiest method was discovered, wherelse, in Stack Overflow. Thanks Damo.

CGPoint center = myImage.center;
center.x = self.view.center.x;
myImage.center = center;

Best part of this solution, other than its simplicity, is it is not that difficult to determine how you could possible sort out the vertical orientation too!

Retrieving user details from Sharepoint 2007 using Javascript

As part of our Tin Can test implementation we needed a way to identify the current Sharepoint user via Javascript. This is so we could pass that user’s credentials as part of the Tin Can message.

We could have hand-coded some solution (probably) but why bother when you can stand on the shoulders of giants. In this case the giant we leant on was Marc Anderson and his fantastic SPServices library.

Getting Started

SPServices provides a way to interact with Sharepoint via JQuery. This means before you can use you need to add both the JQuery and SPServices libraries to your page.

If you don’t have high enough access to add these libraries at some default/server level then you need to manually add directly to each page that needs them. This is easy to do via script reference in a Content Editor webpart. You can either reference the libraries online or download copies and store locally in a sharepoint library. We always download and save within our site (usually in a dedicated /scripts document library) so the code will be fully operable even for staff without internet access.

To reference your libraries just add a Content Editor Webpart, edit the source and add the Javascript references:

<script src="path/to/jquery-1.9.1.min.js"></script>
<script src="path/to/SPServices-0.7.2.min.js"></script>

Refer to the SPServices documentation for some constraints over which versions of each library play well together. We had no issues with downloading the current of each.

Retrieving user details

Once the libraries are installed, the command needed to retrieve user details is SPGetCurrentUser. For a detailed description refer to the documentation, as this lists all the values that are obtainable and the code to use.

Essentially the method allows you to retrieve any details that appear on your user profile page. For example: the profile field labelled “Account” can be accessed as the Name user property. Just add as a Content Editor webpart and insert the following via the Edit Source button:

var thisUserAccount = $().SPServices.SPGetCurrentUser({
		 fieldName: "Name",
		 debug: false
});
document.write ("<p>You are logged in as " + thisUserAccount + "</p>");

Refer to the documentation to see how to retrieve all other information, including email address, name, etc.

Retrieving multiple details for the same user

Often you’ll want a few details for your user. You can either add a series of individual calls, or make one call passing the list of values you need as an array. For example, here’s how to obtain the account, name and email address in one go:

var currentUserDetails = $().SPServices.SPGetCurrentUser({
	fieldNames: ["Name", "Title", "EMail"],
	debug: false
});
document.write ("<ul>");
document.write ("<li>Account = " + currentUserDetails['Name'] + "</li>");
document.write ("<li>Name = " + currentUserDetails['Title'] + "</li>");
document.write ("<li>Email = " + currentUserDetails['EMail'] + "</li>");
document.write ("</ul>");

Here’s one I prepared earlier

As a quick start, download the following ZIP file, extract the webpart (.DWP) and import on your page.

SPServices

As long as you’ve an internet connection you should then see your user name, login and email address presented automagically.

Internet access is required because this webpart relies on accessing online instances of the two libraries. Full code is as follows.

<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/
  0.7.2/jquery.SPServices-0.7.2.min.js"></script>

<div style="font-size:larger; margin-top:10px">
Retrieving details of the current user (i.e. you):
<ul>

<script>
var currentUserDetails = $().SPServices.SPGetCurrentUser({
	fieldNames: ["Name", "Title", "EMail"],
	debug: false
});
document.write ("<li>Account = " + currentUserDetails['Name'] + "</li>");
document.write ("<li>Name = " + currentUserDetails['Title'] + "</li>");
document.write ("<li>Email = " + currentUserDetails['EMail'] + "</li>");
</script>

</ul>
</div>

Conclusion

And that’s all there is to it. With just a couple of lines of code (and import of two major libraries!) you can easily obtain all the pertinent user information ready for whatever further processing is required.

Sharepoint 2007 Custom Lists – Losing the Title Field

Every now and then you need to use a custom list as the basis for development.  When created, however, you always get given a Title text field amongst other things:

TitleField

But what if you don’t want that field? For example because the required data in your list does not include a text “Title”.  What can you do?

Grade 1 – Make it optional

First option is to downgrade the field itself so its optional.  By default its mandatory.

Also while editing the properties you can consider adding a description that makes clear how unimportant the field is to you.

TitleProperties

However, while this will make you feel better, it does not really change the availability of this field for viewing or updating. 

Time for grade 2.

Grade 2 – Remove from View

To make this field disappear modify the view(s) being used to display items and remove the Title field from that view.

Untick the checkbox next to Title and visitors will not see the value ever again.

editView

Looks good, but two problems with stopping at this stage:

(1) Cannot edit item in default view

In the default view, the Edit option for an item is linked to the Title field.  Hide this field and you hide the ability to edit an existing record.

This is easily resolved by displaying the Edit item in the view as a replacement. I usually set it to be the first column.

SNAG-0014

(2) Still see field when adding/updating an item

Trickier to resolve is the problem that the Title field will still display when adding or modifying items in your list:

badForm

If you’re the only one making updates then that might be acceptable (particularly if you added a poignant description like above).  But if editing is open to a wider group then preferable to get this field out completely.

On to grade 3.

Grade 3 – Hide field via Content Type

While we cannot delete the Title field, the next best thing is to hide it in the form.  To do so you need to enable and then modify the default content type for the list.

  1. On the list choose Settings > List Settings
  2. Select Advanced Settings
  3. In those settings, select to allow management of content types

    contentTypes

    Bonus: while in there, also check some of the other fields to correctly configure your list.  For example I invariably disable the “enable attachments” option as rarely do I want to let uses add files.

  4. Save changes.
  5. Back in list settings, select the newly displayed Item content type.

    list content types

  6. Click on the Title column in the column list.

    titleContentType

  7. Set to Hidden.

    hidden

  8. Save your changes.
  9. Now when you launch the form to add/update the unwanted Title field is gone.

    correctForm

    Notice in this form I also took the option to disable attachments.  So compared to the previous form the Attachments option has disappeared also.

    Conclusion

    Note we are still unable to delete this field.  But by editing the view and the content type you can hide it from all visitors.  Which will have to be close enough.

    Note there is a school of thought that says after making these changes you should disable the content type management.  Can see the logic of locking it up again but never been worried about other sneaky edits so I tend to leave it as is.

Sharepoint 2007, jQuery and Expand/Collapse Sections

One of the first uses for jQuery is to add some polish to your interface. For one Sharepoint 2007 project we wanted to add an FAQ (frequently asked questions). Preferred design was to simply list all the questions, and allow the user to click on any question to display the answer. This way the user could quickly scan all the available questions and only get the details for the questions they’re interested in.

The following documents our path to the final solution.

Stage One: Basic Expand/Collapse

There are plenty of resources online to help with this one. Our first version was a combination of this one:

http://designgala.com/how-to-expand-collapse-toggle-div-layer-using-jquery/

And this one:

http://api.jquery.com/hover/

This provides the required expand/collapse, with the question behaving like a link to encourage users to click on it.

Paste the following into a content editor webpart (source editor mode) and all is well:

<script type="text/javascript" src="/path/to/jquery-1.9.1.min.js"></script>
<script type="text/javascript">

$(document).ready(function() {
    $(".answer").hide();
    $(".question").hover (
        function () {
            $(this).css("text-decoration", "underline");
        },
        function () {
            $(this).css("text-decoration", "none");
        }
    );


    $(".question").click(
	function() {
            $(this).next(".answer").slideToggle(500);
    });
});

</script>

<style>
.faq {
  width:600px;
}
.question {
  color : #003399;
  cursor : pointer;  
}
.answer {
  margin-left: 12px;
  padding: 6px;
  background-color: #ddd;
}
</style>

<div class="faq">
<p class="question">Question1</p>
<p class="answer">Answer 1.</p>
<p class="question">Question2</p>
<p class="answer">Answer 2.</p>
<p class="question">Question3</p>
<p class="answer">Answer 3.</p>
<p class="question">Question4</p>
<p class="answer">Answer 4.</p>
</div>

If already managing a site level stylesheet, add these style references to it rather than defining in this one location.

Similarly if already using jQuery elsewhere, consider downloading to your site and referencing the local link. Very handy particularly if not all your users have internet access.

Stage Two: IE6 Flicker

A bonus level for us lucky few still supporting IE6. The toggle function has a crazy flicker event with IE6 when hiding the answer. Over to Stack Overflow for a solution: add overflow:hidden to the element being shown and hidden.

And so the other browsers don’t feel left out, we also added rounded corners to the answer background box:

.answer {
	margin-left: 12px;
	padding: 6px;
	background-color: #ddd;
	overflow:hidden;
	display:none;
	border-radius: 12px;
}

Stage the Third: Add expand/collapse icons

So this gives us expanding and collapsing sections accessed as a series of links. For the next enhancement we wanted to add expand/collapse icons with each link.

First we need to add the default “expand” icon. Quickest method is as background image for the answer style:

.question {
	color : #003399;
	cursor : pointer;
	padding-left : 20px;
	background-image: url('/path/to/expand.png');
	background-repeat: no-repeat;
}

Simply adjust the left padding to provide the necessary space for your image to appear without overwriting your text.

Then to swap the image when expanded, add the CSS code change call to the jQuery click event:

$(".faq .question").click(
	function() {
        	$(this).next(".answer").slideToggle(500);
            	$(this).css("background-image", "url(/path/to/collapse.png)");
    	});

Put it all together and now works beautifully when you click on a section to expand it. But now the problem is the image does not switch back when you collapse it. From that point on the icon remains as “collapse”.

So what this now needs is a way to know the current visibility status for each element as clicked. And the entire point of the slideToggle method is you don’t track the status; it does it for you. Once we start needing to track status time to ditch slideToggle and go to the fundamental show and hide methods.

$(".question").click(
  function() {
    if ($(this).next(".answer").is(":visible")) {
      //currently visible, so hide it
      $(this).next(".answer").hide(500);
      $(this).css("background-image", "url(/path/to/expand.png)");
    } else {
      //currently not visible, so show it	
      $(this).next(".answer").show(500);
      $(this).css("background-image", "url(/path/to/collapse.png)");
    }
  });

So now we have each question expanding/collapsing when clicked, and the intro icon updating accordingly. Perfect.

expandCollapse

As a bonus the show/hide functions do not appear to have the same flicker issue in IE6 as slideToggle() does. No idea why….

Stage the Last: hide other sections when expanding one

As a final step, one possible enhancement is to make the list automatically close an open question when opening another.

However will leave that as an exercise for the reader, because we didn’t get that far..

Editing a Webpart with Embedded Video (Sharepoint 2007)

If you’ve embedded video in your Sharepoint page, especially using the roll-your-own approach I use, you’ll have come across a problem when trying to edit.

Issue is the embedded video lives in its own world, and covers up attempts to access the modify webpart menu:

editVideoFail

In the above image the black box is the video, and it appears as a layer that sits over the top of everything else on the page. Specifically, if you want to modify the webpart, good luck guessing where that menu option lives because the menu remains hidden behind the video window.

Thankfully there is a simple workaround. Minimize the webpart. Since that’s the only menu item still visible, you can click it without issue.

editVideo-Mini

And then once the video has been minimised the full edit menu is available to you.

editVideoModify

Afer you’ve completed your editing magic, simply Restore the webpart to put the video back into view.

editVideoRestore

Alternatively…

editVideo-Menu If all the above is too hard (really?) there’s another option IF you are using the publishing toolbar.

Just choose Modify from the Page menu in that toolbar. But note this is only viable if you’ve bothered to name your webparts uniquely.

Removing columns from SQLite Databases

For a while I’d been annoyed that my SQLite database for Flagster contained a few dead-end columns. Since SQLite does not allow you to drop columns, I was resigned to having them gathering dust, and space.

However searching for unrelated help, came across a neat trick for removing columns. Although it takes three stages.

This was all tested/completed using Base, arguably the best SQLite editor on the Mac. Make sure you take a backup before starting though, just in case.

(1) duplicate table (without the unwanted columns) as a new table in your database

To create a new table from an old one, use a combination of CREATE and SELECT commands:

CREATE TABLE newTable AS
  SELECT col1, col2, col3, col4 FROM oldTable;

Just only list the columns you want in the SELECT statement, and list them in the order you want them in the table. For bonus points you can also sort the records as they’re written to the table.

CREATE TABLE newTable AS
  SELECT col1, col2, col3, col4 FROM oldTable
  SORT BY col2;

(2) drop the old table (with the unwanted columns)

Once confident your newTable has all the data you need, you can remove the old one. This is simple using the DROP command:

DROP TABLE oldTable;

(3) rename the new table with the old name

Finally, to tidy up and save updating any existing code, rename the new table to match the old table name:

ALTER TABLE newTable
  RENAME TO oldTable;

And that’s it. Three steps later you’ve cleaned up your database, sorted your records, and made everything right in the world.

OSX Terminal Does Image Editing. Who Knew?

Wonders never cease.

Thanks to Cory at maclife, just discovered that OSX Terminal has a built in image resizing tool, SIPS.

You can read the official manual entry for SIPS to see the full power. But here’s some simple examples that I was using an image resizing tool for.

(1) resize all JPGs in current folder to fit in a box 800×800

 sips *.jpg -Z 800 

This will automatically find the largest dimension (width or height), resize that to be 800 and adjust the other to keep the same aspect ratio. Noice.

(2) resize all PNGs in current folder to 100 wide (keep aspect ratio)

 sips *.png --resampleWidth 100 

You can guess what the command is to set the height instead of width.

Works really well, and really fast. But beware of a couple of limitations.

  • edits the original file directly. If worried take copies beforehand.
  • doesn’t support changing the filename. If needed you’ll need to do that step separately before/after.