Jul 24, 2010

Help Me Solve My Google Maps API Info Window Problem

I'm quite stuck. I'm using the Google Maps API via the gwt-google-apis project. The symptom of the problem is that I create a <table> (that Firebug says has computed dimensions of 658 x 196) and Google Maps API wraps this with a <div style="position: absolute; left: 16px; top: 16px; width: 658px; height: 142px; z-index: 10;">.

I haven't found any way to force the info window to be resized or to set it's height. This is what it looks like:


Notice how the edit button floats off the bottom of the bubble. Yuck!

Here's the link to the app (click the YesMail link after the list has loaded).

Any ideas? I'm using this method to display the info window:

FlexTable content = new FlexTable();
//...
map.getInfoWindow().open(company.getMarker(),
new InfoWindowContent(content));

Jul 20, 2010

com.google.gdata.util.ParseException: name must have a value

For some reason the Google Maps API gdata core recently started failing to read my feature feed. This is the error I see in my App Engine log:


Caused by: com.google.gdata.util.ParseException: [Line 1, Column 3457, element atom:name] name must have a value
at com.google.gdata.util.XmlParser.throwParseException(XmlParser.java:730)
at com.google.gdata.util.XmlParser.parse(XmlParser.java:693)
at com.google.gdata.util.XmlParser.parse(XmlParser.java:576)
at com.google.gdata.data.BaseFeed.parseAtom(BaseFeed.java:867)
at com.google.gdata.wireformats.input.AtomDataParser.parse(AtomDataParser.java:68)
at com.google.gdata.wireformats.input.AtomDataParser.parse(AtomDataParser.java:39)
at com.google.gdata.wireformats.input.CharacterParser.parse(CharacterParser.java:100)
at com.google.gdata.wireformats.input.XmlInputParser.parse(XmlInputParser.java:52)
at com.google.gdata.wireformats.input.AtomDualParser.parse(AtomDualParser.java:66)
at com.google.gdata.wireformats.input.AtomDualParser.parse(AtomDualParser.java:34)
at com.google.gdata.client.Service.parseResponseData(Service.java:2165)
at com.google.gdata.client.Service.parseResponseData(Service.java:2098)
at com.google.gdata.client.Service.getFeed(Service.java:1136)
at com.google.gdata.client.Service.getFeed(Service.java:998)
at com.google.gdata.client.GoogleService.getFeed(GoogleService.java:631)
at com.google.gdata.client.Service.getFeed(Service.java:1017)
at com.curiousattemptbunny.server.CompanyServiceImpl.refreshCompanies(CompanyServiceImpl.java:80)
... 52 more
Caused by: com.google.gdata.util.ParseException: name must have a value
at com.google.gdata.data.Person$AtomHandler$NameHandler.processEndElement(Person.java:251)
at com.google.gdata.util.XmlParser.endElement(XmlParser.java:1004)
at org.xml.sax.helpers.ParserAdapter.endElement(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.xml.sax.helpers.ParserAdapter.parse(Unknown Source)
at com.google.gdata.util.XmlParser.parse(XmlParser.java:685)
... 67 more
The culprit appears to be the lack of an <atom:name> tag in the feature feed. Until the reason for this reveals itself or an update to the API is released, I'm using a custom build of the gdata-core-1.0.jar. I simply substituted a non-null value for the name in the Person.NameHandler class:
if (value == null) {
//throw new ParseException(CoreErrorDomain.ERR.nameValueRequired);
value = "N/A";
}

Sun/Oracle - You Suck

require.client.dependencies:

BUILD FAILED
/.../gdata-java-client/java/build-src/core.xml:394: missing jar file: /tmp/gdata_dep/mail.jar
The GData client requires Sun's javamail API (version 1.4), which
is not included in this distribution.

You can download it from:
http://java.sun.com/products/javamail/downloads/index.html

Then save it under:
/tmp/gdata_dep/mail.jar

Jul 9, 2010

Time Machine Backup Over The Network

Are you like me and want to back up just a few pet projects to another one of your computers on the network? If so it's not hard:

On the machine you want to backup to:
* Share a new folder in the System Preferences > Share page.

On the machine you want to backup from:
* Open up the shared folder in Finder: Go > Network.
* From Terminal run:
defaults write com.apple.systempreferences \
TMShowUnsupportedNetworkVolumes 1

* Open up Time Machine Preferences and exclude everything - you can shift-select everything on your HDD. Then selectivels remove from the list the things you don't want excluded - if you follow me.
* Verify that the total calculated size is managable - less than 10Gb say.
* Kick off a backup!
* Come back in a day or so! :)

