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)

    Read more...

  • 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.

     

    Read more...

  • 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.

    Read more...

  • 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?

    Read more...

  • 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;
      }

    Read more...

  • 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.

    Read more...

  • 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.

    Read more...

  • 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!

     

    Read more...

  • 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.

    Read more...