December 4, 2009
I use PushMail to get push notifications of e-mail on my iPhone. And because I have Google Voice send all my SMS and voicemails to my e-mail address, I get notified of those too. Here are some PushMail Custom Profiles that make it an even better experience:
Custom Profile 1 – Text Messages
- Pattern: voice.google.com
- Sound: SMS Received
- Action: URL: http://voice.google.com
- Notification Format: From, Body
Custom Profile 2 – Voicemails
- Pattern: voice-noreply@google.com
- Sound: Ping (default)
- Action: URL: http://voice.google.com
- Notification Format: Subject
Leave a Comment » |
Personal | Tagged: google voice, iphone, push, pushmail, sms, voicemail |
Permalink
Posted by Josh Justice
November 30, 2009
In approximate order of how often I use them, or how useful I find them.
Paid
- PushMail – push notifications of e-mails, including preview text (great for getting free instant notifications of Google Voice SMS and voicemails, instead of using SMS)
- Tweetie – twitter
- Outliner – outlines, especially hierarchical to-do lists
- IM+ – instant messaging
- GPS Drive – cheap GPS program with some improvements over Google Maps
- Wedding Day – now, how long we’ve been married =]
Free
- Files lite – reading text files, such as videogame walkthroughs (it saves your place!)
- AudioMemos Free – voice memos (better UI than Apple’s Voice Memos app)
- ICHC – funny images
- NetNewsWire – Google Reader / RSS
- The Weather Channel – detailed weather forecasts and radar
- Logos – free ESV, NASB, NKJV Bible – plus Greek morphology!
- Pandora – customized streaming music stations
- Pollen Lite – pollen forecast
- Loopt – for tweeting my current location
- iTweetSong – tweeting the song/podcast I’m currently listening to
- Flixster – movie showtimes
- Fandango – buy movie tickets (but smaller list of theatres and worse UI than Flixster)
- Shazam – recognize a song playing on the radio
- PS Mobile – simple photo manipulation
- WhitePages – look up a person’s address
- PhoneFlicks – view/update my Netflix queue
- ESPN ScoreCenter – for my wife to look up Broncos scores
- Dictionary
- eBay
- Amazon.com
- Facebook
- Wikipedia
Leave a Comment » |
Uncategorized | Tagged: app, iphone |
Permalink
Posted by Josh Justice
October 27, 2009
We’re in the process of converting our web site to use CSS sprites to improve frontend performance. To implement CSS sprites, I’d recommend using SmartSprites. It’s a simple build-time tool that allows you to build your CSS using regular separate background images, annotate the CSS files using CSS comments, then run the tool and have it generate the CSS sprite image files and updated CSS files. It’s an excellent tool.
Unfortunately, due to limitations in the CSS sprite concept, SmartSprites can’t work with just any background image usage you already have. Here are a few pointers to keep in mind when building your CSS, to make sure it’s as spritable as possible.
- Don’t use CSS sprites pre-SmartSprites. This may sound obvious, but there are some reasons why you might end up with some CSS sprites before you use SmartSprites. For example, our design firm implemented hover states for UI elements as CSS sprites: the same image has normal and hover states, and a hover event just changes the background alignment. Also, we use YUI widgets, and some of their default styles use CSS sprites.
The reason SmartSprites doesn’t work on existing CSS sprites is that it ignores your existing background positioning declarations. It assumes you have a single background image, includes that image in the sprite, then positions the sprite to show that one image.
The workaround I used for this was to split out the smaller CSS sprites into individual images, which are then recombined by SmartSprites into the macro sprites.
- Separate out “background“ properties into “background-image.” SmartSprites requires background-image to be on its own line. It’s not too hard to refactor later, but if you can write the styles this way to begin with, you’ll save some time.
- Make sure repeating images are as few pixels as possible in the repeating dimension – preferably 1px. In order to get repeating sprites to tile properly, SmartSprites has to find the lowest common denominator of the image size. For example, if you have a 2px repeating image and a 3px one, it can’t just sprite them together, because then the 2px one would have a 1px empty row. And it can’t just repeat the first pixel of the 2px one, because the pattern might not tile properly. So it needs to create a 6px image, repeat the 2px one 3 times, and the 3px one twice. 6px isn’t too bad, but if you add a few more images of different sizes, it can expand out of control.
- Whenever possible, make your background images cover the whole element, not just part of it. Don’t create a vertically-expandable div and style a background image to cover just the top of it – instead, create one div that’s the height of that background image, and style that. Remember, a CSS sprite is a bunch of images concatenated together, so you won’t get blank space below it: you’ll get more images. One way you can get around this is to take advantage of SmartSprites’ ability to organize the images either horizontally or vertically. If you append the images horizontally left-to-right, there won’t be anything below that header image, so you can still style it to cover just the top. One case where this won’t work, though, is in repeating sprites. If you have a horizontally-repeating sprite at the top of an element, then it’s difficult to put it in a sprite, because the only place to put other elements is above or below it, and the below ones will show up in the element.
1 Comment |
Development | Tagged: css, css sprite, image, performance, smartsprites, sprite, ui, yslow |
Permalink
Posted by Josh Justice
October 16, 2009
Just ran into a defect that came up because QA’s web browser had cached an old version of a JS file. I was hoping to find an easy way to configure caching for static assets in my webapp. Turns out that there’s a J2EE cache-filter that does it quite easily. Just add it to your pom or lib directory, then add a few filters and filter-mappings to your web.xml, and you’re good to go!
I configured 1 hr caching for JS and CSS, so they’ll be refreshed by the time I do a QA build. You could also set up your build script to make your cache settings environment-specific, so prod caches longer than QA. You can also use this to set longer caches on things like images (I set ‘em to cache for 1 day), to increase performance.
Leave a Comment » |
Development | Tagged: cache, filter, j2ee |
Permalink
Posted by Josh Justice
October 12, 2009
My app has a search screen that fetches the results via Ajax and displays them in a table. Worked fine in Firefox, but in IE there’s a slight processor jump for a second or so. Strange, but not a problem. The users of this app, however, use a remote desktop app to run IE to access it. And when they did the search, their CPU would hit 100% for 1-5 minutes, making the entire terminal completely unusable.
I agonized over different JavaScript fixes: removed a table JS widget, switched off of tables altogether, switched to innerHTML, used DocumentFragments. Nothing worked.
Then, on a whim, I disabled all the CSS files on the app, and it worked like a charm. As I narrowed it down, I discovered that some CSS I was using to emulate frames (non-scrolling header, footer, and sidebar) was the offending code.
Let’s step back and think about that one again. What caused the processor to hit 100% for 5 minutes was not JavaScript, but CSS.
Sigh. So, if you have an issue with IE hitting 100% processor load for any reason, don’t assume that JS is necessarily the problem. Try disabling your CSS and see if that fixes it.
Leave a Comment » |
Buglog, Development | Tagged: cpu, css, Development, dom, ie, javascript |
Permalink
Posted by Josh Justice
October 10, 2009
I just finally activated my Google Voice account today. I’m pretty happy with the setup right now. The bottom line is:
- I get a notification on my iPhone for all e-mails, voicemails (transcribed), text messages (free), IMs, and twitter replies and DMs
- I can e-mail, text message, IM, or tweet back from the iPhone
Here’s the setup:
- My personal e-mail address is a POP account with my ISP. I have it set up to forward to my gmail account, so I get IMAP support. But I also have a backup of the e-mails stored locally in case something goes wrong with gmail.
- My Google Voice account is set up to transcribe voicemails, and then send voicemail transcriptions and text messages to my gmail account. Gmail is set to filter these messages and automatically put them in a VM or SMS folder.
- My gmail account forwards all e-mails to my PushMail e-mail account – this is an iPhone app that will show push notifications on my iPhone with sender/subject/title/body etc. By contrast, using the iPhone mail app to do push only buzzes and updates the app’s icon – it doesn’t show a notification with the contents.
- Meanwhile, I use IM+ as an iPhone IM client. It supports most IM services, and also does push notifications when receiving IMs.
- I use Tweetie 2 as my iPhone twitter client. It’s great, but unfortunately it doesn’t support global push notifications for all mentions and DMs. So, instead, I use IM+’s Twitter push support – IM+ notifies me when I receive a mention or DM, and then I read/reply in Tweetie.
Leave a Comment » |
Personal | Tagged: google voice, iphone, push |
Permalink
Posted by Josh Justice
October 6, 2009
On the project I’m on, I’ve run into a number of problems getting various types of button to run JavaScript and not submit the form they’re on. My conclusion:
The most reliable way to have buttons that run JavaScript instead of submitting the form they’re on, is to use <input type=”button”/>.
The other options are <input type=”submit”/>, <button/>, and <button type=”submit”/>. But all of these have their issues.
Theoretically, <button/> should also not submit the form you’re on. It works that way in IE6, 7, and 8, but in FF3 it does submit the form you’re on.
There are ways you should be able to disable form submission when JavaScript is running. Theoretically, any “onsubmit” handler that returns false should prevent the form from being submitted. I wasn’t able to get this to work by using YUI.util.Event.addListener, but I was able to get it to work fairly reliably by using formNode.onsubmit = function() { return false; }. However, this started working only sporadically in IE8.
Since the project I’m on requires JavaScript, the most reliable way I found is to change all the buttons to <input type=”button”/>. There may be something more complicated going on that could be worked-around, but this way seems to be the least likely to cause future problems.
If your project needs to work with or without JavaScript enabled, here’s what I’d recommend. Code the page to use <input type=”submit”/>. Then, when your JavaScript init runs, change the type attribute to “button,” and attach your click listeners.
Leave a Comment » |
Development |
Permalink
Posted by Josh Justice
September 25, 2009
DWR is a great Ajax framework. One of the things that makes it easy is its web interface for generating JS interface files. However, that’s not something you probably want to expose to end-users. For one thing, it gives you an easy GUI interface to call any method you have with any parameters they like – a great tool for hacking!
Now, ultimately your server-side code should ensure security. But it’s also good to hide this DWR published interface. Here are some security settings you can add to your web.xml file to hide them, while still allowing DWR calls to go through:
<security-constraint>
<display-name>Protect DWR</display-name>
<web-resource-collection>
<web-resource-name>Test</web-resource-name>
<url-pattern>/dwr/test/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<web-resource-collection>
<web-resource-name>Index</web-resource-name>
<url-pattern>/dwr/index.html</url-pattern>
</web-resource-collection>
<auth-constraint>
<description>Forbidden</description>
<role-name>Forbidden</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
What this code does is put a security wrapper on /dwr/index.html and the /dwr/test directory. It’s requiring a role called “Forbidden,” and since you don’t define any users with that role, it effectively prevents anyone from getting to it. However, /dwr/call/ is kept free, so true DWR calls can make it through.
Leave a Comment » |
Development | Tagged: dwr, java, security, web |
Permalink
Posted by Josh Justice
August 25, 2009
The “disabled” attribute on an HTML form element prevents the field from being edited. Unfortunately, it also prevents the field from being submitted in the form. If you do need to submit the field even though it’s disabled, use the following instead of the disabled attribute:
this.event.addListener( field, “click”, function(e)
{
var targ;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
targ.blur();
});
YAHOO.util.Event.addListener( field, “click”, function(e)
{
var targ;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
targ.blur();
});
This will blur (deselect) the field as soon as you select it. Combine it with some gray styling and you’ve got a great form disabler.
Leave a Comment » |
Development | Tagged: disable, event, form, javascript, yui |
Permalink
Posted by Josh Justice