Musings<Rampage>
- curiosities of development, life, the universe and everything -
November 24th, 2008

Here is some useful JavaScript that wrote today to change a CSS class based on the state of a checkbox.

function replaceCssClassOnElementBasedOnCheckBoxState(checkboxId, elementToChangeId, checkedCssClassName, uncheckedCssClassName)
{
    var selectedElement = document.getElementById(elementToChangeId);
    var checkBox = document.getElementById(checkboxId);
    if(selectedElement && checkBox)
    {
        if(checkBox.checked)
            selectedElement.className = checkedCssClassName;
        else
            selectedElement.className = uncheckedCssClassName;
    }
}

For Example:

The style of this div should change based on the state of the checkbox.

September 17th, 2008

I recently needed a textbox that would fire a server event when the textbox’s onblur JavaScript event was fired.  It took a while of googling and asking coworkers questions to figure out how exactly to do it.  Couldn’t seem to find an example of exactly what I needed.

I started off by creating a class that inherited from textbox and implemented ICallBackEventHandler.  I soon realized that this was not going to work for what I needed.  The ICallBackEventHandler is best suited for a simple Ajax control that just needs to update its own content.  Problem is that I need a post back to happen in order to update other controls on the page.

 

So instead of implementing the ICallBackEventHandler interface I implemented the IPostBackEventHanlder interface.  This turned out to be a much simpler, cleaner way to do it.

When implementing the IPostBackEventHandler you must Implement the RaisePostBackEvent method:

 

public class BlurTextbox : TextBox, IPostBackEventHandler
{
    #region Implementation of IPostBackEventHandler

    /// <summary>
    /// When implemented by a class, enables a server control to process an event raised when a form is posted to the server.
    /// </summary>
    /// <param name="eventArgument">A <see cref="T:System.String" /> that represents an optional event argument to be passed to the event handler. </param>
    public void RaisePostBackEvent(string eventArgument)
    {

    }

    #endregion
}

 

This method is what gets called by .net’s JavaScript when your control does a post back.

Now what we want to do is create the JavaScript function that will cause the post back will allow the RaisePostBackEvent method to handle the logic for that event.

 

I just created a method on the textbox that returns the script.  You can use the Page.ClientScript.GetPostBackEventReference(Control control, string argument) method but this is not necessary because all the it generates is __doPostBack(’controlName’,'argument’), either way works.

 

If you want to be able to have multiple instances of the control on the same page you need to write it yourself, this is what I did:

private string GetScript()
{
    return "function OnBlurred(control, arg)\n{\n __doPostBack(control, arg);\n}";
}

There are two parameters needed, the control and the argument, the control string that the asp.net JavaScript call is expecting will need the textbox’s UniqueID for it to work properly. 

 

Next I created a server side event on the control called Blur:

public delegate void OnBlurDelegate(object sender, EventArgs e);

public event OnBlurDelegate Blur;

private void RaiseOnBlurEvent()
{
    if(Blur != null)
    {
        Blur(this, EventArgs.Empty);
    }
}

Now we can call the RaiseOnBlurEvent() method in the implemented RaisePostBackEvent() method like:

public void RaisePostBackEvent(string eventArgument)
{
    RaiseOnBlurEvent();
}

Lastly I overrode the OnInit event, called the base.  I check if that script is already registered, if it’s not I register it, otherwise move one.  Then registered the OnBlurred script we created, and added the JavaScript onblur event attribute to the textbox.  I pass in the UniqueID and empty quotes because I don’t need any arguments.

 

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    if (!Page.ClientScript.IsClientScriptBlockRegistered("OnBlurTextboxEvent"))
        Page.ClientScript.RegisterStartupScript(GetType(), "OnBlurTextboxEvent", GetScript(), true);
    Attributes.Add("onblur", "OnBlurred(’" + UniqueID + "’,”)");
}

Now all that is left to do is use it on some web page and setup the server side handling.

 

Aspx:

<cc3:BlurTextbox ID="Test" runat="server" OnBlur="Test_OnBlur"></cc3:BlurTextbox>

Server Handling:

 

protected void Test_OnBlur(object sender, EventArgs e)
{
}

The whole thing is here.

September 7th, 2008

I just started working on a new Firefox theme, it is actually just a modification of the existing one.  I went through and de-saturated all of the icons in the default Firefox 3 theme.  I have plans to eventually create my own icons and provide monochromed icons for some of the popular extensions.

 

