Monday, December 21, 2009

Easy Fluid Rounded Gradient Tabs

Found this great, simple tutorial on Clean Tab Bar Digg-like Using CSS this morning and thought I'd create my own background image and give it a try.

The goal was to have a similar look-and-feel to an existing page (which used image-based tabs, absolute positioning, and a single background image for all of the tabs). Unfortunately, am doing this for a portal site where the tabs must be fluid and I don't know what the text is in the tabs, but I can make a guess at their typical length.

(Using Firefox 3.5.6) I started off by using the Colorzilla plugin. Clicking on the eyedropper in the lower-left hand corner and then finding the existing color of the gradient at the top and bottom of the other site's tab to determine that the top color of the gradient was #ffffff (white) and bottom color was #e8e8e8 (greyish-white). While I was using the eyedropper, I got the top and bottom positions of the tab to determine the height of the tab image I'd need, which was 45 (kind of tall).

Then, I went to Dynamic Drive: Gradient Image Maker and entered a gradient width of 400, gradient height of 45, top color of ffffff and bottom color of e8e8e8. Then I clicked on get full size image and right-clicked on the resulting image to download locally.

I then opened up Seashore and opened up the gradient image I made. I then clicked on the top rectangle to choose a color and clicked on the magnifying glass. Then I hovered over the existing site's tabs to click on each color right around the top left and top right pixels and used the pencil tool in Seashore to set those same pixels to the same color in my tab image. This was not as tedious as it sounds, and it could be done with a transparency as well to make rounded corners work with any background, but since I only needed these tabs to work on a blue background, I didn't mess with transparencies.

After the tab image looked good (even though it was much longer than it would be in the final version), I saved it and put it where the page I was going to alter could then access it easily.

