Saturday 21 March 2009

Problems Upgrading to IE 8

Upgrading to Internet Explorer 8.0

There are plenty of sites already out there listing all the many bugs or "features" that IE 8 has brought to the table but so far the two main ones I have come across are:


Problems when FirebugLite is also running in IE 8.

I was getting a "Function Expected" error on line 1499 in the IsArray function. As a workaround I added the following line as the first line in the function e.g



IsArray:function(_object){
if(!_object) return false;



This prevents the error but the Firebug-lite console does not display correctly in IE 8 when the document mode is also IE 8. To get round this I set the document mode to IE 7 and then it works fine.

Remember IE 8 now has a console in the developer tools options for outputting custom debug messages plus its now got a great debugger tool with all the same features as Firebug so Firebug-Lite isn't really needed anymore. However it should still be possible to run the two side by side.


Issue with clip and rect function

I also found an "invalid argument" error when setting the clip properties using the rect function. The code was for a scroller and the original version that raised the error was:



this.canvas.style.clip = "rect(0 " + this.canvasWidth + " " + this.canvasHeight + " 0)";



The fix was to add "px" after the dimension values and separate the values with commas e.g



this.canvas.style.clip = "rect(0px, " + parseInt(this.canvasWidth) + "px, " + parseInt(this.canvasHeight) + "px, 0px)";



I have come across a few errors such as "null is null or not an object" (you don't say!) which have been simple fixes and have just required testing the values correctly before using them.

I am sure there are hundreds more errors and that many many hours will be devoted to fixing them all in a similar manner to the last 2 major releases of IE. However overall I am very happy that they seem to have caught up with Firefox and the others and have implemented a pretty decent developer tools section including a great debugger that actually gives you a useful error message for once. Plus I like the fact that the GUI hasn't changed very much in the way that IE 6 to IE 7 did and I do like the little touches like the accelerators.

However its a shame that with such a major release they couldn't have gone the whole hog and sorted their Javascript engine out to make that standards compliant as well as the CSS. Apparently they have rewritten the whole JS engine so now was as good a time as any to bite the bullet and do it and they would have made the whole web development community very happy if they had done so. Even with the rewrite their event model is still pretty shoddy and even if they wanted to keep with their intermediary event model (attachEvent, removeEvent, returnValue, srcElement etc) then they could have fixed those annoying little issues that people have spent thousands of development hours resolving such as the this keyword referring to the window and not the object in question and attaching event listeners in order rather than randomly.

It seems pretty likely that more and more companies will get to the point where developing for IE becomes too much work and stop supporting it. Market share of Firefox, Chrome, Safari and Opera are increasing all the time so it may not be that long until you find a lot of sites just redirecting to a Mozilla download page when you access their site in IE. If that does happen then it might be a shame to some people but Microsoft will only have themselves to blame and may find that they have missed a great opportunity with this release to prevent that from occurring.

Detecting IE 8 Compatibility Modes with Javascript

Using Javascript to determine a users browser settings in IE 8

Microsoft's new version of Internet Explorer, IE 8 comes with two configuration settings that allow the user to control the rendering mode and the browser mode so that in fact IE 8 comes with 6 different settings that can drastically alter the behaviour of the browser. See this article about the different settings for an overview.

If you want to be able to determine client side what configuration mix is currently enabled for the browser you can use the following function I have written which will output a little object with the relevant details. Either use it by itself or incorporate it into a fuller browser detection object such as my browser object.

If you are running IE 8 you will see below the output from the function:


download the script here: IE 8 compatibility mode detection script

How to detect which settings the user has enabled in IE 8?

To determine the browser mode you can test the user-agent which will mention Trident/4.0 for IE 8, and IE 8 in compatibility mode. IE 8 running as IE 7 will not mention this so combining this with a check for document.documentMode which is only available in IE 8 will enable you tell if the user has IE 7 or is running IE 8 as IE 7.

To determine the document mode you can test the new property which is available in IE 8 document.documentMode which will return the rendering mode its currently set to e.g 8, 7 or 5 (for quirks mode). Combining this with a check for document.compatMode for previous IE versions lets us determine the rendering engine settings.

IE 8 Document and Browser modes

Controlling IE 8 Browser and Document Modes

In Internet Explorer 8 the developer toolbar can control the following settings and will override any other settings that have been set e.g META tags or the Compatibility View options. On changing a setting the browser will refresh and load the appropriate new configuration.

I will list out the various document and browser modes with the basic differences but if you are in a hurry and just require a Javascript function that you can use to determine the clients current IE8 settings then that link will sort that for you. For an explanation on browser compatibility mode testing then this link will give you an article explaining the combination of agent sniffing and object detection that is required for identifying a clients IE8 browser settings.




Browser Modes:

Internet Explorer 8 Mode

The browser will run as IE 8.0 and the user-agent will appear as an IE 8.0 user-agent e.g

Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB5; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 1.1.4322; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)

Notice the mention of Trident/4.0 which is the name and version of the rendering engine.

A new Javascript engine is used in IE 8.0 so there will be numerous differences for example using getElementById to return an element by name will not work anymore which is the correct way of doing things however if you didn't know this and did use it in IE to access elements you will experience errors when running in full IE 8 mode.

Internet Explorer 7 Mode

The browser will run as if it were actually IE 7.0 and the user-agent will appear as an IE 7.0 user-agent e.g:

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB5; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 1.1.4322; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)

