Archive Page 2

txjs

I’ve already helloed into the box about this, but I am still sort of having some issues getting over it. Hlysht, Texas Javascript was amazing. Pretty much everything I saw was just crazy awesome. I learned things, which was a problem I had with most of the technical talks I went to at SXSWi (note that sx didn’t inspire me to come back and drool about it on my stupid never-updated blog). There was exactly one talk that didn’t teach me something new or make an argument I hadn’t heard before, and even that would have been mind-blowing if I hadn’t been working on the specific project I’ve been working on for the past year. I wish I could do this shit every weekend.

My favorite talks were Crockford’s, John Resig’s, Nicole Sullivan’s, and Paul Irish’s. I’d link to them, but as far as I know they’re not online yet.. I plan to link to them, though, because I want to revisit every single one of them (and most of the others, honestly).

It really never occurred to me until yesterday how jaded I am about what I do. It’s like I left my brain back in the 90s, when front end development was something dirty and every other kind of developer thought you were a moron if you messed around with webpages (something I still contend is bullshit, because it’s a lot easier just getting something to compile and run on a server that’s completely under your control than to build applications that have to work in places you’ve never even imagined out of what in the past amounted to packing peanuts and duct tape). While I’ve been walking around with a giant chip on my shoulder after having been talked down to one too many times, Javascript has been transforming into something thoroughly badass. I’ve been aware of this, but never actually noticed, if that makes any sense. Even if the frontend still doesn’t get the respect it deserves in certain circles, um, we have geniuses.

The one thing I regret about yesterday was not trying to talk to more of those geniuses. For reasons I can’t really explain, I was completely terrified of them, even though the ones I did manage to speak to were totally nice and awesome. Ok, that’s not 100% true, as I was rude (stupidity, not malice) to one of the speakers and pissed him off. So two regrets, the other being that I didn’t go to any of the server side Javascript talks. I got my ass schooled at the Driskell and am now finally convinced that this is something I should find a way to implement as soon as possible.

A final to-do item is to try and contribute some of the plugins and fixes I’ve made for my own use to the open source projects they correspond to. I feel like there’s another world where the Javascript is more exciting by orders of magnitude, and it’s kind of chickenshit to hang out around the perimeter implementing things other people have written instead of trying to actually participate. On the whole, I feel genuinely inspired in a way I haven’t since I started doing layouts with CSS instead of tables. There’s some really cool shit going on and I can’t believe I’m just now realizing it.

jTemplates: easy answers to dumb questions

I’ve been trying to use jTemplates for a fairly complex interface that displays quite a bit of data. The documentation on their site is pretty minimal, so I’ve come up with a lot of what may be very dumb questions that I’ve been forced to answer myself, by trial and error (how tacky).

I figured I would post these in hopes of saving someone else some wondering:

1. Can you treat an array like an array once it’s part of your template data?

Yep. In my data, Columns is an array, and this code works great:

