Javascript tricks: a .data() method for Prototype

I was recently working on an old project that is still using Prototype as it’s JavaScript framework. We’ve been so deep in jQuery on our other projects that I needed a little mind shifting to get back into the Prototype way of doing things.

One function in jQuery that I’ve used heavily is the .data() method. I like that I can stick data on a DOM element with an accepted convention, as opposed to adding arbitrarily named attributes to elements. But I haven’t seen this in Prototype. So I wrote it up.

Once you’ve got this snippet in your JS code, and integrated into prototype (notice the last line where we extend Prototype with our new methods), you are off to the races. In your html, you can attach data to dom elements with

<div id="dom_with_data" data-my_param="here we go">
  This element has data.
</div>

and then you can use it in your javascript like so

  alert($('dom_with_data').data('my_param'));

It’s not yet as functional as the jQuery version. But it was all I needed at the time. There are a couple items I’d like to add, when I find some time:

  • make the regex a little more forgiving. Currently the attribute data-123 won’t work. And neither will data-this-is-my-param.
  • make the function return all data if called with no keys.
  • make the setter work. Currently this only works to fetch data which has been stuck on elements by way of the data-* attribute. It’d be nice to be able to set data on an element with the same method, like jQueryUPDATE 7/12/12 Added the setter functionality and updated the gist

For now, I’m happy to let it roll. If you use it and make improvements, let me know and I’ll merge’em in.

Advertisements

Javascript tricks: Regular Expression Tester

A while back we posted here about Rubular. My cohort called it the last ruby regex tool you will need. And he was right, it’s the last *ruby* regex tool. I’ve already spent too much time in the Firefox console playing with regular expressions just to figure out the right matchers. It was time to find a better tool for the job.

The voice in my head said, “Stop your whining, and write that sucker.”

And so I did.

Javascript Regex Playground is now available for your regular expression testing needs. Give it a regex, a test string and it’ll show you the matches. Simple and straight forward. The code is available on github if you want to pull your own copy.

Jasmine Headless vs In Browser

In the last couple projects, we’ve been using Jasmine for our Javascript testing. It’s been great. Tying that in with jasmine-headless-webkit has made our Javascript testing super fast for both development and our CI box.

One problem we’ve hit a couple times is differences between the real browser and the fake browser (headless-mode). For example: in the real browser, you can build an iframe with a src attribute and it will do the right thing.

$('body').append(
  $('',
    {src:'http://embedded_page.example.com'})
);

However, if you run this through your headless tests, depending on where this code is executed, you may get errors like this from jQuery:

Fixture could not be loaded: spec/javascripts/fixtures/recipe_subnav.html
(status: error, message: NETWORK_ERR: XMLHttpRequest Exception 101)

or like this from the Jasmine framework:

Can't load file:///projects/myproject/specrunner.11688.html, the file may be broken.
Out of curiosity, did your tests try to submit a form and you haven't prevented that?
Try running your tests in your browser with the Jasmine server and see what happens.

Certainly, we could probably stub out a bunch of stuff to make this fly, but sometimes time is better spent pushing forward. To get around this, we wanted a simple way to check for the command line tests vs in browser tests. We added to our SpecHelper.js file:

var is_headless = function() {
  return (/jasmine-headless-webkit/.test(navigator.userAgent));
};

With this now in place, we can write tests like this:

describe('save scroll top cookie plugin', function() {
  beforeEach(function() {
    loadFixtures('my_fixture.html');
    $('body').scrollTop(123);
    $('#fixture').saveScrollTopCookie();
  });
  if(is_headless()) {
    it('it sets a cookie for scroll position', function() {
      expect($.cookie('scrollTop')).toEqual('123');
    });
  }
  it('does something else', function() {
    expect(somethingElse).toBe(true);
  });
});

With this setup, instead of missing tests because we’ve constructed a bunch of xit or xdescribe blocks, we can keep all the tests around, and simply skip those that don’t lend themselves to the specific situation (in-browser or headless).

It is not something that is used a lot, because we really strive to make tests which are universal, but in those special cases where we still may want a spec, this simple helper method works pretty nicely.