BigBinary Blog

Archives

Return False Has Changed in Jquery 1.4.3

jQuery 1.4.3 was recently released. If you upgrade to jQuery 1.4.3 you will notice that the behavior of return false has changed in this version. First let’s see what return false does.

return false

1
2
3
4
$('a').click(function(){
  console.log('clicked');
  return false;
});

First ensure that above code is executed on domready. Now if I click on any link then two things will happen.

e.preventDefault() will be called .
e.stopPropagation() will be called .

e.preventDefault()

As the name suggets, calling e.preventDefault() will make sure that the default beahvior is not executed.

<a href='www.google.com'>click me</a>

If above link is clicked then the default behavior of the browser is to take you to www.google.com. However by invoking e.preventDefault() browser will not go ahead with default behavior and I will not be taken to www.google.com.

e.stopPropagation

When a link is clicked then an event “click event” is created. And this event bubbles all the way up to the top. By invoking e.stopPropagation I am asking browser to not to propagate the event. In other words the event will stop bubbling.

<div class='first'>
  <div class='two'>
    <a href='www.google.com'>click me</a>
  </div>
</div>

If I click on “click me” then “click event” will start bubbling. Now let’s say that I catch this event at .two and if I call e.stopPropagation() then this event will never reach to .first .

e.stopImmediatePropagation

First note that you can bind more than one event to an element. Take a look at following case.

<a class='one'>one</a>

I am going to bind three events to the above element.

1
2
3
4
5
6
7
8
9
10
11
12
$('a').bind('click', function(e){
  console.log('first');
});

$('a').bind('click', function(e){
  console.log('second');
  e.stopImmediatePropagation();
});

$('a').bind('click', function(e){
  console.log('third');
});

In this case there are three events bound to the same element. Notice that second event binding invokes e.stopImmediatePropagation() . Calling e.stopImmediatePropagation does two things.

Just like stopPropagation it will stop the bubbling of the event. So any parent of this element will not get this event.

However stopImmdiatePropagation stops the event bubbling even to the siblings. It kills the event right then and there. That’s it. End of the event.

Once again calling stopPropagation means stop this event going to parent. And calling stopImmediatePropagation means stop passing this even to other evevent handlers bound to itself.

If you are interested here is link to DOM Level 3 Events sepc.

Back to original problem

Now that I have described what preventDefault, stopPropagation and stopImmediatePropagation does lets see what changed in jQuery 1.4.3.

In jQuery 1.4.2 when I execute “return false” then that action was same as executing:

e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()

Now e.stopImmediatePropagation internally calls e.stopPragation but I have added here for visual clarity.

Fact that return false was calling e.stopImmeidatePropagation was a bug. Get that. It was a bug which got fixed in jquery 1.4.3.

So in jquery 1.4.3 e.stopImmediatePropagation is not called. Checkout this piece of code from events.js of jquery code base.

1
2
3
4
5
6
7
if ( ret !== undefined ) {
  event.result = ret;
  if ( ret === false ) {
    event.preventDefault();
    event.stopPropagation();
  }
}

As you can see when return false is invoked then e.stopImmediatePropagation is not called.

I tried to find which commit made this change but I could not go far because of this issue.

It gets complicated with live and a bug in jQuery 1.4.3

To make the case complicated, jQuery 1.4.3 has a bug in which e.preventStopImmediatePropagation doest not work. Here is a link to this bug I reported.

To understand the bug take a look at following code:

<a href='' class='first'>click me</a>

$('a.first').live('click', function(e){
    alert('hello');
    e.preventDefault();
    e.stopImmediatePropagation();
});

$('a.first').live('click', function(){
    alert('world');
});

Since I am invoking e.stopImmediatePropagation I should never see alert world. However you will see that alert if you are using jQuery 1.4.3. You can play with it here .

This bug has been fixed as per this commit . Note that the commit mentioned was done after the release of jQuery 1.4.3. To get the fix you will have to wait for jQuery 1.4.4 release or use jQuery edge.

I am using rails.js (jquery-ujs). What do I do?

