Iframe opens in new window problem in Firefox

Developers use iframe for many different things: ‘ajax’ file upload, loading content in an overlay, storing data, calling a REST page and etc.

Turns out if you create an iframe without specifying the name attribute, it will open the iframe in a new window or tab in firefox.

I’m putting this under the ‘blog it to remind my future self’ category.

Search on multiple social networks via realtimesearch.me

The 4-hours hackathon project turned out to be a blast. My project concept is simple – provide a service where user can search for content on major social sites with apparent ease. It was a fun hack and I met some great people from the event. It also gave me an opportunity to play around with Twitter’s bootstrap, jquery History and handlebarJS. It has never been easier to throw up a quick web prototype with all these free lovings going around :).

Check it out – realtimesearch.me

Javascript HTML5 geolocation with geo-IP fallback

Javascript Geo location helps you find your user position(latitude and longitude) via javascript. It will at first try to locate user position via native html5 geolocation position and if that fails, fallback to GEO-IP api via freegeoip.net. This script requires jQuery.

Existing api has be known to be quirky, usually unstable and outputting inaccurate result for many developers. This library minimizes the pain and provide a better user-interaction and better fallback method.

Javascript Geo Location

Nodejs, LESS, Express and Html5 boilerplate

So how to easily generate a project template that contains these lovely web muffins?

First, assuming you have express installed, generate a simple express project using LESS framework

express -c less project_name

This will generate a file structure like this for your project.

Replace the codes inside layout.jade with:

!!! 5
//if lt IE 7
  <html class="no-js ie6 oldie" lang="en">
//if IE 7
  <html class="no-js ie7 oldie" lang="en">
//if IE 8
  <html class="no-js ie8 oldie" lang="en">
//[if gt IE 8]><!
html(class='no-js', lang='en')
  //<![endif]
  head
    meta(charset='utf-8')
    meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')

    title
    meta(name='description', content='')
    meta(name='author', content='')

    meta(name='viewport', content='width=device-width,initial-scale=1')

    link(rel='stylesheet', href='stylesheets/style.css')

    script(src='javascripts/libs/modernizr-2.0.6.min.js')

  body!=body
    #container
      header
      #main(role='main')
      footer

    script(src='//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js')
    script window.jQuery || document.write('<script src="javascripts/libs/jquery-1.6.3.min.js"><\\/script>')

    script(defer, src='javascripts/plugins.js')
    script(defer, src='javascripts/script.js')

    script
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview'],['_trackPageLoadTime']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));

    //if lt IE 7
      script(src='//ajax.googleapis.com/ajax/libs/chrome-frame/1.0.3/CFInstall.min.js', defer)
      script(defer) window.attachEvent('onload',function(){CFInstall.check({mode:'overlay'})})

Next up, style.less:

/*-------------------------------------------------------------------------------------*\
        HTML5 Boilerplate Lite

http://html5boilerplate.org

        less.css same as style.css with added LESS CSS nesting, mixins, and variables
        --
        credit is left where credit is due.
\*-------------------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*\
                                                                LESS CSS
\*---------------------------------------------------------------------------*/
/*........................................................*\
                                                Variables
\*........................................................*/

/* Colors */
        @white: rgba(255, 255, 255, 1);
        @black: rgba(0, 0, 0, 1);
        @yellow: #ff9;
        @blue: #007DC5;
        @darkBlue: #33589F;
        @veryDarkBlue: #143352;
        @grey: #999999;
        @pink: #FF5E99;

/* Font */
        @font: 'Droid Sans', arial, sans-serif;

        @small: 12px;
        @medium: 15px;
        @large: 24px;

