Rico Sta. Cruz
Rico Sta. Cruz
Cofounder, Sinefunc, Inc.
www.sinefunc.com
  github.com/sinefunc
We &heart; Ruby.
We &heart; Sinatra.
We &heart; making
people's lives easier through
      good web apps.
Rico Sta. Cruz
github.com/rstacruz
Things that web apps do
that seem really difficult
   to do but really is
        dirt easy.
aka:

Cheap tricks!
Aura CMS
auraisawesome.wordpress.com
Challenge:
In-place AJAX reloading.
“You know,
like Twitter, or Gmail.”
You may think
 it's difficult.
FUCK NO
LOL
It's dirt easy!
Like this:
$('a').live('click', function () {
$('a').live('click', function () {
   var href = $(this).attr('href');
$('a').live('click', function () {
   var href = $(this).attr('href');
   $('#loading').show();
$('a').live('click', function () {
   var href = $(this).attr('href');
   $('#loading').show();


   $.get(href, function (html) {
$('a').live('click', function () {
   var href = $(this).attr('href');
   $('#loading').show();


   $.get(href, function (html) {
        $('body').html(html);
$('a').live('click', function () {
      var href = $(this).attr('href');
      $('#loading').show();


      $.get(href, function (html) {
            $('body').html(html);
            $('#loading').hide();
      });
});
Voila!
!
“But it just loads everything.
       That's cheating!”
Optimization
<head>
 <script src="/js/script.js"></script>
 <link rel="stylesheet" href="/css/style.css" />
</head>


<body>



 <div id="top">Your site name and nav here</div>



 <%= yield %>


</body>
<% unless request.xhr? %>
<head>
 <script src="/js/script.js"></script>
 <link rel="stylesheet" href="/css/style.css" />
</head>
<% end %>
<body>


 <% unless request.xhr? %>
 <div id="top">Your site name and nav here</div>
 <% end %>


 <%= yield %>


</body>
<% unless request.xhr? %>
<head>
 <script src="/js/script.js"></script>
 <link rel="stylesheet" href="/css/style.css" />
</head>
<% end %>
<body>


 <% unless request.xhr? %>
 <div id="top">Your site name and nav here</div>
 <% end %>


 <%= yield %>
                                    “Hey, don't render this cruft when the
</body>                                   page is loaded via AJAX.”
Meanwhile,
in JavaScript land...
$('a').live('click', function () {
      var href = $(this).attr('href');
      $('#loading').show();


      $.get(href, function (html) {
            $('body').html(html);
            $('#loading').hide();
      });
});
$('a').live('click', function () {
      var href = $(this).attr('href');
      $('#loading').show();


      $.get(href, function (html) {
            var $new = $('<div>').html(html);
            $('#content').html($new.find('#content'));
            $('#sidebar').html($new.find('#sidebar'));
            $('#loading').hide();
      });
});
Awesome.
!
 “What about
the back button?”
Hash
jQuery.hashlisten
github.com/sinefunc/jquery.hashlisten



          2kb of simplicity
$('a').live('click', function () {
      var href = $(this).attr('href');
      window.location.hash = '#!' + href;
      return false;
});
$('a').live('click', function () {
      var href = $(this).attr('href');
      window.location.hash = '#!' + href;
      return false;
});


$.hashListen('!(.*)', function (href) {
$('a').live('click', function () {
          var href = $(this).attr('href');
          window.location.hash = '#!' + href;
          return false;
    });


    $.hashListen('!(.*)', function (href) {




Every time the hash changes to this, do this.
$('a').live('click', function () {
      var href = $(this).attr('href');
      window.location.hash = '#!' + href;
      return false;
});


$.hashListen('!(.*)', function (href) {
      var href = $(this).attr('href');
      $('#loading').show();


      $.get(href, function (html) {
            var $new = $('<div>').html(html);
            $('#content').html($new.find('#content'));
            $('#sidebar').html($new.find('#sidebar'));
            $('#loading').hide();
      });
});
Sweet!
Next challenge:
IE compatibility.
“Oh. √£÷¡*.”
Attempt 1: The Paul Irish method
?
“Can that even be
  done in HAML?”
Kinda—
!
Not in a straight-forward way.
  ...unless you make a helper!
%html
  %head
    %title= 'My site'


  %body
     ...stuff
!= cc_html do
  %head
    %title= 'My site'


  %body
     ...stuff
def cc_html(options={}, &blk)
 attrs = options.map { |(k, v)| " #{h k}='#{h v}'" }.join('')


 [ "<!--[if lt IE 7 ]> <html#{attrs} class='ie6'> <![endif]-->",
      "<!--[if IE 7 ]>   <html#{attrs} class='ie7'> <![endif]-->",
      "<!--[if IE 8 ]>   <html#{attrs} class='ie8'> <![endif]-->",
      "<!--[if IE 9 ]>   <html#{attrs} class='ie9'> <![endif]-->",
      "<!--[if (gt IE 9)|!(IE)]><!--> <html#{attrs}> <!--<![endif]-->",
      capture_haml(&blk).strip,
      "</html>"
 ].join("n")
end
Good!
Better way
AgentSniff
github.com/sinefunc/agentstiff



            ~3kb
browser.ie6?             #=> false
browser.webkit?          #=> true
browser.android?         #=> true

# Helper
def browser
 UserAgent.new(env['HTTP_USER_AGENT'])
end
class UserAgent
  def initialize(ua_string)
    @ua = ua_string
  end

 def webkit?()    product?('AppleWebKit'); end
 def chrome?()    product?('Chrome'); end
 def ie6?()       detail?(/^MSIE 6/, 'Mozilla'); end
 # ...

  def product?(spec); !! @ua.match(spec); end
  # ...
End
browser.body_class
#=> 'webkit safari mac'
#=> 'ie ie6 windows'
#=> 'webkit android'
class UserAgent
  # ...


  def body_class
      (%w(webkit chrome ios gecko opera ie linux) +
        %w(ipad windows mac ie6 ie7 ie8 ie9)).map do |aspect|
        aspect   if self.send :"#{aspect}?"
      end.compact.join(' ')
  end
end
%html
 %head
    %title= 'My site'


 %body


        ...stuff
%html{class: browser.body_class}
 %head
   %title= 'My site'


 %body


     ...stuff
%html{class: browser.body_class}
 %head
   %title= 'My site'


 %body
     - if browser.ie6?
         %p Please upgrade your prehistoric browser!


     ...stuff
Effect:
<html class='mac webkit chrome'>


/* CSS: Fix chrome's button padding bug */
button { padding: 3px; }
.chrome button { padding: 1px 2px; }
<html class='windows ie ie6'>


/* CSS: Fix the double margin bug */
#posts { margin-left: 10px; }
.ie6 #posts { margin-left: 5px; }
Even better
with SASS!
<html class='windows ie ie6'>


/* CSS: Fix the double margin bug */
#posts {
    margin-left: 10px;
    .ie6 & { margin-left: 5px; }
}
twitter.com/rstacruz
github.com/rstacruz




   sinefunc.com

Cheap frontend tricks