Using JQuery with DotNetNuke 4.x

I’m currently doing a project using DotNetNuke, and we’re using JQuery plugins to achieve certain content rotation and scroller functionality.  All was ‘amost’ good as I’d found a way to inject the JQuery script to the page header on a per-skin basis, but in ‘edit’ mode the actions button wasn’t showing up at the top of containers in FireFox and was causing JavaScript errors in IE.

I’d already gone through the hoops of declaring jQuery.noConflict(), but it still appeared to be conflicting with the dnn:actions (solpartactions) control.  I’d read somewhere else about Solpart code being incompatible with JQuery.

I tried one last thing, adding the noConflict() call in the JQuery library script file itself – rather than running as a fragment on page load.  This fixed everything, as something else was obviously getting in and hijacking in the meantime.  Apparently with V5 this will all be fixed as JQuery’s more integrated with the framework.  Anyway, for those interested here’s what I had to do to get JQuery (and associated plugins) talking nicely whilst still allowing the actions menu to pop up on my containers…

  1. Amend the JQuery library (jquery.1.x.x.min.js) by adding the following line at the bottom…

    jQuery.noConflict();

  2. Amend the skin you want to load the jquery library (and plugins) in (we’ve got it only in specific skins to avoid the overhead where it’s not required).  You could also do this in the module by checking ‘if loaded’, but here’s the code for a skin (in ascx file)…

    <script runat=”server”>
        Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
            ‘add a script reference for Javascript to the head section
            AddScript(“/js/jquery.scrollable-1.0.2.min.js”)
            AddScript(“/js/jquery.mousewheel.js”)
            AddScript(“/js/jquery-1.3.2.min.js”)
        End Sub
       
        Private Sub AddScript(ByVal fileName As String)
            Dim oLink As New HtmlGenericControl(“script”)
            oLink.Attributes(“language”) = “javascript”
            oLink.Attributes(“type”) = “text/javascript”
            oLink.Attributes(“src”) = fileName
            Dim oCSS As Control = Me.Page.FindControl(“CSS”)
            If Not oCSS Is Nothing Then
                oCSS.Controls.AddAt(0, oLink)
            End If
        End Sub
    </script>

    The order is important, as we’re adding the scripts to the ‘top’ of the scripts each time.  JQuery needs to be the first referenced.

  3. Make sure that anywhere you use jQuery you use the jQuery(xx) syntax, and not $(xx).

That’s it.

Making Web Wireframes easier with Visio – The Pixel Dimensions Shape

Many people use Adobe Illustrator or Photoshop for designing Web layouts, but a lot of companies use Visio – especially for higer level ‘wireframes’.  One of Visio’s problems (<= 2003 anyway) is that it doesn’t support pixel units.  This means you’ll always be approximating the sizes of content areas and page elements, making the developer’s job more difficult.

Enter ‘Visio Guy’, and the Pixel Unit Line Shape.  This is just a great addition for anyone using Visio.  Before you know it you’ll be laying out pixel perfect shapes that the developers will then give you great pleasure in declaring ‘this won’t work in IE6!’ 🙂 

A thing to note with Visio as well: If you’re working with pretty small dimensions then the only way to get really precise is to zoom right in (like 500%), otherwise the whole ‘snap/glue’ thing will kick in based on the page units (probably mm), regardless of whether you’ve switched snap/glue off.

HOW TO Use SQL Server DTS Transform Data Task to export to dynamic Excel spreadsheet file

Many people (including me) are often still using SQL 2000 – which means that you might be using DTS (Data Transformation Services) to perform utility jobs on your databases. 
I’ve had a requirement to output data to Excel (not my choice – Excel usually isn’t!) – which is subtly different to text output as CSV*.  Another requirement was to have a ‘generated’ file name in a known folder.  This is as simple as a date/time driven file name.  The ‘job’ runs once (or more) a day and so creates a new file each time.  Easy right?

Well – it turns out that if you go through the normal motions of creating an Excel connection and using a Transform Data Task it’s likely to work first time and leave you thinking ‘great’.  Unfortunately when you run it again you’re likely to get a message similar to the following:

Table ‘New_Table$’ not found. 

After much digging (hence the reason for writing this), I discovered that in order to map the columns successfully you basically have to create the table in the spreadsheet before running the transformation (the ‘create table’ part of creating the transformation).  If you’ve got a dynamic file name then the next time you’ll  effectively have a blank spreadsheet without the required receiving ‘table’, and it will fail, unless you’ve recreated the sheet before the transformation.

