Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Saturday, 21 February 2009

JavaScript Collapsible Links

Coding in JavaScript used to be like loving a naughty child. OK, it’s not strongly typed, the debugging is terrible and the cross browser issues are pretty unpleasant but look at his cheeky face. Awwww – he’s so cute running round and setting fire to dogs and he makes my web pages look all clever and interactive.

Over the last few years the naughty JavaScript child has grown up a bit. The The prototype project has swept away a the cross browser unpleasantness, extended the DOM and made the entire thing a lot more like a proper grown up coding language. So in the spirit of playing with an adult I whipped up a collapsible link control using the prototype library.

I’ve published a demo of the collapsible links and the images are a plus and a minus and can be grabbed from the above link. The code uses divs to construct the tree

The code uses divs to construct the tree. Css is used to show and hide the div panels and swap the plus and minus images. Prototype enabled JavaScript is used to wire it together

<html>
<head>
<script src="scripts/prototype.js"></script>
<script>
function setupGrid()
{
arrLinks = $$('#JsGrid a');

for(var i=0;i<arrLinks.length;i++)
{
arrLinks[i].observe('click', togglePanel);
}
}

function togglePanel()
{
var clickedLink = Event.element(event);
var panel = clickedLink.up().next();

if(clickedLink.className == "linkOpen")
{
clickedLink.className = "linkClose"
}
else
{
clickedLink.className = "linkOpen"
}

if(panel.className == "panelClose")
{
panel.className = "panelOpen"
}
else
{
panel.className = "panelClose"
}

}
</script>
<style type="text/css" >
.panelOpen
{
padding: 0px 0px 0px 20px;
display:block;
}

.panelClose
{
padding: 0px 0px 0px 20px;
display:none;
}

.linkOpen
{
padding: 0px 0px 0px 20px;
background:url('images/minus.gif') no-repeat center left;
}

.linkClose
{
padding: 0px 0px 0px 20px;
background:url('images/plus.gif') no-repeat center left;
}

</style>
</head>
<body onload="setupGrid();">
<div id="JsGrid">
<div><a href="#" class="linkOpen">Test 1</a></div>
<div class="panelOpen" >Test content 1</div>
<div><a href="#" class="linkOpen">Test 2</a></div>
<div class="panelOpen">Test content 2</div>
<div><a href="#" class="linkOpen">Test 3</a></div>
<div class="panelOpen">Test content 3</div>
<div><a href="#" class="linkOpen">Test 4</a></div>
<div class="panelOpen">Test content 4</div>
</div>
</body>
</html>

The setupGrid method wires the togglePanel method to the click event of each link. The $$('#JsGrid a'); is prototype cleverness to pick up all the links under the JsGrid element. The togglePanel function does what it says on the tin – shows and hides the panel giving the collapsible tree structure its collapsibility. The only prototype sprinkle is clickedLink.up().next(); which shows off the prototype DOM navigation rather than the old document.getElementById unpleasantness.

All in all I was surprised how little code it took and how readable the code was. Mmmm, tasty and virtually calorie free.

Saturday, 24 January 2009

Estimating Lines of Code

I’ve always been a bit puzzled on why people would use lines of code to estimate projects. It seems that estimating (more realistically guessing) lines of code (LOC) to estimate effort and schedule is way harder that splitting the project into jobs and undertaking an estimate for each job. However reading Steve McConnell’s Rapid Development book has changed my mind.

In it he has charts linking lines of code to effort over a range of criteria. So if you know the LOC for your projects you can plug them into the tables and see how you projects measure up. Moreover you could get lines of code for a project to build a historic set of data tailored to your team to take some of the guess work out of that blackest of all arts – software estimation.

Which got me thinking of how you would quickly get non-commented, non-whitespace lines of code for a Web Application written it ASP.Net



C#
Count the semicolons C#.

