Facebookifying Pages

I became really sick of Google Chrome because of its crashing every now and then. Somebody informed me about SRWare Iron which is basically Chrome-like browser and I really like it for personal use, it has never crashed for the last few months I have been using it.

Though this browser works fine, I noticed that on some sites where there is facebook connect, you get “FB is not defined”, this seemed to happen only with this browser. I figured out that  for some reason, it does not fetch the FB’s JS API file eg http://connect.facebook.net/en_US/all.js. Now I love this browser for personal use but I was unable to use on some sites such as slideshare.net.

This made me inject FB object manually in the page which produced above error. For that I created bookmarklet which injected FB script in current page and told about that status. Here is the code for that bookmarklet you can add to your bookmarks toolbar:

</pre>
javascript: function loadScript(src, callback) {
 var s,
 r,
 root_node = document.createElement('div');
 s = document.createElement('script');
 s.src = src;
 s.onload = s.onreadystatechange = function() {
 if (!r && (!this.readyState || this.readyState === 'complete')) {
 r = true;
 callback()
 }
 };
 root_node.id = 'fb-root';
 document.body.appendChild(root_node);
 document.body.appendChild(s)
 }
loadScript('http://connect.facebook.net/en_US/all.js', function() {
 var el = document.createElement('div');
 el.style.position = 'fixed';
 el.style.textAlign = 'center';
 el.style.fontWeight = 'bold';
 el.style.MozBorderRadius = '5px';
 el.style.WebkitBorderRadius = '5px';
 el.style.borderRadius = '5px';
 el.style.margin = '0 auto 0 auto';
 el.style.top = '0';
 el.style.left = '40%';
 el.style.color = '#fff';
 el.style.padding = '5px 10px 5px 10px';
 el.style.backgroundColor = (typeof window.FB === 'object') ? 'green': 'red';
 el.innerHTML = (typeof window.FB == 'object') ? 'Page Facebookified :)': 'Unable to Facebookfiy :(';
 document.body.appendChild(el);
 window.setTimeout(function() {
 document.body.removeChild(el)
 }, 2500)
 });
<pre>

However, with this one would have to press Facebookify bookmarklet button manually. I then thought of auto-inserting FB object in each page I visited, so I went on developing a Greasemonkey addon for this which  automatically inserts FB object into visited page as soon as DOM is available. You can download it here if you want:

Greasemonkey Facebookify Userscript

This way, the FB problem is no more there and I continue to use this nice browser.
This post can be helpful for anyone who is also using SRWare Iron browser or anyone who wants to play around with FB JS API by injecting it on any page.

Outputting PHP To Browser Console

Although there exist classes for outputting PHP to browser console such as Google’s PHP Console and certain others, I was looking for a way to output PHP to browser console without including those classes in my PHP files or installing any browsesr plugin to do the same. Currently, I am working on facebook application development in which you have to commit/upload the code to check certain output out of PHP unlike offline development where you check the code output before committing it up. This makes facebook application development a longer process for a developer but you got to live with it because you don’t have a choice.

Anyways, to speed up the code output checking process a little and rather using debug_backtrace, print_r, print/echo, var_dump, etc which you need to remove/comment again, I created a function to get output of PHP on the browser console. One could use error_log function but even that makes you go to your log file and then see the output. Of course, browser needs to support/have the console so that code result is output there. Because IE less than 8 doesn’t have console, this won’t work in IE less than 8, though result won’t be affected in it. Notice that you can see console in IE=>8 by pressing F12 key and then going to Script tab where you need to make sure Console tab is selected on the right side.

Here is the function:

     /**
     * Logs messages/variables/data to browser console from within php
     *
     * @param $name: message to be shown for optional data/vars
     * @param $data: variable (scalar/mixed) arrays/objects, etc to be logged
     * @param $jsEval: whether to apply JS eval() to arrays/objects
     *
     * @return none
     * @author Sarfraz
     */
     function logConsole($name, $data = NULL, $jsEval = FALSE)
     {
          if (! $name) return false;

          $isevaled = false;
          $type = ($data || gettype($data)) ? 'Type: ' . gettype($data) : '';

          if ($jsEval && (is_array($data) || is_object($data)))
          {
               $data = 'eval(' . preg_replace('#[\s\r\n\t\0\x0B]+#', '', json_encode($data)) . ')';
               $isevaled = true;
          }
          else
          {
               $data = json_encode($data);
          }

          # sanitalize
          $data = $data ? $data : '';
          $search_array = array("#'#", '#""#', "#''#", "#\n#", "#\r\n#");
          $replace_array = array('"', '', '', '\\n', '\\n');
          $data = preg_replace($search_array,  $replace_array, $data);
          $data = ltrim(rtrim($data, '"'), '"');
          $data = $isevaled ? $data : ($data[0] === "'") ? $data : "'" . $data . "'";

$js = <<<JSCODE
\n<script>
     // fallback - to deal with IE (or browsers that don't have console)
     if (! window.console) console = {};
     console.log = console.log || function(name, data){};
     // end of fallback

     console.log('$name');
     console.log('------------------------------------------');
     console.log('$type');
     console.log($data);
     console.log('\\n');
</script>
JSCODE;

          echo $js;
     } # end logConsole

