Paul On Technology

Exploring technology
JQuery selectors – selecting elements by a partial id

Recently a coworker had a grid like the one below in an ASP.Net page. He wanted me too see if there was any way to make the javascript the manages the checkboxes easier to maintain.

CheckboxGrid +

The checkboxes on the left check or uncheck the day check boxes for the corresponding row. When the checkbox next to Barney Rubble is checked the grid looks like this:

CheckboxGridDays

The SO button checks all signoff checkboxes in the grid and when it is clicked the grid looks like this:

CheckboxGridDaysSO

The original programmer had a load of javascript to select the day checkboxes for the row, and to select all of the signoff checkboxes he did a post back to do the work on the server.

Right away I knew this would be easy to do with JQuery. The only problem that I had was how to get just the day checkboxes or just the signoff checkboxes. Luckily, all of the day checkbox Ids had the word “Day” in them and the signoff checkboxes had the words “IsSignedOff” in their Ids.

Here is how I check all of the day checkboxes in the row that the select all checkbox resides in:

The function call from the select all checkbox’s onclick event:

 

<input id="ctl00_ContentPlaceHolder1_grdTest_ctl03_SelectAll" type="checkbox" onclick="javascript:onSelectAll(this);" name="ctl00$ContentPlaceHolder1$grdTest$ctl03$SelectAll" />

I pass “this”, which is the checkbox, to the function. Now for the function that does the work:

function

onSelectAll(checkbox) {

 

var cb = $("#" + checkbox.id);

 

var td = cb.parent("td");

 

var tr = td.parent("tr");

tr.children().children(

"input:checkbox[id*=Day]").attr('checked', cb.attr('checked'));

}

Let’s break the function down. It has to get checkboxes with html like this:

<td style="border-color: Black; border-style: Solid;">

<input id="ctl00_ContentPlaceHolder1_grdTest_ctl03_Day1" type="checkbox" name="ctl00$ContentPlaceHolder1$grdTest$ctl03$Day1" />

</td>

The actual select all checkbox is passed as an argument. I then get the JQuery handle to that checkbox by using a JQuery id selector built using the actual id of the checkbox passed in.

Next I get the TD that contains the select all checkbox using the JQuery parent function on the checkbox. Then I get the TD’s parent row using the JQuery parent function on the TD.

Now that I have the rows I can get all of the checkboxes that are descendent children of that row, but I only want the checkboxes that contain the string “Day” in their ids. Remember, that last checkbox in the row has “IsSignedOff” in it’s id and the first one in the row is the select all checkbox.

Using a css selector of input:checkbox[id*=Day] says give me the input controls that are of type checkbox that have an id that contains the string “Day”. The *= is the JQuery operator for contains.

So this function gets me all of the day checkboxes and sets their checked attribute to the checked attribute of the select all checkbox that initiates the function call.

The last piece is to get the is signed off checkboxes in all rows, one per row. This is really easy. The button html looks like this:

<input type=”button” onclick="javascript:checkSignOffs();" value=”Sign Off” />

The function is this:

function

checkSignOffs() {

$("#grdTest input:checkbox[id*=IsSignedOff]").attr('checked', true);

}

It has to get checkboxes with html like this:

 

<input id="ctl00_ContentPlaceHolder1_grdTest_ctl03_IsSignedOff" type="checkbox" name="ctl00$ContentPlaceHolder1$grdTest$ctl03$IsSignedOff" />

The selector says for a table with an id of “grdTest”, get me the input controls of type checkbox that have an id that contains the string “IsSignedOff”. When JQuery gets the set of checkboxes, set the checked attribute of each one to checked.

Not  bad for a few lines of code. Now maintenance will be much easy. We ripped out alot of javascript, removed a post back and best of all, I now have JQuery in another application.

If anyone has a cleaner, more concise way of doing this please leave a comment. I know I can get the table row in the first set of code easier, I just need to figure it out. I will post an update when I do. I was in a hurry to share this :0)

Toggling visibility with JQuery

There is a subtle issue with the JQuery toggle method. I had a page that had a div set up similar to this

 

<div id="divGoodbye" style="border: 1px solid green; visibility: hidden; float: right;">Goodbye</div>

I was trying to toggle it from not visible to visible by doing this

 

function toggleGoodbye() {

$("#divGoodbye").toggle();

}

