Entries Tagged 'ajax' ↓

IE6 vs JavaScript (Prototype) and Sortable Elements Hidden/Disappearing/Invisible

Today I have another IE6 quirk in dealing with Prototype. I have a bunch of elements that I want to sort with a Sortable object, which works as expected for the most part, except in IE6!

I set background-color: #E6F2FF; to the rows of my ‘table’ which of course isn’t a real table, just some nicely styled div’s! The problem with this is that there’s a bug in this situation with IE6. All the contents of my rows are hidden! That means text, links, images. It looks as if all of the rows are just empty… except I can mouse-over and my mouse can interact with the elements.

It turns out, the opacity css attribute is 0. Or at least IE6 behaves as if it is. The thing is, FireBug doesn’t agree, and if you set opacity: 1; in your stylesheet it won’t cut it. The problem begins just after the Sortable.Create call. Removing this call fixes the problem, obviously, but that’s not what we want!

Here’s my solution. After the Sortable.Create call, do this:

if (Prototype.Browser.IE) {
    $$('.relevant_class_name').invoke.setStyle({opacity: 1});
}

where relevant_class_name is the css class assigned to the row’s of data on my page. This sets the opacity to all of the affected elements after the the Sortable object screws things up.

Hooray! I hope this helps someone else.

IE vs JavaScript (Prototype) and position: relative

In the current project I’m working on I have all sorts of cool AJAX madness happening to add things to my pages. For one particular example, I have AJAX calls that add pieces to the page with more AJAX functions inside of those pieces. Fun, huh?

The kicker is that some of the elements on the page there are being shown with the style attribute of position: static;. It just so happens that Prototype and position: static do not always play nicely in this case.

Let me show you what I mean. Here you see an image with two links placed with position: static;.

Clicking on “+ Add Foo” twice and “+ Change Bar” gives:

This works as expected. However if I add a duplication of this segment of the page using an AJAX call, the new portion does not work as expected while in Internet Explorer (every other browser works just fine of course).

To illustrate the problem while trying to do the same thing with the new segment, first I add the new segment via the “+ Add Many Things” link.

Then I click “- Change Bar” which hides the following two lines. You now see the two links I’ve been referring do not follow the movement of the page. They should have scrolled up and they did not.

To handle this, I need some extra JavaScript. First I add the following to the parameters of my AJAX call:

onSuccess: function(request){ reposition(); }

Next I want to take the elements that I know I have this problem with (selected by class name) and then first turn off the “relative” position by setting it to “static” and then back to “relative” again. By the way I figured this out thanks to way too much time fiddling with things in FireBug and the IE Dom Inspector. I can’t come up with any real sense to it. To make this happen, I add the following JavaScript for IE only:


function reposition() {
  if (Prototype.Browser.IE) {
     $('publication_list').select('.remove').each(swapStaticToRelative);
     $('publication_list').select('.add_company_role').each(swapStaticToRelative);
     $('publication_list').select('.add_cover').each(swapStaticToRelative);
  }
}
function swapStaticToRelative(item) {
	item.setStyle({ position: 'static' });
	item.setStyle({ position: 'relative' });
}

Note that the following also works for detecting that the browser is any version of IE:

function reposition() {
     /*@cc_on
          /*@if (@_win32)
               $('publication_list').select('.remove').each(swapStaticToRelative);
               $('publication_list').select('.add_company_role').each(swapStaticToRelative);
               $('publication_list').select('.add_cover').each(swapStaticToRelative);
          @else @*/
	      
          /*@end
     @*/
}

I wish I could remember where I found that, but it’s crazy cool. Sure the Prototype way is better… but this is a fun one to stare at for a while until you figure out how it’s working.

So with that change in place, this time it works as expected.

The only thing better I think (aside from IE not sucking) would be to have a way to select fields by style attributes. If I could figure that out, I’d be able to make a single call to swap these CSS attributes for all instances on the page that are relevant to this problem. If I could do that, then it might be a candidate for a patch to Prototype.

If you have a suggestion for a better way to handle this or if my post helped you out, please let me know by leaving a comment!

Javascript (RJS) Not Called In Ruby on Rails 2.0.2

After updating to Ruby on Rails 2.0.2 I ran into a problem where old code stopped working. The Ruby on Rails Weblog talks about new functionality to allow for us to use .html.erb instead of .rhtml and .js.erb instead of .rjs.

However it appears they may have broken something. In my project I have a controller with a ‘join’ method ending with this code:

respond_to do |format|
  format.html { render :layout => 'join' }
  format.js
end

My problem was that the join.rjs file was not called at all when the join action was called with text/javascript in the header (an AJAX call). Instead, the .html layout would always return.

Interestingly enough, renaming join.rjs to join.js.erb did allow for the file to be returned when I made an AJAX call, but RoR did not format it into Javascript.

My solution was to rename the join.rhtml to join.html.erb. Now the Javascript file gets properly executed with both .rjs and .js.erb.

I’m not sure under what exact conditions this bug pops up, but I know I have many other AJAX calls and many other .rhtml and .rjs files working just fine in other areas of my project. However, until this bug (if it really is a bug) is adequately dealt with, this workaround seems to do just fine.

I’ve posted a bug report here.

Edit: According to this forum post, while the original documentation is misleading, the desired format is .js.rjs. This should also solve this problem.

Script.aculo.us Patch – InPlaceEditor Incorrectly Determining Row Count

Recently in a project that my brother and I were working on we ran across a problem with the Ajax.InPlaceEditor resulting in the number of rows for the editor being incorrectly determined. Here you can see the area before it’s used:
Ajax.InPlaceEditor before clicking
When I clicked on the edit icon I got:
Ajax.InPlaceEditor bugged
Clearly not what I wanted. After fiddling with all the possible pieces and configurable parameters I finally traced it down to the source and realized there was a bug in the original code:

createEditField: function() {
var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {

Looking in the 2nd check of the if statement you see it’s checking for line breaks in “this.getText()”. It should have been checking the “text” variable it had just created above it. Changing that code to:

createEditField: function() {
var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
if (1 >= this.options.rows && !/\r|\n/.test(text)) {

…fixed the problem! Now when I click my InPlaceEditor I get:
Ajax.InPlaceEditor fixed

To share my fix I went to the Script.aculo.us page on Submitting Patches but unfortunately their instructions didn’t work right away for me.

Luckily Ryan Bates posted a Railscast called Contributing to Rails that had the right information I needed. Once I had successfully produced my diff file I submitted the patch to the Rails Trac.

Hooray! My first ever patch!