By Vasken

Facebook JavaScript SDK “Uncaught RangeError: Maximum call stack size exceeded” error

volcano-ecuador-825x558

I’ve been dealing with an issue for a couple of months where the Facebook JavaScript SDK wouldn’t function properly on my local development instance, even though it was working fine in our testing and production environments. I tried all the obvious things–confirmed the correct URLs in the Facebook App settings, made sure I was using the right App ID and Secret, etc. The weird thing is, according to the console FB was an object, and XFBML was an object, but parse() was not a method of XFBML.

I wasn’t seeing any of the usual JS errors in the console in Chrome either, which was a bit confusing, at least until I opened Safari and saw this:

Uncaught RangeError: Maximum call stack size exceeded

According to this question on StackOverflow, the problem is caused by running the old Facebook SDK (FeatureLoader.js) alongside the new one (all.js). I was positive that FeatureLoader.js wasn’t loading anywhere in my codebase, and a quick check with ack didn’t show anything either. FeatureLoader.js definitely was getting loaded though, and when I double-checked I saw that it was being loaded by a locally-installed dev plugin that I have running (but that isn’t on our dev or production sites). Plugin removed, problem solved.

On Safari Mobile for iOS 5, event.pageY is the new event.clientY

safari-logo-lg

We have some tooltips running at my work that are used to render sharing buttons when a user clicks or taps on them. When the recent upgrade to iOS came around, the tooltips stopped being rendered properly in iOS 5.

After running into a few problems with jQuery Tools and the iPad, I came up with a solution for getting the tooltips to appear next to the anchor element like they were supposed to. By using the event.clientY value from the touch event, I was able to detect where in the DOM the touch had happened, and simply position the tooltip right next to it, with something like this:

$('#tooltip').css('position', 'absolute !important').css('top', event.clientY);

In iOS 4.3, event.clientY was reporting the absolute position of the touch event relative to the entire document. In iOS 5, I discovered that it was reporting the position of the touch event relative to the window. So, if you tapped a tooltip way down on the page, but near the top of the current viewport window, the tooltip would appear right near the top of the document, completely off screen.

A little digging on Google yielded this page on the Apple site. The reference to an event.pageY property made me think that maybe that would do the trick, and it seems to work.

$('#tooltip').css('position', 'absolute !important').css('top', event.pageY);

Now, with iOS 5, the touch event was properly setting the tooltip’s top value to the position of the touch event within the entire DOM, not just the viewport. I’m not exactly sure what’s changed between iOS 4.3 and 5, but at least now I have something that works for both.

Lazy-load a LinkedIn Sharing button after the JavaScript window.load event

Adding social networking sharing buttons to your site has become almost a ubiquitous step in Web development, to the point when some designers have stopped thinking about the performance impact of rendering multiple buttons via JavaScript while a page is still loading. The delay might not be noticeable for, say, 1 or 2 buttons, but when you’re rendering multiple buttons per page (when you have a button to share individual Tweets on a page, for example), it can get out of hand (turns out JavaScript crashing the browser creates a user-unfriendly experience for most people).

The solution is to lazy-load the buttons when you need them, either when a user clicks to expose a previously hidden div, or at the very least after the window.load JavaScript event, to prevent slowing your pageload times down. Here’s an example of a simple way to lazy-load a LinkedIn Share button on window.load:

First, include the necessary scripts (LinkedIn’s in.js and jQuery). You can do this in the footer if you want…after all, you’re not doing anything with them until much later in JavaScript-time:



Next, add some jQuery in a script tag that looks for any script tag with a type of ‘unparsed-IN/Share’ (the name doesn’t matter, as long as it’s NOT IN/Share, since the whole point here is you don’t want the in.js script to parse the tag). Depending on the size of your DOM, you may want to be more specific with your jQuery selector…a div or a section of content is fine, and you can bind to a click event, a scroll event, or whatever else you’d like to initiate the parsing of your LinkedIn buttons:

 jQuery(window).load(function(){
    jQuery('body').find('script[type="unparsed-IN/Share"]').each(function(){
      jQuery(this).attr('type', 'IN/Share');
      IN.parse(document); //you can also use getElementById('id') in place of document here
    });
  });