It didn’t work; however, if the div was initially styled with visibility:visible it worked perfectly. So I logged a bug report and the JQuery team got back to me with this

In jQuery, visibility is defined as taking up no space in the document.
Most commonly that would be via {{{display:none}}} or {{{width:0}}}. There
are other ways that an element might not be visible in the browser's
viewport, including {{{visibility:hidden}}}, {{{opacity:0}}}, {{{margin-
left:-10000px}}}, or being completely obscured by other elements higher in
the {{{z-index}}} order. Those do not count as hidden as far as jQuery is
concerned.

If you need to use the {{{visibility}}} (or {{{opacity}}}) attribute as
your method of making an element invisible, just track and toggle it
yourself.In jQuery, visibility is defined as taking up no space in the document.
Most commonly that would be via {{{display:none}}} or {{{width:0}}}. There
are other ways that an element might not be visible in the browser's
viewport, including {{{visibility:hidden}}}, {{{opacity:0}}}, {{{margin-
left:-10000px}}}, or being completely obscured by other elements higher in
the {{{z-index}}} order. Those do not count as hidden as far as jQuery is
concerned.

If you need to use the {{{visibility}}} (or {{{opacity}}}) attribute as
your method of making an element invisible, just track and toggle it
yourself.

So I changed the style to this

 

<div id="divHello" style="border: 1px solid red; display:none; float:left;">

Hello

 

</div>

This works every time as expected. Hopefully this will save someone a bit of frustration. All scenarios worked in IE7, Firefox and Safari.

 

My new love - jQuery

I have been learning jQuery for about a month now. All I can say is wow! Where were they hiding this? I have been trying to write a post on it for about a week but everytime someone beats me to what I was going to say.

I am going to start sharing some knowledge on jQuery but I wanted to get this one out. Along with the great joy that jQuery brings there is also some sadness. Once again I am reminded of how fallible Microsoft is. Now I am definitely a .Net fanboy, but while Mr. Resig was cooking up jQuery Microsoft was cooking up that useless pile of bloat called ASP.Net Ajax. Once again, like the iPhone, this should have been what Microsoft unleashed.

Maybe it is better that they didn’t. Take a look at the crappy Ajax controls in the box and from that community. Then look at what jQuery has. Why is that?

So I am trying to wade my way through getting and keeping any MS Ajax stuff out of my webforms, including the script manager. I want it clean. I am going to learn MVC to see if there is anything in there for me. But I’ll still be using webforms, just finding ways to do it better with jQuery. I was going to learn Silverlight but I think at this point, until I see what the next version has, jQuery will keep me working in more places.

Yes, I am excited about front end stuff again. And its starting to fell good, hey!

Curly braces and C# Code generation using Sparx Systems' Enterprise Architect

When I write code I like the curly braces to be on the next line

public class Customer

{

}

 

I use Enterprise Architect by Sparx Systems to create my UML. Unfortunately, the code generated looks like this

public class Customer{

}

 

There is no option to change this behavior in EA. To get this to happen in EA you need to modify the code generation template for C#. Go to Settings, Code Generation Templates and select C#. Using the code below update the EA templates for the sections in the headers with ======== underneath. For properties the item you need to select Operation Body and then in the list box below the main list box select Property. Remember to click save for each section that you modify. If you don't like the changes you can click the Get Defaukt Template button for each section.

 

Namespace Body
===============

$COMMENT="WARNING: THIS IS AN ADVANCED TEMPLATE"
$COMMENT="DO NOT MODIFY UNLESS YOU ARE AN"
$COMMENT="ADVANCED USER!"
%if packageHasGenClasses != "T"%
%list="Namespace" @separator="\n\n" @indent=""%
%endTemplate%

%if packagePath == "" or genOptCSGenNamespace != "T"%
%PI="\n\n"%
%list="Namespace" @separator="\n\n" @indent=""%
%list="Class" @separator="\n\n" @indent=""%
%endTemplate%

\n{
%PI="\n\n"%
%list="Namespace" @separator="\n\n" @indent="\t"%
%list="Class" @separator="\n\n" @indent="\t"%
}//end namespace %packageName%

 


Class Body
==========

%if elemType == "Interface"%
{\n
%list="Operation" @separator="\n\n" @indent="\t"%
%PI=""%
}//end %className%
%endTemplate%

