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: , , , , , , ,

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, 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 2, 2008

How to Create Spry Tabbed panels with the tabs at the bottom

Spry Tabbed panels in 1.6.1 allow you to have your tabs at the top or on the left. Dreamweaver CS3 & CS4 (try the CS4 beta) will allow you to insert the tabs on the top, but it's pretty easy to change to vertical tab on the left by swapping out the class for the widget wrapper from TabbedPanels to VTabbedPanels. See the Spry Tabbed Panels documentation for more info on how the default tabbed panels work.

However, if you want you tabs to appear on the bottom of the panels, then you're outta luck, by default that is. Fortunately the Tabbed Panels are pretty easy to tweak to allow you to have your tabs on the bottom, by making three small changes. The first is to reorder the code that comprises the widget such that the container for the tabs is after the container for the panel content. So you move from:
<div id="TabbedPanels1" class="TabbedPanels">
<ul class="TabbedPanelsTabGroup">
<li class="TabbedPanelsTab" tabindex="0">Tab 1</li>
<li class="TabbedPanelsTab" tabindex="0">Tab 2</li>
<li class="TabbedPanelsTab" tabindex="0">Tab 3</li>
<li class="TabbedPanelsTab" tabindex="0">Tab 4</li>
</ul>
<div class="TabbedPanelsContentGroup">
<div class="TabbedPanelsContent">Content 1</div>
<div class="TabbedPanelsContent">Content 2</div>
<div class="TabbedPanelsContent">Content 3</div>
<div class="TabbedPanelsContent">Content 4</div>
</div>
</div>

To:
<div id="TabbedPanels1" class="TabbedPanels">
<div class="TabbedPanelsContentGroup">
<div class="TabbedPanelsContent">Content 1</div>
<div class="TabbedPanelsContent">Content 2</div>
<div class="TabbedPanelsContent">Content 3</div>
<div class="TabbedPanelsContent">Content 4</div>
</div>
<ul class="TabbedPanelsTabGroup">
<li class="TabbedPanelsTab" tabindex="0">Tab 1</li>
<li class="TabbedPanelsTab" tabindex="0">Tab 2</li>
<li class="TabbedPanelsTab" tabindex="0">Tab 3</li>
<li class="TabbedPanelsTab" tabindex="0">Tab 4</li>
</ul>
</div>

This change allows for easy display of the tabs at the bottom, because the tabs are now below the content panels.


Then you need to tweak the CSS a bit. You can change the code in the SpryTabbedPanels.css, but you may need the default for some other tabbed panel instance. So if you add the following style block to your page (or add it to a separate CSS file):
<style type="text/css">
<!--
.TabbedPanelsTab {
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;
}
.TabbedPanelsTabSelected {
background-color: #EEE;
border-top: 1px solid #EEE;
}
-->
</style>

If you compare the selectors to the matching styles in SpryTabbedPanels.css (.TabbedPanelsTab selector lines 67-83, and .TabbedPanelsTabSelected selector lines 105-108), you'll note that there are only two changes, moving from "top:1px;" to "top:-1px" for .TabbedPanelsTab and moving from "border-bottom: 1px solid #EEE;" to "border-top: 1px solid #EEE;". These changes will allow the bottom tab to overlap the bottom of the content making it look seamless for the "selected" tab.

So two down, one to go. The next change is in the JavaScript to allow the Spry Tabbed Panales widget to recognize the reordered tabs and content panels. As with the CSS, I'm putting this code into the page itself rather than modify the Spry files. Add the following to your page (pulled from SpryTabbedPanels.js lines 124-133 and lines 144-153):
<script type="text/javascript">
<!--
Spry.Widget.TabbedPanels.prototype.getTabGroup = function()
{
if (this.element)
{
var children = this.getElementChildren(this.element);
if (children.length)
return children[1];
}
return null;
};

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

The only changes here are moving from "return children[0];" to "return children[1];" in Spry.Widget.TabbedPanels.prototype.getTabGroup.

Both changes reflect the change in order of the tabs and the content panels within the Tabbed panel wrapper div (<div id="TabbedPanels1" class="TabbedPanels"></div>).

Save and preview your page and viola, bottom tabs on your Spry Tabbed Panels.

A couple of things to keep in mind. Dreamweaver won't properly display your tabs and content panels in design view, so you'll lose a bit there, and if your content panels are of differing heights, sat tab 1 content is 200 pixels high and tab 2 is 50 pixels high, then switching tabs will cause the bottom of the tabbed panels to move up and down (taking with them the tabs too).

The former issue can't be worked around without mucking about a good int in Dreamweaver's internals, the second probably can be worked around by setting specific heights for the content areas and then maybe setting an overflow:scroll to allow for content that is too tall to the height you set. I haven't tested that type of change, but should be something like that.

