Adobe AIR 1.5 Print Styles (UGH)

by Jason on

While writing a new Adobe Air app it’s come to my attention that along with the pitiful print functions available in Adobe Air 1.5, print media stylesheets also do not appear to work.

Here’s the contents of my test stylesheet:

@media screen
			{
			    .noprint {display:none;}
			}

@media print { .noprint { display:block !important; padding: 5px; border: solid 3px #0000FF; font-weight:bold; text-align:center; } }

As you can see the display style “noprint” is defined as “none” in screen and block in print. I’ve attached a pdf of the output of what it should look like and what it does in fact look like.

All in all printing in Air has been an extreme disappointment. If you are building a desktop application then printing is, by necessity, a highly probable feature.

Test file Printed w/ Air Adobe Air “printing” (PDF)

Same file printed w/ Firefox: Firefox Printing (PDF)

Frankly I just don’t see an excuse for the shoddy print functionality in Air.

If you’re considering Air for your next desktop widget please consider the following:

  1. Does your application need to print anything?
  2. Do you mind your print looking like monkey-ass?
If you answered Yes to either of those questions then Air may not be the tool for you just yet.

For no particular reason . . .

by Jason on

I haven’t blogged for over a year… Of course it was blogger’s fault and not my lack of inspiration. So on to wordpress and perhaps we’ll see some posts soon.

Position:fixed and floating divs in IE6+

by Jason on

I had a need to keep a “header” div at the top of the page at all times. This was surprisingly difficult considering that IE6 and apparently IE7 do not support position:fixed.

After a lot of tweaking and various hacks I came across this solution which works nicely.

Simply put after creating my div I assigned it an id of “top” and created the following style rule in my stylesheet:

#top{
position:fixed;
_position:absolute;
top:0;
_top:expression(eval(document.body.scrollTop));
left:0;
margin:0;
padding:0;
height: 100px;
width:100%;
z-index: 999;
}


This is based on Anne’s example here.

Very handy, tested in IE6, IE7, Firefox 2.0.0.7, Safari for Windows beta.

Safari gives some funny results on a menu that is contained in my div, but Safari gives funny results for all sorts of things so I’m not going to lose sleep over it.

Tree / Hierarchical Recordset in Sql Server 2005

by Jason on


Scenario: Your uncle Tim has been selling AmWay products since 1987.  Over the years he’s brought on quite a few “distributors” and needs to know the structure of his mighty branch of the multi-level marketing machine.  Lucky for you he’s been keeping records digitally on the same computer he purchased in 1984 with Lotus 123.  Unfortunately it’s a mess and he wants you to turn that data into something useful.

After losing a few hours of your life reading up on some documentation you have successfully imported that data into your handy copy of MS SQL Server.  With much conversation you two decide that what he needs is the ability to drill down to whatever branch of the tree he feels like.

Example Data:


You could recursively loop through the data in a Stored Procedure to spit out your new recordset but what a lot of code!

Enter Sql Server 2005’s CTEs (MS: Using Common Table Expressions)

Warning: Notice I said SQL Server.  CTEs do not appear to be available in Express / MSDE. Please correct me if I’m wrong, would be handy to know.
  
I first came across CTEs in a book I bought for a coworker who is learning a bit of SQL for one of our in-house tools.  After about 5 minutes of reading I had to slap my forehead against the desk a few times for wasting so much time on so much unnecessary code.

A CTE could be considered an in-line recordset but because of it’s recursive abilities it’s a lot more powerful than a traditional table variable.    (See the MS article above for a real in-depth explanation that does a better job than me).

In short to produce the hierarchical recordset for this requirement we need essentially to build a CTE using a Union within.

 
 
DECLARE @Branch AS Integer;
SET @Branch = 1;
 
With PeopleCTE
    As (
        Select ID, FirstName + ‘ ‘ + LastName As FullName, ParentID, 0 as Lvl
            From tmpPeople where ID = @Branch
        UNION ALL
        Select Child.ID, Child.FirstName + ‘ ‘ + Child.LastName, Child.ParentID, Parent.Lvl + 1
            FROM PeopleCTE As Parent
                JOIN dbo.tmpPeople As Child
                    on Child.ParentID = Parent.ID
    )
 
Select * from PeopleCTE
    Order By Lvl


Example Output from the statement:

 
In the example we start off by declaring the root or branch as @Branch.   We then declare the CTE with the “With” statement.

Note: the statement preceding a CTE declaration must be properly closed with a semicolon (;).  I’m terrible about this so I kept my code as close to my normal code (sans-semicolons) as po ssible as an example of what not to do.

 Within the CTE notice that the column definition (much like a normal union) is completely determined by the first statement.  That statement is where we set our root node or @Branch.

The second Unioned statement is a join between our tmpPeople table and the CTE itself.  This is a recursive statement and lets us avoid a loop.  Note:  a recursive CTE can only drill down to 100 levels of recursion.   So watch out for infinite loops in your relationships.


By enclosing our Query in a Table-valued Function we could make our Hierarchical recordset searchable. 

Example:


CREATE FUNCTION [dbo].[fn_PeopleTree] 
(    
    @Branch Int
)
RETURNS @People TABLE (
    ID Int,
    FullName VarChar(255),
    ParentID Int,
    Lvl Int)
 
BEGIN
    With PeopleCTE
    As (
        Select ID, FirstName + ‘ ‘ + LastName As FullName, ParentID, 0 as Lvl
            From People where ID = @Branch
        UNION ALL
        Select Child.ID, Child.FirstName + ‘ ‘ + ChildLastName, Child.ParentID, Parent.Lvl + 1
            FROM PeopleCTE As Parent
                JOIN dbo.People As Child
                    on Child.ParentID = Parent.ID
    )
 
    Insert INTO @People (ID, FullName, ParentID, Lvl)
        Select ID, FullName, ParentID, Lvl from PeopleCTE
 
    RETURN;
END

 


And now Uncle Tim can search by the individual branch of the tree and easily spot weaker branches in his burgeoning empire.