Javascript will run as it does in IE 7.0 for example using getElementById to return an element by name will work.

Internet Explorer 8 Compatibility Mode

This mode means that, and I quote from ieblog

"In a nutshell, Compatibility View allows content designed for older web browsers to still work well in Internet Explorer 8."

So in all respects the browser is still running as IE 8.0 but allows sites that worked perfectly well in IE 7.0 to continue to work correctly without having to revert to IE 7.0 mode.

By default IE will set all publicly accessible Internet sites to run in IE 8 mode and all Intranet sites to IE 8 compat mode.

For Internet sites it comes across which it feels should run in compatibility mode such as those with strict doctypes then it will display a button to the user to allow them to change to compatibility mode. For sites that are using quirks mode it will not offer this option so do not expect the button to appear all the time.

The user-agent in IE 8 Compatibility Mode is displayed similarly to IE 8 but with a 7 e.g

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; GTB5; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 1.1.4322; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)

Javascript should run as it did in IE 7 for example using getElementById to return an element by name will work.



Document Modes:

Quirks Mode (e.g IE 5)

This document mode setting will render pages as if there was no doctype specified. This will be the same as if you were using older IE versions such as IE 5.0.

Internet Explorer 7 Standards Mode

This document mode will render pages as they would be displayed in IE 7.0 when a strict doctype was specified.

Internet Explorer 8 Standards Mode (Page Default)

This document mode will render pages in the new IE 8 standards compliant manner. IE 8 apparently adheres to the CSS 2.1 specification and there are numerous changes to be aware of. For instance there is no longer any support for CSS expressions.

For a list of the various changes and potential problems that IE 8 will bring to your development view the following article: http://blogs.msdn.com/ie/archive/2009/03/12/site-compatibility-and-ie8.aspx


How to detect which settings are enabled

If for whatever reason you need to detect client side which of these various settings the user currently has enabled in their browser then you can use a combination of user-agent sniffing and object detection to work out the true browser version and rendering engine. See the following article about how to detect the settings using Javascript.


The new META UA-Compatible tag

Another new feature in IE 8 is the ability to quickly fix any potential problems that all these new document and browser modes may bring by adding a META tag to your existing sites. To force a page to run in IE 8 standards mode we can add the following META tag to pages:

<meta http-equiv="X-UA-Compatible" content="IE=8">

Or if you find that your sites do not currently work in IE 8.0 standards mode you can force them to work as they did in IE 7.0 with the following META tag:

<meta http-equiv="X-UA-Compatible" content="IE=7">

Once you get your site up to scratch you can remove the tags.

Sunday 15 March 2009

Comments For Script Articles - CSS Style Object, Linked Lists, Browser, Lazy Form Validator, Social Bookmarks

Example Scripts, Comments section

There are a number of scripts that I have posted on this site that are actually on another domain and therefore not part of blogger. Therefore I have added this article so that if anyone wants to post comments related to those scripts they can by adding them to this article.


Scripts List

JavaScript Unpacker. This simple form allows you to reverse engineer a block of JavaScript code that has been obfuscated by being encoded and is usually identified because the first few characters of the function look like this eval(p,a,c,k,e,r) . This method is usually used by hackers to try and hide the types of operation they are trying to carry out so its a wonderful way of being able to work out what the code is doing. Just paste the packed code into the box at the top, hit the "Unpack" button and hey presto you now have some readable code

CSS Style Object. A Javascript object that correctly calculates the computed style for Internet Explorer. Currently the example is using a function dedicated to correctly calculating styles for font-sizes but the core details could be applied to other styles requiring a computed size in pixels.

Querystring Parser: A small Javascript object dedicated to parsing a querystring something I thought would be inbuilt into the language but isn't. This article is on the blog and has its own comment section.

Linked Lists: A Javascript object dedicated to handling linked lists where the list box options in a parent list control the options that appear in a child list. The source of the data within the lists is not important this object controls the event handlers and the flow down of the hierarchy when a parent list has an item change as well as other default display options.

Lazy Form Validator: A Javascript object that can be used either in full production or when you want to quickly add client side form validation to a page with nothing more than including a reference to this script and then setting specific classes on each form element if special validation is required.

Social Bookmark Include: A simple include file and Javascript function that can be used on blogs or other sites to include links to social sites such as Digg, Stumble, Reddit etc. The script will append the appropriate URI and title details which it extracts from the source of the page containing the scripts. No need to customise the script on each page its used.

Browser Object. A little object dedicated to the now dirty art of browser sniffing containing details about css box model, spoofing, flash support, browser details etc. Most frameworks will still contain something similar and there are still cases where the the browser type and version is required knowledge due to feature support that cannot be tested with object testing.

Please specify which script you are commenting about when posting. Thanks.

Saturday 14 March 2009

System Views, Stored Procedures and SET NOCOUNT

Problems with data providers and SET NOCOUNT

Its standard good practise to always use SET NOCOUNT ON in your stored procedures to prevent system messages about the number of rows affected by DML statements from being returned. However as well as being good practise I have found that it can actually cause issues in certain cases depending on the data access provider used to connect to your SQL database from your front end application. If you have read my article about migrating from 32 bit to 64 bit applications you will see that I mention certain issues there. I have experienced problems when moving from MDAC to SQLOLEDB when stored procedures contain multiple DML statements and SET NOCOUNT has not been set as it seems these system messages are being returned as a recordset and whereas MDAC will ignore them SQLOLEDB doesn't. Therefore you may experience errors such as "Operation not allowed when the object is closed" or "item or ordinal does not exist in collection" because these system messages are being returned or accessed before your intended recordset is.


Solution - Add SET NOCOUNT ON

Therefore the solution is simple, make sure all stored procedures have this command set at the top of them. However if you have a large database containing hundreds of stored procedures then this would be quite a task to carry out manually. Therefore I came up with a way to automate this task when upgrading large database systems by using the system views available in SQL Server.

The idea is pretty simple.

  • Find out which stored procedures do not contain the SET NOCOUNT statement.
  • Script out those stored procedures and update them to contain the statement.
  • Run the script to ALTER the stored procs and update the database
  • Use standard functions and pure TSQL to accomplish the task.

Syscomments and Sysobjects