/*........................................................*\
                                                        Mixins
\*........................................................*/
.border-radius (@radius: 5px) { border-radius: @radius; }
.box-shadow (@hor: 3px, @vert: 2px, @blur: 5px, @shadow: #000) { box-shadow: @hor @vert @blur @shadow; }
.text-shadow (@hor: 3px, @vert: 2px, @blur: 5px, @shadow: #000) { text-shadow: @hor @vert @blur @shadow; }

.clear-text-shadow { text-shadow: none; }
.clear-box-shadow { box-shadow: none; }

.hide { display: none; }
.show { display: block; }
.invisible { visibility: hidden; }
.left { float: left; }
.right { float: right; }

/*---------------------------------------------------------------------------*\
                                                                Styles Reset
\*---------------------------------------------------------------------------*/
a, abbr, acronym, address, applet, article, aside, audio,b, blockquote,big, body,center, canvas, caption, cite, code, command,datalist, dd, del, details, dfn, dl, div, dt, em, embed,fieldset, figcaption, figure, font, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, html,i, iframe, img, ins,kbd, keygen,label, legend, li, meter,nav,object, ol, output,p, pre, progress,q, s, samp, section, small, span, source, strike, strong, sub, sup,table, tbody, tfoot, thead, th, tr, tdvideo, tt,u, ul, var { background: transparent; border: 0 none; font-size: 100%; margin: 0; padding: 0; vertical-align: baseline; }
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; }

blockquote, q   {       quotes: none;
                                        &:before { content: ''; content: none; }
                                        &:after { content: ''; content: none; }
                                }
ins { text-decoration: none; }
mark { background-color: @yellow; color: @black; font-weight: bold; }
abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; }
table { border-collapse: collapse; border-spacing: 0; }
hr { display:block; height:1px; border:0; border-top:1px solid #ccc; margin:1em 0; padding:0; }
input, select { vertical-align: middle; }

/*---------------------------------------------------------------------*\
                                                        Typography
        fonts.css from the YUI Library: http://developer.yahoo.com/yui/
\*---------------------------------------------------------------------*/
body { font:13px/1.231 @font; }
pre, code, kbd, samp { font-family: 'Courier New', monospace, sans-serif; }

/* -:[ Fibonacci based heading scale ratio ]:- */
        h1 { font-size: 4.4em; font-weight: normal; }
        h2 { font-size: 2.8em; font-weight: bold; }
        h3 { font-size: 1.6em; font-weight: bold; }
        h4 { font-size: 1.2em; font-weight: bold; }

/* -:[ Remove text-shadow from text selection for better readability: http://twitter.com/miketaylr/status/12228805301  ]:- */
::-moz-selection{ background: @pink; color: @white; .clear-text-shadow; }
::selection { background: @pink; color: @white; .clear-text-shadow; } 

/*---------------------------------------------------------------------------------------------*\
                                                                        Shortcuts & Helpers
\*---------------------------------------------------------------------------------------------*/

.separator { clear: both; float: left; height: 1px; width: 100%; }      /* -:[ If  ain't enough ]:- */

/*---------------------------------------------------------------------------------------------------------*\
                Clearfix

http://j.mp/bestclearfix

http://blueprintcss.lighthouseapp.com/projects/15318/tickets/5-extra-margin-padding-bottom-of-page

\*---------------------------------------------------------------------------------------------------------*/
.clearfix:before, .clearfix:after { content: "\0020"; display: block; height: 0; visibility: hidden; }
.clearfix:after { clear: both; }
.clearfix { zoom: 1; }

/*----------------------------------------------------------------------------------*\
                                                                Real styles start here
\*----------------------------------------------------------------------------------*/

body    {
                        /*      background: ;
                                color: ;
                                font: ..px @font;       */
            }

header  {
                        .inside {  }

                        nav     {
                                        ul      {
                                                        li      {
                                                                        a       {
                                                                                        &:hover {  }
                                                                                        &:active {  }
                                                                                }
                                                                }
                                                }
                                }
                }

#wrap   { 

                }

footer  {
                        .inside {  }
                }

/*------------------------------------------------------------------------------*\
                                                                Media queries
\*------------------------------------------------------------------------------*/
@media all and (orientation:portrait) { /* Style adjustments for portrait mode goes here */ }
@media all and (orientation:landscape) { /* Style adjustments for landscape mode goes here */ }

/*      ........................................................................
        Grade-A Mobile Browsers (Opera Mobile, iPhone Safari, Android Chrome)
        link: www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/

        Stop iOS and WinMobile from mobile-optimize the text:
        link: http://j.mp/textsizeadjust
                html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; }
        ........................................................................*/
