Why your fonts don’t look right on the Chrome app

chrome

So, fun fact: the Chrome app for Android or iOS tries to help you SOOOO MUCH. In fact, it will hijack the CSS styles of text on your web site and tweak them to be more readable. Tweak by as much as 300%. Tweak only some of the text elements and leave other ones alone. So yeah, HUUUUUUGE form labels next to teeny tiny form elements for example. Ugh.

Chrome calls this “font boosting”. I call this “stress boosting”.

If you’re like me (and I know I am), you find this annoying because it makes your web site look like garbage.

Do you want to tell the Chrome to disable font boosting? Luckily, it’s easy to do so. Just apply this style to some root element of your page like this:

#page_wrapper {
max-height: 999999px;
}

if you have a page wrapper. If not, do this instead:

html * {
max-height: 999999px;
}

The style will cascade down, and Chrome will stop being such a control freak helpy helperton. You’ll have control to style your css as you see fit.

Comments

comments

Powered by Facebook Comments

Facebook Login, My Old Nemesis

An Alternative Login with Facebook Implementation

So every app of sufficient complexity has one feature that always seems to break in odd ways. You tweak it, duct tape it, adjust it, but it just breaks, breaks, breaks. When this happens enough, you tear it down and rebuild the silly thing from scratch. This is what happened with my Facebook login implementation for babynamester.com

Facebook-My-Nemesis

I used to have an implementation based on this: https://developers.facebook.com/docs/facebook-login/getting-started-web/

This default implementation runs on event listeners. For whatever reason, this version of Facebook login proved to be really fragile for me. After many hours trying to shore it up, I spent some quality time with the Facebook API documentation and built the version below instead.

My version works by passing callbacks to the FB.login function to perform an app login on success.

1. Create a Facebook app

Just follow the instructions here under section 1 of this page: https://developers.facebook.com/docs/facebook-login/getting-started-web/

2. Initialize the Facebook SDK on your page

Next, make sure your page initializes with Facebook’s API correctly. There’s no need to nest any of the javascript in a document ready function.

<div id="fb-root"></div>

<script type="text/javascript">
(function(d){
   var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
   if (d.getElementById(id)) {return;}
   js = d.createElement('script'); js.id = id; js.async = true;
   js.src = "//connect.facebook.net/en_US/all.js";
   ref.parentNode.insertBefore(js, ref);
}(document));
  
window.fbAsyncInit = function() {
   FB.init({
      appId      : '123456789123456789', // replace this with your appId
      channelUrl : '//'+window.location.hostname+'/channel.php', // Path to your Channel File
      status     : true, // check login status
      cookie     : true, // enable cookies to allow the server to access the session
      xfbml      : true  // parse XFBML
   });
}
</script>

3. Write a function to handle success

Let’s skip to the end before circling back. After we have a successful Facebook login, we’ll need to tell our app that we’ve validated a Facebook login for a specific user and create the appropriate session. At this stage we’ll have a Facebook user object to work with, ‘me’. We’ll see how we get that in step 4 below – just go with it for now.

Let’s make sure this object is valid (i.e. has an id). If it is, I hit an endpoint in the app to get a signature for that id. This is to prevent people from spoofing my app’s facebook login form and creating bogus accounts and sessions in the app. Once we get the signature (‘key’) back from the app’s endpoint, we enter the id, the signature, and some basic user information (found on the user object) into the login with facebook form and submit it. The form submits to an action that will validate the id against the signature. If it checks out, it will see if a user exists in the app. If not, we create one. And then either way we create a session.

The code I’m showing you is everything in the view layer. I leave the signature endpoint and login endpoint to your imagination. Those will be specific to your app anyway. This code also does not need to be in a wait for document ready.

<script type="text/javascript">