Labels:

Tuesday, June 3, 2008

Nested Spry Collapsible Panels

I ran into a project where I wanted to be able to use nested Spry collapsible panels in Spry 1.6.1 but I saw that when I expanded the child panels that they expanded over the border of the parent panel. I'll try to get a sample up soon to show how it didn't work correctly for me. But in the mean time, you can fix it by opening up SpryCollapsiblePanel.js (within a SpryAssets folder is you added the panel via Dreamweaver) and go to line 431, which reads:
this.content.style.height = this.toHeight + "px";

Change that to:
this.content.style.height = "auto";

And you should be good to go. The first fix I had tried set the height to an empty string which worked for any panel that doesn't have a height set in the CSS for the content. If you do have a height set in the CSS for the content, then setting the height to an empty string causes the CSS to take effect and if the CSS height is different than the height that Spry determined the content of the panel to be when the panel opens, then you could get some jumping as the animation finishes and then the height adjusts to the value set in the CSS.

Labels:

Wednesday, May 28, 2008

Are CDNs for JavaScript libraries a good idea?

I was reading Ajaxian and I see that Google has launched what seems to be a CDN (content delivery network) for JavaScript libraries, in particular the following libraries are currently supported:
The discussion over at Ajaxian has it's share of folks in favor as well as detractors and I understand the potential issues where you'd now be dependent on Google's goodwill and server uptime for your site to function properly, but that you could get a potential speed boost as well some caching benefits as well. I knew that dojo was available via a CDN from AOL already, so it seems at first to be a good idea to "prime the pump" of user browser caches, but I'm wondering if this is really it's cracked up to be.

The Google Ajax API entry specifically calls out speed as a benefit of this service, but the Google Ajax Libraries API doesn't list any real world, or theoretical usage stats. I'm sure Google's data centers are plenty fast, but if anyone has done any testing to back this up, I'd really like to see it so we all can see the potential in this. And if it is a Good Idea™ then I'm wondering if Adobe's Spry should jump on that bandwagon too.

So if you have any thoughts on JavaScript libraries, especially any testing done with CDNs, it would be good to hear from you. Comment away!

Labels: , , , , , , ,

Tuesday, May 27, 2008

Starting out on the curve

I've been involved with Dreamweaver since I got a copy of Dreamweaver 1.2 ( for free on a CD that came with a British technology magazine that I don't recall the name of). I think that Dreamweaver 3 was about to come out or that it was just out and the 1.2 freebie was the incentive was to get 3 with an upgrade price. I was immediately struck with how lacking my then svelte Notepad-Netscape 3 driven development seemed so lacking. :-)

From there thinking back a bit, it seems that the learning curve really hasn't flattened out.

After getting Dreamweaver 4 and Fireworks 4 studio I really started looking more at the way that Dreamweaver was truly built to be extended and I rooted around in the configuration folder and learned a ton. I struck up some friendships on the Dreamweaver forums and on the recommendation of Angela Buraglia I volunteered and was accepted to join Team Macromedia for Dreamweaver in early 2002 or so (has it been that long already?). With the Adobe purchase of Macromedia a couple of years ago I became part of the Adobe Community Experts with my primary focus still being Dreamweaver. Along the way I've written a number of articles and tutorials at CommunityMX a great resource site for all things Adobe, contributed a chapter to a book and have been the technical editor for quite a few Macromedia and now Adobe product related books.

I'm working at WebAssist (3 years June 1st this year, time files) where I mainly build extensions for Dreamweaver using the fantastic extensibility layer as well as coding ASP (JavaScript & VBScript), ColdFusion and PHP.

But as with all things, nothing stays the same; so I'm always looking for something to learn to stay on the up good side of the curve (notice a trend here? I'm parenthetical)(he says parenthetically). I've been doing a good bit of playing around and reading up on JavaScript libraries including Adobe's Spry, Script.aculo.us jQuery, and MooTools among many many others and how they can be used to enhance the user experience. When WebAssist had their latest redesign I helped put in some Moo.fx flavored actions. Intriguing also are content replacement/enhancements such a sIFR, swfIR and SoundManager. I've also been thinking a bit about the possibilities that Adobe AIR (and by extension Flex) offers to web developers like me by bringing the technologies I know to the desktop.

I hope to be able to keep on learning new and interesting technologies as well as learn about new ideas and trends, both in the realm of the technology I work with and the greater world at large. So join me and I'll join you in this fantastic learn experience that is life.

Well I guess that's enough linking around, so I'll sign off this initial post.

Labels: , , , , , , ,