@media screen and (max-device-width: 480px) {  }

/*----------------------------------------------------------------------------------------------*\
                                                                                Print styles

        Inlined to avoid required HTTP connection - link: http://www.phpied.com/delay-loading-your-print-css/
\*----------------------------------------------------------------------------------------------*/
@media print {
                                  * { background: transparent !important; color: #444 !important; .clear-text-shadow; }
                                  a, a:visited { color: #444 !important; text-decoration: underline; }
                                  a:after { content: " (" attr(href) ")"; }
                                  abbr:after { content: " (" attr(title) ")"; }
                                  .ir a:after { content: ""; }  /* Don't show links for images */
                                  pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
                                  thead { display: table-header-group; } /* css-discuss.incutio.com/wiki/Printing_Tables */
                                  tr, img { page-break-inside: avoid; }
                                  @page { margin: 0.5cm; }
                                  p, h2, h3 { orphans: 3; widows: 3; }
                                  h2, h3{ page-break-after: avoid; }
                        }

That’s it.

Distinguish between Jquery click and double click

I wish there’s a better way. Or maybe perhaps there is?

var flag = 1;

$(element).click(function(){
    setTimeout(function(){
        if(flag){
            console.log('this is a click');
        }
    }, 500);
    flag = 1;
})

$(element).dblclick(function(){
    console.log('this is a double click');
    flag = null;
})

Unicode in nodeJS and passing arguments with Cloudmade api

Not all NodeJS libraries come with unicode support out-of-the-box, but some do very well (props to express). I found most of the problems in those libraries can be fixed if you look for the writeHead function argument. More likely than not, javascript is served as text/javascript and no charset is set so if the browser requests something else by default (iso-8859-15 in many case), the resource gets interpreted as such. It can either be fixed by changing generated tags to request type=”text/javascript;charset=utf-8″ or by serving the actual resource with a “text/javascript;charset=utf-8″ header. Watch out for the content length call as well.

//before
res.writeHead(code,
    { "Content-Type": "text/json" , "Content-Length": body.length }
);

//after
res.writeHead(code,
    { "Content-Type": "text/javascript; charset=utf-8" , "Content-Length": Buffer.byteLength(body) }
);

Moving on to the next thing. While working on stupidmap.com, I came across a simple trick to pass additional argument via Cloudmade LatLng API. They should have documented this in the API doc :P

//third parameter onwards can be used to pass arguments
var marker = new CM.Marker(new CM.LatLng(lat, lon),
{ icon: CloudMadeIcon, title: title, n_argument: data });

//pass data as an argument
CM.Event.addListener(marker, 'click', function(){
    var _data = this._options.n_argument;
    infoWindow(_data, this);
});

I assume you can do the same thing with Google Maps and Leaflet API.

4 dollars 7-Eleven’s t-shirt

There are an unbelievable number of 7-Eleven’s in Taipei. One for every 6200 people in fact, compared to one for every 48000 people in the US. I have always been intrigued by the concept of disposable, no-frills garments that are sold there. They are packaged and sold like something you would see coming out of a vending machine.

So I bought one. They cost like 4 dollars USD each. Nicely folded. None of those weird fresh scent. Herpes-free as far as my human eyes can tell. The fabric is a little bit light – it is no American Apparel that’s for sure. But it is still pleasantly comfy. Fit nicely too.

I can imagine buying 50 of these and just stock them in my closet. Takes care of the daily annoyance of having to figure out what to wear.




29

So far, everything turned out better than expected. We are now a quarter past 2011 and I am turning 29 in a few weeks. What do people do when they are 29? Are we even allowed to make wishes at this age?

It’s an awkward age. Too young to die but old enough to gradually come to a sad realization that this is pretty much it.

I am perfectly fine with that. :-)

WAP love

developing for WAP browsers (you know, Nokia feature phone users…) is worse than fixing IE 6 bugs but today someone posted this pic that makes all the pains worthwhile :)

Bye 2010