Tuesday, November 6, 2012

Using class as jquery selector

We are so much used codes such as following,

$('a.mark_locked').live('click', function () {
  // your code goes here
});

Using class as a selector for putting a javascript business logic is kind of evil.
The purpose of class in HTML is for styling. After jquery or prototype came to light, people have been using it for selectors as well. But to me this is not right. I myself used to do this a lot. But not anymore. Because when you hire a designer to change the html or dom then the designer has to know which class to keep and which to change. He does not have a clue which are the classes used for javascript. And for a large project it is a huge issue. Eventually no classes are removed and the HTML dom becomes heavy and clumsy.

A much better approach is to use attribute selector, as following,
$('a[mark_locked]').live('click', function () {
  // your code goes here
});

Now your designer has more freedom for manipulating classes in dom.

Sunday, July 29, 2012

HTML widgets using jquery

What is post is about

This post is an extension of the post by Alex Marandon. In that post you will find the following topic discussed

  • Web widget
  • Usage
  • Bootstrap code using jquery
So what this post is about? I faced some issues while creating a jquery based widget and found some issues and solution. Here is my findings.

Things to care for

There are some aspect that you need to take care of to create a nice widget that works across  different sites.
  • Widget must not interfere with css and javascript of existing site
  • For rendering widget it is better to provide the following choices
    • Some default theme to show the widget nicely
    • Provide the option for the site owner to override the theme with custom css
  • Allow widget to be customized by user

Solutions

Javascript conflicts

If you are using jquery then Alex Marandon has made it clear how to use jquery using noConflict. But when you will be using plugins for jquery in the widget you have to use no conflict is the following way,

jQuery = window.jQuery.noConflict(false);

The reason to use false is telling jquery not to remove the jquery from the window.jquery, because plugins use jquery from window.jquery. If you use true in the param then any plugin that you add in the widget will not work.

Css conflicts

It is very important if you want to provide some out of box theme that the user may choose from. Then you need to make sure that your css does not conflict with existing ones. I found that the best way is to use sass. Because then you can use nesting to ensure that the css that you provide only impacts the container of the widget and nothing else.

Customization

You can customize widget using HTML 5 data attribute to provide the widget extra information that they need.

Demo

Here is a demo of a HTML widget which fetches data from blogger if you pass the name of your blogger.

I have developed a sample project on rails. The reason to use rails is to use the built in SCSS and be able to deploy to heroku. The 2 files that you need to see is here,

Here is the jsFuddle of the widget.

Reference

Wednesday, May 23, 2012

Cucumber remove Rack::Cache logging

I am using a cucumber and capybara-webkit in a project that uses Dragonfly.
When I used capybara-webkit I suddenly started getting some Rack::Cache debug log. Which looked like the following,

 @javascript
  Scenario: Save new event as draft                               # features/manage_events.feature:23
cache: [GET /user/sign_out] miss
cache: [GET /] miss
cache: [POST /user/sign_in] invalidate, pass
cache: [GET /events/new] miss
http://maps.gstatic.com/cat_js/intl/en_us/mapfiles/api-3/8/11/%7Bmain,geometry%7D.js|43|Warning: you have included the Google Maps API multiple times on this page. This may cause unexpected errors.
cache: [PUT /users/update_time_zone] invalidate, pass
cache: [GET /events/new] miss
http://maps.gstatic.com/cat_js/intl/en_us/mapfiles/api-3/8/11/%7Bmain,geometry%7D.js|43|Warning: you have included the Google Maps API multiple times on this page. This may cause unexpected errors.
cache: [PUT /users/update_time_zone] invalidate, pass
    When I fill in "Event Name" with "Event 1"                    # features/step_definitions/web_steps.rb:3
    And I fill in "Event Description" with "This is a test event" # features/step_definitions/web_steps.rb:3
    And I fill in "Event Venue" with "Dhaka, Bangladesh"          # features/step_definitions/web_steps.rb:3
    And I press "Search"                                          # features/step_definitions/web_steps.rb:7
cache: [GET /events/location_search?str=Dhaka,%20Bangladesh] miss
    And I fill in "Event Start date" with "2012-05-22"            # features/step_definitions/web_steps.rb:3
    And I fill in "Event End date" with "2012-05-23"              # features/step_definitions/web_steps.rb:3
    And I press "Save as draft"                                   # features/step_definitions/web_steps.rb:7
cache: [POST /events/4fbc72688621ff1a31000026] invalidate, pass
cache: [GET /my/events?p=false] miss
cache: [GET /assets/ui-bg_glass_65_ffffff_1x400.png] miss
cache: [GET /assets/bg.gif] miss
    Then I should see "Event was successfully updated."           # features/step_definitions/web_steps.rb:11
