jqGrid Text/Word Wrapping

On December 3, 2009, in Web Design, by shereen

Just a quick post for anyone else having this issue. I am working with the latest version of jqGrid, and I am dealing with cell data that is longer than the width of the cell making it difficult to see. I wanted to have this data wrap and the height of the cell adjust to fit the wrapped content.

I found a ton of useful info on the jqGrid forums but it didn’t quite get me there.

The forum article in the above link suggests that you add the follwing CSS to your page:

1
2
3
.ui-jqgrid tr.jqgrow td {
    white-space: normal !important;
}

The above worked great for FF, but in IE, it would wrap the content, but the cell height would not auto adjust and therefore you really couldn’t see the full content. So I made a couple more changes as per the code snippet below and this seemed to work for me.

So the height:auto forces the cell height to auto adjust based on the size of the wrapped content. I haven’t noticed any side effects of changing this. If anyone has I’d love to hear about it. The vertical-align:top ensures that the text positions at the top so that the cells with less content don’t disappear in the centre due to the larger cell blocks. And finally, I added a bit of padding so that my cells don’t look oddly aligned due to the vertical-align bit, but that’s optional. It’ll work without it.

1
2
3
4
5
6
.ui-jqgrid tr.jqgrow td {
    white-space: normal !important;
    height:auto;
    vertical-align:text-top;
    padding-top:2px;
}

If anyone else has run into this issue or has had to make a similar change, add your contribution to the comments below.

Tagged with:  

I’ve been doing a lot of work recently with Telerik’s RadGrid configuration client side. This includes data binding, sorting, paging and working with columns and data rows. I’ll likely be doing a series on some of the issues I’ve encountered trying to work with these grids completely client side. The first of this series is a relatively simple thing to do server side, but I definitely had issue with it client side.

Scenario:

I have a RadGrid called rgProjects configured with several GridBoundColumn fields and a single GridHyperLinkColumn field. The data binding for this grid is being done via an ajax call to a method in another page that returns some json that I then bind to the grid. I’m leveraging the OnRowDataBound client event of this grid to perform some custom row manipulation. I figured this would be a good place to set up my HyperLink.

Step 1 - Add the GridHyperLinkColumn to the grid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<telerik:RadGrid ID="rgProjects" EnableViewState="false" runat="server"
            GridLines="None" AutoGenerateColumns="False" AllowSorting="true" Width="100%">
            <MasterTableView TableLayout="Fixed"> 
                <Columns>
                    <telerik:GridNumericColumn DataField="ID" HeaderText="ID" />
                    <telerik:GridNumericColumn DataField="Title" HeaderText="Title" Display="false" />
                    <telerik:GridHyperLinkColumn DataTextField="Project" DataNavigateUrlFields="Project"
                        UniqueName="Project" HeaderText="Project" ItemStyle-Font-Underline="true" />
                </Columns>
            </MasterTableView>
            <ClientSettings>
                <ClientEvents OnRowDataBound="rgProjects_OnRowDataBound" />
            </ClientSettings>
</telerik:RadGrid>

The JSON that’s being returned:

[{"ID":"1204","Title":"shereen's test project","Project":"http://server.local/_layouts/Demo/editform.aspx?ID=1204"}]

So the basic idea was, I wanted my hyperlink to have it’s value set to: “shereen’s test project” and I wanted the url to be set to: http://server.local/_layouts/Demo/editform.aspx?ID=1204.

Do not confuse TITLE with VALUE. By TITLE, I mean the actual TITLE attribute of the A tag that’s used for a tooltip and by VALUE I mean the innerHTML that’s set and is actually visible to the user as the hyperlink itself.

So it would read as follows:

shereen’s test project

This was not working for me initially because both the hyperlink’s value and url were being set as the url, which is not what I wanted:

http://server.local/_layouts/Demo/editform.aspx?ID=1204

In comes the OnRowDataBound event where I can override what’s happening above with what it is I actually want:

Step 2 - Leverage the OnRowDataBound client event to configure our HyperLink

