Archive for the 'browsers' Category

Replace the Home button with a script

Tuesday, March 3rd, 2009

Robert Ames commented on my previous post suggesting replacing the Home button with my little site search bookmarklet. I didn't even know this was possible, but I found it pretty cool, so I just had to try.

x-browser

I tried this in Firefox/Mac and IE/Windows and it works just fine.

ok, what is it?

Well, the idea is simple: when setting the homepage in your browser, instead of providing an http://... URL, you can use the javascript:... pseudo-protocol. So for example you can type:

javascript:alert(document.title)

And then every time you hit the Home button in the browser, an alert with the page title will pop up. How cool is that!

Naturally, you can replace the simple javascript with any sophisticated bookmarklet of your choosing (hint, hint)

how-to

In Firefox on the Mac you go Firefox / Preferences. On Windows: Tools / Options. Then in the Main tab, you type/paste the bookmarklet code.

Setting the Home to a javascript bookmarklet in Firefox

For IE/Windows go Tools / Internet Options and select the General tab

Internet Explorer - setting the Home button to a javascript bookmarklet

 

Javascript console in IE

Saturday, October 18th, 2008

I'm a sucker for consoles. The ability to quickly type some code and see it executed right then and there... priceless. That's why I'm a huge fan of Firebug's JavaScript console. But what about IE?

option 1 - Firebug lite

Firebug lite is a lighter version of the proper Firebug which runs in browsers other than Firefox. You "install" the bookmarklet and voila - JavaScript console and other goodies are available on any page.

You visit any page and click the "Firebug lite" bookmarklet...
firebug lite bookmarklet

... then you hack away in the shiny console!
firebug lite bookmaklet in action

option 2 - built-in MS script editor/debugger

If you do any javascript in IE, it's a good idea to have this debugger guy enabled. There's actually at least three different debuggers, but one of them is already installed without you lifting a finger. If you enable it, you can debug any time there's a JavaScript error on the page. It also features a console! You can't get to the console unless there's a JS error, so you may need to cause the error yourself. Here's the step-by-step scenario.

Go to menu Tools / Internet Options... / Advanced tab. Under the "Browsing" category uncheck the box that says "Disable Script Debugging"
set the IE options

Go to any page and cause an error, by typing in the address bar some non-existing property or some non-existing object for example. Like javascript:alert(a.a.a)
Go to anypage and cause an error

Non-surprisingly, you get an error, but now you have the option of debugging the error:
A error and a debug option

You're given a list of debuggers, in case you've installed more debuggers from MS. Select your debugger or just hit Yes:
pick a debugger

Just say OK here...
step into procedure

Click "Break"...
Break

Finally - a console! We're in! The console is the so-called "Immediate" window, which is not displayed by default. To see it go to menu Debug / Windows / Immediate. Then just start fiddling with the page. Type anything and hit enter to see it evaluated. You also list the properties of an object by typing its name, like document.images[0] or just document.
Fiddle with document.images[0]

Once you've had your fun, stop debugging:

Enjoy the results of your hard work, a.k.a. replacing some logo with a shot of your favorite book ;)
your fav book

 

a DOCTYPE is all it takes

Friday, July 25th, 2008

At a lunch conversation about quirks vs standards mode, the question was raised: but what if you don't have those kinda important tags such as <html> or <body>? is this going to be quirks mode?

Well, the following test case shows that a DOCTYPE is all it takes in order to have standards mode rendering. Was this a Cinderella song: "We all need a little DOCTYPE, just a little helper, ooh and it will be alright" :)

» Run test example

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

hello

<script type="text/javascript">
alert("Quirks? " + document.compatMode);
</script>
 

Browser Wars 2.0?

Monday, December 17th, 2007

browserwars.png

 

Smart browsers don’t download unneeded images

Saturday, June 23rd, 2007

We ofter complain about browsers, browser inconsistencies, quirks, hickups, the list goes on. Let's say something nice to them, and hope for good karma :)

It happens as your web app grows in size and team members that some parts of the stylesheets become obsolete, no one remembers why they were there in the first place, but no one has cojones to remove them, because of fear that removing them might break something you forgot to take into consideration. Same case when you have the same stylesheet for 50 different pages and on some pages only some of the styles are actually used. I was wondering, do you pay performance penalty when you have style rules that refer to images, but the rules are never needed to render the page? Will the browser download all those unneeded images? The answer is No. The browser will try to avoid downloading the image assets as much as possible. And this behavior is pleasantly consistent across IE, FF, Safari (for Windows), Opera.

Test #1

I tried this stylesheet:

body {
    background: url(bg.png);
}
#some-id {
    background: url(ie.png);
}
.some-class-name {
    background: url(o.png);
}
p {
    background: url(image.php);
}

