Thursday, April 23, 2009

Dreamweaver Design Time Style Sheets and Diagnostic CSS

From time to time WebAssist ( my employer) in releases some free web development related training/education material called RoadMaps. Recently I contributed to this effort by writing an article on how to use Design Time Style Sheets for page diagnostic purposes. Essentially, what this means is that you can use CSS to visually determine how well your page is doing from a standards/best practices perspective. This is especially useful when taking over pages created by others.

One example discussed in the article uses CSS to cause all links that have an event attached to them, say onclick, to be rendered with a thick red border. This allows you to quickly identify when you may want to move to an unobtrusive method of applying JavaScript on your page. To read more up on the subject, take a look at Diagnostic CSS Styling (Issue 7).

Let me know if you have any questions about the article.

Labels: , ,

Tuesday, March 3, 2009

Bottom and top Spry tabbed panels on one page

I posted a while back about how to create a Spry tabbed panel with the tabs at the bottom of the panel. The changes I suggested will cause other tabbed panels to be broken. I should have warned about that happening in that post, and suggested a different way that allows bottoms and tops to co-exist peacefully. Someone ran into the issue when they wanted to have top and bottom tabs on the same page. Here is what should work to allow both:

1). Add the following code to the head of your document. The styles and functions will be used to make sure that the bottom tabs look and work properly.

<style type="text/css">
<!--
.TabbedPanelsBottomTab {
position: relative;
top: -1px;
float: left;
padding: 4px 10px;
margin: 0px 1px 0px 0px;
font: bold 0.7em sans-serif;
background-color: #DDD;
list-style: none;
border-left: solid 1px #CCC;
border-bottom: solid 1px #999;
border-top: solid 1px #999;
border-right: solid 1px #999;
-moz-user-select: none;
-khtml-user-select: none;
cursor: pointer;
}
.TabbedPanelsBottomTabSelected {
background-color: #EEE;
border-top: 1px solid #EEE;
}
-->
</style>
<script type="text/javascript">
<!--
var getBottomTabGroup = function()
{
if (this.element)
{
var children = this.getElementChildren(this.element);
if (children.length)
return children[1];
}
return null;
};

var getBottomContentPanelGroup = function()
{
if (this.element)
{
var children = this.getElementChildren(this.element);
if (children.length > 1)
return children[0];
}
return null;
};
-->
</script>




2). Next modify your bottom tabs to look similar to the following code. Note that the main changes from a top tab is that the tabs UL is at the bottom, and that the LIs now have a class of "TabbedPanelsBottomTab" (defined in the STYLE block above):

<div id="TabbedPanels2" class="TabbedPanels">
<div class="TabbedPanelsContentGroup">
<div class="TabbedPanelsContent">Content 1</div>
<div class="TabbedPanelsContent">Content 2</div>
</div>
<ul class="TabbedPanelsTabGroup">
<li class="TabbedPanelsBottomTab" tabindex="0">Tab 1</li>
<li class="TabbedPanelsBottomTab" tabindex="0">Tab 2</li>
</ul>
</div>



3). Next, in the constructor for the bottom tabbed panel, change it to (all one line of code if you like):

var TabbedPanels2 = new Spry.Widget.TabbedPanels("TabbedPanels2",
{
tabSelectedClass:"TabbedPanelsBottomTabSelected",
getTabGroup : getBottomTabGroup,
getContentPanelGroup: getBottomContentPanelGroup
}
);

The options being passed in tell the bottom tabbed panel to use the "TabbedPanelsBottomTabSelected" CSS class as the class when a tab is selected (this class is defined in the STYLE block added in step 1), as well as override the getTabGroup and getContentPanelGroup methods of the Spry Tabbed panel object to use the functions defined in the SCRIPT block added in step 1.

Now preview your page. The bottom and top tabs should work correctly. Note: The bottom tabs will not look correct in Dreamweaver's design view due to how Dreamweaver handle's the display of Spry widgets is not compatible with the changes made above. In particular, in design view you will likely see the content of each tab, and only see the first tab displayed.