That log comes from the Rack::Cache which is used by Dragonfly. So you can add the following code snippet in the test.rb,
  require 'rack/cache'
  config.middleware.delete ::Rack::Cache
  rack_cache_already_inserted = Rails.application.config.action_controller.perform_caching && Rails.application.config.action_dispatch.rack_cache

  Rails.application.middleware.insert 0, Rack::Cache, {
      :verbose => false,
      :metastore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/meta"), # URI encoded in case of spaces
      :entitystore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/body")
  } unless rack_cache_already_inserted



References

Tuesday, May 22, 2012

Cucumber on rails

The purpose of this document is the following

  • Setup cucumber with rails
  • Define basic features
  • To test ajax response
The version for gems that are used to create the documents are,
  • cucumber (1.2.0)
  • cucumber-rails (1.3.0)

Setup

Cucumber-rails gem makes it easier to install cucumber in rails, but I faced some issues which I would like to document. The following is from the cucumber-rails document,
group :test do
  gem 'cucumber-rails', :require => false
  # database_cleaner is not required, but highly recommended
  gem 'database_cleaner'
  gem 'cucumber-rails-training-wheels'
  gem 'capybara'
  gem 'rspec-expectations'
  gem 'fabrication' #for test fixture creation
end
Then run,
bundle install
rails generate cucumber:install
This will generate the necessary file for cucumber.
  create  config/cucumber.yml
  create  script/cucumber
   chmod  script/cucumber
  create  features/step_definitions
  create  features/support
  create  features/support/env.rb
   exist  lib/tasks
  create  lib/tasks/cucumber.rake
If you are using mongo, then it should give you a warning that you can not use 'transaction' strategy for mongo. Then you can change that to 'truncation' in your 'features/support/env.rb' file. Change the env.rb as following,
DatabaseCleaner.strategy = :truncation
Now it is time to write some features to test. cucumber-rails-training-wheels gem help you with generators, so that you can generate features quickly. To generate use the command as follows,
rails generate cucumber_rails_training_wheels:feature post title:string body:text number:integer published:boolean
With this plug-in you can generate cucumber feature when you are using scaffold generator. For details please see the reference.
I am working on a sample cucumber project that can facilitate newbies to get started with cucumber and get to know the best practices. Any contribution is very welcome.

Global fixture setup and tear down

If you have some global data that is needed to be loaded for every test then you can use cucumber hooks. You can create the fixtures that you always need, for an example users for login or initialize admin global settings.

Reference

Wednesday, May 2, 2012

Parameterizing translation files in rails I18n

In en.yml,

delete_confirm_with_title: 'Are you sure, you want to delete "%{title}"?'

In erb
<%= link_to 'X', resource, confirm: t('delete_confirm_with_title', {:title => resource.name}), method: :delete %>

Friday, April 27, 2012

Date time stamp using jquery ui framework

If you are using jquery ui framework then you can show you date time in a cool way. The final result will look like this,




It will of course depend on what theme you are using. Here it goes.

HTML

Apr ´10
25th

1:05 pm


CSS

.date {
 width: 55px;
 text-align:center;
 font-family: cursive;
}

.date .ui-widget-header {
 padding: 2px 5px 2px 5px;
 font-size: .9em !important;
}

.day, .time {
 font-size: .8em !important;
}

.date hr {
 margin: 0px;
 border: 0;
 height: 1px;
 background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(31,52,60,0.75), rgba(0,0,0,0)); 
 background-image:    -moz-linear-gradient(left, rgba(0,0,0,0), rgba(31,52,60,0.75), rgba(0,0,0,0)); 
 background-image:     -ms-linear-gradient(left, rgba(0,0,0,0), rgba(31,52,60,0.75), rgba(0,0,0,0)); 
 background-image:      -o-linear-gradient(left, rgba(0,0,0,0), rgba(31,52,60,0.75), rgba(0,0,0,0));
}

sup, sub {
 vertical-align: baseline;
 position: relative;
 top: -0.4em;
}
sub { top: 0.4em; }

The style of hr element will of course vary for different theme.

Thursday, April 12, 2012

Using helper method in Rials 3 controllers

Here is a rails 3 way to access you helper methods from rails3 controllers.

# app/controllers/posts_controller.rb
class PostsController < ActionController::Base
  def show
    # ...
    tags = view_context.generate_tags(@post)
    email_link = view_context.mail_to(@user.email)
    # ...
  end 
end

# app/helpers/posts_helper.rb
module PostsHelper
  def generate_tags(post)
    "Generate Tags"
  end
end

Found the solution from the blog of Samnang Chhun.

Reference

Friday, March 9, 2012

Rails JSON mapping

Rails to_json is great when you are using web service to talk to your own application. But sometimes when you expose service for some third party application, then you need to export you own data in their format. In my can I had to expose my data to be able to use fullcalendar. And fullcalendar expects data in their format. So thanks to the discussion here, I found a way to represent your in the following way,

  def story_feed
    @stories = @project.stories
    render :json => @stories.map { |story| 
      { :id => story.id,
        :title => story.title,
        :start => story.start_at || Date.today,
        :end => story.complete_at || Date.today }
    }
  end