CSS
I would count the number of {

HTML
LOC are more difficult here. Possibility to count open angled brackets (<) and maybe divide by 5 – making the assumption that there is 5 tags per line JavaScript and VB.Net
Semicolons doesn’t work so well here as they are optional in the code. You’d need to be a bit cleverer and count the number of carriage returns without comments and with a length of more then one when been trimmed

OR

Quick and dirty: arbitrarily estimate the number of characters per line then whip through all the files and could the characters and divide by the per line estimate.

SQL stored procedures and functions
Like JavaScript you’d be looking at using carriage returns or using the quick and dirty method

Other elements.
For example SQL reports, Data extract components etc…
Can’t do anything with these so get the back of the envelope out and estimate what fraction of the project was spend on these activities. Multiple the LOC by this ratio.



In the best of all worlds we would all use function points or some kind of automated formula based approach but I moved out of the best of all worlds sometime ago and sadly my software development occurs in the dirty old real world. In this world one frequently doesn’t have time to spend half a day calculating historical effort but you’ll always have the opportunity to spend a sneaky 15 minutes seeing how many LOC were wrote and how long it took. It’s always good to marvel at how much work you’ve done and it may even make software estimation a slightly less black art in the future.

Thursday, 2 October 2008

JavaScript and Html Not-Comments

Here’s a puzzle for your Mum, Grandma or beloved

Take one scoop of HTML

<body>
<!--element 1 -->
<div id="element1">Content</div>
<!-- element 2 -->
<div id="element2">Content</div>
</body>

And run a cheeky sprinkle of JavaScript against it


Var element = document.getElementById("element2").previousSibling
Alert(element);

Which element do you hit?

You don’t need to be a Web developing genius to work out that it going to pickup the div element2 then navigate back one so it will hit div element1. Easy! Welll – not really – it actually navigates to the comment. The alert spits out

<!-- element 2 -->

So if you’re navigating the JavaScript DOM that can be a real gotcha. What I found particularly interesting is that this code totally breaks my mental model of how all programming/scripting/markup languages work i.e. comments never count. They’re not included in binaries, they don’t count for code coverage analysis, they don’t display on the UI. Comments never count – except when they do.

Saturday, 13 September 2008

How to make friends and deal with Byzantine .Net control Ids

Anyone who spends anytime developing in ASP.Net rapidly builds up hierarchies of controls. They can rapidly become deep. A typical hierarchy might be

  • Master Page

  • Child Page

  • User Control

  • ASP.Net control


This is simple – multiple stacks of child pages user controls etc.. are possible and I certainly use them all the time.

What surprised me when I started doing this was the effect it had on the element Ids as exposed to JavaScript. I printed off one such example this week – an id of a dropdown list.

ctl00_ContentPlaceHolder1_dashboardMain_ddlOrganisation

Mmmmm – but I thought I’d just called it ddlOrganisation. Apparently not. The breakdown is

  • ct100 – from the master page

  • ContentPlaceHolder1 – from the child page (hold my hand up for this – it’s a rubbish name)

  • dashboardMain – the user control

  • ddlOrganisation – my control that I want to target.



OK, fine. Lots of under the hood .Net stuff going on. But it confused the hell out of me when I wanted to target this stuff in the Javascript DOM. Once you figure out the ID then you could just use it. But any change in the names of your controls higher up in the hierarchy will break it. And it will break it 5.00 p.m. on the day before you are due to ship – believe me. A better idea is to use the ClientID property that ASP.Net controls expose. This will provide the Byzantine ID that we see above.

So to add a JavaScript event I would add the JavaScript into the attribute collection of the control within the ASP.Net page – so adding a JavaScript method to the OnSelect event

ddlOrganisation.Attributes.Add("OnChange", "activateSurveyStart('" + ddlOrganisation.ClientID + "')");

And to complete the circle – register the Javascript file programmatically in your usercontrol to avoid tears later

Page.ClientScript.RegisterClientScriptInclude("genericScript", "scripts/genericScript.js");

Not a revolutionary method admittedly (none of my stuff ever will be – promise). But I use this all the time and I think it’s more obscure than it should be. And the making friends thing? Well, be nice to people and bring cakes into your office every Friday. That’ll do the trick