Saturday, November 17, 2012

Interesting bug & how I squashed it



I was working on a Scrollview implementation using YUI3 library for my personal web site. The idea was to make a re-usable JS for travel slideshows. Basically, for Scrollview implementation, you take a list structure and then configure the swiping to work vertically or horizontally with some additional configurations.

I had the added complexity that I was building my DOM on the fly from a Flickr feed via YQL open tables. So, the object has a constructor function which creates an instance variable for the container where the Scrollview will plug in, an overlay container and elements within the overlay, which will be used to show a larger version of the images once the preview is clicked from the Scrollview slider.

There is a getPhotos method, which fetches the photo metadata from YQL using the Flickr photoset ID.  The getPhotos method then builds the DOM for the Scrollview container (a list) and then attaches some additional listeners to the container.

I noticed a bug where sometimes the whole set of photos was not scrollable in the slider. Each page reload would have the slider end in different spot - almost never including the entire set. I made the assumption that Scrollview was dynamically calculating the "width" or "height" of the scrollable area (right assumption), and that I had a timing bug (wrong assumption). Below is how the method started out:


getPhotos : function(e) {
  var t = this,
  handleJSONP = function(data) {
    var html = '<ul>';
    for (i=0, x=data.query.results.photo.length; i<x; i++) {
      html += '<li><a href="http://farm'+data.query.results.photo[i].farm+'.staticflickr.com/'+data.query.results.photo[i].server+'/'+data.query.results.photo[i].id+'_'+data.query.results.photo[i].secret+'_c.jpg" target="_blank"><img src="http://farm'+data.query.results.photo[i].farm+'.staticflickr.com/'+data.query.results.photo[i].server+'/'+data.query.results.photo[i].id+'_'+data.query.results.photo[i].secret+'_q.jpg" alt="'+data.query.results.photo[i].title+'"/></a></li>';
     }
    t.container.set("innerHTML", html + '</ul>');
    t.pluginScrollView();
    
  },
  url = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20flickr.photosets.photos(0)%20where%20(photoset_id%3D'72157631913782316'%20and%20api_key%3D'dd0a6e3d9ef751ea725c2c0b8ec81259')&format=json&diagnostics=true&callback={callback}";
  Y.jsonp(url, handleJSONP);
},

So, I first thought that the timing issue was that the DOM had not finished constructing before I called the pluginScrollView method. So, I modified the code to be as follows:

getPhotos : function(e) {
  var t = this,
  handleJSONP = function(data) {
    var html = '<ul>';
    for (i=0, x=data.query.results.photo.length; i<x; i++) {
      html += '<li><a href="http://farm'+data.query.results.photo[i].farm+'.staticflickr.com/'+data.query.results.photo[i].server+'/'+data.query.results.photo[i].id+'_'+data.query.results.photo[i].secret+'_c.jpg" target="_blank"><img src="http://farm'+data.query.results.photo[i].farm+'.staticflickr.com/'+data.query.results.photo[i].server+'/'+data.query.results.photo[i].id+'_'+data.query.results.photo[i].secret+'_q.jpg" alt="'+data.query.results.photo[i].title+'"/></a></li>';
     if (i === x-1) {
      t.container.set("innerHTML", html + '</ul>');
      t.pluginScrollView();
     }
    }
  },
  url = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20flickr.photosets.photos(0)%20where%20(photoset_id%3D'72157631913782316'%20and%20api_key%3D'dd0a6e3d9ef751ea725c2c0b8ec81259')&format=json&diagnostics=true&callback={callback}";
  Y.jsonp(url, handleJSONP);
},

This way, I would not call the pluginScrollView method until the last iteration through the photo data (ensuring the DOM would be complete before instantiating ScrollView on the container). But, the bug persisted. I finally realized when inspecting the DOM in Chrome and Firebug that the <li> elements containing the photos had no width. And, I had failed to set a width and height on the images in the method that built the DOM. So, it turns out that fixing either problem resolved the bug. 

html += '<li><a href="http://farm'+data.query.results.photo[i].farm+'.staticflickr.com/'+data.query.results.photo[i].server+'/'+data.query.results.photo[i].id+'_'+data.query.results.photo[i].secret+'_c.jpg" target="_blank"><img src="http://farm'+data.query.results.photo[i].farm+'.staticflickr.com/'+data.query.results.photo[i].server+'/'+data.query.results.photo[i].id+'_'+data.query.results.photo[i].secret+'_q.jpg" alt="'+data.query.results.photo[i].title+'" width="150" height="150"/></a></li>';

