JqueryMobile & Autocomplete

I’ve been using an AutoComplete library for a while now, but happened to need to use it again with a new WCF web service this weekend, so I thought I’d cover what I use and how I’ve used it. The Autocomplete is used so that as the user begins typing information into a Text Input widget, it will send out what has been typed in to the WCF Web Service and begin searching for items that match.

Basically, every KeyDown event triggers the function and the search is refined the more you type in. It returns the information via JSON and a drop down list will appear below the text input.

I utilize the AutoComplete library available here: http://www.andymatthews.net/read/2012/03/27/jQuery-Mobile-Autocomplete-now-available

I use it in a JqueryMobile site for my employer and there are some common items that come up frequently in the forms automation we utilize:

  1. Customer information like: Name, Primary Contact, Primary Contact’s Phone and Primary Contact’s Email.
  2. Sales Account Executive information like: Name, Phone, Email, Location.
  3. Project Manager information like: Name, Phone, & Email.

I pull the Sales Account Executive and Project Manager information from Active Directory via a WCF Web Service and new as of this weekend, I’m utilizing our CRM app, ConnectWise, to access Customer information via a WCF Web Service that actually interfaces with ConnectWise’s API.

So, let’s get to some code and practical examples where I’ll walk us through what I’ve done to get the Customer Information into the form.

First, the HTML code for the webpage. Notice in particular with the Customer Name and Customer Primary contact that there is an ‘ul’ tagged field with the ‘id’ that ends in the letters ‘AC’. This is the entry point for the AutoComplete drop down list.

<div class="Sales TSM Engineer" id="CustomerInfoCollapsible" data-collapsed="false" data-role="collapsible" data-theme="b" data-content-theme="b">
    <h1>Customer Information</h1>
    <div class="Sales TSM Engineer" data-role="fieldcontain">
        <label for="CustomerName">Customer:</label>
        <input type="text" id="CustomerName" data-theme="b" data-bvalidator="required"/>
        <ul id="CustomerNameAC" data-role="listview" data-inset="true" data-theme="d"></ul>
    </div>
    <div class="Sales TSM Engineer" data-role="fieldcontain">
        <label for="CustomerPrimaryContact">Primary Contact:</label>
        <input type="text" id="CustomerPrimaryContact" data-theme="b" data-bvalidator="required, alpha"/>
        <ul id="CustomerPrimaryContactAC" data-role="listview" data-inset="true" data-theme="d"></ul>
    </div>
    <div class="Sales TSM Engineer" data-role="fieldcontain">
        <label for="CustomerPhoneNum">Contact Phone #:</label>
        <input type="text" id="CustomerPhoneNum" data-theme="b" data-bvalidator="required"/>
    </div>
    <div class="Sales TSM Engineer" data-role="fieldcontain">
        <label for="CustomerContactEmail">Contact Email Address:</label>
        <input type="text" id="CustomerContactEmail" data-theme="b" data-bvalidator="required, email"/>
        </div>
    </div>

You initialize the AutoComplete at the time you init the page. I put it in the onload() function. How I’ve approached this particular project in lieu of how the ConnectWise API works is first, I get the Customer Name (CompanyName in the API) and once I get that, I go after the Primary Contact’s name. Once I have that, I use a callback function that’s part of the AutoComplete to grab the contacts Phone Number and Email address. So, here are the two AutoComplete functions:

Customer Name:

 function CustomerNameAutoComplete() {
        $("#CustomerName").autocomplete({
            target: $('#CustomerNameAC'),
            minLength: 3,
            icon: 'check',
            matchFromStart: true,
            source: baseURL + "ConnectWiseAPI/ConnectWiseAPIService.svc/GetCompanyName/",
            callback: function (e) {
                lichosen = $(e.currentTarget);
                $('#CustomerName').val(lichosen.text());
                CWAPICompanyName = $('#CustomerName').val();
                $("#CustomerName").autocomplete('clear');

            }
        });
    }  