Edit: My 9.7Gb backup over 11g wireless took just under 3 hours.

Jul 8, 2010

MapsService setUserCredentials Hang Problem

Is the Google Data Maps Feed API MapsService.setUserCredentials hanging for you? You're probably using Java 1.5. Switch to Java 1.6 and the problem goes away.

Best summary of the problem:

"I'm seeing the same thing at the same spot. CharMatcher enters into an infinite loop in setBits() while initializing the SINGE_WIDTH static instance. However, it does NOT hang if I single step over, or through, the initialization in the Eclipse debugger. I can reproduce this hang outside of the setUserCredentials() method by simply forcing the CharMatcher class to be loaded."

Solution found here:

"A follow-up. I was able to switch back to using a 1.6 JVM (1.6.0_18) and found that the hang no longer occurs. Something must be screwed up with how a 1.5 JVM handles the byte code that was generated. Perhaps recompiling the code with a different version of the javac would change the behavior?"

See gdata-client issue 249.

Jul 7, 2010

Grease Monkey & Cooks Illustrated Recipe Printing

Install this script I wrote. Then:

Navigate to a recipe on CooksIllustrated.com. Click the Print link. Now click the Shrink button to eliminate the noise and have a recipe that will print to the width of an index card.

To illustrate, here are the before and after screenshots:

Before

After

This is the code (also here):

// ==UserScript==
// @name CooksIllustrated.com - shrink recipies to index card width for printing
// @namespace http://curious-attempt-bunny.blogspot.com/
// @include http://www.cooksillustrated.com/recipes/print/*
// @require https://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
// ==/UserScript==

$('body').append('<div id="gm_shrink">shrink</div>');

$('#gm_shrink').css(
'position', 'fixed').css(
'top', '2px').css(
'right', '2px').css(
'background-color', '#991111').css(
'color', 'white').css(
'cursor', 'pointer').css(
'padding', '2px 4px 2px 4px').css(
'border', 'solid 1px #000000').css(
'font-weight', 'bold').click(function() {
var shrink = function(el) {
el.css('font-size', '8px').css('margin', '0')
.css('line-height', 'normal').css('font-size', '8px');
}

$('body').css('width', '310px');
$('.pageSectionTop').after('<p><b>'+$('h1').text()+'</b></p>');
$('b').css('font-size', '12px');
$('.dek').hide();
shrink($('em'));
shrink($('p'));
shrink($('td'));
shrink($('a'));
$('.pageSectionTop').hide();
$('.pageSection').hide();
$('img').hide();
$('br').hide();
$('td').css('padding', '0');
$('#contentFooter').hide();
$('.footerText').hide();
$('#gm_shrink').hide();
});

That Doesn't Happen Very Often!

Fifty Dangerous Things

Continuing on from Learning as Fun: 50 dangerous things (you should let your kid do)

What a perfect book! Some of my favourites:
* Play with the vacuum cleaner
* Drop from high places
* Break glass
* Deconstruct an appliance
* Poison your friends
* Super glue your fingers together
* Make a bomb in a bag
* Boil water in a paper cup

Jul 6, 2010

AdSense and Gwt Apps?!?

So I have a GWT app with "zero content" because all the content is rendered by GWT. How do other people solve this?

From Google AdSense:

"Thank you for your interest in Google AdSense. Unfortunately, after
reviewing your application, we're unable to accept you into Google AdSense
at this time.

We did not approve your application for the reasons listed below.

Issues:

- Under construction

---------------------

Further detail:

Under construction: We've found that your site's pages are incomplete or
under construction. To be considered for AdSense, we require websites to
be fully launched and functioning, allowing users to navigate throughout
your site with a menu, sitemap, or appropriate links. Your site must also
contain enough content for our specialists to review and to display
relevant ads. Once the majority of your site is complete and functional,
we'll be happy to reconsider your application.

Learning as Fun

Jul 5, 2010

Updated: Places To Work Down-Town In Portland, OR

I've updated the map of the places a software developer might like to consider working at within a 2 mile radius of down-town Portland. I've changed the Collaboration settings to allow anyone to edit the map:


View Larger Map / See Full List

Jul 4, 2010

How Agile Are We?

Assess your team's Agility, try out this app I've written - and give me some usability feedback!

The app is hosted on appengine: http://how-agile-are-we.appspot.com/.



All the material comes from The Art of Agile Development.