The above fixes the bug. Additionally, it was fixable in the CSS with the following change:

#scrollable li {
  display:inline-block;
  *display:inline;
  *zoom:1;
  padding:0 3px;
  width:150px;
}

Arguably, from a performance standpoint, the former fix is better. Likely both should be employed.  I hope others are able to learn from both my mistake and my bug fixing process. 

The result can be viewed here: 


Saturday, September 22, 2012

Musings on Peru

It's been a week since we returned from Peru. I've been unpacking my many thoughts about the trip over that time. It certainly lived up to the "adventure" billing that I crave in a vacation. I am grateful for the experience and opportunity to go. It was epic in many ways. It was also exciting and at the same time uncomfortable (mentally challenging). Here are some of my high-level impressions, stream of consciousness style (full diary and photo set forthcoming).


Machu Picchu
This archeological site is a logistical nightmare to get to, and also quite expensive. But, it is worth the trouble. It is really quite amazing in many ways. Go while you are young. It is on top of a mountain, and if you are really going to enjoy it, you need to be able to walk deep, uneven granite steps all day long. The most spectacular thing that is hard to capture in photos is the symmetry of the place. The Andean builders valued a reflection of the surrounding landscape in their construction, and you can see peaks inside peaks inside peaks when you look down on the city and its surroundings. You will be amazed with what these people created without wheels, iron or steel.

Driving
Driving (or riding in a car) in Peru is quite "adventurous". Double yellow lines are merely a suggestion.  We witnessed a fatal head-on on a highway between a milk truck and a taxi. After that, I noted a memorial on every blind curve. A taxi driver will take you on a 100 kmh weave through a city if they can. A taxi driver will try to charge you more than a fare in NYC if they can. The standard response to this suggestion is "Eres loco". Much like in Rome, if your car can fit, it is a lane. The lane markings are merely for decoration. You can turn from any lane on the road in any direction. This seems to be cooperative during busy times in the city where everyone wants to do the same thing. You haven't lived until you've ridden in a bus over a 16,000 foot pass on a less-than one lane dirt road with no guard rails and significant vertical exposure. The locals do this standing in an open-air truck. Sometimes you've got to appreciate our litigious society in the USA.


Food
The food really is good in Peru. Don't eat lettuce from the local market. You will puke. I don't know any Spanish colloquialisms for this, but let's just say I was "calling the vicunas" all night in the mountains. And, I didn't exactly get the tent open every time. So, there were 6 loads of laundry when we got home. Other than that, I was astonished at the variety and deliciousness of the food. Inka cola is pretty gross, but I did try it once. It looks like Mountain Dew, but does not taste even close. Rick reports it is available at Target if you want to try it. I also had the cuy (guinea pig). It tasted like chicken. Really. I doubt I'll order it again. The skin was crispy, but there wasn't a lot of meat. Stuffed rocoto pepper with alpaca meat is brilliant. I ate that several times. Just remember the red pepper looks like a bell pepper, but is muy picante! It is not mild-mannered. They have mastered quinoa, potatoes, corn and cream soups. They are all good. Sometimes you get rice and potatoes on your plate. That seems a little starch-tastic. The guacamole will blow your mind. The produce is great. Mangos taste like nothing I have ever eaten in the States. The tomatoes and asparagus are great. Get the suckling pig, and the Peking-style duck. They are both great. Also, the seafood soups (chupe) in Lima are fantastic and the trout (trucha) in the mountains is fantastic. Ceviche is not to be missed when in Peru. We had a few of them...all great.

We had 4 world-class meals in Peru, 2 of which had a world-class price tag. The food on our trek was also consistently gourmet-quality and amazing - especially given the cooking facilities. Here are the world-class spots to try:
$$ El Punto Azul in Lima (Miraflores) - can you eat a plate of ceviche as big as your head? Why yes, you can!
$$ Chi-Cha in Arequipa - fresh, fresh, fresh. Cutting edge.
$$$ Brujas de Cachiche in Lima (several locations) - best meal of the trip.
$$$ Sonccollay Pre-Inka Cuisine in Arequipa - don't miss the passion-fruit ceviche.


Beer/Drink
We sampled pretty much all the beer. Cusquena malt and regular, Arequipena, Pilsen, and Cristal. I think I liked Arequipena and Cristal the best. The malt Cusquena is a lot like Guiness, but sweeter. If you order sparkling water at altitude, open it slowly. You have been warned. Chicha (corn beer) is an acquired taste.