Labels:

Wednesday, February 18, 2009

Picking out the lint, and other JavaScript handling

A while ago I stumbled across a helpful Eclipse plugin called jsLex that helps with working with JavaScript within your applications, and I thought that I should mention it in case someone comes along that is interested in work with Eclipse (and Eclipse based editors) and are doing work in JavaScript. Among the features in the current release that I've found especially interesting are:
Compress/Minify/gzip multiple JavaScript
Concatenate multiple JavaScript (with the ability to specify the order of the files)

But there are a number of other features that I haven't dug into much that could be useful, such as JavaScript Profiling which allows you auto-inject profiling code into your existing JavaScript files. As I said, I've not played with it, mainly as it's not really clear exactly how to go about adding the profile code from the docs. I know that Bob is working on adding documentation for the project so I'm sure that this will be made clearer down the road.

jsLex also includes some "Cloud" functionality, but I'm not there yet, so haven't touched that portion of it at this time, maybe in the future as it seems that a lot of folks are moving in that direction.

The beta version of the plugin also adds Linting JavaScript files with JSLint. As pat on my back, I suggested this feature to Bob Buffone (the developer of jsLex) and he saw the value in it, and was able to add it pretty quickly to jsLex as part of the beta. FWIW: the site lists 1.2.2 as the beta, but the downloaded files indicate 1.2.5 as the beat.

I did run into an issue with jsLEx linting feature when installed into Aptana Studio ( 1.2.1.020234 if it matters) where the Problems panel would randomly remove entries when an entry was double clicked in the Problems panel. Bob tells me that this is Aptana specific, and I do hope that there is a workaround found within jsLex, or an update to Aptana that stops this issue from happening, as it can be annoying when you're trying to nail down some of the issues reported by JSLint. As all things beta, I expect to have a couple of issues here and there, but overall the feature is fairly robust at this point.

I have noticed that the files I've tried linting from Adobe Spry framework will choke JSLint to the point where it will stop reporting "errors". This appears to be mostly due to the coding style the Spry library was written with, not due to functionality issues. As the JSLint site says, it may hurt your feelings, so I do hope the Spry team isn't crying now. ;-)

I had a conversation with Nate Koechley from the Yahoo YUI team when I was at Adobe MAX back in November, and he says that as part of their build process, they always run JavaScript files through JSLint. Perhaps future versions of Spry will consider making JSLint happy part of the coding for future versions of Spry. I'm not religious about JSLint, by any means, but it may be worthwhile to make the effort for Spry.

Labels: , , , , , , ,

Wednesday, January 21, 2009

Web development podcasts, what do you listen to?

I've been listening to a few web/software development podcasts recently and I wanted to share a few that I find that I make sure to listen to as soon as I find out there's a new one out:
Scott Hanselman: covers software design/development, mostly in an interview format with informative guests as well as thoughtful questions/comments by Scott.

Stack Overflow conversations between Jeff Atwood and Joel Spolsky generally covers the design, development, and progress of the Stack Overflow site, but generally spins away from that pretty quickly, as well as discussion about some interesting questions asked at Stack Overflow.

Boagworld: web design news/commentary from a couple of funny guys: Paul Boag and Marcus Lillington both of HeadScape.

Of course, working at home and being in front of a computer all day, I've yet to move any podcast onto a pod, but who's to question the coining of a new term, it's not like I've ever been accused of using fauxcabulary, right? ;-)

So tell me, what podcats do you listen to that you'd recommend to another developer?

Labels:

Thursday, December 18, 2008

Getting the "skinny" on skinning Spry menus

Massimo Foti is ever tweaking code he runs across and is probably the biggest reason I ever got into Dreamweaver extensions in a big way. Lately it seems that some of his spare time has been turned on Spry. He recently announced in the Adobe Spry forum that he is releasing a set of skins for the Spry menu bar in Office 2003 styles: Silver, Green, and Blue.