Here is an example of how to use it:

$name = 'sarfraz';

$fruits = array("banana", "apple", "strawberry", "pineaple");

$user = new stdClass;
$user->name = "Sarfraz";
$user->desig = "Sr. Software Engineer";
$user->lang = "PHP";

logConsole('$name var', $name, true);
logConsole('An array of fruits', $fruits, true);
logConsole('$user object', $user, true);

Above code will result in what is shown in the image above. Although this does not prevent committing code first to see the code output if you are on facebook application development but it defintely does save some time. I have been using this function successfully so far, please let me know your ideas if any on how to improve this piece of code further. Have fun !

Custom Facebook Connect Image

One of the ways you can put facebook connect button on your site is to use <fb:login-button> fbml tag something like this:

  <fb:login-button onlogin="window.location='www.example.com'"></fb:login-button>

That will show default facebook button with a rather small image. You can make the button little larger by specifying length and size attributes like this:

  <fb:login-button onlogin="window.location='www.example.com'" length="long" size="large"></fb:login-button>

However, the requirement in my case was that the button should be even bigger. I searched through the facebook connect docs and elsewhere but did not find a way to customize the facebook connect image (it is rendered directly by facebook; let me know if there is a way via comments please). I thought why I can’t force the facebook connect button to use the image that I specify. I fired up firebug (the addon of firefox) and this is what it showed for the <fb:login-button> fbml tag:

As can be seen, facebook automatically applies FB_login_button class amongst others to the connect button. As you can see, there is an img tag inside, that was all I needed to get my own image for the connect button. The idea is to find the image inside connect button and replace with your own once DOM has loaded. Now you get the idea, I wrote this jQuery code to get custom image for the connect button:

<script type="text/javascript">
$(function(){
  // overwrite the fb connect image - let's force it !!
  $('.FB_login_button').find('img').attr('src', 'img/my-custom-image.png');
});
</script>

We use the selector .FB_login_button and then use find method to find the image inside element (<fb:login-button>) having that class and replace its src attribute with the path of our custom image.  Since we have wrapped our code in ready handler $(function(){…}), our code will execute as soon as DOM becomes ready and when you visit the page, it will have your own custom facebook connect button image.

I also noticed that there was a link tag generated with the class of fbconnect_login_button. We could use that just as well like this:

<script type="text/javascript">
$(function(){
  // overwrite the fb connect image - let's force it !!
  $('.fbconnect_login_button').find('img').attr('src', 'img/my-custom-image.png');
});
</script>

Now this is good as long as you are using jQuery on the page where facebook connect button exists. But if you are not using jQuery, you can do the same thing with vanilla javascript albeit with little more code. Here is how you can do the same thing with vanilla javascript:

<script type="text/javascript">
window.onload = function(){
  var ourImg = null; // this will store the facebook connect img tag

  // find all the links on the current page
  var links = document.getElementsByTagName('a');

  // loop over all the links
  for(var i = 0; i < links.length; i++){
    // get class of this link
    var cls = links[i].className;

    // check to see if this is the link with specified class
    if (cls === 'fbconnect_login_button'){
      ourImg = links[i].firstChild; // which is img tag we need
      break;  // done, let's get the hell out of here
    }
  }

  // finally replace with our own image !
  ourImg.src = '<?php echo base_url() ?>images/fb.png';
};
</script>

Ops ! that is a lot of code I have written compared to jQuery’s but that’s what you need if you are not using jQuery on your page. Note that this time, we are using load event of the window window.onload = function(){…} which will fire when all the page resources are loaded including images, frames and the DOM unlike ready handler of jQuery which fires as soon as DOM becomes ready and runs before images, frames or any other external resources loaded into the page.

Finally, this is the page that now uses custom facebook connect button image while using <fb:login-button> fbml tag:

View the Page