A front-end tale: Google Places Library, jQuery promises and Coffeescript

When it comes to define my working position I often need to state (and clarify) the differences between design, frontend and backend development.
Given my academic background and my interests I can easily be considered more a backend developer than a frontend. I do not have a great “esthetic sense” and despite my knowledge of HTML5 and CSS (with all its SCSS, SASS, LESS and so on) I do not have the expertise of a “real frontend developer”.
Don’t get me wrong, I studied Javascript basics and I like to keep myself updated with its community news but still, it is not (at least for now ;P) my area of expertise.

image

Nevertheless I like to solve problems independently on their nature and so if there is a “frontend problem” to tackle I’m always ready to dive in.

This is exactly what happened last week.

Continue reading “A front-end tale: Google Places Library, jQuery promises and Coffeescript”

Dead simple view layer with Opal and jQuery

Dead simple view layer with Opal and jQuery

Lately I noticed that I started to port from project to project a simple class that implements a basic view layer with Opal and jQuery.

In this post we will rebuild it from scratch, you can consider it as an introduction for both Opal and Ruby, and maybe also a bit of OOP

The View class

If you still generate your HTML on the server (making happy search engines) and progressively add functionality via CSS and JavaScript then this class is probably a good fit.

Let’s start by defining our API. We want an object that:

  • takes charge of a piece of HTML
  • can setup listeners and handlers for events on that HTML node
  • can be easily composed with other objects
  • exposes behavior, hiding implementation

Step 1: An object, representing a piece of HTML

Say we have this HTML, representing a search bar:

<section class="search">
  <form>
    <input type="search" placeholder="Type here"></input>
    <input type="submit" value="Search">
  </form>
</section>

This is how we want to instantiate our view:

Document.ready? do
  element = Element.find('section.search')
  search_bar = SearchBar.new(element)
  search_bar.setup
end

The SearchBar class can look like this:

class SearchBar
  def initialize(element)
    @element = element
  end

  attr_reader :element

  def setup
    # do your thing here…
  end
end

Step 2: Adding behavior

Now that we have a place let’s add some behavior. For example we want to clear the field if the ESC key is pressed and to block the submission if the field is empty. We need to concentrate on the #setup method.

feature 1: “clear the field on ESC”

class SearchBar
  # …

  ESC_KEY = 27

  def setup
    element.on :keypress do |event|
      clear if event.key_code == ESC_KEY
    end
  end


  private

  def clear
    input.value = ''
  end

  def input
    @input ||= element.find('input')
  end
end

As you may have noted we’re memoizing #input and we’re searching the element inside our current HTML subtree. The latter is quite important, especially if you’re coming from jQuery and used to $-search everything every time. Sticking to this convention will avoid down the road those nasty bugs caused by selector ambiguities.

feature 2: “prevent submit if the field’s empty”

class SearchBar
  # …

  def setup
    element.on :keypress do |event|
      clear if event.key_code == ESC_KEY
    end

    form.on :submit do |event|
      event.prevent_default if input.value.empty?
    end
  end


  private

  def form
    @form ||= element.find('form')
  end
end

YAY! Sounds like we’re almost done!

Step 3: Extracting the View class

Now seems a good time to extract our view layer, thus leaving the SearchBar class with just the business logic:

class View
  def initialize(element)
    @element = element
  end

  attr_reader :element

  def setup
    # noop, implementation in subclasses
  end
end


class SearchBar < View
  def setup
    # …
  end

  private

  # …
end

Step 4: Topping with some “Usability”

Now that the View class has come to life we can add some sugar to make out lives easier.

Default Selector

We already know that the class will always stick to some specific HTML and its selector, it’s a good thing then to have some sensible defaults while still allowing to customize. We’ll define a default selector at the class definition, this way:

class SearchBar < View
  self.selector = 'section.search'
end

Document.ready? { SearchBar.new.setup }

The implementation looks like this:

class View
  class << self
    attr_accessor :selector
  end

  def initialize(options)
    parent   = options[:parent] || Element
    @element = options[:element] || parent.find(self.class.selector)
  end
end

ActiveRecord style creation

I’d also like to get rid of that Document.ready? that pops up every time. As always let’s define the API first:

class SearchBar < View
  self.selector = 'section.search'
end

SearchBar.create

And then the implementation

class View
  # …

  def self.create(*args)
    Document.ready? { create!(*args) }
    nil
  end

  def self.create!(*args)
    instance = new(*args)
    if instance.exist?
      instances << instance
      instance.setup
    end
    instance
  end

  def exist?
    element.any?
  end

  def self.instances
    @instances ||= []
  end
end