I've thought a good bit recently that skinning Spry widgets would be quite useful, as nobody likes out of the box styles these days. I mean, imagine a Spry version of Themeroller!

Labels:

Tuesday, December 16, 2008

Spry 1.7 feature preview updates SpryData for basic xpath functionality

Looks like some action on the Adobe Spry Framework front and a preview of a change that the 1.7 release will bring. Better basic xpath support in the Spry Data sets are set in the preview that can allow users to avoid including xpath.js which can save ~72kb according to the post on the Spry Team's blog.

I'm looking forward to seeing what else might be included in the 1.7 release. I think that it would be good if the Spry team could post a roadmap for the Spry framework so that we can see what sort of widgets and functionality are being planned. This would allow people to be able to comment on what is proposed, as well as give Spry widget developers some ideas on what to avoid working on so as to prevent duplicate work.

Labels:

Saturday, September 20, 2008

Pesudo Threading in JavaScript: Watch what you're doing

I was working on some debugging and I wanted to do some logging of some variables that were going through numerous changes. However I didn't want to be littering my code with all the debug/logging code, you just know that I'd leave some of it in and cause me to do more searching and potentially have additional errors down the road.

Anyway, I ended up using the JavaScript object watch method when working with simple values by adding the watch to the parent object. This allowed me to keep my debugging/logging code in just a couple of places. The watch method also allows you to perform data validation by intercepting changes to values.

A basic example:

// Basic logger object
function Logger(){
this.loggedItems = [];
this.logItem = function(itemToLog){
this.loggedItems.push(itemToLog);
}
this.showLog = function(){
alert(this.loggedItems.join('\n'));
}
}
// Create an instance of the logger object
var myLog = new Logger();

// Basic object
function Person(){
this.age = 0;

// add watch on age property
this.watch('age',
function(prop, oldVal, newVal){
myLog.logItem('setting ' + prop + ' to ' + newVal);
return newVal;
}
);
}

// Create new object
var p = new Person();
// set value
p.age = 80;
// drink from the fountain of youth
p.age = 70;
p.age = 60;
p.age = 50;
// Let's see that log
myLog.showLog();
// result:
// setting age to 80
// setting age to 70
// setting age to 60
// setting age to 50


So what this does is to react any time that age is changed. So when age is changed, a function intercepts that change and is passed three parameters, the name of the property that was watched, the old value of the property, and then the new value of the property. This function then returns the value that will be used as the value that is actually assigned to the property when it is changed. In this example, we aren't doing any validation (you know a person can't be -12 years old right?), so we could check the value and if it isn't a valid value being assigned to the property, then we can return the old value and effectively not make any change to the property.

What we are doing instead is logging the new value. This allows us to track the changes to this property as the application runs. In this simple example, we just just show the log after a couple of changes. You could expand this to more of your simple value properties.

When I'm done debugging I just pull the code from the parent objects rather than from many places within the application. Still prone to leaving in some logging code, but it seems less so than logging at every point the property is changed.

A caveat: Changes to an object or adding an element to an array aren't handled with the watch method as the "value" of the property being watched isn't changing, that is, the array contents are changing, but it's still that same array, and it's the array that is being watched, not the contents of the array, same thing with an object.

Of course there are other ways to log and may be some better ways to add the logging in that would even further limit any issues when the debugging is over, but I just wanted to get across the basic usage of the watch method.

So what's with the "pseduo threading" in the post title? Well that is basically from the processing that occurs, it steps through executing each line as it reaches it, until the assignment of the watched property, the processing then breaks off to the function passed into the watch method, does what ever processing needed, then execution picks up where it left off on the next line after the property assignment. So it's sorta "threaded" in that the other code gets executed without being directly called in the code, but it's pseduo in that it's actually executed inline.

Alright, I think that's enough rambling for now.

Labels: ,

Saturday, August 16, 2008

Help for creating custom Spry transitions