Here are some screen shots:

 

It was all fairly simple to do, but ran into a bit of an issue after uploading it Mozilla’s official add-on page.  A good resource is Mozilla’s own documentation, http://developer.mozilla.org/En/Creating_a_Skin_for_Firefox.

Basically all I had to do was grab Firefox’s default theme folder, usually located at FireFox\chrome\classic.jar, then you have to extract the items, it is basically just a zip folder, so you can use 7zip or winrar.

 

Then you’ll want to create a new folder somewhere else with the title of your theme, we’ll use BadAssTheme.  Inside that folder you’ll want a chrome folder, copy the browser, communicator, global, help and mozapps folders from the classic theme into your new chrome folder, also copy the icon.png and preview.png files into your chrome folder.  Create a content.rdf and install.rdf, follow the instructions in Mozilla’s documentation for what needs to be in those files.  Go back up to the BadAssTheme folder, create a chrome.manifest file, and put a copy of the icon.png, preview.png, and install.rdf in here as well.  I’ll get to what goes into the manifest next.

 

Once you have gone through and modified all of the images and css you want its time to package everything up.  The way that seems most commonly used is to have an xpi in the chrome folder and then a jar for what is in the root level.  So zip everything up in the chrome folder, rename the file from chrome.zip to chrome.xpi.  Inside of the chrome.manifest you need to specify where the skin files are located inside of the xpi, for example:

 

skin browser BasAssTheme jar:chrome/chrome.xpi!/browser/

skin communicator BasAssTheme jar:chrome/chrome.xpi!/communicator/

skin global BasAssTheme jar:chrome/chrome.xpi!/global/

skin mozapps BasAssTheme jar:chrome/chrome.xpi!/mozapps/

skin help BasAssTheme jar:chrome/chrome.xpi!/help/

 

So now you should only have the xpi container in the chrome folder and a manifest, icon.png, preview.png, install.rdp in the BadAssTheme folder.  Now zip everything in the BadAssTheme folder into a BadAssTheme.zip and rename to BadAssTheme.jar.  You should be good to go now.

 

The issue I ran into with Mozilla’s theme website is that the download works on one of my computers but doesn’t on my other.  The error I am getting is:

 

Firefox could not install the file at

https://addons.mozilla.org/en-US/firefox/downloads/file/37146/monochrome-0.4-fx.jar

because: Invalid file hash (possible download corruption)

-261

 

I am not sure if this is actually a bug in Firefox or with Mozilla’s hosting, because it work on one PC and not the other, they both have the same version of Firefox installed.  Have not been able to find anything helpful through google.  It does install properly if you download it manually and drag and drop it onto Firefox’s add-on manager, so who knows.

 

Source: http://code.google.com/p/monochrometheme

 

Theme: https://addons.mozilla.org/en-US/firefox/addon/8791

September 3rd, 2008

Ran into an issue today when I needed to get a column from a many to many relational table.  It was not in any table that mapped directly to any of my entities, so I was somewhat dumb founded on how to proceed.

 

An example would be if you have a school domain where there are multiple Students associated with multiple Courses.  You would most likely have a Student and Course entity that map to their respective database tables and a Student_Course table that does not map directly to anything.  Depending on the point of view you are working with you would probably have the Student with a collection of Course or vice versa.  For this example let’s say that we are looking at it from the perspective of a student.  As a Student I would want to see my final grade for the Course , for simplicity let’s say that the final grade is stored in the Student_Course table.  The most likely place to want that Grade is on the Course.  When you are mapping the Course you would have a property for Grade mapped out,

<class name="Course" table="Course">

    <id name="Id" column="Id" />
    <property name="Name" column="Name" />
    <property name="Description" column="Description" />
    <property name="FinalGrade" column="FinalGrade" />

</class>

but where would you specify the relational table to pull the Grade from? With the code above NHibernate will blow chunks, saying it cannot find the column FinalGrade in the Course table even though it is a property on your Course entity.

 

Well, in NHibernate there is a <join> mapping that you can use to map columns from other tables to the entity you are working with.  So, in the example we would replace the mapping:

<property name="FinalGrade" column="FinalGrade" />

with:

<join table="Student_Course" optional="true" >
    <key column="CourseId" />
    <property name="FinalGrade" column="FinalGrade" />
</join>

We would specify the many to many relational table with the table parameter.  Set the key column to the CourseId so NHibernate can join on the Id and you specify the property/column as normal.  Note the optional attribute, this is used to specify if you still want results returned where FinalGrade may be null.  This is more apparently useful in situations where you are loading courses and you don’t really care if there are FinalGrades associated with the Courses. 

 

Now when I am looking at a Student’s Courses the will all have the final grade populated.

March 11th, 2008

If and when is it ever good to say no to a customer?

I have been pondering this question a lot lately. My thoughts have been on this topic because of something we promised the customer of my current project.
After all of the requirements gathering, analysis and design our customer informed us that they need to be able to perform a certain process with the system, that was not currently planned for. We inquired further, and came to find out that the chances of them needing this additional functionality is 1 in 1,000,000. They only perform said task very rarely.

This was a new customer so we agreed to add the functionality even though there would have to be some massive changes in the design and in what we had already implemented. I am not sure that agreeing to this proverbial “scope creep” was the correct thing to do.

We are going back and refining some things as we are nearing the end of this project. Unsurprisingly because of that additional functionality some of the customer’s business processes are now broken. By broken, I mean there are some stringent rules about the flow of data and the accuracy of that data. The requested functionality blurs the lines of the data being entirely accurate.

There is now an issue near the end of the project that could have been avoided closer to the start of it. Had we not implemented that request it would have been in no way detrimental to the current system. It’s only on that rare occasion when pigs fly that our client needs to this. In order to prevent further hiccups with future customer my team needs a way to determine if and when to just say no. The point is that I am not entirely sure when to tell your customers no. I’m sure it varies on a case to case basis.

In this case I believe we would have been much better saying no. That would have prevented the hiccup in the end of our development, prolonging the customer’s wait. In turn, they might actually be happier if they received their product sooner rather than later. Maybe even requested the additional functionality as a future enhancement. I still can’t ignore the seeds of the customers first mentality implanted into my brain no doubt by my business professors in college. Damn them for clouding my mind. :-)

March 10th, 2008

A few weeks ago I was looking for a solution to parse an XML file into XHTML. This can be helpful if you want to store data for your web site in XML and want a quick scripting language to access it and parse it, this technique can be used to parse RSS since it is XML.

I spent a couple of hours scouring the web for information. I was able to gather bits and pieces from different ends of the Internet to come up with a solution.

First let’s look at the XML document. The data in my XML file contains multiple choice questions and their answers. This means I will need to parse out the data and form a label for the question and radio buttons for the answers. Nothing fancy here, my question node has a number attribute and a text attribute. The answer nodes have a text attribute as well, and a value attribute to determine whether the radio button should be checked by default.

The XML looks like:

<?xml version=”1.0″ encoding=”iso-8859-1″?>
<questions>
    <question number=”1″ text=”How painful is it to parse XML with JavaScript?”>
        <option value=”Y” text=”Ungodly painful”></option>
        <option value=”N” text=”Extremely painful”></option>
        <option value=”N” text=”Moderately painful”></option>
        <option value=”N” text=”Mildly painful”></option>
    </question>
    <question number=”2″ text=”How retarded is JScript?”>
        <option value=”N” text=”Poo flinging retarded”></option>
        <option value=”N” text=”Extremely retarded”></option>
        <option value=”Y” text=”Moderately retarded”></option>
        <option value=”N” text=”Mildly retarded”></option>
    </question>
</questions>

On to coding, you need to determine what sort of browser the user will be using to view your parsed XML. The function I found to check the browser and load the XML appropriately, checks for Internet Explorer and non-evil-empire browsers, Firefox, Opera, etc.

Internet Explorer uses a different type of type of JavaScript when parsing a web page. Without boring you about the details, the basic difference is Microsoft uses a custom version of JavaScript called JScript, leave it to Microsoft to make life hard on us all.

I gathered the load XML data function from w3schools.
Here’s the function to check the browser and load the XML document:

//create variable to store the XML document
var xmlDoc;
//set variable to a nodeType of ELEMENT_NODE
//this way we can easily tell what type of node we are grabbing in our code
var ELEMENT_NODE = 1;
//create function to load the XML data from the specified document
//found this at w3schools http://www.w3schools.com/xml/xml_parser.asp
function loadXmlData()
{
    // code for IE
    if (window.ActiveXObject)
    {
        //setup active x object
        xmlDoc=new ActiveXObject(“Microsoft.XMLDOM”);
        //tell browser that its not an asynchronous call
        xmlDoc.async=false;
        //provide URL to the XML document to be parsed
        xmlDoc.load(“http://sbiefeld.com/wp-content/uploads/2008/03/questions.xml”);
        //call function to parse data
        writeListForPOSBrowsers();
    }
    // code for Mozilla, Firefox, Opera, etc.
    else if (document.implementation && document.implementation.createDocument)
    {
        //set up document variable
        xmlDoc = document.implementation.createDocument(“”, “”, null);
        //call function to parse data
        xmlDoc.onload = writeListForRealBrowsers;
        //provide URL to the XML document to be parsed
        xmlDoc.load(“http://sbiefeld.com/wp-content/uploads/2008/03/questions.xml”);
    }
    else
    {
        //fire alert if XML cannot be parsed by an unknown browser
        alert(‘Your browser cannot handle this script’);
    }
}

Notice the different function calls per browser, writeListForPOSBrowsers() and writeListForRealBrowsers(). This was to handle the peculiarities of IE and JScript. The writeListForPOSBrowsers() function handles the parsing for IE while the writeListForRealBrowsers() function handles the parsing for other browsers.

I guess I will start with the writeListForPOSBrowsers() first and save the best for last. The basic flow is: loop through the question nodes in the XML file and pull out question attributes and parse them into HTML elements. For each question node, I loop through the answer nodes to and create the radio buttons for the answer choices.

The most frustrating thing is the lack of support for the DOM that JScript has. Instead of being able to reference HTML elements and append data accordingly I had to manually put my HTML elements in a string and then append to that string. Once everything is in place, I put that HTML string in the document. See comments in code for more specifics.

//parses XML for IE browser
//because of lack of sufficient DOM support in JScript things are done a bit differently
//i.e. hard coding html elements
function writeListForPOSBrowsers()
{
    //searches for and gets the question tag elements in the XML file
    var questions = xmlDoc.getElementsByTagName(‘question’);
    //creates an HTML string and adds an unordered list element
    var htmlCode = ‘<ul>’;
    //loop through all of the question elements
    for (i=0; i < questions.length; i++)
    {
        //get the question number from the number attribute of the question element
        var questionId = questions[i].getAttribute(‘number’);
        //add list item and question number to HTML string
        htmlCode += ‘<li>’+‘(’ + questionId + ‘) ‘;
        //ensure we are still dealing with a node of type ELEMENT_NODE
        if (questions[i].nodeType != ELEMENT_NODE) continue;
        //store the question data
        var cdata = questions[i].getAttribute(‘text’);
        //add question data and closing list item tag to HTML string
        htmlCode +=    cdata + ‘</li>’;
        //time to loop through the answer nodes
        for (j=0; j < questions[i].childNodes.length; j++)
        {
            //adds break if not the first item, used purely for aesthetic reasons
            if(j!=0){htmlCode += ‘<br/>’;}
            //create a unique id for the input element
            var inputId =  questionId + ‘_’ + j;
            //ensure we are still dealing with a node of type ELEMENT_NODE
            if (questions[i].childNodes[j].nodeType != ELEMENT_NODE) continue;
            //gets any answer text data from the node
            var rbtnTxt = questions[i].childNodes[j].getAttribute(‘text’);
            //gets any value data from the node
            var isChkd = questions[i].childNodes[j].getAttribute(‘value’);
            //declare variable to hold isChecked value
            var isChkdValue;
            //checks value data to set checked attribute on radio button
            if(isChkd.toUpperCase() == ‘Y’)
            {
                //set radio button to checked
                isChkdValue = ‘checked’;
            }
            else
            {
                //set radio button to unchecked
                isChkdValue = ;
            }
            //adds input element tags and attribute values to the HTML string
            htmlCode += ‘<input type=”radio” id=”‘ + inputId + ‘” name=”question’+i+‘” ‘+isChkdValue+‘ value=”‘+ rbtnTxt+‘”‘;
            //adds label element that stores answer text data to the HTML string
            htmlCode += ‘<label>’+rbtnTxt+‘</label>’;
        }
        //add break elements to the HTML string
        htmlCode += ‘<br/><br/>’;
    }
    //add questions and answers to the page
    document.getElementById(‘updateTarget’).innerHTML = htmlCode;
}

Now, the best for last. The function to parse XML for non-IE browsers. In this function I could use the DOM, w00t for strongly typed objects, well kind of, since JavaScript is inherently not typed at all, but that is another topic.

I use exactly the same process as before loop through the question nodes and for each loop though its answer nodes. Then append the parsed items to the page.

//parses XML for non-IE browsers
function writeListForRealBrowsers()
{
    //searches for and gets the question tag elements in the XML file
    var questions = xmlDoc.getElementsByTagName(‘question’);
    //creates an HTML ul element and stores it in a variable for later use
    var ul = document.createElement(‘ul’);
    //loop through all of the question elements
    for (i=0; i < questions.length; i++)
    {
        //creates an new HTML li element and stores it in a variable
        var li = document.createElement(‘li’);
        //creates an new HTML br element and stores it in a variable
        var brk = document.createElement(‘br’);
        //get the question number from the number attribute of the question element
        var questionId = questions[i].getAttribute(‘number’);
        //I create a text node to store the question number
        var questoinNum = document.createTextNode(‘(’ + questionId + ‘) ‘);
        //append the question number to the list item element
        li.appendChild(questoinNum);
        //append the list item to the unordered list element
        ul.appendChild(li);
        //ensure that the current node we are looking at in the loop is an ELEMENT_NODE, if so continue on our journey
        if (questions[i].nodeType != ELEMENT_NODE) continue;
        //create a text node the hold the question data
        var cdata = document.createTextNode(questions[i].getAttribute(‘text’));
        //append question data to the list item
        li.appendChild(cdata);
        //append a break element to the list item
        li.appendChild(brk);
        //time to loop through the answer nodes
        for (j=0; j < questions[i].childNodes.length; j++)
        {
            //creates an new HTML br element and stores it in a variable
            var brk = document.createElement(‘br’);
            //create a input element for the current answer node we are on
            var inpt = document.createElement(‘input’);
            //create a label to hold the answer data
            var lbl = document.createElement(‘label’);
            //specify the type of input element, in this case a radio button
            inpt.type = ‘radio’;
            //create a unique id for the input element
            var inputId =  questionId + ‘_’ + j;
            //set the unique id
            inpt.id = inputId;
            //create a unique name for the input element
            inpt.name = ‘question’ + i;
            //ensure we are still dealing with a node of type ELEMENT_NODE
            if (questions[i].childNodes[j].nodeType != ELEMENT_NODE) continue;
            //gets any answer text data from the node
            var rbtnTxt = questions[i].childNodes[j].getAttribute(‘text’);
            //gets any value data from the node
            var isChkd = questions[i].childNodes[j].getAttribute(‘value’);
            //checks value data to set checked attribute on radio button
            inpt.checked = (isChkd.toUpperCase() == ‘Y’);
            //sets value data
            inpt.value = rbtnTxt;
            //appends answer text data to list item
            lbl.appendChild(document.createTextNode(rbtnTxt));
            //appends input element to list item
            li.appendChild(inpt);
            //appends answer text to the list item
            li.appendChild(lbl);
            //appends a break element to the list item
            li.appendChild(brk);
        }
    }
    //appends unordered list to the page
    document.getElementById(‘updateTarget’).appendChild(ul);
}

Last but not least, the HTML to use the javascript:

<body onLoad=”loadXmlData()” id=’updateTarget’></body>

Simple enough, right? Well I hope my gatherings of how to parse XML with Javascript has been useful and helpful. This may by no means be the best way to do it, and it could be re-factored. It does however stay true to the title, Quick and Dirty XML Parsing with JavaScript. Grab the XML file and grab and test the HTML/JavaScript. Thanks much and expect more.

March 10th, 2008

Well, I got a working version of my WordPress theme in place. There will still need to be some tweakage. I basically took the default theme and modified it heavily to get it to look the way it does. There are some definite issues, but I will get to those later.

March 9th, 2008

Welcome to my blog, I am still in the process of setting everything up appropriately. Right now I am working on a custom theme. Stay tuned for updates…

Musings<Rampage> is proudly powered by WordPress
Entries (RSS) and Comments (RSS).