1
2
3
4
5
6
7
8
9
10
function rgProjects_OnRowDataBound(sender, args)
{    
    // manually set the hyperlink's title
    var item = args.get_item();
    var dataItem = args.get_dataItem();
    var link = item.get_cell("Project").getElementsByTagName("a")[0];    
    link.innerHTML = dataItem.Title;
    link.href = dataItem.Project;
    link.title = dataItem.Title;
}

So the key thing to note above is you have to set the innerHTML. Title is optional, but the important ones are href and innerHTML. Any problems let me know!

 

jQuery – Get All Divs Whose ID Starts With

On November 12, 2009, in Web Design, by shereen

Structure:

1
2
3
4
<div id="thisismydiv1"></div>
<div id="thisismydiv2"></div>
<div id="thisismydiv3"></div>
<div id="thisismydiv4"></div>

To return an array of all divs that start with ‘thisismydiv’, you would use the following:

1
var divList = $("div[id^='thisismydiv']");

The above translates to, find me all divs whose id starts with ‘thisismydiv’. You could now do something cool like add a class to all those divs:

1
$("div[id^='thisismydiv']").addClass('myClass');
Tagged with:  

Just a quick thing to note, if you’re trying to write to the event log within your custom SharePoint solutions and run across this error:

Cannot open log for source {0}. You may not have write access.

This is definitely permissions related. A quick bit of searching and I found some useful info:

The CustomSD registry value for the Application event log is found under the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Applicationregistry key.  It is a string value which uses Security Descriptor Definition Language (SDDL) to describe which accounts have access to which functions (e.g. read, write, clear) of the event log.  By default the application event log will allow any IIS 6 application pool identity write access (either as a service logon or, in the case of custom accounts in the IIS_WPG group, as a batch logon). (reference: http://forums.asp.net/t/1131903.aspx)

So the key in the above paragraph is that the app pool identity already has permission to write to the event log, so instead of mucking around with permissions, I made sure my function for writing to the eventlog is elevated as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void LogMessage(string message)
{
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        if (!EventLog.SourceExists("SharePoint Custom Solutions"))
        {
            EventLog.CreateEventSource("SharePoint Custom Solutions", "Application");
        }
 
        EventLog.WriteEntry("SharePoint Custom Solutions",
                                    message,
                                    EventLogEntryType.Error);
    });
}
 

Ok, so this is really a follow up to my previous post where I outlined how to build jQuery Tabs that Open and Close. I did end that post with a small TODO for myself: integrate the close capability into the tab itself so the user didn’t have to click a button to close that tab.

Now after doing a bit of digging, I learned that this is actually functionality that is in the works for future releases of jQuery UI. Ticket 3924 is currently open and in development, which is a good sign. Further investigation landed me on this page: http://jsbin.com/uqage which is a fantastic example of how the Closable Tabs concept could work.

My final solution involved me tweaking the above to work as follows:

Setting Up the HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="mytabs"> 
   <ul>
      <li><a href="#tabs-home">My Projects Home</a></li>
   </ul>
   <div id="tabs-home">
      <h3>Welcome to My Projects Home</h3>
      <p><a href="#" onclick="addTab('myActiveProjects', 'My Active Projects', 'RadGrid1')">My Active Projects</a></p>
      <p><a href="#" onclick="addTab('mySalesActivities', 'My Sales Activities', 'RadGrid2')">My Sales Activities</a></p>
   </div>
</div>
<div id="tabs-myActiveProjects" style="display:none;">
<h3>My Active Projects</h3>
 
</div>
<div id="tabs-mySalesActivities" style="display:none;">
<h3>My Sales Activities</h3>
 
</div>

Wiring Up the Javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$(document).ready(init);
 