\n{\n
%PI="\n\n"%
%list="InnerClass" @separator="\n\n" @indent="\t"%
%list="Attribute" @separator="\n" @indent="\t"%

$ops=""
%if genOptGenConstructor == "T" and classHasConstructor != "T"%
$ops+="\tpublic "+%className%+"()\n\t{\n\n\t}"
%endIf%

%if genOptGenDestructor == "T" and classHasDestructor != "T" and classHasFinalizer != "T"%
$ops+="\n\n\t~"+%className%+"()\n\t{\n\n\t}"
%endIf%

%if genOptCSGenDispose == "T" and classHasDispose != "T"%
$ops+="\n\n\tpublic "
$ops+=%classHasParent=="T" ? "override " : "virtual "%
$ops+="void Dispose()\n{\n\n\t}"
%endIf%

%if genOptCSGenFinalizer == "T" and genOptGenDestructor != "T" and classHasFinalizer != "T" and classHasDestructor != "T"%
$ops+="\n\n\tprotected "
$ops+=%classHasParent=="T" ? "override " : "virtual "%
$ops+="void Finalize()\n{\n"
$ops+=%classHasParent=="T" ? "\t\tbase.Finalize();" : ""% + "\n\t}"
%endIf%

%if genOptGenCopyConstructor == "T" and classHasCopyConstructor != "T"%
$ops+="\n\n\tpublic "
$ops+=%className%+"("+%className%+" the"+%className%+")\n\n{\n\n\t}"
%endIf%

$ops
%list="Operation" @separator="\n\n" @indent="\t"%

}//end %className%

 

Operation Body
==============

%if elemType == "Interface" or opTag:"delegate" == "true" or opAbstract == "T" or opTag:"extern" == "true"%
%PI=""%
;
%endTemplate%

{\n
$wrap = %genOptWrapComment=="-1" ? "-1" : "40"%
$behavior = %WRAP_LINES(opBehavior, $wrap, "\t//", "")%
%if $behavior != ""%
$behavior\n\n
%endIf%
$destName = "~" + %className%
%if opCode != ""%
%WRAP_LINES(opCode, "-1", "\t", "")%
%elseIf opName == className or opName == $destName%
%elseIf opReturnType == "byte" or opReturnType == "char" or opReturnType == "decimal" or opReturnType == "double" or opReturnType == "float" or opReturnType == "int" or opReturnType == "long" or opReturnType == "sbyte" or opReturnType == "short" or opReturnType == "uint" or opReturnType == "ulong" or opReturnType == "ushort"%
\treturn 0;
%elseIf opReturnType == "bool"%
\treturn false;
%elseIf opReturnType == "string"%
\treturn "";
%elseIf opReturnType != "void" and opReturnType != ""%
\treturn null;
%endIf%
}


Operation Body : Property
=========================

%if elemType == "Interface" or opAbstract == "T"%
$att=%opTag:"attribute_name"=="" ? "<unknown>" : value%
%if opTag:"writeonly" == ""%
$read="\tget;"
%endIf%
%if opTag:"readonly" == ""%
$write="\tset;"
%endIf%

{
$wrap = %genOptWrapComment=="-1" ? "-1" : "40"%
$behavior = %WRAP_LINES(opBehavior, $wrap, "\t//", "")%
%if $behavior != ""%
$behavior\n
%endIf%

$code = %WRAP_LINES(opCode, "-1", "\t", "")%
%if $code != ""%
$code
%else%
$read
$write
%endIf%
}
%endTemplate%


$att=%opTag:"attribute_name"=="" ? "<unknown>" : value%
%if opTag:"writeonly" == ""%
$read="\tget\n\t{\n\t\treturn " + $att + ";\n\t}"
%endIf%
%if opTag:"readonly" == ""%
$write="\tset\n\t{\n\t\t" + $att + " = value;\n\t}"
%endIf%

\n{
$wrap = %genOptWrapComment=="-1" ? "-1" : "40"%
$behavior = %WRAP_LINES(opBehavior, $wrap, "\t//", "")%
%if $behavior != ""%
$behavior\n
%endIf%

$code = %WRAP_LINES(opCode, "-1", "\t", "")%
%if $code != ""%
$code
%else%
$read
$write
%endIf%
}

What should Microsoft do next?

Ok, so the Yahoo! thing seems to be dead for now. So what does everyone think they should do with the money that they obviously have lying around to invest in other companies?