OK so assuming you want to output some data to a spreadsheet with a dynamic filename with a Transform Data task then here’s how you do it.

  1. I put all files in the same folder so I use 2 global variables to build the filename – NetworkLocation and FinalLocation
    1. First, Right-click on a blank part of your package screen and choose Package Properties, then Global Variables tab.
    2. Create the two global variables NetworkLocation and FinalLocation
    3. Edit the NetworkLocation value to be the folder (including a final ‘\’) of where you want to store the files.
    4. Leave FinalLocation blank (we’ll create that in the next step.
  2. Add an ActiveX Script Task with the following code (which you can
    obviously tailor the name to your needs).  It basically creates a
    date/time based file name, and stores a concatenation of the network
    location and file name in the FinalLocation global variable.

    ‘**********************************************************************
    ‘  Visual Basic ActiveX Script
    ‘************************************************************************
    Function Main()

        Dim fileName
        fileName = “MyOutput_” & DatePart(“yyyy”,Date) & Right(“0” & DatePart(“m”,Date), 2) & Right(“0” & DatePart(“d”,Date), 2) & “_” & Right(“0” & DatePart(“h”,Now), 2) & Right(“0” & DatePart(“n”,Now), 2) & Right(“0” & DatePart(“s”,Now), 2)
        DTSGlobalVariables(“FinalLocation”).Value = DTSGlobalVariables(“NetworkLocation”).Value + fileName + “.xls”

        Main = DTSTaskExecResult_Success

    End Function

  3. Add your data connections
    1. Create your source connection (presumably SQL Server or wherever your data’s coming from)
    2. Create your destination connection (A Microsoft Excel 97-2000
      connection) and set an initial file name (best to be in the folder
      specified in NetworkLocation)
  4. Create a Data Transformation Task connecting your source and destination connections as per normal
    1. Add in your Table/View or SQL Query to define the source data.
    2. In the Destination tab click ‘Create…’ next to ‘Table name:’ (a
      dialog will pop up ‘Create Destination Table’).  Change the table name
      (or column definitions) if you like, then COPY THE ENTIRE TEXT – and
      paste into a text editor for safe keeping.
    3. Click OK (This will create a new sheet in the spreadsheet you’ve
      specified in your connection, ready to receive your data).  Your fields
      should then also be populated in the table below.
    4. Check the transformations tab – you should get a nice one to one mapping between source and destination columns.
  5. Create a Dynamic Properties Task (Here’s where it all comes together)
    1. Click ‘Add…’ to create a new property.  Choose your Excel Connection and pick the ‘DataSource’ property, then click ‘Set…’
    2. Choose ‘Global Variable’ as the source and FinalLocation as the variable – Click OK.
    3. Click ‘Add…’ to create another property.  Choose the
      DTSTask_DTSDataPumpTask_? in the Tasks node (your data transformation
      task) and pick the ‘DestinationObjectName’ property.
    4. Choose ‘Query’ as the source and paste in your ‘CREATE TABLE‘ statement from earlier – Parse to check, then click OK.
  6. Create the Workflow for the task
    1. Select the Dynamic Properties Task, right-click and select Workflow –> Workflow Properties.
    2. Click ‘New’ and set the ActiveX Script Task as ‘Source Step’.
    3. Select the Data Transformation Task, right-click and choose Workflow Properties.
    4. Click ‘New’ and set the Dynamic Properties Task as ‘Source Step’.

That’s basically it – the package should look something like this:

It should also now do the following (in order):

  1. Set filenames (stored in global variables)
  2. Set filename of the excel connection, create the destination ‘sheet’
    from the global variables and the query in the transformation
  3. Do the transformation and store the results in a date/time named Excel spreadsheet in your configured folder

If you ever need to change the query (columns) then you’ll need to regenerate the ‘CREATE TABLE’ statement and reflect it in the Dynamic Properties Task (5.c)

*Typically an Excel export covers your back with datatypes where a CSV export won’t – so when you open in Excel you’ll have to format columns specifically yourself – like converting dates, and also long numbers from scientific format to text format.

ASPNETCOMPILER The Target Directory could not be deleted. Please delete it manually or choose a different target – SubVersion

I’d added some projects to SubVersion today and later on added a CruiseControl.NET build.  I then started getting build failures due to the following:

ASPNETCOMPILER The Target Directory could not be deleted. Please delete it manually, or choose a different target

After a bit of looking around with the SysInternals Process Monitor I couldn’t find anything weird (e.g access denied due to someone locking the folder) and then saw that my output folder from the project (ASP.NET Web Deployment Project) was under SubVersion control (below)

Whoops! – after a swift delete of the folder (also in SubVersion) normality was resumed.  That’s another good reason not to put binaries into source control!

How to generate a list of Visual Studio Shortcuts

I’d seen addins that list Visual Studio shortcuts before, but seem to have lost them.  I also used to use ReSharper, so memorised its shortcuts.  I’m now back to ‘naked’ Visual Studio, so am having to re-learn the standard shortcuts.

I was surprised to find this article on MSDN that has code for a macro to produce a html page of all the shortcuts.  Just run the macro, open it up and search in the browser whenever you’re having problems remembering – unless you really want to print it (in which case I’d be inclined to bang a bit of CSS in there 🙂 ).  I might improve upon the whole situation if I find myself needing to refer to it more often, and will post updates here.

ASP.NET Data Binding – Accessing a parent data item from within a nested repeater

I’m maintaining an app at the moment that uses quite a few nested repeaters, and found that headers were being output when there was no data present.  It was found that the header was being written in the ItemTemplate of an ‘outer’ repeater, rather than as the HeaderTemplate of the ‘inner’ repeater.  The next problem was how to reference the outer repeater from the ‘inner’ HeaderTemplate…

The following will bind to a field called HeaderDescription.

<%# DataBinder.Eval(Container.Parent.Parent, “DataItem.HeaderDescription”) %>

The parent of the inner item is it’s repeater, so you have to go to it’s parent to get the right RepeaterItem.  Why don’t you just do the following you ask?

<%# DataBinder.Eval(Container.Parent.Parent.DataItem, “HeaderDescription”) %>

..’cos it doesn’t work – The Eval method expects a ‘Control’ as its first parameter.  There’s other ways to do this server-side, but the first option is probably the easiest.

To complete the picture and only show when there’s data you can add the following to the ‘inner’ repeater declaration

OnItemDataBound=”ItemDataBound” Visible=”false”

then..

        protected void ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item)
            {
                if (!e.Item.Parent.Visible)
                    e.Item.Parent.Visible = true;
            }

        }