function init() {
 
    // tabs init with a custom tab template and an "add" callback filling in the content
    var $tabs = $("#mytabs").tabs({
        tabTemplate: '<li><a href="#{href}">#{label}</a> <span class="ui-test"><img src="images/cross.png" /></span></li>'
    });
 
    // close icon: removing the tab on click
    // note: closable tabs gonna be an option in the future - see http://dev.jqueryui.com/ticket/3924
    $('#mytabs span.ui-test').live('click', function() {
        var index = $('li',$tabs).index($(this).parent());
        $('#mytabs span.ui-test').parent().remove();
        $("#mytabs").tabs('select', 0);
    });
}
 
function addTab(tabID, tabName, grid) 
{
    // double check to see if tab is already open
    if($("a[href^=#tabs-"+ tabID +"]").length > 0)
    {
        $("a[href^=#tabs-"+ tabID +"]").parent().show();
    } else {
        currentTabID = tabID;
 
        // this will add a tab via the standard method
        $("#mytabs").tabs("add","#tabs-" + tabID,tabName);
        $("#tabs-" + tabID).css("display","block");
    }
 
    $("#mytabs").tabs('select', tabID);
}

Finalizing the Styles

1
2
3
4
5
6
7
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="jquery-ui-1.7.2.custom.min.js"></script>
<link type="text/css" href="styles/smoothness/jquery-ui-1.7.2.custom.css" rel="stylesheet" />
<style type="text/css">
    #mytabs { margin-top: 1em; }
    #mytabs li .ui-test { float: left; margin: 0.5em 0.4em 0 0; cursor: pointer; }
</style>

Please, please leave a comment if you have any difficulty with this and I’ll do my best to help!

Tagged with:  

Building jQuery Tabs That Open & Close

On October 27, 2009, in ASP.NET, SharePoint 2007, by shereen

jQuery is obviously a really powerful tool. If you’ve done any work with it, you don’t need convincing. My latest project involving jQuery was a bit tricky because I couldn’t find anything that detailed how to generate a tab once a user clicked on a link, and then how to close that tab if the user clicked the close button. Here is my setup:

  1. I needed to create a page with some static links, that when clicked on would spawn a new tab.
  2. The content area for each tab would contain a Close button that would remove the tab and hide the div contents. I didn’t want the div contents removed because I wanted users to be able to open the tabs again if they wanted to.

NOTE: I did attempt to dynamically generate the div contents by using a jQuery append statement on the content divs, but I ran into issues with this when placing a Telerik RadGrid onto the page and had to abandon that approach.

Building the above with the jQuery UI Tabs library took me part of the way there. In the end, my solution looks as follows:

Building the UI Tabs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="mytabs"> 
   <ul>
      <li><a href="#tabs-home">My Projects Home</a></li>
   </ul>
   <div id="tabs-home">
      <h3>Welcome to My Projects Home</h3>
      <p><a href="#" onclick="showTab('myActiveProjects', 'My Active Projects')">My Active Projects</a></p>
      <p><a href="#" onclick="showTab('mySalesActivities', 'My Sales Activities')">My Sales Activities</a></p>
   </div>
</div>
<div id="tabs-myActiveProjects" style="display:none;">
    <h3>My Active Projects</h3>
    <p><input type="button" name="killTab" value="Close" onclick="hideTab('myActiveProjects')" /></p>
</div>
<div id="tabs-mySalesActivities" style="display:none;">
    <h3>My Sales Activities</h3>
    <p><input type="button" name="killTab" value="Close" onclick="hideTab('mySalesActivities')" /></p>
</div>

Wiring Up The Javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function init()
{
    $("#mytabs").tabs();
}
 
function showTab(tabID, tabName)
{
    currentTabID = tabID;
 
    // this will add a tab via the standard method
    $("#mytabs").tabs("add","#tabs-" + tabID, tabName);
    $("#tabs-" + tabID).css("display","block");
 
    $("#mytabs").tabs('select', tabID);
}
 
function hideTab(tabID) 
{
    $("#tabs-" + tabID).css("display","none");
    $("a[href^=#tabs-"+ tabID +"]").parent().remove();
    $("#mytabs").tabs('select', 0);
}
 
$(document).ready(init);

Don’t forget to include the jQuery UI JS file and the corresponding CSS. You’ll also need to include the jQuery JS file as well. If you have any troubles with this, drop me a note.