<table class="{#if $T.Columns.length == 1}onecolumn{#/if}">
{#if $T.Columns[0].Label != null}
<thead>
...

2. Does whitespace matter?

Apparently not – see above.

3. How do you refer to a property of a parent object from a child template?

I couldn’t figure this out, so I worked around it by adding the property I needed to the root object I was passing into the child. I ended up doing this in a function because neither of the two delimiters jTemplates uses – {} and {#} – can be used for straight assignment as far as I could tell.

{#foreach $T.Columns as c_f}
{#include COLUMN_CELL root=addFieldType($T.c_f,$T.FieldType)}
{#/for}
...
function addFieldType(obj, ft) {
obj.FieldType = ft;
return obj;
}

4. Can I put a property of the current object into my call to a child template?

Seems like no. What I really wanted to do instead of the code above was this, which does not work:

{#foreach $T.Columns as c_f}
{#include COLUMN_CELL[$T.FieldType] root=$T.c_f}
{#/for}
...
{#template COLUMN_CELL[0]}
<td><input type="radio" disabled="disabled"/></td>
{#/template COLUMN_CELL[0]}
{#template COLUMN_CELL[1]}
<td><input type="checkbox" disabled="disabled"/></td>
{#/template COLUMN_CELL[1]}

For now, all I have is those four items.. I’m sure I’ll come up with more as I get into the hard parts.

MVC in Javascript

Nothing against Ajaxian, but I don’t usually look to them for pithy wisdom – mostly I look to them for clever jQuery plugins and stuff. However, the paragraph at the end of this post on MVC for Javascript sums up my feelings pretty well:

If you think that view source / semantic markup is a great feature of the Web platform, then this kind of world is a touch worrying, but major apps have been doing this for years.

Once I worked on this project with a lot of contractors from IBM, and they were the ones defining the architecture. They had a very literal approach to MVC. As in, every single link went through a controller. Home link? Ask the controller. About Us link? Ask the controller. I’ve implemented MVC in C# (back before they had the framework for it, which from what I gather is pretty cool) and had it be useful, don’t get me wrong.

MVC to me is one of those FUD problems, though. Even the experts can’t quite agree on how it should be implemented. Reminds me of the not-Agile-enough or not-semantic-enough debates that seem to eat up a lot of valuable time that would be better spent coding. This is why I want MVC to keep its white-gloved, mechanically precise fingers off my Javascript.

As far as I’m concerned, there is no good pattern except the one that is obvious. The one that makes you smack your head, exclaiming, “Of course!” because it is perfectly suited to your problem and its application is absolutely clear. I think of the Factory pattern as a good example. What it does and why you need it aren’t up for debate. MVC, on the other hand, is subject to interpretation once you try to apply it to environments it didn’t grow up in. Javascript is a language for manipulating CSS and HTML. Manipulating the View. There is no single, clear answer to the question of how to apply MVC to Javascript because MVC in Javascript doesn’t answer a need. Forgive me because – again – MVC has been very useful to me in the past (on the backend), but in this context MVC is nothing more than a buzzword.

cheesy vs. reinventing the wheel

I kind of want to use the Google Docs API for Slushmine. However, I worry that would be totally cheesy. How do you weigh costs and benefits when deciding whether to add third-party functionality?

If this were a site that I wanted to make tons and tons of money, that would be one thing, but really I just want it to be useful. Brand isn’t so important and so if people see a Google logo on something, I don’t think it’s the end of the world. And if the functionality were a necessity, I’d definitely never consider using something I didn’t have any control over to solve the problem. However, we really need very little document processing functionality. Mainly I want to offer people an easy way to copy and paste.

If I mistrusted Google, as I know a lot of people do, I’d also probably be quicker to consider reinventing the wheel. But I don’t. Google produces useful tools and products, doesn’t misrepresent their intentions or stoop to gimmicks, and is a company I think of as fairly ethical. That could change somewhere down the line, but if it does, it’s easy to yank references to an external API and replace it with something written in-house. In the short term, my goal is just to get something working. That said, though, I’d never consider using Google for site search. So why is that too cheesy, while using Google Docs isn’t?

@font-face: ur doin it wrong.

The good news is that slushmine is getting closer to live. If you’re interested in writing for fun, you can sign up to be updated when the site goes live, or leave me a comment here if you want to be part of the closed beta.

The bad news is my tragic failure to grasp @font-face. Despite the rumors that Safari, Opera, and the latest Firefox release support it, it does absolutely nothing when I try to apply it to that little welcome page. I’m currently trying to use the font Junction from The League of Moveable Type, but I’ve tried several others, in case the font file I downloaded was the problem. Seemingly, it wasn’t. Currently, Firebug doesn’t even show my @font-face declaration, which leaves me a little concerned about my syntax.

I’m using some pretty simple code, nothing remotely fancy:

/* Font credit: http://www.theleagueofmoveabletype.com/fonts/1-junction */
@font-face {
font-family: Junction;
src: url(font-info/Junction-01.otf) format("opentype");
font-style: normal;
}

I’ve been reading bits and pieces on @font-face for months and been excited to have a place to try it out. Slushmine’s dull Tahoma seemed like a great candidate, but if I bang my head against the desk much longer I may just settle for that.

two steps back

I’m in a bad place. I have over 8,000 lines of Javascript here that control a cool AJAX-heavy application. These 8,000-some-odd lines don’t perform so hot. In IE6, some silent memory leak causes the application to get slower and slower until it stops performing altogether. Worse, my code only constitutes about 600 of those lines, so I’m not completely confident in my plans to refactor it.

After going all through it and reading everyone’s lists of tips on increasing performance, there still weren’t a lot of apparent problem areas. The main issues I saw were:

  • 8,000+ lines of code
  • People keep opening the site in IE6

Neither of those are things I can really correct. Especially the latter, for reasons I can’t discuss lest my head explode.

One reason there’s so much code in this application is that numerous DOM elements are added and wired up dynamically. Modern browsers seem to handle this well, so I don’t want to imply it’s excessive, but it is the thing I can control that’ll offer the biggest performance boost if I change it. In most cases, these elements are added dynamically so the code doesn’t have to go looking for them later to toggle their CSS classes or attach event listeners. Because of a custom templating system that provides the meat of the frontend, adding unique IDs to have a handy reference to these elements isn’t an option.

What I’m considering right now is what can be moved inline. This is hard to consider because of the voices in my head screaming that we don’t put things inline anymore, not CSS and especially not calls to Javascript functions. The truth is, though, that if I moved a lot of the event code into functions accessible from outside the objects that call it right now, moved properties that are being saved on Javascript objects into unglamorous innerHTML, and simply set the styles of elements inline rather than using YUI methods, I’d probably save a bunch of code.

Since I started using Javascript libraries I’ve been imagining a coming utopia where we’d never worry about cross-browser compatibility and our frontends would be as complex as we wanted. Now I’m wondering where the tipping point is. It’s uncomfortable to think we may have to throttle back usage of the wide variety of impressive tools the past few years have provided because what we’re doing with them is more than the average machine can handle.

hierarchies, taxonomies, categories, drill-downs, etc.

I searched all over the place for a tidy pattern to deal with displaying hierarchical data for selection (as in a set of categories and sub-categories or a taxonomy), and couldn’t find anything. I think everyone’s aware of how this can be done with AJAX, but I wanted something that would still work without needing Javascript or a round-trip to the server each time a parent category changed. Obviously that means storing the entire taxonomy on the page, which is only realistic for some uses of this sort of control, but it’s those uses I’m interested in.

My solution is to load the entire taxonomy into an unordered list and include a radio button in each list item. This shows the hierarchy clearly and lets the user select a node of any depth (a requirement in my case). I use some Javascript to hide the radio buttons and show/hide child lists based on clicks on the list items themselves, then check the radio buttons behind the scenes. I’m wondering if this is the best possible solution for my circumstances. My hope is that neatly organizing the data in this way makes it more accessible, but I’m no accessibility expert.

The HTML itself is pretty simple (excuse the junk data):

<div id="taxonomy">
	<ul>
		<li><input type="radio" name="ghj" value="A" /> A
			<ul>
				<li><input type="radio" name="ghj" value="I" /> I
					<ul>
						<li><input type="radio" name="ghj" value="1" /> 1
							<ul>
								<li><input type="radio" name="ghj" value="a" /> a</li>
								<li><input type="radio" name="ghj" value="b" /> b</li>
								<li><input type="radio" name="ghj" value="c" /> c</li>
								<li><input type="radio" name="ghj" value="d" /> d</li>
								<li><input type="radio" name="ghj" value="e" /> e</li>
							</ul>
						</li>
						<li><input type="radio" name="ghj" value="2" /> 2</li>
						<li><input type="radio" name="ghj" value="3" /> 3</li>
						<li><input type="radio" name="ghj" value="4" /> 4</li>
						<li><input type="radio" name="ghj" value="5" /> 5</li>
					</ul>
				</li>
				<li><input type="radio" name="ghj" value="II" /> II</li>
				<li><input type="radio" name="ghj" value="III" /> III
					<ul>
						<li><input type="radio" name="ghj" value="6" /> 6
							<ul>
								<li><input type="radio" name="ghj" value="f" /> f</li>
								<li><input type="radio" name="ghj" value="g" /> g</li>
								<li><input type="radio" name="ghj" value="h" /> h</li>
								<li><input type="radio" name="ghj" value="i" /> i</li>
								<li><input type="radio" name="ghj" value="j" /> j</li>
							</ul>
						</li>
						<li><input type="radio" name="ghj" value="7" /> 7</li>
						<li><input type="radio" name="ghj" value="8" /> 8</li>
						<li><input type="radio" name="ghj" value="9" /> 9</li>
						<li><input type="radio" name="ghj" value="10" /> 10</li>
					</ul></li>
				<li><input type="radio" name="ghj" value="IV" /> IV</li>
				<li><input type="radio" name="ghj" value="V" /> V</li>
			</ul>
		</li>
		<li><input type="radio" name="ghj" value="B" /> B</li>
		<li><input type="radio" name="ghj" value="C" /> C</li>
		<li><input type="radio" name="ghj" value="D" /> D</li>
		<li><input type="radio" name="ghj" value="E" /> E</li>
	</ul>
</div>
The finished product with some simple styling

The finished product with some simple styling

Styling is split up so that positioning the child lists doesn’t interfere with the display of the un-enhanced version:

	#taxonomy { padding: 50px; background-color: #fff; height: 300px; }
	#taxonomy ul {
		margin: 0px 0px 0px 10px;
		padding: 10px;
		border: 1px solid #ccc;
		-moz-border-radius: 10px;
		-webkit-border-radius: 10px;
		border-radius: 10px;
		list-style-type: none;
		background-color: #fff;
	}
	#taxonomy ul.dyn {		
		position: absolute;
		left: 50px;
		top: 50px;
		height: 280px;
		width: 180px;
	}
	#taxonomy ul ul { border-color: #fff; }
	#taxonomy ul.dyn ul
	{
		position: absolute;
		top: 0px;
		left: 200px;
		display: none;
		height: 280px;
		width: 180px;
	}
	#taxonomy ul.dyn li:hover {
		border: none;
		background-color: #eee;
		-moz-border-radius: 10px;
		-webkit-border-radius: 10px;
		border-radius: 10px;
		width: 100%;
		padding-right: 30px;
		z-index: -1;
	}
	#taxonomy ul.dyn li > ul { background-color: #eee; border-color: #eee; }
	#taxonomy ul.dyn ul li:hover, #taxonomy ul.dyn ul li > ul { border-color: #ddd; background-color: #ddd; }
	#taxonomy ul.dyn ul ul li:hover, #taxonomy ul.dyn ul ul li > ul { border-color: #ccc; background-color: #ccc; }
	#taxonomy ul.dyn ul ul ul li:hover { width: auto; padding-right: 0px; }

Finally, some Javascript breaks the list up and provides its positioning:

	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
	<script type="text/javascript">
	$(document).ready(function () {
		$("#taxonomy > ul").addClass("dyn");
		$("#taxonomy input").css("visibility","hidden");
		$("#taxonomy li").each(function (i) {
			$(this).bind("click",function(e) {
				$(this).siblings().find("ul").hide();
				$(this).children().find("ul").hide();
				$(this).children("ul:first").show();
				var rad = $(this).children("input");
				rad.attr("checked","true");
				return false;
			});
		});
	});
	</script>

Initially, I was using a noscript block to add this style: input:checked ~ ul {display:block;} and the only visual change the Javascript made was to hide the radio buttons (there was no “dyn” class). That works very well in modern browsers if your hierarchy is only two levels deep or users can only select from the lowest level, as in the classic example of vehicle make, model, and year. It didn’t work for my purposes, though, because users can select from any of four levels. It’s an easy change to make, though. The only thing to check is that IE6 is getting the correct styling, since it won’t recognize many of the selectors used here. I’m going to create a special script to handle that, but if you weren’t encumbered by that browser you could skip that step entirely.

Whew! So.. Is there a better way to accomplish this?


RSS Recent posts on the live version of this blog

  • An error has occurred; the feed is probably down. Try again later.