Here was the fun part. Reading the Clean Tab Bar Digg-like Using CSS post, I figured out that the main gist of it was that it is as simple as having an anchor ("a" element") wrapping a span element, each using backgrounds. The span element uses the left part of the tab background, and when it ends, the encompassing anchor element uses the right part of the tab background and sets a right padding at least enough to see the top right edge of the background. The anchor and span need to have 0 top padding set so that they start at the same vertical position. For my example, the anchor needed to be display: block; margin: 0 0 0 0; padding: 0 3px 0 0; and the span needed to be display: block; margin: 0 0 0 0; padding: 0.65em 1.18em 0.65em 1.18em; (the latter padding you just need to play with until the text is centered where you want in the tab, and the 3px is length of right edge. Without the latter set, you won't see the right edge).

In our implementation, the tab only needed to show when it is active. If you wanted to show different color tabs, etc. all you have to do though is to use different single tab images like mentioned above and use the styling similar to the cur class here:


#nav { height: 45px; list-style-type: none; position: absolute; top: 110px; }
#nav li { float: left; }
#nav a { display: block; height: 45px; outline-color: -moz-use-text-color; outline-style: none; outline-width: medium; font-family: Helvetica, Arial, sans-serif; font-size: 1.16em; text-transform: uppercase; padding: 0 3px 0 0; margin: 0 0 0 0; color: #bbc2d2;} 
#nav span { display: block; margin: 0 0 0 0; padding: 0.65em 1.18em 0.65em 1.18em; }
#nav a:hover {color:white; text-decoration: none;}    
#nav .cur a {background:url('./slices/brand-new-tab.png') top right; display:block; color: #435685; font-weight: bold;}    
#nav .cur span {background:url('./slices/brand-new-tab.png') top left; display:block; color: #435685; font-weight: bold;}
And the HTML is:

<ol id="nav">
<li class="cur"><a href="..."><span>Tab 1</span></a></li>
<li><a href="..."><span>Tab 2</span></a></li>
<li><a href="..."><span>Tab 3</span></a></li>
</ol>

Thursday, December 17, 2009

Show Contents of File on Path

This bash script will show the contents on any file on the path:

#!/bin/sh

# fmore.sh
#
# Written by Gary S. Weaver

more `which $1`
Put it on the path, name the file fmore, and chmod +x it. Then can use it like:

fmore some_script.sh
and regardless of where it is, it will show you its contents.

Wednesday, December 16, 2009

Find and Diff Only Certain Files in One Directory Structure to Another

If you want to compare a directory structure only containing files and directories to change/overlay atop another, it is useful to have a tool to compare only the files (and perhaps only certain ones) from that one directory structure to the other directory structure you wish to overlay those files atop of.

I started using a similar method a few years ago, and thought I'd already noted it, but maybe I forgot. Anyway, hope the diffo.sh bash script helps:


#!/bin/sh

# diffo.sh
#
# Written by Gary S. Weaver

set -e

d1="$1"
d2="$2"
exp="$3"

if [ $# -ne 3 ]; then
  echo
  echo "usage: diffonly.sh dir1 dir2 expression"
  echo
  exit 1
fi

# canonicalize and set as variables
d1c=`cd -P -- "$(dirname -- "$d1")" && printf '%s\n' "$(pwd -P)/$(basename -- "$d1")"`
d2c=`cd -P -- "$(dirname -- "$d2")" && printf '%s\n' "$(pwd -P)/$(basename -- "$d2")"`

set -x verbose
cd "${d1}"
find . -name "${exp}" -exec echo "Comparing \"${d1c}/{}\" to \"${d2c}/{}\" ..." \; -exec diff "{}" "${d2c}/{}" \;
Put that file on the path (I called mine "diffo") and chmod +x it. Then use it like:

diffo dir1 dir2 "*"
or

diffo dir1 dir2 *.java
which will only compare those files found in dir1 to dir2 (not the same as diff -r. diff -r also compares dir2 to dir1).

Tips and tricks:
* Add --side-by-side option before the last \; and get a side by side diff.
* For those using OS X, TextWrangler is free and you can do twdiff on files that are different to easily merge changes (click on difference at bottom and use the apply button).

Note: the line to canonicalize was based on the "canonicalize" bash script by Jesse Wilson.

Monday, December 14, 2009

Native Extensions Not Included in Frozen Gems

As you'd think, Rails does not include native extensions in frozen gems. This is so that the app is portable if deployed.

However, having to build native gems on the server by-hand may not be that great of an option either (what if you forget?).

Jim found this discussion where Jacob Helwig provides an example of something you can do in your Capistrano deploy.rb to resolve this:


task :after_update_code, :roles => :app do
  # Rebuild the gem native extensions, unless we explicitly say not to.
  unless ENV['BUILD_GEMS'] and ENV['BUILD_GEMS'] == '0'
    run "rake -f #{release_path}/Rakefile gems:build"
  end
end
Via Jacob's method, if you wanted to deploy without building gems you'd do:

BUILD_GEMS=0 cap deploy
However, you might want to do the opposite, and only build gems on demand. That way as Jim and I discussed, it would speed up most deployments that you do, because typically when you deploy you aren't adding or updating a gem.

Thursday, December 10, 2009

Evaluating Methods of Online Team Communication

Our team is evaluating a few different options for sharing info across the team. Here are the ones we've used so far:

Jabber

I know that at one point there was IRC setup, but for the longest time since I was here we were using a conference room on our shared work Jabber server. However a member of the team could never get Adium working with it such that that person could just open the room from their contacts. Jabber allowed sending of attachments, but sometimes people had trouble with that also. The advantage (to me) of Jabber was that you could not delete or change what you wrote and could not delete or change what anyone else wrote, although you could clear your Chat Transcripts in Adium of course (but you can't clear what you wrote on everyone else's transcripts). In addition, there is the possibility of people seeing logs of messages sent in the Jabber server I suppose (although maybe encrypting messages helps avoid that?).

Twitter

We used this with an API to post interesting things happening in our environment (really just deployments) to a private account. I know that we could use it for team communication also, but basically we just didn't take it any further. I think the main thing is that Twitter is really geared toward one person announcing what they done more than conversing with others, even though the latter happens a lot between people that are Twitteratics/Twitter-addicts, but there are few of those here afaik.

Google Wave (wave.google.com)

Recently we had a team member that had been using Google Wave, so we got invites and started using it. I along with a few others were using Waveboard 0.11 as the OS X client so that there could be a notification number shown in the OS X dock. However, I had to restart it periodically because it doesn't catch changes like when someone's profile picture changed. It is certainly really neat to have threads within each topic of conversation and to see what others are typing as they type. Also the various extensions, chatbots, etc. available in Google Wave are neat (although unless you are the topic starter you can't seem to invite a chatbot, and some of the things on that list didn't work for me even if I added them as the topic starter, I think). However, with the whole team working on a thread and having fun, it quickly got out of control. In the current (beta) version, you can edit each others' blips (messages) which could be a big problem. And it is really hectic to try to keep track of people writing things in different places in the same wave. I also rewrite what I'm thinking sometimes, and I don't like people seeing that. So I don't think that editing blipped blips, threading within topics, or seeing what someone is typing should be enabled by default- but unfortunately that would make it not much different than other IM-like tools. As a free-form idea tool it is great. But to track quickly what is going on in a team, it is probably currently the wrong tool to use, which is a shame, because obviously its creation involved a lot of "out-of-the-box" creative thinking. Unfortunately, Google Wave seems to create more problems than it solves. But maybe that will change as it evolves.

Present.ly (presentlyapp.com)

Present.ly went down briefly a few times during the evaluation (it didn't let us post). However, having a private web-based conversation with feed is pretty good. A con like Twitter and Google Wave is that you can delete your own posts (which deletes them from everyone else's), and you can delete others' posts from your feed, even though everyone else still has them. There are two clients for OS X at time of writing which are an Adobe AIR app available via the presentlyapp.com site and you can use Fluid to create an app for it (which is what I did because a co-worker that had been using the Adobe AIR app said it wasn't as functional). You "follow" people like Twitter, but it feels different than Twitter and allows you to attach things, etc. (it's just more full-featured at the moment). It has email, SMS, and a few types of IM support. I tried to hook it up to my Google Talk account and then added Google Talk to Adium, but it didn't work. I don't really like the email functionality, because I like keeping email and IM-like communication separate. It automatically provides a RSS feed for your present.ly posts. If you install RssGrowler and change preferences to check every 5 seconds, and add your "private" feed, being sure to set your username and password, then it is a great way to get notifications when someone says something. So far, present.ly is the winner in my opinion, although I'm trying to keep an open mind to Google Wave, because I know that Google will fix it up or come out with something even cooler within a year or two, most likely.

Yammer

Yammer not only provides Facebook-like microblogging for business, but lets you set up groups which have their own microblog pages, allows each employee to have a profile page, has org chart, group directory, what appears to be a big tag cloud page, a file directory, image directory, and admin area where if you are a paying customer of Yammer you can setup policies, etc.

We've not evaluated this one yet, but it looks interesting.

Update: While we have been using Present.ly for some time now, team members have not stopped using Jabber. One thing recently discussed related to this is that we don't feel safe posting some internal communication related to security to an externally-hosted, free service. I think that team communication may have increased since using both Present.ly (which attracts more status updates, although there is no reason Jabber couldn't be used for status updates) and Jabber (which allows faster communication, fits more communication in the screen, and is much easier to manage/view/copy and paste chatlogs). However, the tradeoff for increased communication is that there isn't a single source of record for that communication (not that there was before- after all we use email, etc. also).

Update #2: If you were using Fluid and it broke, they changed the domain from presentlyapp.com to presently.com. Recreate the Fluid app to point at the correct domain and it'll be working again.

Friday, December 4, 2009

Preserving Data in a Digital Format Forever

Henry Newman, in his article "Error Correction: An Urgent Need for Files" (enterprisestorageforum.com, December 3, 2009), proposed one method for the preservation of information in a digital format in a way that would better withstand corruption.

I had another idea though. Often with optical filmstrips, by examining any part of the tape, you can tell what the format of that tape is. What if the same were true of files? Throughout the file (before every frame of a film and before every chunk of audio), the type of compression and format could be noted in a standardized way. If this were the case, then there would be no problem with some of the bits being mangled here and there. Not very efficient for sure, but this sort of duplication would ensure that even a severely corrupted file could very likely be read, by looking at frame headers that either are readable or by using the average of the bits in frame header to produce a good or "likely" type for the media.