While there we also added a check on element existence and a list of active instances so that we can play nice with JS garbage collection and instantiate the class even if the HTML it needs is missing (e.g. we’re on a different page).

Conclusion

Hope you enjoyed and maybe learned a couple of things about Opal and opal-jquery, below are some links for you:

The full implementation is available in this gist: https://gist.github.com/elia/50a723e6133a645b4858

Opal’s website: http://opalrb.org
Opal API documentation: http://opalrb.org/docs/api
Opal-jQuery API documentation: http://opal.github.io/opal-jquery/doc/master/api
jQuery documentation: http://jqapi.com (unofficial but handy)
Vienna, a complete MVC framework: https://github.com/opal/vienna (unofficial but handy)

Facebook share buttons and history.pushState()

If you’ve ever tried to use Facebook social plugins‘ latest version in your website, you might have noticed how smooth and streamlined is now the embedding process.

Select a button type, include the SDK, copy-paste a snippet of code and… you’re done! You can also leave the data-href attribute blank, so the plugin will like/share the current page. Awesome!

At this point you might ask yourself, “Well, will this nice little button work with my super cool AJAX-powered app?”. The answer is not really.

The problem

Facebook social plugins won’t work properly when your application routing is based on Javascript’s history.pushState() API – this includes a large number of Rails applications that rely on Turbolinks for their navigation.

This is because the page metadata is parsed by Facebook SDK only when a full page load is triggered. So, if I navigate from example.com/page-one to example.com/page-two and try to click on my Facebook share button, it will prompt a share for /page-one.

The solution

How to solve this? It’s actually quite easy. A small snippet (here in CoffeeScript, but easily convertible in plain JavaScript) that will update our button and retrigger a parse will be enough:

updateFbButtonHref = (el) ->
  $fbButton = $(el).find('.fb-share-button')
  $fbButton.attr('data-href', window.location.href)

  FB.XFBML.parse()

Now, we can bind this function to the “page:load” event (in the case of a Turbolinks application), or generally after every pushState():


$(document).on 'page:load', ->
  updateFbButtonHref('.my-fb-button-container')

And we’re cool! Our button will now share the correct page.

Replicating the deprecated jQuery property .selector in CoffeeScript

Recently I found myself needing a way to get any (id or class) selector from any DOM element as a string in an easy way. 

After a quick search I discovered that jQuery had an handy .selector property that would have been a perfect fit for my needs.

Unluckily, it was deprecated in version 1.7.

image

I felt like the solution suggested by the guys at jQuery wasn’t flexible enough and not very user-friendly – passing the element selector as a parameter of the plugin method call is definitely not an elegant way to deal with the problem.

So I tried to write a simple function to solve it… in CoffeeScript!

The snippet

getSelector = (el) ->
  firstClass = $(el).attr('class')?.split(' ')[0]
  elId       = $(el).attr('id')

  if (elId isnt undefined) then "##{elId}" else ".#{firstClass}"

As you can see, it’s really easy to understand: it just checks if there’s an id attribute and returns it as a string. If it’s undefined, it returns the first class instead.

Here you can see it in action in a CodePen example.

I could write it in a single line without the two variables declaration, but I wanted to get the most out of the beautiful human-friendly CoffeeScript syntax, and I think it actually makes the snippet a lot more readable.

More jQuery pls

If you wanted to, you could also extend jQuery itself adding this little function as a method in a very easy way:

jQuery.fn.extend(
  getSelector: ->
    firstClass = $(this).attr('class')?.split(' ')[0]
    elId       = $(this).attr('id')

    if (elId isnt undefined) then "##{elId}" else ".#{firstClass}"
)

And then use it like that:


$ ->
  mySelector = $('div').getSelector()

Hope that helped you!

Tendina, a super-simple jQuery plugin for dropdown side menus

I have just released the first beta version of my jQuery plugin Tendina.

image

Tendina is a easy-to-use jQuery plugin to rapidly build dropdown side menus.

Its usage is very simple and straightforward: you just need a basic unordered list menu markup and a link to jQuery and the plugin. For example:

    
<body>
<ul class="dropdown">
<li>
<a href="#">Menu 1</a>
<ul>
<li><a href="#">Submenu 1</a></li>
</ul>
</li>
<li>
<a href="#">Menu 2</a>
<ul>
<li><a href="#">Submenu 2</a></li>
<li><a href="#">Submenu 2</a></li>
<li><a href="#">Submenu 2</a></li>
</ul>
</li>
<li>
<a href="#">Menu 3</a>
<ul>
<li><a href="#">Submenu 3</a></li>
<li><a href="#">Submenu 3</a></li>
</ul>
</li>
</ul>