Cities
I had mixed impressions of the cities in Peru. I'm not really a big-city gal...add to that the slums and other sub-standard housing, tons of traffic, and a "thriving nightlife", and well, there you have it. The center of Arequipa and Cusco are both charming if you can dodge the street vendors and keep your head about you. The Miraflores neighborhood in Lima is the same, though walking around at night isn't great. There are fabulous restaurants in all 3 cities, and some pretty interesting museums and archeological sites. Downtown Lima is a zoo. I could only take a couple hours of the chaos. Though, we did get a cheap and tasty lunch there. Staying and eating in a good neighborhood in a city will cost you about the same in the U.S. The nuevo sole is pretty strong against the dollar and the economy of Peru is outpacing ours.

Tours
It seemed all the tours (other than our trek) were focused more on shopping than on historical sites. This was the most true for the Sacred Valley tour. The others at least struck more of a balance. They are cheap, so I suspect a kickback system is in place. If you really want to focus on the archeological sites, hire a private driver and guide.


The Andes
The Andes are truly spectacular. They are not to be missed. The only bummer is that you have to get above 14,000 feet to really see the stars. This is due to a lot of burning in the air - the fields are burned, the ovens are all wood-burning, and there are not a lot of trees on the leeward side of the mountains to freshen the air. They are also a bit overrun with camping trekkers. I feel that Peru could benefit from a refugio system like in the Alps and Dolomites - permanent structures to house trekkers and provide a meal would help keep human waste contained and provide a clean cooking source and an income source for the local villagers. The smaller cities in the mountains are quite charming - like Chivay. They are big enough to have services and a nice community feel, but small enough to lack crime. And, while still impoverished, the locals seem to have a nice rhythm and quality of life in these towns. The mountains also have a bit of a technological paradox - you can be at 16,000 feet in between villages of stone houses without electricity or running water - and you can talk on your cell phone. There seems to be coverage everywhere. Don't miss the exquisite beauty of the ladies' hats. Every drainage/village you enter in the Andes has a different style of hat, and they are all stunningly beautiful.


Language
Most of the people in the Andes speak Quechua as their first language and Spanish as their second. My name means "maize" in Quechua. My Spanish understanding remains quite good, while my speaking is  a bit rusty. But, I got along OK. We had two tours in Spanish + English and I understood both equally well - it was like hearing an echo the whole way. Let's just say I can't speak any Quechua other than "chicha" and "sara". So, I can order corn and corn beer. I have a ways to go.

Best. Time. Ever.

Well, this post is a bit more than overdue. I skipped the Nor Cal State TT Championships, as I could not register early, and my Tahoe lodging hookup ended up coinciding with another weekend. But, I thought it was no big deal, as I had not really been training.

So, I entered the Beat the Clock TT the following week. Well, to my surprise, I was in MUCH better shape than I thought. I had a record-setting day. Not only did I go under 30 minutes for the first time, but I also broke my prior best time by over 2 minutes! That was certainly welcomed. Perhaps it was a release of the stress following a decision to switch jobs...I don't know. But, I'll take it! Now, I have some serious work to do before I get on the course again. New best time: 29:18. July 7, 2012.

Tuesday, May 8, 2012

Race Reportage

After a mostly down year last year, I've picked up a bit with the racing this year - mostly time-trial stuff, as that is what I seem to enjoy the most.


Lodi TT
This was a new race on the calendar this year - an out and back race to the west of I-5 in Lodi which turns around when you hit the Delta - about 11.5 miles in length. I actually felt quite good during this race and placed 2nd. Now, I have a standard against which to compare myself next year. The conditions were quite good with an incoming rain storm. Winds were light, and conditions overcast. The course was just about the flattest I've ever ridden. Pavement was good by Velo Promo standards, but definitely not pristine.

Beat the Clock #2
Weather conditions were pretty perfect for the 2nd Beat the Clock race this year. It was quite cold, and I ended up drinking some hot tea at the start instead of doing a longer warm-up, which was regrettable. After my time got all messed up in the last race by some group rides, I was ready for vengeance! I went out a bit too hard and caught my minute girl early. I regretted my fast beginning pace and short warmup during the last 2 miles of the race....I was really suffering. But, at the en,d I had recorded 31:26, or my best time by 1 second. Official time was 31:28, or 1 second off my best, but a good effort nonetheless. I will try to get under 31:20 in my next effort. Better pacing should get me there.



