Arrow

Posts on this site are never sponsored.

Lenovo ThinkPad T430s review

The Lenovo ThinkPad T430s is a light, sturdy, 14-inch Windows laptop that is a great blend of performance, usability, and portability. I had previously never owned a ThinkPad but now, having used this one daily for over 6 months, I can highly recommend it.

In my opinion, advances in laptops have slowed down over the past few years, and the T430s is essentially an upgrade over the previous computer that I bought 3.5 years earlier without any groundbreaking new features. However, it is an all around high quality machine that is almost perfect for my needs. I need something that can easily be ported to and from the office daily and taken on travels. For business purposes, it needs to be good for web development; for personal purposes, the most demanding tasks are probably playing movies and editing images. The biggest downside of the T430s is battery life, although that can be mitigated as noted below.

General look and feel

As with all ThinkPads, the design is very plain:

ThinkPad 430s closed

ThinkPad 430s open

The computer is very solidly built and there are no creaky pieces. The T430s is the thinner and lighter version of the T430 and is worth the extra money if you are going to carry it around regularly. Without an extra battery, the T430s weighs about 4 pounds.

The laptop is well ventilated and does not get hot anywhere.

You can choose a US-layout keyboard. The only issue with the keyboard is that the bottom left key is the “Fn” key instead of the “Ctrl” key. This takes some getting used to and I will often press the wrong key when I use a different keyboard.

The touchpad has a nice feel to it and the distinct left and right buttons are easy to use. If you’ve never used a “TrackPoint” (the red circle mouse controller in the middle of the keyboard) you might be surprised that it comes in quite handy.

I have never used the fingerprint reader.

I don’t use the T430s for particularly demanding tasks, but it is more than fast enough for my needs.

Ports

There are ports on the back of the computer as well as on the left side.

ThinkPad 430s back

ThinkPad 430s left side

There are 3 USB ports, a single headset / microphone plug (for which you can get an adapter if you have an analog headset with two plugs), VGA video output, a mini DisplayPort (which I’ve never used), a smart card / flash card reader, an Ethernet port (much appreciated), and a built-in webcam.

On the right side there is the swappable UltraBay slot, which is an internal slot where you can plug in a CD/DVD drive (the lightest option), an extra battery, an extra hard drive, or a few other options. This is quite convenient for a couple of reasons: 1) It is easy to swap in a different piece of hardware; and 2) If you need any of those extra pieces of equipment, they essentially become internal to the computer (since you are more susceptible to forgetting them if they are external).

ThinkPad 430s UltraBay

Screen

Integrated graphics are sufficient; you shouldn’t need a dedicated graphics card unless you’re playing demanding video games, editing video, or performing similar tasks.

The matte screen is easy to look at for long periods of time (although you should take breaks anyway). I ended up getting the 1600×900 resolution screen, although 1366×768 is good enough and easier to read without increasing the text size.

The screen can tilt back fully 180 degrees.

Battery life

Battery life with the 6-cell battery is quite disappointing compared to other modern laptops, and especially compared to the heavier T430, which apparently lasts almost 10 hours with its 9-cell battery. With moderate usage, I find that the T430s only gets around 4 hours. With an extra UltraBay battery, however, I have gotten at least 2.5 hours more use.

Buying tips

Lenovo recently became the top seller of personal computers worldwide, although they are not as widespread in traditional retail stores as some other brands. I bought the T430s online, which gives you a plethora of customization options but obviously you cannot see the laptop in person until it is shipped to you.

Whenever you buy a Lenovo product online, be sure to use a coupon. For example, look for its friends and family or employee discounts and an ongoing Visa discount where you can get up to 35% off using a Visa credit card.

RAM directly from Lenovo can be quite expensive compared to what you can get at other retail stores. Consider buying the minimum amount of RAM with your computer and then upgrade the RAM yourself.

Exporting Facebook comments from Comments Box using xid and migrated=1

If you’ve been using the Facebook Comments Box on your website for a few years, you might have gone through a migration in 2011 where you simply added a “migrated=1″ parameter as suggested by Facebook:

<fb:comments xid="[id_of_page]" migrated="1"></fb:comments>