As I have shown “return false” does not work in jQuery 1.4.3 . However I would have to like have as much backward compatibility in jquery-ujs as much possible so that the same code base works with jQuery 1.4 through 1.4.3 since not every one upgrades immediately.

This commit should make jquery-ujs jquery 1.4.3 compatible. Many issues have been logged at jquery-ujs and I will take a look at all of them one by one. Pleaes do provide your feedback.

Instance_exec , Changing Self and Params

Following code will print 99 as the output.

1
2
3
4
5
6
class Klass
  def initialize
    @secret = 99
  end
end
puts Klass.new.instance_eval { @secret }

Nothing great there. However try passing a paramter to instance_eval .

1
puts Klass.new.instance_eval(self) { @secret }

You will get following error.

1
wrong number of arguments (1 for 0)

So instance_eval does not allow you to pass parameters to a block.

How to get around to the restriction that instance_eval does not accept parameters

instance_exec was added to ruby 1.9 and it allows you to pass parameters to a proc. This feature has been backported to ruby 1.8.7 so we don’t really need ruby 1.9 to test this feature. Try this.

1
2
3
4
5
6
class Klass
  def initialize
    @secret = 99
  end
end
puts Klass.new.instance_exec('secret') { |t| eval"@#{t}" }

Above code works. So now we can pass parameters to block. Good.

Changing value of self

Another feature of instance_exec is that it changes the value of self. To illustrate that I need to give a longer example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module Kernel
  def singleton_class
    class << self
      self
    end
  end
end

class Human
  proc = lambda { puts 'proc says my class is ' + self.name.to_s }

  singleton_class.instance_eval do
    define_method(:lab)  do
      proc.call
    end
  end
end

class Developer < Human
end

Human.lab # class is Human
Developer.lab # class is Human ; oops

Notice that in that above case Developer.lab says “Human”. And that is the right answer from ruby perspective. However that is not what I intended. ruby stores the binding of the proc in the context it was created and hence it rightly reports that self is “Human” even though it is being called by Developer.

Go to http://facets.rubyforge.org/apidoc/api/core/index.html and look for instance_exec method. The doc says

Evaluate the block with the given arguments within the context of this object, so self is set to the method receiver.

It means that instance_exec evaluates self in a new context. Now try the same code with instance_exec .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module Kernel
  def singleton_class
    class << self
      self
    end
  end
end

class Human
  proc = lambda { puts 'proc says my class is ' + self.name.to_s }

  singleton_class.instance_eval do
    define_method(:lab)  do
      self.instance_exec &proc
    end
  end
end

class Developer < Human
end

Human.lab # class is Human
Developer.lab # class is Developer

In this case Developer.lab says Developer and not Human.

You can also checkout this page which has much more detailed explanation of instance_exec and also emphasizes that instance_exec does pass a new value of self .

instance_exec is so useful that ActiveSupport needs it. And since ruby 1.8.6 does not have it ActiveSupport has code to support it.

I came across instance_exec issue while resolving #4507 rails ticket . The final solution did not need instance_exec but I learned a bit about it.

$LOADED_FEATURES and Require, Load, Require_dependency

Rails developers know that in development mode classes are loaded on demand. In production mode all the classes are loaded as part of bootstrapping the system. Also in development mode classes are reloaded every single time page is refreshed.

In order to reload the class, Rails first has to unload . That unloading is done something like this.

1
2
# unload User class
Objet.send(:remove_const, :User)

However a class might have other constants and they need to be unloaded too. Before you unload those constants you need to know all the constants that are defined in the class that is being loaded. Long story short rails keep track of every single constant that is loaded when it loads User or UserController.

Dependecy mechanism is not perfect

Sometimes dependecy mechanism by rails lets a few things fall through the crack. Try following case.

1
2
3
4
5
6
7
require 'open-uri'
class UsersController < ApplicationController
  def index
    open("http://www.ruby-lang.org/") {|f| }
    render :text => 'hello'
  end
end

