Disclaimer

The views expressed on this weblog are mine alone and do not necessarily reflect the views of my employer, Avanade.

Search
Recomends...
  • Code Complete, Second Edition
    Code Complete, Second Edition
    by Steve McConnell
Login

Code Snippets makes developers more productive

I created this tool to make reusing common functions, queries or other pieces of code easy as pie.
Saturday
Jan252014

Announcing Mtelligent, My first attempt at open source.

Yes it's the name of the blog too, but I decided to name my current side project after it. And I decided to open source it. It's a A/B, Multivariant Testing and Cohort Analysis Framework for ASP.Net.

Instead of writing a blog post about it, I put all the detail into the read me file. You can find it on Git Hub here.

Over the next few weeks, I'll share more details about the internals of the framework, and hopefully make some progress toward closing some of the gaps I've already identified.

I'm releasing it now, because I think it's in good enough shape to share, and I actually wanted to get some feedback on it.

 

Sunday
Dec222013

Share Location Confusion (Geolocation Settings for IPhone and Android)

A few weeks ago I shared some tips for leveraging the HTML5 geolocation api's. The API is great, and opens some very cool possibilities, especially when coupled with Google maps API's, but the one weakness is the browser implementation of user preferences when it comes to sharing your location with a website.

Maybe if it wasn't so inconsistent between IPhone and Android devices, it would be more managable, but right now it can be downright confusing.

Android's stock browser has a bit better implementation in my opinion. The first time you come to a site that requests your current location you get prompted on whether or not you want to share your location with that website. Whatever you answer, the stock browser will remember forever. You never get prompted again, it will just continue to share or deny access to your location for that website. If you do want to change the answer, you can go to Settings (from the Browser Menu), then Content Settings, then Website Settings and actually control your location settings for each website.

IPhone and Mobile Safari is a bit more complicated. The first time you come to a site that requests your current location you get prompted on whether or not you want to share your location with that website. But unlike Android, you do get prompted a second time if you refresh the page. As long as you answer the same, after the second prompt you will never get prompted again. Plus there is no way to change your location preferences for individual websites. The only way to change it, would be to nuke all your location settings by going outside of safari to settings, General, Reset, Reset Location and Privacy. And that removes everything. You actually get prompted to allow safari access to your location before getting prompted again to allow access to the website, bringing the total number of prompts to 3 if you change your mind.

In either case, if a user deny access to a website, talking them through reversing that decision is daunting at best, and you should give it some thought when you figure out when and how to prompt a user to share their location, because chances are, you will not get a second chance if they deny you.

 

Saturday
Dec142013

IPhone scrolling woes 

We were experiencing some weird behavior when testing the mobile site we were developing on IPhones. Long pages were missing their scrollbars. Touch scrolling was not smooth at all. And on pages with form elements, the page would seem to get stuck when scrolling. Stuck such that you couldn't scroll any further down or you couldn't scroll up if you were already down. 

After a bit of research, I found this webkit css style that when applied to our outmost div, seemed to resolve these scrolling issues.

-webkit-overflow-scrolling: touch;

After adding that single line of css, all the scrolling issues mentioned earlier seemed to disappear. But there were additional issues that appeared.

The first issue surfaced when scrolling quickly on pages of our site with complex layouts. When they were scrolled too fast, white blocks temporarily showed up. The renderer caught up and displayed the content after the scrolling stopped, but it just felt and looked weird. 

The second issue we noticed on pages with text boxes. When you went to type in the textboxes, you wouldn't see the text, but it would show up after exiting the focus of that textbox.

Researching the first issue, I came across this post about rendering issues with webkit overflow scrolling which mentioned a work around. So I went through all of our css, adding an additional style rule to any rules that had position: relative defined.

-webkit-transform: translate3d(0,0,0);

And that seemed to fix both the fast scrolling and form issues I mentioned. Very strange, but applying a no move/change 3D transformation gets the css to be hardware accelerated and makes the page behave better. I know it feels like a hack, but it's a hack that seems to work.

 

Sunday
Dec082013

What I expect you to know about Chrome Dev Tools

Too often we make things difficult on ourselves. We don't take the time to learn our own tools. We do things the long and hard way, never realizing the various short cuts available to us. This is especially true of web development. I suspect way too many developers make small fixes, rebuild and retest, elongating their build/test cycles unnecessarily. Chrome Dev Tools have been around a long time and getting better every day, and yet I frequently find myself on teams with folks not taking advantage of it.

And yes there are similar tools for Firefox, Safari and even internet explorer, but to date, I've found myself most comfortable with chrome. So if you're on one of my teams, and you haven't spent a lot of time using Chrome Dev Tools, here's what I expect you to know: 

Working with JavaScript? Use the Console

A few years ago, I used to add "debugger;" statements to debug javaScript in Internet Explorer. It wasn't pretty. Chrome's Dev tools give you everything you need to get your javaScript to work. If you rebuild your project to fix clientside javaScript issues, you're doing it wrong.  If you write javaScript at all, you need to use the javaScript console. And by use it, I mean use if before, during and after you write JavaScript code. 

Here are my tips for javaScript debugging with Chrome Dev Tools

  • Add console.log statements generously. They make it a ton easier to see what's happening. Especially when asyncronous calls are made. Don't like having them in production code? Remove them with a pre-processor before deploying to production.
  • Try out code in the console. Not sure the syntax of the code you're writing? Get it to run on a single line and run it in the console. This works especially well for testing to make sure you are using the correct jquery selectors.
  • Make a copy of tempory data and inspect it later. Code ran with no errors but things still don't work? Assign values to global variables like "lastData" or "tempData" and inspect them after your code runs to see what happened. Maybe what you got isn't what you expected.