This will ensure that you’ll only show if you’ve bound a ‘data’ item (remember you’re doing binding in the HeaderTemplate too).  You could also hook similar things into other events, but it’s generally more convenient to put these things into events that relate to the actual control (pre_render’s probably another good candidate as it will only get called once and you can check the count in the DataSource).

Technorati Profile

Converting from scientific number format to decimal or string in C#

I’m a programmer, but there are a few things I’ll admit I don’t do much of (as I have little interest in learning).  Playing with numbers in scientific notation is one of them.

I was importing from a spreadsheet and needed to get “6.00234419836431E+15” to something readable.

I discovered that you need to specify a NumberStyle when you parse as a decimal, because by default you’ll get an error as it expects an ‘easy’ conversion.

The number above had decimals, exponent, the lot – so the following line of code does the job nicely…

Console.WriteLine(decimal.Parse(“6.00234419836431E+15”, System.Globalization.NumberStyles.Any).ToString());
//Globalisation namespace just shown for clarity – you’ll want to put this in a using statement 🙂

This gives you “6002344198364310”. Sweet.

Make JQuery and Prototpye coexist and play together with a GreaseMonkey User Script

I’ve been playing with Greasemonkey scripts recently – for Redbubble.com, and wanted to use JQuery with GreaseMonkey.  This is pretty well documented, but I discovered an incompatibility with my script and the host site, as it uses the Prototype Javascript library (must admit I didn’t know much about it).

Prototype (like JQuery) uses the $ notation, and so by default any GreaseMonkey User Script loaded will hijack the $ object, meaning that stuff on the original site may stop working.

I thought I was sunk but it turns out JQuery just gets better, and it can gracefully give back control of the $ to whichever library originally loaded it.  Just call..

jQuery.noConflict();

You then have to use jQuery instead of $ (e.g. jQuery(“#myID”) instead of $(“#myID”) ), but hey – that’s a small price to pay when the alternative is rewriting the whole thing long-hand.

CommaDelimitedStringCollection – for when you want to write a comma delimited string from a collection !

Amazing that I still find BCL classes every day in .NET to do simple tasks.  I had a feeling that something may exist but didn’t expect to find it in the System.Configuration namespace.

using System.Configuration;

CommaDelimitedStringCollection strings = new CommaDelimitedStringCollection();

foreach(string item in myOtherCollection)
{
    strings.Add(item);
}

//Spit out your comma separated string
string output = strings.ToString();

Simple!