Finally, you just need to add LinkedIn sharing tags in the following manner. The key here is to change the JS script type from IN/Share to unparsed-IN/Share (or whatever you chose in the jQuery above), which will cause the tag not to be rendered when in.js is loaded, allowing you to control with the JS when the tag is actually parsed, using IN.parse (which can be applied to the document as a whole, or an element as retrieved by the built-in JS document.getElementById method.


Update: As Howard points out in the comment section, if you don’t need to load the in.js script to render any LinkedIn buttons or content earlier, you can always accomplish lazy-loading by simply deferring the script load until you want to render the buttons. This allows you to avoid parsing and replacing the ‘type’ on each JavaScript snippet. If you need LinkedIn content to render both before the onload event as well as after, though, you’ll still need to do the replacement.

Install Siege on Mac OS X Snow Leopard

I recently needed to install Siege on my MacBookPro. Here’s what I did:

wget ftp://ftp.joedog.org/pub/siege/siege-latest.tar.gz
tar -xvf siege-latest.tar.gz
cd siege-2.70/
./configure && make && make install

That’s it! Now you should be able to do something like this:

siege -c50 http://yourserver.com

That will simulate 50 concurrent users hitting that particular URL. After siege runs for a bit, you can hit Ctrl+C to kill it and it will output some handy stats about performance.

Chicken Soup with Mushrooms & Rice

Chicken Soup with Mushrooms & Rice

I recently discovered Reynolds Slow Cooker Liners, which make cleaning up after using our slow cooker 100% easier, so as a follow-up to the chili I made recently, I decided to make a few quarts of chicken soup. I started with a recipe from Epicurious for Chicken Rice Soup, and added a few extra ingredients. What I ended up with was something like this:

  • 1 large onion, coarsely chopped
  • 3 large celery ribs, cut into 1/4-inch-thick slices
  • 3 medium carrots, cut into 1/4-inch-thick slices
  • 1 (3 1/2- to 4-pound) chicken
  • 2 cups long-grain brown rice
  • 1/3 cup packed fresh fresh cilantro leaves
  • 3 quarts water
  • Freshly ground black pepper
  • Fresh 8oz shiitake, portabella, and oyster mushroom mix from Hannaford

Preparation was not complicated. Everything except the cilantro gets chopped up and thrown in the slow cooker, then add enough water to cover the other ingredients. I put the slow cooker on high for 4 hours, and added the cilantro about 2 1/2 hours in. It’s worth noting the original recipe called for 3 teaspoons of salt, but I don’t see that being necessary. And if it’s not salty enough, people can always add their own.

Chicken Soup with Mushrooms & Rice

Beef Chili with Beans

wpid-IMG_20110411_220145.jpg

I made some chili in our Crock Pot this weekend that came out pretty tasty. Here’s the recipe I ended up using, a modified version of Beef Chili with Chipotle Chilies and Cilantro that adds beans and substitutes green chiles for the chipotles (I’m not a big fan of those):

  • 3 pounds lean ground beef
  • 3 cups chopped onions
  • 4 tablespoons ground cumin
  • 4 tablespoons chili powder
  • 2 1/2 tablespoons garlic powder
  • 1 small can chopped green chiles
  • 3 1/2 cups (or more) water
  • 1 cup finely chopped fresh cilantro
  • 1 14.5oz can of red beans
  • 1 14.5oz can of pinto beans
  • Grated cheddar cheese
  • Sour cream
  • Additional chopped onion

Basically, you throw everything in the first list into the slow cooker and cook it on high for 4 hours. Top with additional onions, cheddar cheese, and/or sour cream as desired, and enjoy!

image

 

TomTom randomly disconnects during update on Mac OS X 10.6 Snow Leopard

TomTom Manage My Device

When I went to update my TomTom XL to the latest version of the operating system, I ran into a problem where the update failed and the device was stuck at a blinking screen with a red X across it. I Googled the problem a bit, but didn’t really find any good solutions. This Apple forum was trying to solve the problem, so I applied the first two suggestions, but to no avail. Following the instructions on repairing a bricked device on TomTom’s site was similarly unsuccessful.

Then I started watching the TomTom every time I ran the update, and I noticed that the little hard drive icon would stop flashing before each disconnect, not the other way around. This led me to believe the problem started on the device. When I went into the Manage my device option in TomTom HOME, I noticed the device’s memory was nearly full.

I think the problem is that the TomTom update/map is larger (or at least requires more room during unpack) than the previous version of the OS or map. In my case, the problem was solved in the following way:

  • In TomTom HOME, choose More->Manage my device
  • Make sure you’re looking at Item on my device (not on the computer)
  • Navigate through and delete any unncessary files (in my case deleting extra downloaded voices was enough)
  • Go back to the HOME menu and choose Update my device

The update should finish. If it fails, check to see if it’s failed on a different file (that means it used more space, but still failed because it ran out), and delete more files. If your device is already bricked (like mine was), deleting the application itself (see screenshot below) couldn’t hurt (in fact, this might’ve been necessary for my OS update to successfully install).