I've mentioned one way to add more transitions to Spry in Upping Your Transition Count, but that assumes that you have pre-created easing equations. What if you none of the ones you've found meet your needs? Well you can create your own...if you know how to write one. All I've seen in my research is that your function needs to work like f(0) = 0 and f(1) = 1, but really what does that mean to someone that doesn't work with math functions much, and what is the 0 and 1 in this case when easing equations take 4 parameters (at least that's the case with Spry and Robert Penner's equations)?

To be honest, I really don't know (at least not yet), but I have found a tool that can be useful in creating a custom equation. Check out the easing function generator, a Flash application that allows you to use drag and drop or directly enter in some values to see what your easing equation will look like. For use with Spry, make sure to select the F5/FMX radio button at the top of the application. Drag and drop the numbered boxes at the bottom which will change the graph of the curve on the left. Then to see how the new equation changes the movement of an object, click on the red ball, then click elsewhere in the movie and the ball will move to that second location using your equation. Rinse lather, repeat as necessary to get an transition equation that you like.

Once you have an equation, copy the text of the function and paste it into SpryEffects.js at the end of the built in equations. Make sure to give the equation a unique name, and put a comma at the end of the previous equation. growSpecificTransition is the last transition in the default SpryEffects.js file (at least in 1.6.1), and the resulting code would look similar to:
growSpecificTransition: function(time, begin, change, duration)
{
if (time > duration) return change+begin;
var pos = time/duration;
return begin + (5 * Math.pow(pos, 3) - 6.4 * Math.pow(pos, 2) + 2 * pos) * change;
},

myNewTransition: function(t, b, c, d) {
var ts=(t/=d)*t;
var tc=ts*t;
return b+c*(17.495*tc*ts + -42.84*ts*ts + 35.695*tc + -11.2*ts + 1.85*t);
}


Once you add that to your copy of SpryEffects.js, then you can use your new transition like you would any other transition. For example, an accordion could be written as:
var Accordion1 = new Spry.Widget.Accordion("Accordion1", {transition: Spry.Effect.Transitions.myNewTransition});

Or because SpryEffects.js automatically adds all transition off of the Spry obejct, youc an use:
var Accordion1 = new Spry.Widget.Accordion("Accordion1", {transition: Spry.myNewTransition});

You can also try to integrate your new equation into the Spry Effects Transition Sample (online, or within the Spry download package: /samples/effects/transition_sample.html). Just add your equation to the SpryEffects.js for the sampler and add the name of your equation to the transitions select list, and you should be good to go.

Please post a link to any examples of any fun easing equations you've come up with. Also, if you happen to know how to write easing equations and can explain how in layman's terms, please do post your explanation, thanks!

Labels: , , ,

Wednesday, July 30, 2008

Speaking at MAX 2008: Extending Spry Framework

I added the speaker badge a few days ago, but forgot to mention that I'll be speaking at MAX 2008 in San Francisco in November. The title of the session if Extending the Spry Framework, and I'll be giving it on Wednesday, November 19th at 9:30 am - 10:30 am. Check out the session browser select Spry from the Product list to see the Spry related sessions. Here's the session description:
Move beyond the standard widgets, transitions, and effects available with the Spry framework. We’ll explore how both novices and power users can enhance their work by extending existing widgets to add new functionality, building new widgets with custom transitions from powerful Spry base components, and combining multiple visual effects to enhance the user experience.
If you have any thoughts on what widgets you'd like to see added to the framework, please do leave a comment so I can try to work it into the presentation.

If you're coming to MAX, please stop by and we can talk Dreamweaver and Spry!

Wednesday, July 2, 2008

Conceptual condensation: meaning scales

Well, I guess that didn't take long, only about 10 minutes since the last one, so here's another in the series.

Hitting one of my frequent blog stops I ran into "meaning scales" on gapingvoid, in particular this quote:

The size of the endeavor doesn't matter as much as how meaningful it becomes to you.


Source: Meaning Scales, People Don't

Labels: