Firefox 3 Revisited

It’s been a few days since I posted about my dislikes in Firefox 3. I’ve given it a little bit of thought, and I decided to post again with a suggestion for improvement. My criticism of the skin is probably the easiest issue to resolve, so here is how I would fix the navigation problem I previously mentioned:

Simple. Makes sense. You’re showing the entire history (backwards and forwards) between the two arrows. the only other thing I might do is highlight the down arrow a bit more, but I’m not *that* good at photoshop to do it up for a simple blog post. You get the idea…

Firefox 3

I hate to say this, I really do, but: I don’t think I like the new version of Firefox. I want to like it, but they’ve just made some of the standard features look hideous to my eyes. The biggest eyesore, in my opinion, is the fancy new autocomplete feature (which I have not found a way to turn off):

I don’t like being a stick in the mud, because I bet this is probably one of the dev team’s favourite features, but I find this new autocomplete difficult to read, and completely unnecessary. All you want to see in an autocomplete is the domain you’re trying to complete. Why do I care about their meta data? Meta-data is really just marketing blather, and if I’m typing a domain name, chances are I already know what I’m looking for. Why do I need the browser to make my eyes bleed with all of this badly rendered, improperly sized nonsense?

[edit] Oldbar to the rescue. Thanks, Michael! [/edit]

The skin leaves something to be desired as well:

I realize that the skin can be changed, but I just need to point out that the dropdown on the right-hand side of the grayed out right-arrow is simply badly placed. When I first started using this new version, I wanted to navigate back to a page I had been at about ten clicks ago. At first glance, I didn’t think that the dropdown-arrow was clickable because the right-arrow beside it was grayed out. I was in a rush and didn’t have time to mess around with the browser, so I just clicked the back arrow ten times to get where I wanted to go. Later I discovered that the dropdown-arrow was actually clickable even though it doesn’t look like it. If I found this confusing, imagine how my mom (or worse, grandmother) will find it when they try to use it?

They also changed the download manager:

Again, what is going on with the font-sizing and kerning? This looks like it’s actually a web-page. My mom would see this, think that her computer had a virus, and she’d call me for help.

Last but not least, CSS formatting is all different:

See how “/entertainment/” wraps to the second line? That line has a “white-space: nowrap” and an “overflow: hidden” on it. It used to just disappear on the right-hand side of that box, but now for some reason it wraps to the second line. I’m not going to get too upset about this one. I’ve dealt with web standards for years and years, and often when things like this crop up, it actually means that the way it worked before was incorrect, and his is how it was supposed to work all along. But it is still annoying that I’m going to have to go through all of my applications with a fine-tooth comb and fix all of the new css glitches that are going to crop up because Firefox “fixed” some things.

Canadians: Make Your Voice Heard

http://www.faircopyright.ca/

Dear Canadians…


NHL Star Called Up To Big Leagues To Play For NFL Team

Fido Announces Bandwidth Costs

The news is in. It looks like Fido/Rogers may actually turn a new leaf, after all.

Apparently you will be able to do “unlimited surfing” for just $7 per month.

No mention of the iPhone on this new site (yet), but I imagine it’s coming. I wonder if this plan will apply to the iPhone?

I need to find some fine-print.

Fun with jQuery (part 2)

CPR

I recently posted about having some problems getting things to work properly with jQuery. Admittedly, I’m not that great with javascript. But I’m finding this to be a very steep learning curve. I understand the basics of jQuery. The problem I keep having is that I run into things that I just don’t think jQuery can do. Here is my latest one:

How do you use selectors to identify a parent element?

Much like you can identify a span within a div like this:

$('div > span').doSomethingNeato();

How can I identify the span’s parent through selectors? I mean something like this:

$('div < span').doSomethingNeato();

Of course I can go the distance with something like this:

$('span').doSomethingNeato(function() {
    var mydiv = $(this).parent();
});

But what if I need to get at the div directly through the selectors alone? Is there a way to do it that I don't know about? Doesn't this pose a problem?

In my case it is a big problem because I am trying to write a general purpose plugin that needs to perform an action on some element, get a response, and then place the response in the page somewhere. The place where the response is placed is going to be relative to the button that was clicked which caused the action. It could be within the place that was clicked, it could be the place that was clicked, or it could be within a parent of the place that was clicked. I need to be able to specify a selector to identify the place.

Edit
The only idea I've had is to pass in a function that takes "this" as it's only parameter and use that function to return the target whenever it is needed. I don't know if that will work yet - I'll have to try...

Edit #2
Thanks to everyone for their input - but especially thanks to dinoboff who pointed me to John Resig's blog where he shows that you can accomplish what I want with:

$("div:has(span)")

Oh jQuery, I'll never doubt you again.

Canadian Bacon

evil

Remember when I wrote about the outrageous data transfer rates in Canada due to the monopoly that Roger’s Canada holds over wireless networks?

Well, the other day Apple announced that the iPhone 3G will be available in Canada on July 11th through Rogers and Fido Canada. I am a Fido customer (which is the same as saying I’m a Rogers customer since Fido piggybacks on the Rogers network. As a matter of fact, there are no wireless providers in Canada that don’t use the Roger’s network in one form or another), so I immediately contacted Fido to find out what the phone will cost, what the data transfer plans will cost, etc.

Fido responded to my questions with:

Dear Mr. O’Sullivan,

We would like to thank you for visiting our Fido Web site.

Unfortunately, there are no further details available regarding retail
availability, functionality and pricing.

Kind regards,

Richard
Fido Internet Consultant

Introduce your friends to Fido and you each receive a $20 credit.
For more information, simply click here: http://www.fido.ca/rip/you/off.jsp*

*I love how they threw a nice little advertisement in there for me.

So Richard didn’t know anything, but I figured the internet would. I did some more digging and found a press release on the Rogers website. The press release was pretty much two sentences announcing what Steve Jobs had already told us, two paragraphs bragging about how great Fido and Rogers are, and then the kick in the balls:

iPhone 3G will be available to Fido customers at $199 for the 8GB model and $299 for the 16GB model on a three-year price plan. Stay tuned for price plan information and retail availability.

So wait. Did I just read that right? If I buy an iPhone for the manufacturer’s retail suggested price of $199, I have to sign on to a 3 year contract? I thought the price of the phone was supposed to be discounted if you signed a multi-year contract. That’s how it works for every other phone I’ve ever purchased. MSRP is $500 and I sign a 1 year contract, I only pay $400 for the phone, right? Right?!

So what are Fido and Rogers saying that the iPhone is actually worth if I have to get a 3 year contract? What will I pay if I don’t get any contract and want to buy the phone outright? $499? $599?! If the standard 1-year-plan-equals-one-hundred-dollars rule holds true, that means that Canadians will be paying $599 for the 8Gb iPhone.

And that’s before the absurd data plans that we’ll have to shell out for every month!
The worst part of all of this is that I know for a fact that Canadians won’t say a damn word about it because they’ll be too busy scrambling to get their hands on the new toy that our down-south USA pals have had for years already.

Update
So, MySchizzoBuddy tells me that the $199 pricetag is not actually the MSRP, but the price after the plans have already been discounted. He also says that the deal in the states is that the phone will cost $199 with a 2-year plan. Of course Roger’s had to give us the gears a little bit – heaven forbid we should get the same deal as the Americans (who’s dollar is swiftly becoming less valuable than ours).

Now we just have to wait and see what Rogers has done about the data transfer rates.

jQuery, closures, objects, instances, suicide

CPR

Do you have a fantastic grasp of jQuery and closures and would like to help me out?

I’m stumped on how to keep a settings array alive through the life-cycle of a jQuery plugin I’m working on, and I can’t find any answers on the Google or the Internet.

Want to help me? Please reply to this entry. I’ll continue slitting my wrists with the dull edge that is javascript until you do…

Update
After a couple of suggestions on plugin architecture, I’m still no further ahead. I’ve put together a summary of my problem. Check out the following code:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-ca">
<head>
    <title>test</title>
    <script src="/garden/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
<!--

(function($) {
    var opts;

    $.fn.identify = function(options) {
        opts = $.extend({}, $.fn.identify.settings, options);
           
        this.click(function() {
            $.fn.identify.speak();
            return false;
        });
           
        return this;
    }
       
    $.fn.identify.speak = function() {
        alert(opts.parameter);
    }

    $.fn.identify.settings = { parameter: 'default' };

})(jQuery);

jQuery(document).ready(function($) {
   $('a:first').identify({parameter:'first'});
   $('a:last').identify({parameter:'last'});
});


// -->
</script>
<body>
<a href="http://localhost/garden/test.php">http://localhost/garden/test.php</a>
<br /><br /><br />
<a href="http://localhost/garden/test.php">http://localhost/garden/test.php</a>
</body>
</html>

If you create this example and then click the first link, your popup will say “last” even though the parameter that was passed to the anchor was “first”. Simply put: I need it to say “first”.

If I change my javascript slightly, I can make it say first like so:

(function($) {
    $.fn.identify = function(options) {
        var opts = $.extend({}, $.fn.identify.settings, options);
      
        this.click(function() {
            alert(opts.parameter);
            return false;
        });
          
        return this;
    }

    $.fn.identify.settings = { parameter: 'default' };
})(jQuery);

jQuery(document).ready(function($) {
   $('a:first').identify({parameter:'first'});
   $('a:last').identify({parameter:'last'});
});

But the whole problem is that I need to be able to call a *different* function (like the “speak” one above) within the plugin and access the correct parameter. The only way that I have been able to do this successfully is by doing something like this:

(function($) {
    $.fn.identify = function(options) {
        var opts = $.extend({}, $.fn.identify.settings, options);
       
        this.click(function() {
            $.fn.identify.speak(opts);
            return false;
        });
           
        return this;
    }
       
    $.fn.identify.speak = function(opts) {
        alert(opts.parameter);
    }

    $.fn.identify.settings = { parameter: 'default' };
})(jQuery);

jQuery(document).ready(function($) {
   $('a:first').identify({parameter:'first'});
   $('a:last').identify({parameter:'last'});
});

This doesn’t really work for me because I can’t guarantee that opts will be able to get passed into my function if, say, I’m using a callback function that can’t take any parameters.

So, the bottom line: How can I save the parameters specific to the correct instance so that they are properly accessible from an outside function?

Any ideas?

Update #2

Dinoboff suggested that I use jQuery’s data() method to store and retrieve the settings. However, his code didn’t work for me. To get it to work, I had to do this:

(function($) {
    $.fn.identify = function(options) {
        this.data('identify_settings', $.extend({}, $.fn.identify.settings, options));
		
        this.click(function(e) {
            $.fn.identify.speak(e);
            return false;
        });
		
        return this;
    }

    $.fn.identify.speak = function(e) {
        var settings = $.extend({}, $.fn.identify.settings, jQuery.data(e.target, 'identify_settings'));
        alert(settings.parameter);
    }

    $.fn.identify.settings = { parameter: 'default' };

})(jQuery);

Which basically tells me that the source of the problem is that there is no way for the outside function to know what sent it unless you pass in a reference. The click event on the affected element knows what was sent via “this” and/or event arguments.

Unless someone comes up with something different, I’m left thinking that there is no way to do this.

Update #3

Thanks to everyone for their input. In the end I decided to go about it by passing in my settings wherever necessary. I also wanted to be able to programmatically call my identify method, so in the end I went with this type of thing:

(function($) {
    $.identify = function(options) {
        var settings = $.extend({}, $.identify.settings, options);
        $.identify.speak(settings);
    }

    $.fn.identify = function(options) {
        var settings = $.extend({}, $.identify.settings, options);
		
        this.click(function() {
            $.identify.speak(settings);
            return false;
        });
		
        return this;
    }
	
    $.identify.speak = function(settings) {
        alert(settings.parameter);
    }

    $.identify.settings = { parameter: 'default' };
})(jQuery);

jQuery(document).ready(function($) {
    jQuery.identify({parameter:'programmatically set'});
    $('a:first').identify({parameter:'first'});
    $('a:last').identify({parameter:'last'});
});

The page loads and alerts “programmatically set”. Clicking the first link alerts “first”, and clicking the last link alerts “last”.

Plugging In (Part 3)

green light

Just a note to say that after testing the new extension method in Garden, I haven’t noticed any slowdown in performance at all. All you Vanilla addon developers out there are going to love this.

More Scaffolding

Yeah, I know. The scaffolding screenshots are getting boring. But see if you can figure out what’s interesting about this one…