And applied it to a blank page that doesn't have any paragraphs, or elements with class name some-class-name, or ID some-id. The result was that only bg.png was downloaded, which is great.

> test #1

Test #2

I added a button which, when clicked, creates a new P element and sets a 3 seconds timeout before appending the new element to the body. (The background for the P element is the script image.php which only sleeps for 3 seconds for demonstration purposes, before redirecting to ff.png.) The result is that the image is requested only after the element is added to the document flow, not when it was created. Which is smart. It ain't added 'till it's added.

> test #2 (same file as test #1, btw)

Test #3

OK, modified test #2. A P element is created, its visibility is set to hidden and it's added to the document. It's officially in the document flow, although not currently displayed. My guess was that the browsers will download the image at this point. True for FF, IE7, Safari, Opera.

> test #3

Test #4

Here's the only inconsistence in the behavior of the browsers. A P element is created, but with display: none, then added to the document. So it's part of the DOM tree, but not really part of the document flow. Then another button changes display to block.

FF will wait for the display: block before downloading the image background
Opera will also wait until display: block
IE7 begins to crack under the pressure and downloads the image even with display: none
So is Safari

> test #4

So what?

Well, it's nice to know that the browsers won't download the images referred to from our stylesheets unless they are needed for rendering. There is a side effect though. If you happen to create dynamic elements that have some styles with background and no other similar elements already exists on the page, the user experience might suffer slightly as the image will generally be requested after the new element is added. In cases when this is important to you, you might need to take some extra care to make sure the image is downloaded before you add the new element. You might need to do for example a new Image() after initial page load. (reminds me of the good old days of image rollover buttons, those were the days, eh? Seems like no one does image rollover buttons and menus anymore. It's all css this, css that... ;) )

 

Dynamic SCRIPT and STYLE elements in IE

Friday, January 26th, 2007

So you know how to add external scripts and styles, using the DOM, after the page is loaded. And what if you don't have external files, but have some style definitions and some JS code as text and you want it inserted and executed into a page.

The DOM way

"Ha! An easy one", you'd say and then go like:

var ss = document.createElement('script');
var scr = 'alert("bah");';
var tt = document.createTextNode(scr);
ss.appendChild(tt);
var hh = document.getElementsByTagName('head')[0];
hh.appendChild(ss);

"Ha!" in turn says IE, "No way!"

The IE way for SCRIPT

The above won't work in IE, but you can use the text property instead of creating a text node. Interestingly enough, this also works in Firefox.

var ss = document.createElement('script');
var scr = 'alert("bah");';
ss.text = scr;
var hh = document.getElementsByTagName('head')[0];
hh.appendChild(ss);

The IE way for STYLE

STYLE, SCRIPT, what's the difference, they are merely elements of the DOM tree. For the normal browsers, yes, so creating a text node with the stylesheet body will work in Firefox. For IE, you need a workaround.

var ss1 = document.createElement('style');
var def = 'body {color: red;}';
ss1.setAttribute("type", "text/css");
ss1.styleSheet.cssText = def;
var hh1 = document.getElementsByTagName('head')[0];
hh1.appendChild(ss1);

Note that while in the SCRIPT case I took the liberty of skipping the type attribute, it's absolutely required here.

So with a bit of object sniffing, we can get a cross-browser solution:

var ss1 = document.createElement('style');
var def = 'body {color: red;}';
ss1.setAttribute("type", "text/css");
if (ss1.styleSheet) {   // IE
    ss1.styleSheet.cssText = def;
} else {                // the world
    var tt1 = document.createTextNode(def);
    ss1.appendChild(tt1);
}
var hh1 = document.getElementsByTagName('head')[0];
hh1.appendChild(ss1);
 

Firebug console for IE

Wednesday, December 6th, 2006

Update: A better version of what I was trying to do is here. It works around the cross-domain permission problems in IE by not loading a page in the frame, but putting there the actual content.

Firebug - no words to describe how cool it is, really. After the recent new release (1.0. beta) the number of features is overwhelming. I for one can't live anymore without it, seriously.

One of the things I noticed on the website is the ability to use the Firebug console in other browsers than Firefox. I don't know if this existed before version 1.0 but if it did, it was the best kept secret. I am so addicted to the console in Firefox, I use it all the time to tweak a few things here and there when I'm working on a page. Recently I was looking for something similar for IE, but couldn't find it. Lo and behold, it was right under my nose.

So, here's the page that describes how to use Firebug in IE (and others). Basically you unzip the Firebug Lite files somewhere on your server and then you include firebug.js in your pages. But why stop there? And isn't it possible to avoid including this script on every page (and forgetting to remove once you're done, or removing it prematurelly since a page, just like a painting, is never really finished). Bookmarklets to the rescue!

I wanted to host the Firebug files on my hard-drive and then use a javascript dynamic include to load firebug.js via a bookmarklet. This way I would be able to load the firebug console every time I want it, on any page. Unfortunatelly IE's security policy won't allow it. Then?

Solution

The solution I came up with is:

  1. you copy the Firebug Lite files somewhere on your server
  2. you call a bookmarklet that will load firebug.js
  3. you hit F12 and you have a console!

This procedure has to be repeated for every domain you're working on, because of the security policy that won't allow cross-domain frame scripting. You can have one copy for your http://localhost and one for every domain. To ease the creation of bookmarklets that load firebug.js, I came up with a Firebug bookmarklet generator.

In action

  1. I copied Firebug Lite files (get the .zip) on this server (phpied.com), they are here.
  2. I (and you can try the same) generate a bookmarklet, using the bookmarklet tool
  3. Add the generated bookmarklet to the favorites
  4. Go to any page on phpied.com
  5. Click the new favorite
  6. Hit F12 to show/hide the console

Here's how (a readable version of) the generated code looks like:

javascript:(function(){
  var firebug_js = document.createElement('script');
  firebug_js.setAttribute('type', 'text/javascript');
  firebug_js.src = 'http%3A//www.phpied.com/files/firebug/firebug.js';
  document.getElementsByTagName('head')[0].appendChild(firebug_js);
  firebug_js.onreadystatechange = function () {
    if (firebug_js.readyState == 'complete') {
      console.open()
    }
  }
})()

Minor improvement to the console

The Firebug Lite console executes the code you type, but doesn't show it again when you use the up/down arrows, the way it does in Firefox. So I added this feature (copying from myself), you can replace the firebug.js you download with my version.

Not sold yet?

Here's a screenshot of the console in action, I used it to change my photo on the homepage.

firebug-ie-console.png

Go ahead, please

I strongly encourage everyone to try this out. Firebug is a beautiful thing and using even a bit of it in IE is great.

 

Rendering styles

Wednesday, October 4th, 2006

The question is - what will a browser do, given a page with several stylesheets, each of them probably overwriting definitions from the previous ones? Will the browser render the page using the first received css file, while downloading the other ones and after that partially re-rendering where required? The answer is: no, the browser will wait until all CSS files are downloaded, (then probably merge all definitions, just a wild guess) and will render once.

Test

I did this test - one page with two stylesheets that contain pretty much the same selectors for different table styles (thanks to this gallery). Each of the CSS files is actually a PHP script and has a call to sleep(), one sleeps for 5 seconds, the other one for 10.

Result

The browser sits there and waits for the both styles, rendering nothing (except for the page title, but that's not really rendering, is it?). So nothing happens for 10 seconds, then the second style is used for the final rendering. This happens in both FF and IE.

Misc

I also tried sleeping in the actual page, and flushing the output after each row. In my home environment FF renders each row as it's received, but in my hosted environment, it waits for the whole table. IE alsways waits for the complete table.

If I put the page to too much sleep so that the php script dies before the second stylesheet is dowloaded, the browser uses whatever is at hand (css1) to render the page.

Demo/download

 

quirks or no quirks bookmarklet

Wednesday, September 20th, 2006

Here's a bookmarklet that will tell you whether or not the browser renders your page in Standards Complaiance Mode or Quirks Mode. The bookmarklet will figure this out for the page as well as for all the frames (and their frames) recursively. Enjoy!

Install

Drag this to your bookmarklets/favorites or right click and add to favorites:

quirks or !quirks

Sample output

Here's a sample output, produced when used in my Wordpress backend when writing this post:
quirks.png

As you can see the page has two frames (probably iframes, doesn't matter), one of them is rendered in Standards Compliant Mode (CSS1Compat) the other one is in Quirks Mode (BackCompat). The overall document is CSS1Compat as well. For the frames, if they were named, you would see the name of the frame before the URL brackets.

And this is GMail, wow, lotsa frames, none compliant ;)
quircks-gmail.png

The code

The code is pretty simple, just accessing the compatMode of the the document object. Here it is in more human readable form (not one long line like bookmarket code).

var response = 'Document mode: ' + document.compatMode;
function checkFrames(w) {
  if(w.frames && w.frames.length>0){
    response+='\\n\\n';
    for(var i=0;i<w.frames.length;i++){
      var fr=w.frames[i];
      try {
        response+=fr.name +
              ' ('+fr.document.location+') - '+
              fr.document.compatMode+'\\n';
      } catch (e) {
        response+='Could not access this frame\\n';
      }
      checkFrames(fr);
    }
  }
}
checkFrames(window);
alert(response);