// this is the function to login to our app once the Facebook login
// is successful and we have a Facebook user object
function login_with_facebook(me) {
   // this is the endpoint in my app that I get a validation signature from
   url = '/facebook/jskey';

   if ('id' in me && me.id) {
      $.post(url, { 
         'id': me.id 
      }, function(response) {
         // use the user object data and jskey signature to post the #fb_form form
         if (me.name) {
            $('#fb_form input.fb_name').val(me.name);
         }
         if (me.id) {
            $('#fb_form input.fb_id').val(me.id);
         }
         if (me.gender) {
            $('fb_form input.fb_gender').val(me.gender);
         }

         var data = jQuery.parseJSON(response);
         $('#fb_form input.fb_key').val(data['key']);
         $('#fb_form').submit();
      });
   }
}
</script>

4. Hook up a login button or link and a logout link

Finally, we create a button or a link with the class ‘login_with_facebook’ somewhere on our page and another link with the ‘fb_logout’ class. To make it functional, we use this code.

<script type="text/javascript">
$(document).ready(function() {
   $('.login_with_facebook').click(function(e){
      e.preventDefault();

      // Get the login status, perform actions accordingly
      FB.getLoginStatus(function(response) {
         if (response.status === 'connected') {
            // user is logged into Facebook and has already authorized your
            // app. request a user object and call our app login function
            // with it
            FB.api('/me', function(me) {
               if ('id' in me) {
                  login_with_facebook(me);
               }
            });
         }
         else if (response.status === 'not_authorized') {
            // user is logged into Facebook, but has not authorized your app.
            // Facebook login, passing in a callback to fetch the user object
            // and perform an app login on success
            FB.login(function(response) {
               if (response.authResponse) {
                  FB.api('/me', function(me){
                     login_with_facebook(me);
                  });
               }
            });
         } else {
            // not logged in to Facebook. We do a Facebook login, passing in
            // a callback that fetches the user object and fires an app login
            // on success. The same actions as the previous case, but I'm
            // keeping them separate to more clearly show the three possible 
            // states you can be in relation to Facebook. You also may want
            // to handle these cases differently.
            FB.login(function(response) {
               if (response.authResponse) {
                  FB.api('/me', function(me){
                     login_with_facebook(me);
                  });
               }
            });
         }
      });
   });

   // who said breaking up is hard to do?
   $('a.fb_logout').click(function(e){
      // preventing default to make sure our logout request fires and
      // then redirects to where the link points
      e.preventDefault();
      FB.logout();
      window.location = $(this).attr('href');
   });
});

</script>

5. Knit it into your web app
The parts that I haven’t shown you are on the backend of my app. You’ll need to figure out what makes sense for your app. Specifically, the parts of my app I’m not showing you are:
1. the /facebook/jskey endpoint that creates a signature for an id. For best security, the signature for a given id should change over time.
2. the endpoint that the form submits to. This endpoint validates the id against the signature. If valid, it checks to see if the user exists yet for that Facebook id in our app. If so, it just creates a session and redirects back to the page. If not, it will also create a new user.

Also, I leave my #fb_form form, login button, and logout link html to your imagination.

We’re not handling failure with much sophistication, just ignoring it. In the places where failure is detected, you could easily add some code to flash the user a helpful message if you desire.

That’s it, I hope you find this useful.

Comments

comments

Powered by Facebook Comments

tagtacular.js

tagtacular.js

tagtacular.js is a jQuery plugin for tag management that I just released as an open source project. My project goals are:

  • very easy to setup with default behavior
  • very flexible customization options
  • minimal requirements and minimal assumptions about your technology stack and architecture

Check it out and let me know what you think:

 

Comments

comments

Powered by Facebook Comments

Developer Diary: Taming Doctrine’s 2000 Flushes

I’ve just started a new side project that will involve finding some creative solutions to tough problems. I thought it would be neat to share what I learn as I go, so here goes…

For my project I decided to use the Doctrine 2 ORM to manage my data layer. We also use this at work, so the biggest reason I chose this was to be able to learn more about Doctrine to help me in my job. But this decision also makes sense for my project because my entity relationships will likely be fairly straightforward for the most part and using an ORM will allow me to make a lot of progress very quickly without (I hope) causing me lots of trouble later on.