I think they need some drastic changes. Take the iPhone for example. Windows Mobile is up to version 6 right? How does Apple come along and get it so right on version one? Go ahead, tell me what the iPhone doesn't have and WM does. Apple just disrupted the whole cell phone industry with the iPhone. Even the new phones coming out still suck for the average user. I don't need to see the start menu on my cell phone. And there in lies the root of the problem. Microsoft should have made the iPhone in the first place.

Look at Salesforce.com. Again Microsoft should have been there first. What a great story that could have been tied in with desktop and web versions of Office. Incrementally. when Salesforce started a few years back it sucked but it supported every browser and grew better as the browsers got better. Spend some cash and put Office on the web and make a big deal out of it. Look at what Zoho is doing. Why aren't you doing the experimenting in this space?

We have Silverlight coming - hopefully we can get away from HTML and CSS which to me is a big hack on top of a lump of crap that was never meant to do the things that it is being made to do. That's right, you read it right. We basically have the same 15 html controls we started with 10 years ago. We just found some new ways to put 5 pounds of poop into a 2 pound bag. Web apps are just so obnoxious to develop. Don't you think we have been working like jackasses for 10 years to long? I say you do it right, embrace whatever Adobe does and do them 100 times better in addition to Silverlight. Leave no one out. Truly support linux, which I believe that you are doing with Novell.

The whole Microsoft stack is a great set of technologies. To me it trumps everything else out there, hands down. Yet so many developers hate them. You know what? Stop being a bunch of pricks - you don't own the universe anymore, but you could if you do it right. I saw a major project get done without even considering the superior Microsoft product out of pure hatred and contempt.

There are a lot of great alternatives out there. Better? Maybe, maybe not, but follow this logic. How many entity-data frameworks are you going to throw at us? I'm confused and to make matters worse your frameworks only seem to work with SQL Server. Spend the money and support the 2 next biggest players. And stop making me have to hunt for and download 10 different files from different CTPs from 10 different web locations (yes you from the extensions teams). If you are giving me the next rev of Visual Studio tools give me everything I need in one download. I now have a headache.

One of my friends, a complete java / open source bigot, is trying to get me to take a look at NHibernate. Let's see - something similar, works with all databases, it's free. Why aren't you guys doing this? As soon as you see these things coming, help the teams and support at least the .Net version. Make it better than the Java version, which shouldn't be to hard.

When you create a web property don't make people have to have a Live Id. Let people create an id using their own email address and a password, just like most other sites do. With all of the resources that you have people should be looked at like total freaks if they want to use any other platform.

Don't become irrelevant  like IBM did. Google is a search engine with advertisements. They are the darlings of the tech world. Are you kidding me? This should be you. It still could. Remember what you learned from your mother and in kindergarten? Play nice.

So anyway, I know this could have been a more cohesive post but I just wanted to get some thoughts out there. Fire away.

Getting calendar items using Exchange Web Services

I am no expert at exchange, let alone Exchange Web Services (EWS), but I recently had to use it to get at calendar information for a project. Let me tell you that the documentation for EWS sucks and the API is not very intuitive. That said, I was able to piece together what I needed. The code is not perfect and could definitely use a good once over by someone with more than 2 days experience.

The code will show how to get at calendar items, how to use a date range and how to get the body of the calendar item. I racked my brain for a while to get the body - you have  to make a call to get the calendar items and then for each item you have to go and use the ID to get its body in another call. The  idea is that the first call gets only the small parts of an item. If you want things like attachments then you make another call to get it. Here is a link to an article that gets into it.

The code is not perfect but I want to save someone the time that I spent. Please leave comments with suggestions and improvements.

UPDATE: I have attached some code. I don’t have access to an exchange server. It compiles but at least the classes are there for you. 