Woodside Trail Run
I entered the Woodside Trail Run for the second year in a row. This year, I opted for the 10K instead of the 17K, as I was going to go meet my parents for hiking at the Pinnacles in the afternoon and didn't want to be completely trashed. The conditions were once again EPIC. It was not actively raining this year, but had just rained heavily for the prior two days, and the water was coursing down the trail again. I was pretty slow, but it was good to push myself. Of course, I realized that I may as well do the 17K as the 10K has about 95% of the climbing of the 17K.

During the race, I was concerned with my footing, given the deep mud and water on the trail. I was paying most of my attention to that, and missed the fact that I ran into some poison oak with my right arm. I suspected contamination and washed with my Burt's Bees soap when I got home. Alas, I think I missed the window of opportunity, and a huge rash started spreading on my arm the following Tuesday. I decided to suck it up and try to heal naturally. Unfortunately, when we were in Mexico the following week, my arm swelled to double its normal size, and I had to spend a nice morning in the clinic with the Medico. Nothing some cortisone and antibiotics couldn't sort out, though!

Sunday, February 19, 2012

First Race of the Season

Well, it's been almost a year since my last "bike race" posting. I finally got out and raced again yesterday, albeit at a low-key time trial.

I don't have my results yet, but I think I was at least in the general ballpark with last year's time. That's good, since I pretty much haven't been training at all. Anyway, it was a good day and a good opportunity to re-learn how to suffer.

Next up...a 9k trail run in Pacifica next Saturday...it's beginning to look at tad bit like a season! (photo snapped by Linda Locke - teammate extraordinaire!)

Friday, January 20, 2012

Forced Training

Last week I had a meeting with the new CTO of the company. The meeting was scheduled to be in Santa Clara. So, I put it on my personal calendar to cycle that day and end up at the Santa Clara office. The evening before the meeting, there was a calendar update with a document attached. I opened the document, but didn't pay any mind to anything else about the update.

I did a 1 hour ride, arriving at 8:25 - about 35 minutes before the meeting start. I got to the locker room to shower, and opened my laptop to confirm which room the meeting was in. To my dismay, the meeting was moved to the Sunnyvale office - about 6 miles from the Santa Clara office. I did mental calculations and realized I was going to need to average 20 mph to get to the meeting on time with a few minutes to change my clothes. So, I put my jacket and messenger bag back on and started the all-out TT back to Sunnyvale. Time trilling on a heavy touring bike with heavy messenger bag with clothes and computer is a bit of a challenge. But, I made it at 8:53, dashed into the locker room and did the world's fastest shower/change. But, I got a nice, hard 20+ minute effort in for the first time this season. There's nothing like a little forced training to kick off the HIT season.

Thursday, February 24, 2011

Huh, a race report, what's that?

I was eager to try out my new steed (the Ellsworth COefficient) for the first time in a race situation. Also, I was curious to see where my fitness was as I have been un-training for the last 6 months - doing whatever strikes my mood. I definitely still push myself, but don't do any structured cycling workouts. So, I signed up for the Beat the Clock time trial.

I rolled up just before the start having parked at Woodside Town Hall and used my ride in as my "warmup". It was near freezing and raining. I had 3 layers sausaged under my skinsuit and the seal skinz on my feet. I was happy to see teammates - Marsha, Liz, Andrea and Cammy around, as well as a few other brave souls who showed up despite the weather. 

I got a good hold from veteran TTer Lisa and a good start. I was a little tentative with the wet conditions and the new bike. I never let myself touch the brakes, but I also didn't put as much gas into the downhill sections as I normally would. I felt it was going to be hard as the winds as well as most of the climbing would be back-loaded with the storm coming in. I was happy to see I was able to "spin" in some slightly larger gears than in previous attempts. That was a good sign for my power output. I had no computer at all on the bike, so I was just "keep looking at the horizon and go as hard as feels reasonable". I was planning a 10k run for the following morning, so definitely held myself below the "all out to puking" effort. As I crossed the line, I felt reasonably well, looked at my watch, and knew I had posted my best time on the course....but not sure of the exact time.

When the results were posted, I was 31:27...WAY better than my prior best of 32:45. Yay! I don't know if this is a testament to the awesomeness of the new bike or to just letting myself have fun...but a good result, nonetheless. I'm looking forward to going under 30 mins for the first time when the conditions are good on this course and I'm able to put on the aero wheels, too.