In the above code, we are initializing the AutoComplete on the $(“#CustomerName”) text input. I’ve set it so that it doesn’t begin to go out to the WCF service until the 3rd character is typed in. The source is the URL to the WCF Webservice. ‘baseURL’ is a global variable that is shared amongst all my WFC Services. It’s basically https://www.webserver.com/

In the callback function, I’m setting a global variable ‘lichosen’ to the item chosen the drop down list and then setting the value of $(“#CustomerName”) to the label of the particular ‘li’ chosen in the drop down list. I then set a global variable’s value to the Customer Name and then clear out the autocomplete for future use.

Next, let’s talk about what I’m doing for the Primary Contact Name. For it, I have to use the Customer Name (CompanyName in the API) that was just entered via the previous AutoComplete so that I can search for all contacts that belong to the Company. In the callback function you’ll notice that I call a function that is actually used to call a second function that will in turn call a third function that does the actual Ajax call. I’ll detail those functions later below. Based on how I’ve structured the data coming back from the first Web service, I’m calling the 2nd one with an item of data that was brought back.

The 1st Web Service is structured to bring back an Array of Objects (the AutoComplete library requires this). I bring back the Contacts First and Last Name put together into one Name and I also bring back the Contact’s Id out of the API. In the 2nd Web Service that is ultimately called, I’m actually using the Contact’s Id as the condition that it searches the API against and then it brings back the Contact’s Phone Number and Email address.

function CustomerPrimaryContactAutoComplete() {
        $("#CustomerPrimaryContact").autocomplete({
            target: $('#CustomerPrimaryContactAC'),
            minLength: 1,
            icon: 'check',
            matchFromStart: true,
            source: baseURL + "ConnectWiseAPI/ConnectWiseAPIService.svc/GetContactName/?Conditions=" + $('#CustomerName').val(),
            callback: function (e) {
                lichosen = $(e.currentTarget);
                CWApiGetContactInfoSvc(lichosen.data('autocomplete').value);
                $('#CustomerPrimaryContact').val(lichosen.text());
                $("#CustomerPrimaryContact").autocomplete('clear');
            }
        });
    }   

2nd Webservice’s 1st function:

CWApiGetContactInfoSvc = (function CWApiGetContactInfoSvc(Conditions) {
        var jsondata = { term: Conditions};
        Type = "GET";
        Url = baseURL + "ConnectWiseAPI/ConnectWiseAPIService.svc/GetContactInfo/";
        Data = jsondata;
        ContentType = "application/json; charset=utf-8";
        DataType = "json";
        ProcessData = true;

        // Call the Web Service....
        GETWCFService();
        return;
    });

You’ll notice that once again, I call yet another function that uses global variables that I populated in the previous function. The reason I do this is that I try and have as generic as function’s as possible built into the site so that they can be utilized by multiple pages in multiple ways. Here is the GETWCFService function:

function GETWCFService() {
        $.ajax({
            type: Type, //GET or POST or PUT or DELETE verb
            url: Url, // Location of the service
            data: Data, //Data sent to server
            contentType: ContentType, // content type sent to server
            dataType: DataType, //Expected data format from server
            processdata: ProcessData, //True or False
            //cache: false,
            crossDomain: true,
            success: function (msg)
                //On Successfull service call
            {
                if (msg.hasOwnProperty("d"))
                    // Leave the .d behind and pass the rest of 
                    //  the JSON object forward.
                    GETServiceSucceeded(msg.d);
                else
                    // No .d; no transformation necessary.
                    GETServiceSucceeded(msg);

            },
            // When Service call fails
            error: ServiceFailed
        });
    }

And finally, I call a function on success named ‘GETServiceSucceeded’ where if the data is received and parsed successfully, I do certain operations on the data depending on certain values the data may possess. Basically, I populate fields in the page with the information provided via the Web Service.

   function GETServiceSucceeded(result) {
        if (DataType == "json") {
            resultObject = result;
            if (resultObject) {
                var userdata = JSON.parse(resultObject);
                  if (userdata.Type == "GetUserInfo" && userdata.Role == "AM") {
                    $('#AMPhoneNum').val(userdata.Phone);
                    $('#AMEmail').val(userdata.Email);
                    $('#AMBranch').val(userdata.Branch);
                };
                if (userdata.Type == "GetContactInfo") {
                    $('#CustomerPhoneNum').val(userdata.Phone);
                    $('#CustomerContactEmail').val(userdata.Email);
                };
            } else {
                alert("Error in processing data!");
            };
        } else {
            alert("Result Data type is not JSON");
        };
    };

So, here’s a rundown of the flow of how things work:

  1. Get the Customer Name via the AutoComplete function and populate the text input with the item chosen in the drop down list.
  2. Get the Primary Contact’s Name via the AutoComplete function and populate the text input with the item chosen in the drop down list
  3. In the data that is received with the Primary Contact Name, we get the Contact’s Id and via a callback function, we call another function.
  4. In this function we setup Global variables that will be utilized by yet another function that actually does the Ajax call to the WCF Web service.
  5. With data returned, the previous function calls another function that will process the data and based on values in the data, it will know what text inputs in the page to populate the data into.

So, now let’s look at the WCF Web Services. Here is the service definition:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace ConnectWiseAPI
{

    [ServiceContract]
    public interface IConnectWiseAPIService
    {


        [OperationContract]
        [WebInvoke(Method = "POST",
                    BodyStyle = WebMessageBodyStyle.WrappedRequest,
                    RequestFormat = WebMessageFormat.Json,
                    ResponseFormat = WebMessageFormat.Json)]

        List<string> GetCompanyInfo(ConnectWiseAPI Data);


        [OperationContract]
        [WebGet(
                    UriTemplate = "/GetCompanyName/?term={AutoCompleteString}",
                    BodyStyle = WebMessageBodyStyle.WrappedRequest,
                    RequestFormat = WebMessageFormat.Json,
                    ResponseFormat = WebMessageFormat.Json)]

        string[] GetCompanyName(string AutoCompleteString);

        [OperationContract]
        [WebGet(
                    UriTemplate = "/GetContactName/?Conditions={Conditions}&term={AutoCompleteString}",
                    BodyStyle = WebMessageBodyStyle.WrappedRequest,
                    RequestFormat = WebMessageFormat.Json,
                    ResponseFormat = WebMessageFormat.Json)]

        ConnectWiseAPIService.GetContactNameInfo[] GetContactName(string Conditions, string AutoCompleteString);

        [OperationContract]
        [WebGet(
                    UriTemplate = "/GetContactInfo/?term={Conditions}",
                    BodyStyle = WebMessageBodyStyle.WrappedRequest,
                    RequestFormat = WebMessageFormat.Json,
                    ResponseFormat = WebMessageFormat.Json)]

        string GetContactInfo(string Conditions);

    }


    [DataContract]

    public class ConnectWiseAPI
    {
        
        // The API function we're going to call
        [DataMember(Name = "Action", IsRequired = true)]
        public string Action { get; set; }

        // Search conditions (see "ConnectWise APIs Find by Conditions Syntax" for more information) 
        [DataMember(Name = "Conditions", IsRequired = false)]
        public string Condition { get; set; }

        // optional sort field
        [DataMember(Name = "OrderBy", IsRequired = false)]
        public string OrderBy { get; set; }

        // optional limit on the number of results returned
        [DataMember(Name = "Limit", IsRequired = false)]
        public string Limit { get; set; }

        // optional number of records to skip before returning results
        [DataMember(Name = "Skip", IsRequired = false)]
        public string Skip { get; set; }

    }

}

Here is the Service code behind:

   
using System;
using System.Net;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.ServiceModel.Activation;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Configuration;
using System.Configuration.Provider;

using Newtonsoft.Json;

namespace ConnectWiseAPI
{

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]


    public class ConnectWiseAPIService : IConnectWiseAPIService
    {

        private string url = ConfigurationManager.AppSettings["CWApiHttpUrl"];
        private string site = ConfigurationManager.AppSettings["CWApiBaseSite"];

        public List<string> GetCompanyInfo(ConnectWiseAPI Data)
        {

            List<string> CompanyNames = new List<string>();

            try
            {

                var WebClient = new WebClient();
                var action = new FindPartnerCompaniesAction
                {
                    IntegrationLoginId = "login",
                    IntegrationPassword = "password",
                    CompanyName = "company",
                    Conditions = Data.Condition
                };

                //Make Sure to url encode!
                var result = WebClient.DownloadString(string.Format(url, site, HttpUtility.UrlEncode(action.ToXmlString())));
                var resultAction = FindPartnerCompaniesAction.Deserialize(result);

                for (int i = 0; i < resultAction.Companies.Count; i++)
                {
                    CompanyNames.Add(resultAction.Companies[i].CompanyName);
                }


            }
            catch (Exception ex)
            {
                CompanyNames.Add("Error");
                CompanyNames.Add(ex.Message);
                return CompanyNames;

            }
            return CompanyNames;
        }

        public string[] GetCompanyName(string AutoCompleteString)
        {

  

            var WebClient = new WebClient();
            var action = new FindPartnerCompaniesAction
            {
                IntegrationLoginId = "login",
                IntegrationPassword = "password",
                CompanyName = "company",
                Conditions = "CompanyName like \"" + AutoCompleteString + "*\""
            };

            //Make Sure to url encode!
            var result = WebClient.DownloadString(string.Format(url, site, HttpUtility.UrlEncode(action.ToXmlString())));
            var resultAction = FindPartnerCompaniesAction.Deserialize(result);

            int numofresults = resultAction.Companies.Count;
            int count = 0;

            string[] returnvalues = new string[numofresults];

            for (int i = 0; i < numofresults; i++)
            {
                if (resultAction.Companies[i].CompanyName != null)
                    returnvalues[count] = resultAction.Companies[i].CompanyName;
                else
                    returnvalues[count] = "";
                count++;
            }

            return returnvalues;
            
        }

        public GetContactNameInfo[] GetContactName(string Conditions, string AutoCompleteString)
        {

            var WebClient = new WebClient();
            var action = new FindPartnerContactsAction
            {
                IntegrationLoginId = "login",
                IntegrationPassword = "password",
                CompanyName = "company",
                Conditions = Conditions = "CompanyName = \"" + Conditions + "\" and FirstName like \"" + AutoCompleteString + "*\""
            };

            //Make Sure to url encode!
            var result = WebClient.DownloadString(string.Format(url, site, HttpUtility.UrlEncode(action.ToXmlString())));
            var resultAction = FindPartnerContactsAction.Deserialize(result);
            
	    GetContactNameInfo[] contacts = InitializeArray<GetContactNameInfo>(resultAction.Contacts.Count);

            for (int i = 0; i < resultAction.Contacts.Count; i++)
            {
                if (resultAction.Contacts[i].FirstName != null && resultAction.Contacts[i].LastName != null)
                {
                    contacts[i].value = resultAction.Contacts[i].ContactRecID.ToString();
                    contacts[i].label = resultAction.Contacts[i].FirstName + " " + resultAction.Contacts[i].LastName;
                }
                else
                {
                    contacts[i].value = "";
                    contacts[i].label = "";
                }

            }
            
            return contacts;

        }



        public string GetContactInfo(string Conditions)
        {

            ReturnedContactInfo contact = new ReturnedContactInfo();

            var WebClient = new WebClient();
            var action = new FindPartnerContactsAction
            {
                IntegrationLoginId = "login",
                IntegrationPassword = "password",
                CompanyName = "company",
                Conditions = "ContactRecID = " + Conditions 
            };

            //Make Sure to url encode!
            var result = WebClient.DownloadString(string.Format(url, site, HttpUtility.UrlEncode(action.ToXmlString())));
            var resultAction = FindPartnerContactsAction.Deserialize(result);
            
            contact.Type = "GetContactInfo";

            for (int i = 0; i < resultAction.Contacts.Count; i++)
            {
                if (resultAction.Contacts[i].FirstName != null && resultAction.Contacts[i].LastName != null)
                    contact.Name = resultAction.Contacts[i].FirstName + " " + resultAction.Contacts[i].LastName;
                else
                    contact.Name = "";

                if (resultAction.Contacts[i].Email != null)
                    contact.Email = resultAction.Contacts[i].Email;
                else
                    contact.Email = "";

                if (resultAction.Contacts[i].Phone != null)
                {
                    contact.Phone = resultAction.Contacts[i].Phone;
                    contact.Phone = contact.Phone.Insert(3, "-");
                    contact.Phone = contact.Phone.Insert(7, "-");
                }
                else
                    contact.Phone = "";
            }
            string returnvalues = JsonConvert.SerializeObject(contact);
            return returnvalues;

        }


        T[] InitializeArray<T>(int length) where T : new()
        {
            T[] array = new T[length];
            for (int i = 0; i < length; ++i)
            {
                array[i] = new T();
            }

            return array;
        }


        public class GetContactNameInfo
        {
            public string value { get; set; }
            public string label { get; set; }

        }

        public class ReturnedContactInfo
        {
            public string Type { get; set; }
            public string Name { get; set; }
            public string Phone { get; set; }
            public string Email { get; set; }
        }
    
    }
}

And finally, here is a class file I use to interface with the ConnectWise API:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace ConnectWiseAPI
{
    public class FindPartnerContactsAction
    {
        //Mandatory to all actions
        public string CompanyName { get; set; }
        public string IntegrationLoginId { get; set; }
        public string IntegrationPassword { get; set; }
        
        //Standard fields for Find
        //See documentation for valid conditions
        public string Conditions { get; set; }
        
        //Property to sort by i.e. SRServiceRecID
        public string OrderBy { get; set; }

        //Limit the results to a certain number
        public int? Limit { get; set; }

        //Allow you to do some paging
        //if you limit to 10, the second page you would skip 10
        public int? Skip { get; set; }

        //Returned
        public List<Contact> Contacts { get; set; }

        //When creating the xml, either use a serializer or make sure you xml encode the values.
        public string ToXmlString()
        {
            using (var sw = new StringWriter())
            {
                using (var tw = new XmlTextWriter(sw))
                {
                    new XmlSerializer(typeof(FindPartnerContactsAction)).Serialize(tw, this);
                    tw.Flush();
                    tw.Close();
                    sw.Flush();
                    return sw.ToString();
                }
            }
        }

        public static FindPartnerContactsAction Deserialize(string xml)
        {
            using (var r = new XmlTextReader(new StringReader(xml)))
            {
                return (FindPartnerContactsAction)new XmlSerializer(typeof(FindPartnerContactsAction)).Deserialize(r);
            }
        }

        public class Contact
        {

            public int ContactRecID { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public string CompanyName { get; set; }
            public string Phone { get; set; }
            public string Email { get; set; }
            public string Type { get; set; }
            public string Relationship { get; set; }
            public bool DefaultFlag { get; set; }
            public string AddressLine1 { get; set; }
            public string AddressLine2 { get; set; }
            public string City { get; set; }
            public string State { get; set; }
            public string Zip { get; set; }
            public string Country { get; set; }

        }
    }
} 

That’s basically it. Hopefully you’ll find this helpful if you need to utilize something similar in a project you are working on.

Advertisements
Posted in HTML, Javascript, JQueryMobile, Programming

Dynamically inserting elements into a JQueryMobile page

This is a topic that has come up recently for me so I wanted to share how I went about making it happen.

Say you want to dynamically add an input box, a text area, or even an entire collapsible widget with all sorts of elements inside the collapsible widget.  Why might you want to do this?  Because you need to check a user’s response to something before you decision a reaction in the page.  For example, you have a Checkbox Group that has several items to pick from.  Based on which checkboxes are selected, you may want certain other elements to appear or disappear.

You have two options:

  1. Code all the elements that might ever be needed in the page itself.
  2. Dynamically insert them as needed.

As a new coder, I went with #1 for several starter projects until I came across a project that was complex enough that the there was going to be over 10k lines of HTML code needed.  On top of that, I needed to be able to add items in sequence depending on certain selections by the user.  So I researched how to dynamically add elements into the page as needed.  Now, there are many ways to do this, but I’m going to highlight two main ways that I’ve done this. 

I code everything I do in HTML5, and JavaScript.  Hopefully you’ll be able to extrapolate based on your language of choice:

  1. Have functions built into your JavaScript that have the necessary HTML included in them.
  2. Have separate HTML pages that are loaded dynamically on demand.

Both ways of doing it are similar in many respects with some common code in the main page.  I have a span setup as a marker that tells me where I want a dynamic element to be located at.  I then use JQueryMobile’s ‘InsertBefore’ method to insert a 2nd span dynamically into the HTML and finally, I load the dynamic elements into the 2nd span. 

So why do I use two span’s?  One is to mark where I want to insert at, and the second is used to insert the actual dynamic elements into but it also allows for me to have a simple and clean way of deleting the dynamic element back out of the DOM if needed and later add it back at the right location.  Basically with one line of code, I remove the 2nd span and everything in it is gone.

Here is an example of the first span that I have in my page code upon page load:

<span id="WebHostingCollapsibleInsertBeforeSpan"></span><!-- /WebHostingCollapsibleSpan -->

So, let’s say I have a Checkbox Group and based on a selection in it, I want to insert an entire collapsible that will allow me to answer some questions about what kind of Web Hosting needs I have. Here’s some JavaScript for that.

   $(document).on("change", "#CheckboxGroup", function () {
        if (!$(this).attr('disabled')) {

            // Setup a variable that checks to see if a specific checkbox has been checked
            // If it has, then the value will be 'true'.  If not, it's 'false'.	
            var WebHostingisChecked = $('#WebHostingCheckbox').is(':checked');
            
            // We check the value of the variable and if it is true, we insert
            // the dynamic content into the DOM
            if (WebHostingisChecked == true) {

                // Add a span so that if we later need to delete things, we simply delete the span and everything contained within the span.
                var AddSpan = "<span id=\"WebHostingCollapsibleSpan\"></span>";

                // Insert the span right before the span that was included at page load.
                $(AddSpan).insertBefore("#WebHostingCollapsibleInsertBeforeSpan");

                // Here we use the load() method to load an external html file and then use
                // the trigger method to have it appear in the DOM.
                $("#WebHostingCollapsibleSpan").load('./SubPages/WebHostingCollapsible.html', function () {
                    $(this).trigger('create');
                });

            } else {

                // Since we've unselected the checkbox, we call a function to delete the 
                // element out of the DOM.
                DestroyWebHosting();
            };

        }
    });

If you wanted to store your HTML code in your javascript code that would do the same thing instead of inserting an entire separate HTML file then it would like this:

   // If a change is detected to the checkbox group, then this function is automatically called
   $(document).on("change", "#CheckboxGroup", function () {
        if (!$(this).attr('disabled')) {

            // Setup a variable that checks to see if a specific checkbox has been checked
            // If it has, then the value will be 'true'.  If not, it's 'false'.	
            var WebHostingisChecked = $('#WebHostingCheckbox').is(':checked');
            
            // We check the value of the variable and if it is true, we insert
            // the dynamic content into the DOM
            if (WebHostingisChecked == true) {

                // Add a span so that if we later need to delete things, we simply delete the span and everything contained within the span.
                var AddSpan = "<span id=\"WebHostingCollapsibleSpan\"></span>";

                // Insert the span right before the span that was included at page load.
                $(AddSpan).insertBefore("#WebHostingCollapsibleInsertBeforeSpan");

                var HTMLToInsert = "<div id=\"WebHostingCollapsible\" data-collapsed=\"false\" data-role=\"collapsible\" data-theme=\"b\" data-content-theme=\"b\">";
                HTMLToInsert +=    "    <h1>Web Hosting Services - Worksheet</h1>";
                HTMLToInsert +=    "    <div>";
                HTMLToInsert +=    "        <p>What platforms does the client need for their website(s)</p>";
                HTMLToInsert +=    "        <fieldset data-role=\"controlgroup\" id=\"WebHostingPlatformCheckboxGroup\">";
                HTMLToInsert +=    "            <legend></legend>";		  
                HTMLToInsert +=    "            <input type=\"checkbox\" name=\"WebHostingPlatformCheckboxGroup[]\" id=\"WebHostingPlatformASPDotNetCheckBox\" data-theme=\"a\"/>";
                HTMLToInsert +=    "            <label for=\"WebHostingPlatformASPDotNetCheckBox\">ASP.Net</label>";
                HTMLToInsert +=    "            <input type=\"checkbox\"  name=\"WebHostingPlatformCheckboxGroup[]\" id=\"WebHostingPlatformPHPCheckBox\" data-theme=\"a\"/>";
                HTMLToInsert +=    "            <label for=\"WebHostingPlatformPHPCheckBox\">PHP</label>";
                HTMLToInsert +=    "            <input type=\"checkbox\"  name=\"WebHostingPlatformCheckboxGroup[]\" id=\"WebHostingPlatformHTMLCheckBox\" data-theme=\"a\"/>";
                HTMLToInsert +=    "            <label for=\"WebHostingPlatformHTMLCheckBox\">HTML</label>";
                HTMLToInsert +=    "            <input type=\"checkbox\"  name=\"WebHostingPlatformCheckboxGroup[]\" id=\"WebHostingPlatformColdfusionCheckBox\" data-theme=\"a\"/>";
                HTMLToInsert +=    "            <label for=\"WebHostingPlatformColdfusionCheckBox\">Coldfusion</label>";
                HTMLToInsert +=    "            <input type=\"checkbox\"  name=\"WebHostingPlatformCheckboxGroup[]\" id=\"WebHostingPlatformOtherCheckbox\" data-theme=\"a\"/>";
                HTMLToInsert +=    "            <label for=\"WebHostingPlatformOtherCheckbox\">Other</label>";
                HTMLToInsert +=    "        </fieldset>";
                HTMLToInsert +=    "    </div>";
                HTMLToInsert +=    "    <div id=\"WebHostingPlatformsOtherPlatformDescDiv\">";
                HTMLToInsert +=    "         <label for=\"WebHostingPlatformsOtherPlatformDesc\" class=\"ui-hide-label\">Describe the Other platforms needed:</label>";
                HTMLToInsert +=    "         <textarea id=\"WebHostingPlatformsOtherPlatformDesc\" data-theme=\"b\" data-bvalidator=\"required\"></textarea>";
                HTMLToInsert +=    "     </div>";
                HTMLToInsert +=    "     <div>";    
                HTMLToInsert +=    "         <fieldset data-role=\"controlgroup\" id=\"WebHostingClientNeedPOP3EmailRadioButtonGroup\" data-theme=\"a\">";
                HTMLToInsert +=    "             <legend>Does the Client also need POP3 Email with the website?</legend>";
                HTMLToInsert += "                <input type=\"radio\" id=\"WebHostingClientNeedPOP3EmailYesRadioButton\" name=\"WebHostingClientNeedPOP3EmailRadioButtonGroup\" value=\"Yes\" data-theme=\"a\"/>";
                HTMLToInsert +=    "             <label for=\"WebHostingClientNeedPOP3EmailYesRadioButton\">Yes</label>";
                HTMLToInsert +=    "             <input type=\"radio\" id=\"WebHostingClientNeedPOP3EmailNoRadioButton\" name=\"WebHostingClientNeedPOP3EmailRadioButtonGroup\" value=\"No\" data-theme=\"a\"/>";
                HTMLToInsert +=    "             <label for=\"WebHostingClientNeedPOP3EmailNoRadioButton\">No</label>";
                HTMLToInsert +=    "         </fieldset>";
                HTMLToInsert +=    "     </div>";
                HTMLToInsert +=    "</div>";                          	


                // Insert the HTML into the Span
                $("#WebHostingCollapsibleSpan").html(HTMLToInsert);

                // Trigger a refresh of the DOM so that the new dynamic content shows up.
                $("#WebHostingCollapsibleSpan").trigger('create');


            } else {

                // Since we've unselected the checkbox, we call a function to delete the 
                // element out of the DOM.
                DestroyWebHosting();
            };

        }
    });

Finally, if we want to delete the element we inserted, we have called the DestroyWebHosting() function. Here is the function and within it we use the remove() method:

function DestroyWebHosting() {
    $("#WebHostingCollapsibleSpan").remove();
}

What you probably also want to do just to be thorough is to go and null out any and all variables that may be storing values that were changed in the newly inserted content, null out the actual input boxes if you have any and reset all radio buttons and checkboxes back to default settings and then call the remove() method.

Tagged with: , ,
Posted in HTML, Javascript, JQueryMobile, Programming

First Post

The goals of this blog are many, but suffice to say, it will center around my passion for all things Technology. Hopefully as time goes by, you’ll find posts about Programming, IT Infrastructure, Gadgets, etc. Generally speaking, geekery will abound.

For instance, as I’m writing this, I’m also reloading Windows 7 on the family laptop. It previously had Windows 8 on it.

I absolutely love Windows 8.

After 8 minutes of figuring out where Microsoft had moved everything, I had things under control. The family loves it, especially the 5 year old who went to pre-school the day after having used it the first time and had to tell everyone about it. In fact, I’m writing this post on my home office computer that is running Windows 8.

So why am I reloading Windows 7? Because of two reasons:

The first reason is that Windows 8 doesn’t like the Core 2 Duo CPU in the laptop and the CPU will flat line at 9% utilization.  That’s as high as it goes no matter what the laptop is doing.  That may sound like a good thing, but it’s not.  It causes everything to run really slow.  The 9% is in all reality 100% of what the OS will give me.   After researching this issue for a couple of evenings,  I managed to get around this by loading a utility called RightmarkCPU on the laptop and it allowed me to manually set the voltage and multiplier on the CPU so that it would use more of the available CPU resources.

The problem is the utility requires Administrator access to the machine and has to have a user logged in and running it in the background.   Basically, anytime someone rebooted the laptop, it would go back to using only 9% of the CPU.  To top it off, Windows 8 has to be started in a special mode that will allow the utility to run as the device drivers it loads are unsigned.  Basically, it became a hassle as I had to restart the machine every time someone else restarted it.

The second reason is that the laptop has a built in NIC that is 100 Mbps only and I wanted to setup user profiles that had their docs, pics, vidoes, etc, stored on the PC in the home office.  The 100 Mbps connection was just too slow to effectively do this.  So I researched and found a PCMCIA card that would allow a 1 Gbps network connection.

The problem is, the drivers don’t work very well in Windows 8.   After a few minutes of the PC being on, the NIC becomes unresponsive and loses network connectivity.  Taking the NIC out and putting it back in resets it and you can use the network/Internet for a period of time.  However, at some point, the NIC stops working again.  So, I’m falling back to Windows 7 to see if this fixes this issue.  It may not, but if it does, it also solves the first problem above.

So, this is a random night in my life.  Geekery abounds as I work to get the family laptop working as it should.

Tagged with: , ,
Posted in Uncategorized