private List<CalendarInfo> GetCalendarEvents()
{
    List<CalendarInfo> calendarEvents = new List<CalendarInfo>();

    ExchangeServiceBinding esb =
        new ExchangeHelper().GetExchangeBinding("myUserName", "myPassword", "myDomain");

    // Form the FindItem request.
   
FindItemType findItemRequest = new FindItemType();

    CalendarViewType calendarView = new CalendarViewType();
    calendarView.StartDate = DateTime.Now.AddDays(-1);
    calendarView.EndDate = DateTime.Now.AddDays(1);
    calendarView.MaxEntriesReturned = 100;
    calendarView.MaxEntriesReturnedSpecified = true;

    findItemRequest.Item = calendarView;

    // Define which item properties are returned in the response.
   
ItemResponseShapeType itemProperties = new ItemResponseShapeType();
    // Use the Default shape for the response.
    //itemProperties.BaseShape = DefaultShapeNamesType.IdOnly;
   
itemProperties.BaseShape = DefaultShapeNamesType.AllProperties;
    findItemRequest.ItemShape = itemProperties;

    DistinguishedFolderIdType[] folderIDArray =
        new DistinguishedFolderIdType[1];
    folderIDArray[0] = new DistinguishedFolderIdType();
    folderIDArray[0].Id = DistinguishedFolderIdNameType.calendar;

    if (!string.IsNullOrEmpty(criteria.EmailAddress))
    {
        folderIDArray[0].Mailbox = new EmailAddressType();
        folderIDArray[0].Mailbox.EmailAddress = "myEmail.com";
    }
   
    findItemRequest.ParentFolderIds = folderIDArray;

    // Define the traversal type.
   
findItemRequest.Traversal = ItemQueryTraversalType.Shallow;

    try
   
{
        // Send the FindItem request and get the response.
       
FindItemResponseType findItemResponse =
            esb.FindItem(findItemRequest);

        // Access the response message.
       
ArrayOfResponseMessagesType responseMessages =
            findItemResponse.ResponseMessages;
        ResponseMessageType[] rmta = responseMessages.Items;

        int folderNumber = 0;

        foreach (ResponseMessageType rmt in rmta)
        {
            // One FindItemResponseMessageType per folder searched.
           
FindItemResponseMessageType firmt =
                rmt as FindItemResponseMessageType;

            if (firmt.RootFolder == null)
                continue ;

            FindItemParentType fipt = firmt.RootFolder;
            object obj = fipt.Item;

            // FindItem contains an array of items.
           
if (obj is ArrayOfRealItemsType)
            {
                ArrayOfRealItemsType items =
                    (obj as ArrayOfRealItemsType);
                if (items.Items == null)
                {
                    folderNumber++;
                }
                else
               
{
                    foreach (ItemType it in items.Items)
                    {

                        if (it is CalendarItemType)
                        {
                            CalendarItemType cal = (CalendarItemType)it;
                            CalendarInfo ce = new CalendarInfo();

                            ce.Location = cal.Location;
                            ce.StartTime = cal.Start;
                            ce.EndTime = cal.End;
                            ce.Subject = cal.Subject;
                            ce.Body = GetMeetingBody(esb, cal);

                            calendarEvents.Add(ce);
                        }

                    }

                    folderNumber++;
                }
            }
        }

    }
    catch (Exception e)
    {
        throw;
    }
    finally
   
{
       
    }

    return calendarEvents;
}

private string GetMeetingBody(ExchangeServiceBinding binding, CalendarItemType meeting)
{
    string meetingBody = string.Empty;
    CalendarItemType temp = null;

    // Call GetItem on each ItemId to retrieve the
    // item’s Body property and any AttachmentIds.
    //
    // Form the GetItem request.
   
GetItemType getItemRequest = new GetItemType();

    getItemRequest.ItemShape = new ItemResponseShapeType();
    // AllProperties on a GetItem request WILL return
    // the message body.
   
getItemRequest.ItemShape.BaseShape =
        DefaultShapeNamesType.AllProperties;

    getItemRequest.ItemIds = new ItemIdType[1];
    getItemRequest.ItemIds[0] = (BaseItemIdType)meeting.ItemId;

    // Here is the call to exchange.
   
GetItemResponseType getItemResponse =
        binding.GetItem(getItemRequest);

    // We only passed in one ItemId to the GetItem
    // request. Therefore, we can assume that
    // we got at most one Item back.
   
ItemInfoResponseMessageType getItemResponseMessage =
        getItemResponse.ResponseMessages.Items[0]
        as ItemInfoResponseMessageType;

    if (getItemResponseMessage != null)
    {
        if (getItemResponseMessage.ResponseClass ==
            ResponseClassType.Success
            && getItemResponseMessage.Items.Items != null
           
&& getItemResponseMessage.Items.Items.Length > 0)
        {
            temp = (CalendarItemType)getItemResponseMessage.Items.Items[0];

            if (temp.Body != null)
                meetingBody = temp.Body.Value;
        }
    }

    return meetingBody;
}