<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="../tendina.js"></script>
<script>
$('.dropdown').tendina()
</script>
</body>

As you can see, you just need to call the function on your elements and… That’s it! The plugin will handle all the interactions and leave all the styling to you, so you don’t have to override useless CSS classes.

Tendina will also work on dinamically appended elements, and additionally add a “selected” class to expanded elements.

Check it out on Github or on this demo CodePen!

jQuery injection for profit and profit, cause fun is overrated

Working on a project for an important client (more on that in the next months), we came up with the need to inject jQuery on a page, making it available to your functions.

In addition to that we wanted to be sure it didn’t conflict with other jQueries the page was already using, and, if a new version of jQuery was already available, use that instead of injecting a new one.

This whole injection thing is not very complicated per se. You just have to be sure you’re not messing up with what’s already in the page.

Let’s walk through our solution to see how we implemented it. All the code you see here will be CoffeeScript, the javascript translation is really straightforward and won’t be provided 🙂

We start with an empty html document, something like this:

<!DOCTYPE html>
<head>
  <meta charset="utf-8" />
  <script src="jquery-injection.js"></script>
</head>
<body>
</body>

jQuery-injection.js is the compiled version of our coffeescript source.

The simplest way to inject jQuery would be something like this:

@Injector = 
    injectjQuery: ->
        script = document.createElement('script')
        script.src = "//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"
        head = document.getElementsByTagName('head')[0]
        
        head.appendChild(script)

We’re creating a globally available Injector object with an injectjQuery function that creates a script element, sets its src attribute and adds it to head.

This is all fine and dandy, but what if we already have jQuery? This would load jQuery twice and there would be namespace conflicts. What we want to do is check for an existing jQuery and use jQuery.noconflict() to make sure they don’t clash.

checkAndInjectjQuery: ->
    if jQuery?
      if @versionCompare(jQuery.fn.jquery, "2.0.3") < 0
        @injectjQuery(true)
      else
        @jq = window.jQuery
    else
      @injectjQuery(false)   

What’s going on in here? We check if jQuery exists, and that its version is at least 2.0.3. The version check is done via versionCompare, a coffeescript simplified port of this code I found on StackOverflow.

If jQuery exists and is sufficiently new, we just map this.jq to window.jQuery. Our local jq variable is what we’re gonna use inside our functions instead of using $.

If you paid enough attention, you will have noticed we’re calling injectjQuery with a parameter.

  injectjQuery: (saveOriginal) ->
    script = document.createElement('script')
    script.src = "http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"
    head = document.getElementsByTagName('head')[0]

    if saveOriginal
      @jq = $.noConflict(true)

    head.appendChild(script)

injectjQuery(true) will assume that there’s another jQuery in the page, so it saves it (temporarily) in this.jq, and then cleans after it, making sure it won’t be there when the new jQuery loads.

Wait, did I say “when the new jquery loads”? You can bet I did! Everything we’re doing is asyncronous, so we can’t be sure that the new jQuery is already available.

Avoiding potential issues with that requires some callback magicks. First we edit injectjQuery, adding, immediately after the last line, the following code

@checkLoaded(saveOriginal)

checkLoaded is a function that keeps calling itself until jQuery is effectively loaded.

 checkLoaded: (saveOriginal) ->
    window.setTimeout( =>
      if !jQuery?
        @checkLoaded(saveOriginal)
      else
        if saveOriginal
          temp = @jq
          @jq = $.noConflict(true)
          window.jQuery = temp
          window.$ = jQuery
        else
          @jq = jQuery

        @continueInitialization()
    , 500)

It recognizes the same saveOriginal parameter we used before, restoring the original jQuery where it belongs, and leaving us with our new jQuery, available through this.jq.

continueInitializazion is the function that should handle all of your post-jquery-loaded needs.

In this gist you’ll find the complete Injector class, with some bonus console.log calls to better understand what’s going on.

Thank you for reading up to this last paragraph, and have fun injecting jQuery where you please.

Using HTML5 date fields mantaining backward compatibility

Chrome and Opera (respectively from versions 20 and 12) implement a native date picker. Now, when you have an input field with the date type:

<input type="date" name="user[born_on]" id="user_born_on" />

these two browsers will automatically inject in the page their native datepicker, according to the input[type=date] HTML5 specs.

Native datepicker

And, at least in Chrome, the widget is really really good.

Btw, this doesn’t happen only for date fields. In fact in HTML5 we can find other new input types specifically created to deal with dates and times: datetime, datetime-local, time. Chrome and Opera will show a picker also for these input types.

There is only one little, negligible problem: as I said this feature is implemented only in Chrome and Opera!
Continue reading “Using HTML5 date fields mantaining backward compatibility”