Start the server in development mode and visit http://localhost:3000/users . First time every thing will come up fine. Now refresh the page. This time you should get an exception uninitialized constant OpenURI .

So what’s going on.

After the page is served the very first time then at the end of response rails will unload all the constants that were autoloaded including UsersController. However while unloading UsersContorller rails will also unload OpenURI.

When the page is refreshed then UsersController will be loaded and require ‘open-uri’ will be called. However that require will return false.

Why require returns false

Try the following test case in irb.

step 1

1
2
irb(main):002:0> require 'ostruct'
=> true

step 2

1
2
irb(main):005:0* Object.send(:remove_const, :OpenStruct)
=> OpenStruct

step 3 : ensure that OpenStruct is truly removed

1
2
3
4
5
irb(main):006:0> Object.send(:remove_const, :OpenStruct)
NameError: constant Object::OpenStruct not defined
        from (irb):6:in `remove_const'
        from (irb):6:in `send'
        from (irb):6

step 4

1
2
irb(main):007:0> require 'ostruct'
=> false

step 5

1
2
3
irb(main):009:0> OpenStruct.new
NameError: uninitialized constant OpenStruct
        from (irb):9

Notice that in the above case in step 4 require returns false. ‘require’ checks against $LOADED_FEATURES. When OpenStruct was removed then it was not removed from $LOADED_FEATURES and hence ruby thought ostruct is already loaded.

How to get around to this issue.

require loads only once. However load loads every single time. In stead of ‘require’, ‘load’ could be used in this case.

1
2
3
4
5
irb(main):001:0> load 'ostruct.rb'
=> true

irb(main):002:0> OpenStruct.new
=> #<OpenStruct>

Back to the original problem

In our rails application refresh of the page is failing. To get around to that issue use require_dependency instead of require. require_dependency is a rails thing. Under the hood rails does the same trick we did in the previous step. Rails calls kernel.load to load the constants that would fail if require were used.

I Am Not Seeing Hoptoad Messages. Now I Know Why.

Following code has been tested with Rails 2.3.5 .

Every one knows for sure that hoptoad notifier sends exception messages to server in production environment. Between ‘development’ and ‘production’ there could be a number of environments. Some of these would have settings closer to ‘development’ environment and some would have setting closely matching the settings of ‘production’ environment.

When you have many environments and when an exception occurrs, one is not really sure if that message is getting logged at hoptoad or not. Here is a run down of which messages will get logged and why.

It alls starts with rails

When an exception occurs while rendering a page then action_controller catches the exception. Following logic is evaluated to decide if user should see an error page with full stack trace or ‘we are sorry something went wrong’ message.

1
2
3
4
5
if consider_all_requests_local || local_request?
  rescue_action_locally(exception)
else
  rescue_action_in_public(exception)
end

Let’s look at first part consider_all_requests_local . Open ~/config/environments/development.rb and ~/config/environemtns/production.rb .

1
2
3
4
5
# ~/config/environments/development.rb
config.action_controller.consider_all_requests_local = true

# ~/config/environments/production.rb
config.action_controller.consider_all_requests_local = false

As you can see in development mode all requests are local. Be careful with what you put in your intermediary environments.

If you want to override that value then you can do like this.

1
2
#~/app/contollers/application_controller.rb
ActionController::Base.consider_all_requests_local = true

The second part of the equation was local_request? .

Rails has following code for that method.

1
2
3
4
5
LOCALHOST = '127.0.0.1'.freeze

def local_request?
  request.remote_addr == LOCALHOST && request.remote_ip == LOCALHOST
end

As you can see all requests coming from 127.0.0.1 are considered local even if RAILS_ENV is ‘production’. For testing purpose you can override this value like this.

1
2
3
4
#~/app/contollers/application_controller.rb
def local_request?
 false
end

Hoptoad has access to exception now what

If consider_all_request_local is false and if request is not local then hoptoad will get access to exception thanks to alias_method_chain.

1
2
3
4
def self.included(base)
  base.send(:alias_method, :rescue_action_in_public_without_hoptoad, :rescue_action_in_public)
  base.send(:alias_method, :rescue_action_in_public, :rescue_action_in_public_with_hoptoad)