1
2
3
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="jquery-ui-1.7.2.custom.min.js"></script>
<link type="text/css" href="styles/smoothness/jquery-ui-1.7.2.custom.css" rel="stylesheet" />

My next step with the above is to relocate the Close button so that it is an ‘X’ image on the tab itself that when clicked on would close the tab. I’ll update once I figure that out! Good times!

Tagged with:  

SharePoint 2010 Keynote Overview

On October 19, 2009, in SharePoint 2007, by shereen

Hi all, I wanted to put together a summary of some of the things I felt were worthy of noting at this mornings SharePoint Conference 2009 Keynote. Not all of these may be 100% accurate, I did my best to jot things down as they were thrown out there. Any questions or comments, feel free to ping me.

General

  1. No more hand coding web parts, Visual Studio 2010 now has a visual interface for developing web parts
  2. SharePoint navigation is integrated into Visual Studio, so you don’t have to leave VS to browse the contents of your SharePoint site
  3. You can now map folders in Visual Studio to SharePoint so when you deploy, for example, a image library, the files on the file system are transferred into SharePoint for you
  4. One click deploy and debug, it’s no longer a ’10′ click process
  5. New Developer Dashboard that loads on the page so you can debug your solution and review performance factors — You have to run an stsadm command to enable the dashboard, otherwise you won’t see it
  6. Line of Business systems are greatly improved and the connectivity is a lot easier to implement
  7. Built in spell check for draft items
  8. SharePoint Designer 2010 and Visual Studio 2010 will NOT work with SharePoint 2007
  9. 1,000,000 items to a list or folder, the 2,000 item limit is dead
  10. New Technologies: Microsoft PowerPivot for Excel and PowerPivot for SharePoint
  11. New Ribbon interface is context sensitive
  12. Changes, such as page edits, preview live as you make them
  13. NO MORE PAGE REFRESHES!!
  14. Document Sets is a new concept that is being introduced
  15. All Office desktop apps now have a web version. SharePoint item context menu has a new link called View In Browser that opens files in the web version of desktop app
  16. 2010 is 64 bit only, it will not support anything else

New SharePoint Terminology

  1. SharePoint Foundation – replacement for WSS 4.0
  2. SharePoint Server
  3. FAST SharePoint Search
  4. SharePoint for Internet Sites, Standard Edition
  5. SharePoint for Internet Sites, Enterprise Edition
  6. SharePoint ’12′ hive is now ’14′ hive, but referred to as SharePoint Root

Great first day, looking forward to tomorrow! I spent an hour or so working with the hands on labs and I have to say this new version is pretty darn exciting!

 

Live Blogger Stream SharePoint Conf 2009

On October 16, 2009, in SharePoint 2007, by shereen

Hey everyone! I’ll be headed down to SharePoint Conf on Sunday, very excited to finally get my feet wet with SP 2010. I’ll be contributing to the live blogger stream that Mark Miller has setup over at EndUserSharePoint.com so keep an eye out for content being posted there. The keynote sessions will also be broadcast live, so for those not able to attend this year, that’ll be something to check out.

Live Blogger Stream from SharePoint Conf 2009 – I’ll be a contributor!

Live Twitter Stream from SharePoint Conf 2009

 

If you’re working in a dev environment and you’ve implemented something like this to your web.config, then you’ll notice some odd behavior relating to survey responses.

If your surveys are set to allow only one response per user, and your web.config CallStack property is set to true, just be aware that you’ll encounter the standard ASP.NET server error:

Screen shot 2009-10-14 at 6.45.07 PM

Server Error in ‘/’ Application error: You are not allowed to respond again to this survey.

It’s just a bit uglier for users to see something like the above instead of the standard SharePoint error page. Just something to watch out for. Regardless, it’s probably  not a good idea to have CallStack set to true in your production environments.

Screen shot 2009-10-14 at 6.45.20 PM

 

Very excited to be a part of this and can’t wait for the conference next week!

EUSP-LiveBlogger