In SQL 2000 and 2005 all stored procedure and user defined functions have their source code available for viewing from the syscomments system view. The system views cannot be updated directly so its a case of using them to generate ALTER statements to run if anything requires changing.

You can view all the stored procedures without the SET NOCOUNT statement with the following SQL.


SELECT c.*,o.*
FROM sys.syscomments as c
JOIN sys.sysobjects as o
ON o.id = c.id
WHERE xtype='P' --stored procs
AND Name LIKE 'usp_%' --my prefix
AND LOWER(text) NOT LIKE '%set nocount on%'
ORDER BY o.Name
One of the things you should be aware of is that the text column which contains the code is nvarchar(4000) and procedures or functions that have a code length greater than 4000 will be split up over multiple rows. The id column relates to the system object_id which can be used to join to sysobjects and the colid will contain the subsection of code. Therefore you will notice that the previous SQL is not 100% correct as a procedure that is split over 4 rows maybe returned even if it does have SET NOCOUNT ON set because only the first section with a colid of 1 will not match the filter.


Solution to the problem

The final script I used to solve this solution can be accessed here:

Download SQL script to insert missing SET NOCOUNT ON statements to stored procedures

I have split it into two separate loops mainly to get round limitations of displaying large strings from variables in query analyser and the system stored procedure I have used to return the complete code from syscomments which is called sp_helpText.

There are multiple ways that this task could have been achieved but I wanted to keep it a purely TSQL solution and although its not the most elegant piece of code ever writen it has done the job it was designed to do which was to update 100+ stored procedures so that I didn't have to do it by hand.

To view more solutions to common database problems that I have solved by using the system views please see

Thursday 12 March 2009

SQL Server 2005 Script Fulltext Indexes

Generate Script for all Fulltext indexes within a Fulltext Catalog

One of the things that I have found disappointing about SQL 2005 Management Studio apart from the severe slowness of the GUI compared to 2k is the fact that there is no option (that I can find) that will allow you to generate the necessary scripts for fulltext indexes. If you select a fulltext catalog under the storage section and choose to script a create you will get the following:

CREATE FULLTEXT CATALOG [System_Help]
IN PATH N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\FTData'
WITH ACCENT_SENSITIVITY = OFF
AUTHORIZATION [dbo]

Which is just the script to rebuild the catalog and not the actual indexes within the catalog.

Obviously this is not very useful if you are wanting to quickly re-create the indexes along with the catalog and hopefully they will remedy this in SQL 2008. However until that day comes you can either rebuild the indexes by hand using the GUI or use a script like the one I have created which will:
  • Script a CREATE FULLTEXT CATALOG statement for the catalog.
  • Loop through each fulltext index within the catalog and script the necessary CREATE FULLTEXT INDEX statements.

An example of the SQL generated by my script is below. Its a catalog I created purely for testing that contains two indexes.


CREATE FULLTEXT CATALOG SystemHelp
WITH ACCENT_SENSITIVITY = OFF
GO
CREATE FULLTEXT INDEX ON [dbo].[tbl_CLIENTS] (
CompanyName Language 1033
,description Language 1033
,email Language 1033
,address1 Language 1033
)
KEY INDEX PK_tbl_CLIENTS
ON SystemHelp
WITH CHANGE_TRACKING AUTO
GO
CREATE FULLTEXT INDEX ON [dbo].[tbl_SYSTEM_HELP] (
Title Language 1033
,Article Language 1033
,Tags Language 1033
,PageName Language 1033
,RelatedSection Language 1033
)
KEY INDEX PK_tbl_SYSTEM_HELP
ON SystemHelp
WITH CHANGE_TRACKING AUTO
GO



Obviously you can take my script modify and extend it to incorporate any missing settings that you require as I have created it purely for moving my own existing indexes. However as the script stands its another good example of using the system views to solve common DBA problems and I am still scratching my head about why you can script almost every other object in SQL 2005 apart from the fulltext indexes. Maybe there is a hidden button I have not found yet! If anyone knows where it is please show me.