end

In rescue_action_in_public_with_hoptoad there is a call to notify_or_ignore like this.

1
2
3
unless hoptoad_ignore_user_agent?
  HoptoadNotifier.notify_or_ignore(exception, hoptoad_request_data)
end

For majority of us there is no special handling for a particular user_agent .

1
2
3
4
def notify_or_ignore(exception, opts = {})
  notice = build_notice_for(exception, opts)
  send_notice(notice) unless notice.ignore?
end

Hoptoad defines following methods as ignorable by default and you won’t get notifications for following types of exceptions.

1
2
3
4
5
IGNORE_DEFAULT = ['ActiveRecord::RecordNotFound',
                   'ActionController::RoutingError',
                   'ActionController::InvalidAuthenticityToken',
                   'CGI::Session::CookieStore::TamperedWithCookie',
                   'ActionController::UnknownAction']

Next hop is method send_notice .

1
2
3
4
5
def send_notice(notice)
  if configuration.public?
    sender.send_to_hoptoad(notice.to_xml)
  end
end

configuration.public? is defined like this.

1
2
3
4
@development_environments = %w(development test cucumber)
def public?
  !development_environments.include?(environment_name)
end

As you can see if the Rails.env is development or test or cucumber the exception will not be reported to hoptoad server.

List of Only the Elements That Contains

I was toying with the simple list filter plugin and ended up with this markup.

1
2
3
4
5
6
7
8
<div id="lab">
  <ul id="list">
    <li><a href="">USA</a></li>
  <ul>
  <p>
    <a href=''>USA</a>
  </p>
</div>

I want to get all links that contains the word USA. Simple enough. jQuery supports contains selector.

1
$(":contains('USA')");

Above query results in following items.