One of the odd little things about Doctrine is how it handles persistence. The rules are a bit complex and non-intuitive. Here’s a summary:

  • Changes are saved when you call flush() on the entity manager, and at no other time.
  • Objects that were already in the database that you made changes to will be updated at this time with no special instructions.
  • New objects will not be saved by default.
  • If you want a new object saved, you need to persist() it.
  • If something would have saved and you don’t want it to, you need to detach() it.
  • Objects that are linked to each other through association fields can cause problems when one part is created or deleted and one isn’t – this can cause you to error out nastily and close your entity manager.
  • You can avoid this by creating cascade rules in your model classes, but this can lead to updates happening that you didn’t intend if you aren’t careful!

Clear as mud, right? We kind of have a love and hate (sometimes hate and hate) relationship with Doctrine at work because the hardest 20% of things we need to do with it tend to be very hard and annoying. One of the annoying things is that when a function needs to update an object, it’s not always obvious if we should flush. If we flush, maybe we’re committing a temporary change that shouldn’t be committed. Or maybe our data is still in an inconsistent state and the entity manager will crash. If we don’t flush, maybe we’re creating a burden on the controller layer to remember to do it for us (which isn’t what our controller layer should care about). We’ve sometimes resorted to having a flush flag parameter to a function to tell it whether to flush or not. This is complexity that we’re better off without!

It tends to be easier to solve these problems by adding way more flushes than we strictly need, which is not good for performance. The data in my side project is simple, but there’s a lot of it, so I wanted to mitigate this problem. This is my first stab at a solution:

First of all, I’m not using Doctrine’s entity manager directly. I’ve created an abstraction layer called the Data Manager which my code calls to perform all entity manager actions. This not only gives me better options to tame Doctrine’s rough spots, but gives me a fighting chance to yank Doctrine out and replace it if I decide it’s causing me significant problems.

<?php

class BB_Manager_Data
{
     static protected $instance = null;
     static protected $em = null;
     ...

If I want to go old school and just flush, I have a function for that. If I just call it with no preliminaries, it’s just a pass through. But I’ve borrowed the idea of SQL transactions to handle chunks of related changes. If I call startTransaction(), the flush() function will do nothing. When I call commit(), flush() is reenabled, and then called. This makes the idea of transactions more explicit and allows me to be more flexible about how I commit changes without cluttering my method signatures. Here’s what the first version of my code looked like:

static protected $disableFlush = false;

static public function startTransaction()
{
     self::$disableFlush = true;
}

static public function commit()
{
     self::$disableFlush = false;
     self::flush();
}

static public function flush()
{
     if (!self::$disableFlush) {
          $em = self::getEntityManager();
          $em->flush();
     }
}

Ah, but Doctrine supports transactions! It’s just a matter of calling $em->getConnection()->beginTransaction(); to start and $em->getConnection()->commit(); to complete or $em->getConnection()->rollback(); to cancel. Until commit() is called, the flushes won’t actually flush. So another version of the above would be:

static public function startTransaction()
{
     $em = self::getEntityManager();
     $em->getConnection()->beginTransaction();
}

static public function commit()
{
     $em = self::getEntityManager();
     $em->getConnection()->commit();
}

static public function flush()
{
     $em = self::getEntityManager();
     $em->flush();
}

Or you could just use Doctrine’s transactional functions outside of an abstraction layer.

Which of these versions is better depends on how Doctrine implements its transactional functionality (which I don’t know yet) and what your particular needs are. My initial version may actually be more performant in some cases if Doctrine’s transactions are just pass-throughs to your DBMS’s transactions. But it may be a micro-optimization or none at all. I may dig a little further or do some A/B tests to gather some information about that.

I think the transactional capabilities are an underutilized tool in Doctrine 2′s toolbag that can provide useful flexibility, group related changes, and minimize database writes. And the transactional paradigm (whatever the implementation) goes well with many use cases to help tame those flushes and optimize database writes.

 

Comments

comments

Powered by Facebook Comments