Eventually we'll get our javaScript code right, but until then, use the console.

Inspect Element for the Win

If we haven't been blessed with a design company throwing perfectly tested markup over the wall to the dev team, we're going to need to spend some time getting things to look right.  And that means messing with CSS. When it comes to getting developers to maintain css files, you typically have a couple of options: 

  • Have them add inline styles to the markup. 
  • Have them add style tags to the markup pages themselves.
  • Have them create their own override css file and mark all the rules that don't work !important!.

As daunting as it may seem to have to locate and edit a large complex set of style sheets, everything you need to figure out what and where to make changes is available in chrome dev tools. Here are my tips for working with CSS.

  • Understand the space your divs take up. Right Click, Inspect Element. Scroll to the bottom of the styles tab to see the box (Or click on the computed tab). Margin, Border, Padding, Height and Width. If it's not right, there is a reason, but unless you understand the space your element is taking, good luck fixing it.
  • Test out CSS changes in the browser. Use the style tab to toggle off CSS rules or add your own. Add inline styles to the markup, or edit the HTML directly if necessary. Get it right and then make the same changes in your source.
  • Use Computed to learn where the style came from. The styles tab will tell you if a css rule is being applied or not, but instead of looking through every possible style, it's far easier to click on the computed tab and expand the property you care about. It will tell you where that style came from. Almost feels like you're a detective when you figure out where it originated.

There's a ton you can do click different elements and looking at their styles. You should be able to figure out exactly what changes need to be made before you apply them.

See what came over the wire on the Network Tab

The last super useful tool everyone should know is the network tab. I honestly prefer tools like Fiddler or Http Watch, but for 90% of cases, the network tab will give me what I'm looking for: What was sent to the server and what came back to the client.

Here are my tips for debugging client server communications:

  • Look at posted values in the Headers tab. More and more I'm using complex user interfaces that are just facade's for hidden inputs. If you have a bug in your javaScript, it will be hard to tell what's going wrong unless you check exactly what data is being posted.
  • Find your AJAX call and validate their payloads - Making async calls? Find out exactly what is being sent and received. Don't take anything for granted.
  • Verify Cookies to make sure the right data is being sent across. The headers tab has what cookies are sent to the server, but you can see both incoming and outgoing cookies on the cookie tab. Either way, should give you enough info if your troubleshooting cookie related issues.

The network tool gives you a nice sanity check as to what is actually being sent between the client and server.

Sharpen the Saw

These are just the basics, but they are basics you'll need to master before getting to the hard stuff. Learn your tools and you'll be more efficient and proficient when developing. This goes way beyond browser tools and should be applied to all of your development tools.  

Other areas for exploration

Lately I've been playing with Chrome canary and some of the advanced mobile emulation support it has. Previously I was using the Chrome Add on: Ripple Emulator, but find the support in canary is superior. I also have been playing with remote debugging and screen casting my phone's version of beta chrome. There's a lot of new features in Chrome that are worth looking at, if not tracking what's going on.

On the server side, I've been really enjoying using glimpse, a server side nuget add in for ASP.Net projects that gives you a chrome tools like feel to looking at things like routes and server configuration. 

 

Saturday
Nov302013

Deferreds, Geolocation and Reverse Geocoding with Google Maps API

One of the most useful but little used aspects of jQuery is the Deferred object. It's jquery's implementation of promises and makes it easier and cleaner to expose functionality that is asyncronous. 

I've been working quite a bit with Geocoding and the Google Maps API and usage of deferred to expose this functionality has been very useful.

The basic idea is that instead of relying on callbacks to alter the state of global objects, you can pass a deferred object which will notify the caller when the result is ready to be processed.

Take the standard navigator.geolocation.getCurrentPositionMethod. This is a built it method that will retreive the user's current location if they allow it. Normally you pass to callback functions to this method, one for success and one for failure. By wrapping this call with a method that returns a deferred object, the resultant code is much cleaner for handling the result. Take this implementation as an example:

var getLatLong = function() {
        var def = $.Deferred();

        if (navigator.geolocation){
            navigator.geolocation.getCurrentPosition(
                function (position){
                    def.resolve(position);
                }, 
                function (error) {
                var errors = { 
                    1'Permission denied',
                    2'Position unavailable',
                    3'Request timeout'
                  };
                    def.reject("Error: " + errors[error.code]);
                },
                {timeout:10000});
        }
        else
        {
            def.reject("geolocation not supported");
        }

        return def;
      };

Instead of just firing the call and leaving the callbacks to alter state, we can referred the deferred object and the caller can respond to the result on success, failure or both.

Take this method "getCurrentAddress" which relies on our first method and then calls google's geocoding api to translate the user's current latitude and logitude to an address.

var getCurrentAddress = function (){
        var def = $.Deferred();
        getLatLong().done(function(position){
          //we have current Lat and long in settings object.
          var latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
          
geocoder.geocode({'latLng': latlng}, function(results, status) {

          if (status == google.maps.GeocoderStatus.OK) {
            if (results[0]) {
              def.resolve(results[0].formatted_address);
            }
          } else {
              def.reject("Geocode Failed: " + status);
          }});

        });

        return def;
      }

It chains the result of the call to our first method to the done function, which will automatically be invoked when the first call completes succesfully and the position object is automtically passed as a parameter. We then use that to call Google's geocoding api to get an address back. The whole thing itself also leverages deferred, so we can easily call it and get back the address when it's done. Here's the call on the page which gets the result and updates a div on the page with the user's current address:

<script>
getCurrentAddress().done(function(address){
     $("#address").text(address);
});
</script>

We also could have handled failures, as well as implemented code that executes regardless of the outcome of the deferred, so this approach gives you a very robust approach to dealing with asyncronous dependencies.