private ExchangeServiceBinding GetExchangeBinding(
      string userName, string passwotrd, string domain)
  {

      ExchangeServiceBinding binding = new ExchangeServiceBinding();

      ServicePointManager.ServerCertificateValidationCallback =
              delegate(Object obj, X509Certificate certificate, 
              X509Chain chain, SslPolicyErrors errors)
              {
                  // Replace this line with code to validate server certificate.
                  return true;
              };

      System.Net.WebProxy proxyObject = 
          new System.Net.WebProxy();
      proxyObject.Credentials = 
          System.Net.CredentialCache.DefaultCredentials;

      binding.Credentials = 
          new NetworkCredential(userName, password, domain);
 
      string server = ConfigurationManager.AppSettings["ExchangeServer"] as string;

      if (server == null || string.IsNullOrEmpty(server))
          throw new ArgumentNullException("The Exchange server Url could not be found.");

      binding.Url = server;
      Console.WriteLine("***** " + server);

      binding.Proxy = proxyObject;

      return binding;
  }
Setting up Sandcastle

I just spent an interesting few hours setting up Sandcastle. The whole process is absolutely insane. Sandcastle itself is no problem, and neither is Sandcastle Help File Builder (by the way, nice job). The problem is finding the help compilers. The Help File Builder home page provides a link to resources for all of the compilers which I completely missed. My bad.

You have to install the Visual Studio 2005 SDK. Or is the the VS 2003 SDK? Wait, I have VS 2008, so is it the VS 2008 SDK?  It depends on if you want the Help 1.x files generated or the Help 2.x files generated. The VS 2005 SDK puts HXCOMP.exe in an archive directory.

Why is  this so hard? Even though the Help File Builder seems to be the piece that requires the compilers, when you pull down Sandcastle it should give you everything you need for help files, after all, isn't this the whole point?

In the end I decided to go with the website version for my needs. I am building a help file for a set of WCF services. These will be outward facing and we don't know what our consumers will be using for their apps. Why does the HTML version of the help require an ActiveX control for the browser?

Maybe I am missing something so if anyone has any thoughts please pass them along.

The Big Switch

In December, Michael Arrington had a post that held a contest to win a copy of 'The Big Switch' by Nick Carr of 'Does IT Matter' fame. It talks about computing services becoming a utility. I won a copy by giving my thoughts on the topic.

It was a fast read, provided some background on the history of electric utilities and then makes the parallel with computing services. Corporate infrastructure departments should give it a gander. His theory makes sense as the foundation is already being laid. Smaller shops are already there.

One interesting note - he claims Bill Gates' time has come and gone. I can see that and I guess with the impending changing of the guard at Microsoft, so does Bill.

Anyway, its an interesting book.

Overloaded again

I have just read Keith Harvey's post Slow Down Microsoft, I Can't Take It! about the pace the development of .Net technologies. He says it's not so bad but wow, my head hurts.

With the release of Visual Studio 2008 and .Net 3.5 we have several new things to play with, in addition to the CTPs for MVC, Entity Framework, Astoria plus whatever else I have heard about and can't think of at the moment.

LINQ, with all of its flavors is a monster. Thanks to Scott Guthrie for his tutorials here and here. What is going to be interesting with LINQ is to see how and when Oracle supports it, but I heard its coming.

So here we go again. I can't master it all, heck, I can't even use it all, but for now the goal is to gain a decent understanding of it so I'll know its there for a deeper dive when I start my next project.

UPDATE As Robert pointed out in the comments, I forgot Silverlight. So, while I am at it - WCF which I work with, WPF which I read a book about, WF which I ran a few tutorials for, CardSpace an on an on an on!

 

Ajax and security

I have been toying with Ajax on and off for a few months now. I like the idea and there seems to be a never ending stream of ajax samples, tools and ideas. What I have yet to see is how these calls are secured.

Maybe I am missing something, but I really don't think that I have seen any examples. Maybe I am just getting hung up on the fact that javascript is making the calls but I would like to see some concrete examples just to be sure. The way I see it is that there might be something in calling from javascript that throws something off. Its not as much the things that I might be looking for as much as the things that I don't know to look for.

I found this from Rob Hurlbut's blog. What I think is lacking is that many tutorials leave this kind of stuff out.

 

More Posts Next page »