As of July 10, 2013 they are completely dropping support for the “xid” parameter and requiring an “href” parameter. However, this means that if you “migrated” your comments in 2011, you are in danger of losing all existing comments. The Facebook documentation is silent on this issue and it seems like others are facing the same problem without a known solution. This was enough to finally move one of Mugo‘s clients away from Facebook comments (and specifically to Disqus).

Of course, moving away from Facebook comments means that you need a way to export your existing comments. This is possible with some guesswork, since the documentation doesn’t mention some legacy fields like “xid”, which are crucial to the export. I won’t go through the entire process of using the Facebook Graph API and FQL; there are plenty of tutorials around the general setup. In the example below, we’ll extract the text, author information, and time of each comment.

First, make sure that in your app settings within Facebook, Migration->July 2013 Breaking Changes is “Disabled” (thanks for Darius for the tip!).

Then, using the Graph API Explorer, you can perfect the exact query that you need:

Facebook Graph API Explorer

Select your application in the top right, choose to do an FQL query, and then run a query on the “comment” table:

SELECT time, text, fromid FROM comment WHERE xid = 87902

Note that you do not need to use a “WHERE” clause specifying the “app_id” value — if you do, you will not get any results. It is your access token that already puts you in the scope of the correct application.

Basically, you’ll have to generate, from your website, a list of all the xid values (in other words, page IDs that could possibly have comments), and then pass it to Facebook. FQL supports passing multiple xid values with the “IN” syntax, so you can run a query like this:

SELECT xid, time, text, fromid FROM comment WHERE xid IN ( 87900, 87901, 87902, 87903, 87904 )

As shown in the screenshot above, you will get a JSON result with entries for each comment.

The “fromid” value is the Facebook user ID. For each result, you can directly call a Graph API REST URL to get information about the user’s name:

https://graph.facebook.com/[fromid]

This should yield a JSON result similar to this:

{
   "id": "883724954",
   "name": "Joe Smith",
   "first_name": "Joe",
   "last_name": "Smith",
   "link": "https://www.facebook.com/joesmith",
   "username": "joesmith",
   "gender": "male",
   "locale": "en_GB"
}

Cross-domain Ajax calls in Internet Explorer 8 and 9

I was working on a site (let’s say www.site.com) that had a multi-page quiz feature. Once you are done with the quiz, the results page tells you how you did but also posts your score to a separate domain (let’s say community.site.com) in order to record your score. It also shows you the average score for that quiz based on the JSON response from community.site.com/. This requires sending information to that separate domain and also parsing the response from that domain.

If you are using jQuery, this is rather standard behavior and well-documented. Here’s an example of the JavaScript call:

jQuery.ajax(
{
	type     : 'GET',
	url      : methods.options.quiz_add_result_url,
	data     : { quiz_id : quiz_id, score : ( score_per_cent / 100 ) },
	dataType : 'json',
	timeout  : 4000
})
.done( function( data ) { methods.updateAverageQuizScore( data ) } );

The important additional element is to use cross-origin resource sharing (CORS) by setting the Access-Control-Allow-Origin header in the response.

Here is a PHP example:

$allowedHTTPReadOrigins = array( 'http://www.site.com' );
$requestHeaders = apache_request_headers();
if(
	isset( $requestHeaders[ 'Origin' ] ) &&
	in_array( $requestHeaders[ 'Origin' ], $allowedHTTPReadOrigins ) )
{
	header( 'Access-Control-Allow-Origin: ' . $requestHeaders[ 'Origin' ] );
}

This is enough for the general framework to work for all modern browsers except for IE8 and IE9. I’d tested a few suggested fixes such as forcing the “cors” settings in jQuery, and setting the data type of the request and response to “text”. Some combination of tweaks allowed the Ajax request to be sent, but the response was never being parsed. JSONP is an alternative where the response data executes a callback function. However, I ended up using Internet Explorer’s XDomainRequest object handle the Ajax call. I don’t like the fact that I have two versions of the same Ajax call (one with the standard jQuery Ajax call and one using XDomainRequest) but it successfully makes the call and parses the response:

// average score
// IE8 and IE9
if( 'XDomainRequest' in window && window.XDomainRequest !== null )
{
	var xdr = new XDomainRequest();
	if( xdr )
	{
		xdr.onload = function() { methods.updateAverageQuizScore( jQuery.parseJSON( xdr.responseText ) ); };
		xdr.open( 'GET', methods.options.quiz_add_result_url + '?quiz_id=' + quiz_id + '&score=' + ( score_per_cent / 100 ) );
		xdr.timeout = 4000;
		xdr.send();
	}
}
else
{
	jQuery.ajax(
	{
		type     : 'GET',
		url      : methods.options.quiz_add_result_url,
		data     : { quiz_id : quiz_id, score : ( score_per_cent / 100 ) },
		dataType : 'json',
		timeout  : 4000
	})
	.done( function( data ) { methods.updateAverageQuizScore( data ) } );
}

Connectify alternative: sharing Internet connection wirelessly on Windows 7

I’d previously written about Connectify as a way to:

  • Share my home wired-only network to a smart phone / iPad / tablet (since those devices can only connect wirelessly)
  • Share one Internet connection in a hotel or other public network with multiple devices.

I found that Connectify was really easy to use, but on the two computers where I was using it, it caused issues when I tried to hibernate the computer. (The specific issue was that the computer would never fully hibernate, eventually timing out and forcefully cutting the power, leading to “your computer did not start up properly” problems on the next boot!) I think in my case there was a clash with Cisco AnyConnect Secure Mobility Client or Cisco Systems VPN Client.

Thankfully, there is an alternative: Windows 7 has wireless network sharing built in and it is quite easy to use as well. It has actually been a feature since Windows XP (thanks to Tim for bringing this up!), although it has gotten simpler in subsequent versions.

Here is how to share your Internet connection wirelessly in Windows 7:

1. Ensure that your wireless adapter is enabled, either via a physical button on your computer or in the network adapter settings in Windows

2. Open the Network and Sharing Center from the control panel or the pop-up menu from the taskbar’s connection icon

Open network and sharing center

3. Click “Set up a new connection or network”

Set up a new connection or network

4. Select “Set up a wireless ad hoc (computer-to-computer) network. If this is not an option, go back to step 1!

Choose connection option

5. Click “Next” a couple of times and then fill in the information for your new wireless connection (network name, security details if desired)

Ad hoc network details

6. Once the connection is created, you’ll see it in your list of available wireless networks. Right click it and “Connect” to it to enable it. (This means that other devices should be able to find it and connect to it.) Disconnect from it from your computer to disable it.

Enable wireless network

How to disable WebEx call-back feature

My company uses WebEx a lot for screen sharing and conference calls. When we first had a WebEx account, we quickly learned how fast the costs added up when offering a toll-free call-in number. Enabling that feature always occurred by accident when creating a new meeting. At 12 cents per minute (or possibly more at the time) per participant, a few calls with a few participants using the toll-free number could triple the normal monthly fee. We soon disabled that feature account-wide — it was an unnecessary feature since participants could connect via VoIP or use much cheaper or free long-distance calling to a US number.

Recently WebEx enabled the “call-back” feature by default on our account. This meant that when we selected the normal “WebEx Audio” conference type, participants were offered the option to have WebEx call their number in order to join the meeting.

WebEx audio conference settings

This was a similarly unnecessary feature and extra cost. This time, however, I couldn’t figure out where to disable the feature in the usual account settings, nor could I locate any information about it in WebEx’s online documentation. Eventually I contacted their support team and got this answer, which is still undocumented from what I can tell:

Follow the steps below to disable call-back feature on your WebEx site/host account:
1. Log in to your WebEx Site Administration page. https://[your_account_name].webex.com/admin
2. Click the Edit User List link on the left-hand side of the page.
3. Enter your search criteria into the User name: or Email: field, then click the Search button.
4. Click the name of the account that needs to be modified.
5. Scroll down to the Telephony privilege: section.
6. To disable call-back, uncheck the Call-back teleconferencing box.
7. Scroll to the bottom of the page, then click the Update button.

Editing WebEx telephony privileges

In other words, there isn’t an account-wide setting for this, but you can disable the call-back feature by editing each individual account user’s settings.