1
[html, body#body, div#lab, ul#list, li, a, ul, p, a]

That is because {contains](http://api.jquery.com/contains-selector) looks for given string under all the descendants.

has method to rescue

jQuery has has method which returns the list of elements which have a descendant which has the given string.

1
b = $('*').has(":contains('USA')");

Above query results in following items.

1
[html, body#body, div#lab, ul#list, li, ul, p]

Final result

1
2
3
4
a = $(":contains('USA')");
b = $('*').has(":contains('USA')");
c = a.not(b) ;
console.log(c);

Above query results in following items.

1
 [a, a]

Singleton Function in JavaScript

Recently I was discussed with a friend how to create a singleton function in JavaScript. I am putting the same information here in case it might help someone understand JavaScript better.

Creating an Object

Simplest solution is creating an instance of the object.

1
2
3
4
5
6
7
8
9
10
11
var Logger = function(path) {
  this.path = path;
};

l1 = new Logger('/home');
console.log(l1);

l2 = new Logger('/dev');
console.log(l2);

console.log(l1 === l2);

Above solution works. However l2 is a new instance of Logger .

Singleton solution using a global variable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
window.global_logger = null;
var Logger = function(path) {
  if (global_logger) {
      console.log('global logger already present');
  } else {
      this.path = path;
      window.global_logger = this;
  }
  return window.global_logger;
};

l1 = new Logger('/home');
console.log(l1);

l2 = new Logger('/dev');
console.log(l2);

console.log(l1 === l2);

Above solution works. However this solution relies on creating a global variable. To the extent possible it is best to avoid polluting global namespace.

Single solution without polluting global namespace

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var Logger = function() {

  var _instance;

  return function(path) {

      if (_instance) {
          console.log('an instance is already present');
      } else {
          this.path = path;
          _instance = this;
      }

      return _instance;
  }
} (); //note that it is self invoking function


var l1 = new Logger('/root');
console.log(l1);

var l2 = new Logger('/dev');
console.log(l2);

console.log(l1 === l2);

This solution does not pollute global namespace.

Regular Expression in JavaScript

Regular expressions is a powerful tool in any language. Here I am discussing how to use regular expression in JavaScript.

Defining regular expressions

In JavaScript regular expression can be defined two ways.

1
2
var regex = /hello/ig; // i is for ignore case. g is for global.
var regex = new RegExp("hello", "ig");

If I am defining regular expression using “RegExp”:https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp#Properties_2 then I need to add escape character in certain cases.

1
2
var regex = /hello_\w*/ig;
var regex = new RegExp("hello_\\w*", "ig"); //notice the extra backslash before \w

When I am defining regular expression using RegExp then \w needs to be escaped otherwise it would be taken literally.

test method

test method is to check if a match is found or not. This method returns true or false.

1
2
3
var regex = /hello/ig;
var text = 'hello_you';
var bool = regex.test(text);

exec method

exec method finds if a match is found or not. It returns an array if a match is found. Otherwise it returns null.

1
2
3
4
var regex = /hello_\w*/ig;
var text = 'hello_you';
var matches = regex.exec(text);
console.log(matches); //=> hello_you

match method

match method acts exactly like exec method if no g parameter is passed. When global flag is turned on the match returns an Array containing all the matches.

Note that in exec the syntax was regex.exec(text) while in match method the syntax is text.match(regex) .

1
2
3
4
var regex = /hello_\w*/i;
var text = 'hello_you and hello_me';
var matches = text.match(regex);
console.log(matches); //=> ['hello_you']

Now with global flag turned on.

1
2
3
4
var regex = /hello_\w*/ig;
var text = 'hello_you and hello_me';
var matches = text.match(regex);
console.log(matches); //=> ['hello_you', 'hello_me']

Getting multiple matches

Once again both exec and match method without g option do not get all the matching values from a string. If you want all the matching values then you need to iterate through the text. Here is an example.

Get both the bug numbers in the following case.

1
2
3
4
5
6
7
var matches = [];
var regex = /#(\d+)/ig;
var text = 'I fixed bugs #1234 and #5678';
while (match = regex.exec(text)) {
  matches.push(match[1]);
}
console.log(matches); // ['1234', '5678']

Note that in the above case global flag g. Without that above code will run forever.

1
2
3
4
5
var matches = [];
var regex = /#(\d+)/ig;
var text = 'I fixed bugs #1234 and #5678';
matches = text.match(regex);
console.log(matches);

In the above case match is used instead of regex . However since match with global flag option brings all the matches there was no need to iterate in a loop.

match attributes

When a match is made then an array is returned. That array has two methods.

  • index: This tells where in the string match was done
  • input: the original string
1
2
3
4
5
var regex = /#(\d+)/i;
var text = 'I fixed bugs #1234 and #5678';
var match = text.match(regex);
console.log(match.index); //13
console.log(match.input); //I fixed bugs #1234 and #5678

replace

replace method takes both regexp and string as argument.

1
2
3
var text = 'I fixed bugs #1234 and #5678';
var output = text.replace('bugs', 'defects');
console.log(output); //I fixed defects #1234 and #5678

Example of using a function to replace text.

1
2
3
var text = 'I fixed bugs #1234 and #5678';
var output = text.replace(/\d+/g, function(match){ return match * 2});
console.log(output); //I fixed bugs #2468 and #11356

Another case.

1
2
3
4
// requirement is to change all like within <b> </b> to love.
var text = ' I like JavaScript. <b> I like JavaScript</b> ';
var output = text.replace(/<b>.*?<\/b>/g, function(match) { return match.replace(/like/g, "love") } );
console.log(output); //I like JavaScript. <b> I love JavaScript</b>

Example of using special variables.

  • $& - the matched substring.
  • $` - the portion of the string that precedes the matched substring.
  • $’ - the portion of the string that follows the matched substring.
  • $n - $0, $1, $2 etc where number means the captured group.
1
2
3
4
var regex = /(\w+)\s(\w+)/;
var text = "John Smith";
var output = text.replace(regex, "$2, $1");
console.log(output);//Smith, John
1
2
3
4
var regex = /JavaScript/;
var text = "I think JavaScript is awesome";
var output = text.replace(regex, "before:$` after:$' full:$&");
console.log(output);//I think before:I think after: is awesome full:JavaScript is awesome

Replace method also accepts caputured groups as parameters in the function. Here is an example;

1
2
3
4
5
6
7
8
var regex  = /#(\d*)(.*)@(\w*)/;
var text = 'I fixed bug #1234 and twitted to @javascript';
text.replace(regex,function(_,a,b,c){
  log(_); //#1234 and twitted to @javascript
  log(a); //1234
  log(b); //  and twitted to
  log(c); // javascript
});

As you can see the very first argument to function is the fully matched text. Other captured groups are subsequent arguments. This strategy can be applied recursively.

1
2
3
4
5
6
7
var bugs = [];
var regex = /#(\d+)/g;
var text = 'I fixed bugs #1234 and #5678';
text.replace(regex, function(_,f){
    bugs.push(f);
});
log(bugs); //["1234", "5678"]

Split method

split method can take both string or a regular expression.

An example of split using a string.

1
2
3
var text = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec";
var output = text.split(',');
log(output); // ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

An example of split using regular expression.

1
2
3
4
var text = "Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ;Chris Hand ";
var regex = /\s*;\s*/;
var output = text.split(regex);
log(output); // ["Harry Trump", "Fred Barney", "Helen Rigby", "Bill Abel", "Chris Hand "]

Non capturing Group

The requirement given to me states that I should strictly look for word java, ruby or rails within word boundary. This can be done like this.

1
2
3
var text = 'java';
var regex = /\bjava\b|\bruby\b|\brails\b/;
text.match(regex);

Above code works. However notice the code duplication. This can be refactored to the one given below.

1
2
3
var text = 'rails';
var regex = /\b(java|ruby|rails)\b/;
text.match(regex);

Above code works and there is no code duplication. However in this case I am asking regular expression engine to create a captured group which I’ll not be using. Regex engines need to do extra work to keep track of captured groups. It would be nice if I could say to regex engine do not capture this into a group because I will not be using it.

?: is a special symbol that tells regex engine to create non capturing group. Above code can be refactored into the one given below.

1
2
3
var text = 'rails';
var regex = /\b(?:java|ruby|rails)\b/;
text.match(regex);
1
2
3
text = '#container a.filter(.top).filter(.bottom).filter(.middle)';
matches = text.match(/^[^.]*|\.[^.]*(?=\))/g);
log(matches);

Get Started With Nodejs in Steps

nodejs is awesome. To get people started with nodejs, node-chat has been developed. Source code for node-chat app is here .

When I looked at source code for the first time, it looked intimidating. In order to get started with nodejs, I have developed a small portion of the node-chat application in 13 incremental steps.

The first step is as simple as 15 lines of code .

If you want to follow along then go through README and you can get a feel of nodejs very quickly. How to checkout each step and other information is mentioned in README.

Enjoy nodejs.

Two Ways of Declaring Functions and Impact on Variable Hoisting

All the JavaScript books I read so far do not distinguish between following two ways of declaring a function.

1
2
var foo = function(){};
function foo(){};

Thanks to Ben today I learned that there is a difference .

When a var is used to declare a function then only the variable declaration gets hoisted up

1
2
3
4
5
function test(){
  foo();
  var foo = function(){ console.log('foo'); };
};
test();

Above code is same as one given below.

1
2
3
4
5
6
function test(){
  var foo;
  foo();
  foo = function(){ console.log('foo'); };
};
test();

When a function variable is declared without var then both variable declaration and body gets hoisted up

1
2
3
4
5
function test(){
  foo();
  function foo(){ console.log('foo'); };
};
test();

Above code is same as one given below.

1
2
3
4
5
6
function test(){
  var foo;
  foo = function(){};
  console.log(foo());
};
test();

Conclusion

Now it will be clear why foo() does not work in the following case while bar() does work.

1
2
3
4
5
6
7
8
9
10
11
function test() {
    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
    function bar() { // function declaration, given the name 'bar'
        alert("this will run!");
    }
}
test();