I'm guessing everyone who is reading this knows what Stack Overflow is but I bet most people aren't getting the most out of what really is a very useful tool for developers.
For those of you that don't know, Stack Overflow is in it's simplest form, a forum. Developers post problems or questions that they can't find the solutions for and other developers answer them. Those questions and answers are then stored so that anyone with a similar question can find the answer. After years of this, Stack Overflow has built up a pretty comprehensive archive of common problems that developers have faced and the solutions to those problems. It's one of the reasons that if you search for a development related problem on the internet then nine times out of ten, Stack Overflow is the first hit. It's a great idea and it's been well executed.
So, why am I writing a blog post about it? You already know all that. Well, up until recently that's all I knew about Stack Overflow as well. Until I actually decided to give something back.
I registered for an account and I thought I'd try and answer a few questions. I may not be the greatest programmer in the land but I do have a fair amount of experience with various technologies/frameworks so I should be able to answer the odd question or two. Turns out I was correct, I can answer the odd question. What's more, it's addictive.
Just about every interaction within the Stack Overflow community gives the rest of the community to give you reputation points. Someone likes your answer? They'll vote it up. That's 10 points. Your answer gets accepted as the correct answer, that's 15 points. And the same works in reverse. If you post a load of rubbish, you'll get voted down and that's minus points. Why is this important? Well, the entire website is moderated by the community and these reputation points gauge what you can and can't do in order to help that moderation. I suppose in essence, it runs a bit like humanity does in Star Trek, in the words of Picard "We work to better ourselves and the rest of humanity". I wouldn't class it as work but, you get the idea.
As I said, answering questions becomes addictive because the more you answer, the more reputation points you get. This leads you to reading a lot of questions, a lot of which you won't be able to answer. This is good. Very good. Why? Because you learn a lot. Just by reading questions and their corresponding answers I've learnt all sorts of things, in fact I wish Stack Overflow had the ability to "notify you via e-mail when an answer is posted", there are so many good questions that get posted. I've found better ways of solving problems I solved years ago, I've read questions to problems I haven't even come across yet. It really is a great tool for learning.
In conclusion, it's a good tool for learning to communicate accurately to fellow developers. It gives you the ability to give back to the development community and it is a great tool for learning. So, if you're waiting for something to compile or you've just got a spare 5 minutes, head over there. Try and answer a few questions, read other questions and just learn.
Saturday, 23 March 2013
Tuesday, 19 February 2013
IE8, Filters and IFrames
Everyone loves supporting old versions of Internet Explorer right?
Well, I came across an odd "quirk" with IE8 and it took me a little bit of time to track it down.
The problem occurs when you use a DropShadow IE filter, an Alpha filter and an iframe. When you stick them all together, the iframe becomes totally transparent. Very odd.
Let me walk you through it.
So, the set up is that we have a normal page, that page consists of a div with a DropShadow and that div contains an iframe which loads a new page. In that page, we have an overlay which has a 100% transparency set. When you strip out all the complexity, you end up with two HTML pages that look a little like the below. I've given each page a background colour just to make the problem a little more obvious.
Main.html
<html>
<head>
<title>Top Window</title>
</head>
<body style="background-color: Green;">
<center>
The top window
<br />
<br />
<div style="position: absolute; top: 55px; left; 25px; z-index: 1">Some general text in the top level window</div>
<div style="border: 1px solid black; z-index: 2; position: absolute; top: 50px; left; 20px; filter: progid:DXImageTransform.Microsoft.DropShadow(OffX=5, OffY=5, Color=#888); width: 400px; height: 400px;" >
<iframe src="IFrame.html" style="width: 400px; height: 400px;" frameborder="0" />
</div>
</center>
</body>
</html>
All pretty straightforward so far right?
Wrong.
Here's two images of the what the above produces. One is produced by IE8 and the other, IE9.
See the problem? The entire content of the iframe has become transparent. That's not what we wanted at all! IE9 on the other hand, renders it correctly.
The solution? Remove the DropShadow on the div. Ok, so it doesn't look as good but at least it gives a consistent look across IE browsers. You can always reproduce the box shadow effect using a different method, perhaps a second div that has a grey scaled colour, placed underneath the div containing the iframe but with a bit of an offset, I'd imagine that'd have the same effect although I haven't actually tried it.
Oh the joys of old versions of Internet Explorer.
Well, I came across an odd "quirk" with IE8 and it took me a little bit of time to track it down.
The problem occurs when you use a DropShadow IE filter, an Alpha filter and an iframe. When you stick them all together, the iframe becomes totally transparent. Very odd.
Let me walk you through it.
So, the set up is that we have a normal page, that page consists of a div with a DropShadow and that div contains an iframe which loads a new page. In that page, we have an overlay which has a 100% transparency set. When you strip out all the complexity, you end up with two HTML pages that look a little like the below. I've given each page a background colour just to make the problem a little more obvious.
Main.html
<html>
<head>
<title>Top Window</title>
</head>
<body style="background-color: Green;">
<center>
The top window
<br />
<br />
<div style="position: absolute; top: 55px; left; 25px; z-index: 1">Some general text in the top level window</div>
<div style="border: 1px solid black; z-index: 2; position: absolute; top: 50px; left; 20px; filter: progid:DXImageTransform.Microsoft.DropShadow(OffX=5, OffY=5, Color=#888); width: 400px; height: 400px;" >
<iframe src="IFrame.html" style="width: 400px; height: 400px;" frameborder="0" />
</div>
</center>
</body>
</html>
IFrame.html
<html>
<head>
<title>Inner Frame</title>
</head>
<body style="background-color: blue;">
Text within the iframe
<div style="position: absolute; left: 0px; top: 0px; width:400px; height: 100%; filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); background-color: black;">
This is an overlay within the iframe.
</div>
</div>
</body>
</html>
All pretty straightforward so far right?
Wrong.
Here's two images of the what the above produces. One is produced by IE8 and the other, IE9.
| Internet Explorer 8 | Internet Explorer 9 |
![]() |
![]() |
See the problem? The entire content of the iframe has become transparent. That's not what we wanted at all! IE9 on the other hand, renders it correctly.
The solution? Remove the DropShadow on the div. Ok, so it doesn't look as good but at least it gives a consistent look across IE browsers. You can always reproduce the box shadow effect using a different method, perhaps a second div that has a grey scaled colour, placed underneath the div containing the iframe but with a bit of an offset, I'd imagine that'd have the same effect although I haven't actually tried it.
Oh the joys of old versions of Internet Explorer.
Labels:
css,
filters,
IE8,
iframes,
transparency
Location:
London, UK
Tuesday, 8 January 2013
HttpHandlers and Session State
By default, if you create a new HttpHandler, it does not have access to the session object. Take the following as a very simple example:
public class MyHandler : IHttpHandler
{
#region IHttpHandler Members
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
string s = (string)context.Session["MySessionObject"];
context.Response.Write(s);
}
#endregion
}
Do you see the problem? HttpContext.Current.Session will be null and an exception will be thrown.
So, how do you access the Session object from within an HttpHandler? I've tried all sorts of magical workarounds, some worked, some didn't but by far the easiest is just to simply add the IReadOnlySessionState interface to your handler, so it'll look like this:
public class MyHandler : IHttpHandler, IReadOnlySessionState
{
#region IHttpHandler Members
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
string s = (string)context.Session["MySessionObject"];
context.Response.Write(s);
}
#endregion
}
And as if by magic, your session object is populated and you can access your session objects like you usually would. Fantastic news! You can't write to the session object by the way, but I've not come across a scenario where I've needed to yet.
Thanks to Scott Hansleman's blog for the solution to that little problem!
public class MyHandler : IHttpHandler
{
#region IHttpHandler Members
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
string s = (string)context.Session["MySessionObject"];
context.Response.Write(s);
}
#endregion
}
Do you see the problem? HttpContext.Current.Session will be null and an exception will be thrown.
So, how do you access the Session object from within an HttpHandler? I've tried all sorts of magical workarounds, some worked, some didn't but by far the easiest is just to simply add the IReadOnlySessionState interface to your handler, so it'll look like this:
public class MyHandler : IHttpHandler, IReadOnlySessionState
{
#region IHttpHandler Members
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
string s = (string)context.Session["MySessionObject"];
context.Response.Write(s);
}
#endregion
}
And as if by magic, your session object is populated and you can access your session objects like you usually would. Fantastic news! You can't write to the session object by the way, but I've not come across a scenario where I've needed to yet.
Thanks to Scott Hansleman's blog for the solution to that little problem!
Labels:
ASP.NET,
C#,
HttpHandler,
IHttpHandler,
Session,
State
Location:
London, UK
Saturday, 5 January 2013
League Predictor
For those of you that don't know, I play a fair amount of football and I run the website for the Sunday league team for which I play, Sumners Athletic. For many years I've used that site, and the server it's hosted on, to test new technologies and new methodologies and to improve my understanding of other web technologies.
Every now and again, when I'm playing around I create a control that I can share with the world. It's usually not the polished article but it does a job. Five or six years ago I created one of these controls. I created a "league predictor" in the form of a Java applet (who remembers those?).
What is a league predictor? Well, for a football team like mine that play in a league and each team plays each other twice (home and away), given all the results of the league to date, will work out the remaining fixtures. Those fixtures are then presented to the user so that they can make predictions about those games. At the end, the user hits a button and then re-draws the final league standing based on the predictions that the user has made.
Well, unless you've been out of the web application loop for the past 5 years, you'll probably know that Java applets are all but dead. JavaScript and HTML5 are the way forward so, I thought I'd re-write that original control using those technologies. The re-write is now done so I thought I'd make the code available to all. At some point I'd like to add animations to the league re-draw but that's another post for another day.
Anyway, the JavaScript file and corresponding CSS and HTML files can be found in this zip file.
If you want to see a working example, check this out: Sumners Athletic League Predictor
(Please ignore the fact that my team, Sumners Athletic, are currently bottom of the league!)
Just a few notes about the "control"...
Firstly, the JavaScript requires the initial data to be able to work out the league and what fixtures need to be played. To do this, it needs what I call, a results matrix in the form of a CSV file.
What's a results matrix? Well, it's essentially a grid of all the games played. You can imagine it as a grid, with the team names forming the first row and the first column. The results of each game (assuming you play home and away once) can then fit in the corresponding cells. If you open the CSV file included in the above zip file within a spreadsheet, you'll see what I mean.
This initial data is then requested by JavaScript and processed. It converts the CSV file into a 2D array and constructs team objects from that array. A team object consists of the name of the team, the amount of games played, won, drawn and lost. From this, a league can be constructed.
Then, from the results matrix, we can work out what fixtures are remaining. We can then display these fixtures to the user. Once they hit the "Predict" button, the predictions made are then fed back into the results matrix and the league is re-drawn based on the new results matrix.
And that's it.
Nothing too complex but I thought I'd share the code. I remember when I first started building my first football team website, I looked around for something that would do just this and couldn't find anything, now there's an option out there!
Every now and again, when I'm playing around I create a control that I can share with the world. It's usually not the polished article but it does a job. Five or six years ago I created one of these controls. I created a "league predictor" in the form of a Java applet (who remembers those?).
What is a league predictor? Well, for a football team like mine that play in a league and each team plays each other twice (home and away), given all the results of the league to date, will work out the remaining fixtures. Those fixtures are then presented to the user so that they can make predictions about those games. At the end, the user hits a button and then re-draws the final league standing based on the predictions that the user has made.
Well, unless you've been out of the web application loop for the past 5 years, you'll probably know that Java applets are all but dead. JavaScript and HTML5 are the way forward so, I thought I'd re-write that original control using those technologies. The re-write is now done so I thought I'd make the code available to all. At some point I'd like to add animations to the league re-draw but that's another post for another day.
Anyway, the JavaScript file and corresponding CSS and HTML files can be found in this zip file.
If you want to see a working example, check this out: Sumners Athletic League Predictor
(Please ignore the fact that my team, Sumners Athletic, are currently bottom of the league!)
Just a few notes about the "control"...
Firstly, the JavaScript requires the initial data to be able to work out the league and what fixtures need to be played. To do this, it needs what I call, a results matrix in the form of a CSV file.
What's a results matrix? Well, it's essentially a grid of all the games played. You can imagine it as a grid, with the team names forming the first row and the first column. The results of each game (assuming you play home and away once) can then fit in the corresponding cells. If you open the CSV file included in the above zip file within a spreadsheet, you'll see what I mean.
This initial data is then requested by JavaScript and processed. It converts the CSV file into a 2D array and constructs team objects from that array. A team object consists of the name of the team, the amount of games played, won, drawn and lost. From this, a league can be constructed.
Then, from the results matrix, we can work out what fixtures are remaining. We can then display these fixtures to the user. Once they hit the "Predict" button, the predictions made are then fed back into the results matrix and the league is re-drawn based on the new results matrix.
And that's it.
Nothing too complex but I thought I'd share the code. I remember when I first started building my first football team website, I looked around for something that would do just this and couldn't find anything, now there's an option out there!
Labels:
CSV,
HTML,
JavaScript,
league predictor,
Sumners Athletic
Location:
London, UK
Sunday, 9 December 2012
Web Apps and Pagination Queries
![]() |
| Paging controls are found on many popular web apps. Amazon is a great example. |
But, how is this implemented and what is the best way of doing so?
Well, the results shown on the page are usually held against a database. So the question quickly becomes:
"How can I query the database to bring back a given page of results?"
Now before I carry on lets first state that this blog post consists of database queries that have been run against an Oracle database (both the 10 and 11g versions). There's a strong possibility that they will not run against SQL Server, or any other database for that matter, but I suspect the general concepts remain the same. I should also state that I am by no means an Oracle expert. Yes, I know SQL reasonably well, but an expert? Far from it. So, if you find a better way of implementing the following features then it'd be great to here from you.Now, back to the task in hand. We need to write a SQL command to run on an Oracle database that will bring back a "page" of data of a particular table and as an extra condition, the data returned must be in a given order. Let's also say that a page consists of 25 records.
You'll be surprised at how many ways there are to achieve this. In the 4.5 years that Qube have been using this functionality, our pagination queries have changed no less than four times. Some times we've made the odd small change to optimize the query, in other times we've re-written the whole thing and used a different technique. In each case, we've improved performance over the last iteration of changes. This is done with the goal of making our web application as fast as possible. Finally, we've now got to the stage where using one technique is faster on one table but slower than a different technique on another. This means there is no technique that's best for all tables. It'll depend entirely on the amount of data you have in each table, the indexes you've set up and the way in which your database is optimized.
I'm now going to take you through our little journey of finding the best possible pagination query. In all of the example queries I've highlighted the base query (the query which we want to paginate) in blue. Generally, the following methods wrap that base query up in order to implement paging. You'll need to change the base query to be the actual query you want to use pagination on.
Revision One - Retrieve All
So, our first option was to retrieve all records and let the application handle the pagination. So, if we have a table that consists of 100,000 records, we retrieve all records and then the application will display 25 at a time. The bonus of this method is it's extremely easy to implement. Also, moving from one page to the next is extremely quick, all the records are held in memory so navigating between them is simple and fast. There are however, some major downsides. For starters, retrieving all records is slow so the initial load time for the user is severely affected. If that's not bad enough (and it should be), the memory usage of such a technique is outrageously large, especially when you consider the fact that it's highly unlikely a user will want to navigate through the entire 100,000 records anyway, so you're using valuable memory on records that are never going to be shown. Not cool! Just with these two things in mind, this technique is going to scale very badly.Example Query
SELECT COLUMN_ONE, COLUMN_TWO, COLUMN_THREE
FROM TABLE_NAME
ORDER BY PRIMARY_KEY
Revision Two - Nested Queries
Bringing back everything clearly isn't the way forward. So, with a little bit of use of ROWNUM (an Oracle feature which brings back the number of the row in a dataset, e.g. the first row has a number 1, the second has a number 2, etc.) we can bring back 25 rows at a time which will give us the paging functionality that we need.Using this method the application doesn't need to store all the possible rows which lowers the memory consumption on the application significantly. It also improves the performance of the first page load. Instead of bringing back thousands of rows, the database only returns 25 rows and there's obvious performance implications for that. The downside however is that the performance of the next/last/first/last page buttons will be affected as the query will need to be re-run but for the next page of data. If all the rows were stored on the application from the original query then this additional database query wouldn't need to be run.
Example Query
SELECT * FROM (SELECT rownum as f2n_rownum, f2n_table.*
FROM (SELECT COLUMN_ONE,
COLUMN_TWO,
COLUMN_THREE
FROM TABLE_NAME
ORDER BY PRIMARY_KEY) f2n_table
WHERE rownum <= 25)
WHERE f2n_rownum >= 1
Revision Three - Nested Queries Using WITH
![]() |
| As always, speed is key! |
So, we looked to see if we could improve the performance of our pagination query. If we can then that's a performance improvement across near all of our pages. As it turns out... there is a better way! Kind of.
We could improve the performance in two different ways. Firstly, we can use the WITH clause. This is known as subquery factoring.2 The second improvement is that we can tell the oracle optimizer how many rows we intend on using, this allows the optimizer to use this information to choose a faster explain plan for what we want. We do this by using optimizer hints in the query and in this hint we tell the optimizer that we want the first 25 rows brought back first (or however many rows are contained in your "page" of data). For more information on this try here: www.orafaq.com.
Example Query
SELECT /*+ FIRST_ROWS(25) */
pageouter.*
FROM (WITH page_query AS (SELECT COLUMN_ONE,
COLUMN_TWO,
COLUMN_THREE
FROM TABLE_NAME
ORDER BY PRIMARY_KEY)
SELECT page_query.*,
ROWNUM AS innerrownum
FROM page_query
WHERE rownum <= 25) pageouter
WHERE pageouter.innerrownum >= 1
Revision Four - Nested Queries With ROW_NUMBER
Ok, so we're now using optimizer hints and we're using subquery factoring. All good stuff. But can we do more?Well, we can. Kind of.
There is a SQL function called ROW_NUMBER(). It serves very much the same purpose as ROWNUM in Oracle but it works in both Oracle and SQL Server and oddly, when used can perform better than our previous queries but only in certain scenarios.
The problem here is I can't tell you why it performs better in certain scenarios, I can't even tell you in which scenarios it performs better but here is what I have found:
- It seems to perform better than our previous methods if the query is modified to have a complex 'where' clause.
- It seems to perform better than our previous methods if the data is ordered by a row that is not uniquely indexed.
- The performance gains can be dramatic. In the previous examples, changing from one method to another may have seen an improvement ranging from nothing to a second or two. I've seen this method improve some queries by up to 5-8 seconds, especially on queries that order data by columns that aren't indexed.
Now I suspect all of this is very much dependent on the indexes you have set up on your tables, the amount of data in your tables, how you've got your database optimized and probably a fair few other factors that I have no idea about so, the best way to know how this will perform for your queries is to test it.
Example Query
SELECT /*+ FIRST_ROWS(25) */
*
FROM ( SELECT ROW_ONE,
ROW_TWO,
ROW_THREE,
row_number() OVER(ORDER BY PRIMARY_KEY) innerrownum
FROM TABLE_NAME
)
WHERE innerrownum BETWEEN 1 AND 25
Conclusion
I've shown you three different ways of implementing pagination within the database query. There are other ways which I haven't discussed. For example, you could follow this process:- Run the query for ALL records (no paging) but insert the results of that query into a temporary table.
- Query that temporary table for the "page" of data that you want, using one of the methods above.
- When implementing the next/previous page function, you can then query the temporary table directly.
Assuming that your original query isn't bringing back the entire table, you'll be selecting from a subset of the original data which should make the next/previous functionality faster. However, your original page load time will be slower as you'll need to insert the records into the temp table so, there's a trade off.
I would imagine there's loads of other ways of doing this, if you find any that perform better than the above then let me know, it'd be great to hear from you!
And finally.... SQL Server
I couldn't end without mentioning the latest version of SQL Server and the good work Microsoft have been doing in this area. Microsoft have cottoned on to the fact that this paging functionality is now widely used and, as you can tell by this article, it isn't straight forward. They've gone out of their way to simplify this and built this functionality straight into the language making it very simple and, I would hope, a whole lot quicker than anything we can write in standard SQL.
I can't say I've had the pleasure of testing this but, according to the documentation, the feature is implemented by the introduction of two new keywords, OFFSET and FETCH NEXT and they're used in the following way:
SELECT COLUMN_ONE,
COLUMN_TWO,
COLUMN_THREE
FROM TABLE_NAME
ORDER BY PRIMARY_KEY
OFFSET 0 ROWS
FETCH NEXT 25 ROWS ONLY
This tells the database to bring back the first 25 rows. To bring back the next page, you'd increase the offset by your page size (in our example, 25). For more info, check out raresql.com.
And it's that simple.
The sooner Oracle implement this functionality the better!
1 - Forrester Consulting, “eCommerce Web Site Performance Today: An Updated Look At Consumer Reaction To A Poor Online Shopping Experience” A commissioned study conducted on behalf of Akamai Technologies, Inc., August 17, 2009
2 - For more information on subquery factoring, see www.dba-oracle.com
Location:
London, UK
Saturday, 29 September 2012
Browser Compatibility and Window Management
With more and more users turning to Chrome, Safari and Firefox for their web browsing experience and with the explosion of mobile devices now connecting to the web, the importance of making your web application accessible across browsers has never been greater.
With this in mind, I started to look into exactly what's required to make a web application accessible on all web browsers. There's plenty of blog posts on just this issue but most of them deal with differences in layout engines. In this post, I want to talk about window management namely because different browsers handle this issue completely differently and it's caught me out.
window.focus()
If your application launches new windows, maybe to show a data entry screen then at some point, you're probably going to use window.focus() in order to bring the new window to the front.
In Internet Explorer, this isn't the problem. Take the following code as an example:
<html>
<head>
<title>Untitled</title>
<script language="JavaScript" type="text/javascript">
<!--
function windowFocus(){
var wnd = window.open('','','width=200,height=100')
window.onfocus = function(){ wnd.focus(); };
}
//-->
</script>
</head>
<body>
<a href="javascript: windowFocus();">Launch Window</a>
</body>
</html>
The above code is pretty simple. When you click on the link, a new window should open. Should you try and navigate back to the original window then the new window should re-focus and be put back on top.This can be a handy function, if you absolutely need your user to respond to an event in the popup window, then you can force them too (or the user closes the window, which is responding in a way...).
The problem is this doesn't work in Chrome. And it's not a bug. It's by design. I should add it does work in Safari so it's not a WebKit issue. Essentially, Google argue that you, the developer, should not be able to play around with windows on the desktop. That's something that should only be performed by a user. Personally, I don't agree. To see the actual bug report, check here and here.
If anyone does find a way of getting this to work on Chrome, then it'd be great to hear from you. I unfortunately wasn't able to find a way.
window.open() and resizable
As it goes, the application that I'm working on does open new windows. These windows act as data entry screens and all of these windows are set to be a specific width and height. The reason for this is that we use absolute positioning on all the form controls in order to display them on screen. If we let the browser set the size of the window then it's more than likely that it'll set the size to something that'll either be too small, so scroll bars will be needed to see all of the controls, or, the window will be too large and there will be massive amounts of blank space shown. So, we set the width and height specifically to avoid these issues and then we disable the users ability to re-size the window.
To do this, when we call window.open, we use specific features that set up the window as describe, specifically we set the width, height and set the resizeable attribute to false. (See W3Schools for the window.open definition).
Here is a good example:
window.open('http://www.google.com','','resizable=0,width=200,height=100');
Again, in Internet Explorer, this all behaves exactly as you'd expect. However, in Chrome, Safari and Firefox, we have a different story. And again, it's not a bug, it's by design.
In Chrome, Safari and Firefox it's impossible to make a window non-resizeable. There's no way round this, it's just not possible. The argument is that by making a window non-resizeable, it's possible that the developer has some how messed up their screen layout, making it impossible for the user to see things that aren't on the screen. If you make the screen resizeable then you avoid this possible complication and if everything does render correctly then the user just doesn't have to resize the window and then it's no skin off off of anyone's nose. So, these browsers just ignore the resizable attribute.
I can see where the browser vendors are coming from, their argument does make sense, but, I also think it looks unprofessional if the content of a screen doesn't resize accordingly with a window resize. This then means this functionality needs to be built in to the application to maintain a professional looking user interface.
For more on this issue, check out Firefox's bug report on it found here: https://bugzilla.mozilla.org/show_bug.cgi?id=177838
Window Height
As I said before, this web application opens up windows of a specific width and height. This is achieved by using the width and height attributes of the window.open e.g.
window.open('http://www.google.com','','width=1000,height=700');
In Internet Explorer, the window opens at the specified width and height. In Chrome and Firefox, the same is true but in Safari, it's a different story. For some unknown reason, when the window opens, it opens with a height of 780px. Odd. No other browser behaves like this.
If you try to use window.resizeTo to fix the size, e.g.
window.resizeTo(1000, 700);
Once this is run, the window changes to a height of 620px. So it still doesn't behave as it should. This only seems to occur on Safari 5.1 (I haven't tested on any earlier versions). After a bit of research, I found that this is a bug, check here for more info: https://discussions.apple.com/thread/3341535?start=0&tstart=0
I find it absolutely amazing that a browser that is so recognized and so widely used suffers from such a simple bug. Again, annoyingly, there's nothing we can really do to solve this. In theory, you could loop over different parameters to window.resizeTo until the window is set to the height you require but it's far from an ideal solution. Hopefully, Apple will address this issue shortly and this problem will go away. But I wouldn't like to put money on it.
Anyway, those are a few of the experiences I've had with window management for web applications across differing web browsers. If I come across any more then I'll be sure to post them.
Enjoy.
With this in mind, I started to look into exactly what's required to make a web application accessible on all web browsers. There's plenty of blog posts on just this issue but most of them deal with differences in layout engines. In this post, I want to talk about window management namely because different browsers handle this issue completely differently and it's caught me out.
window.focus()
If your application launches new windows, maybe to show a data entry screen then at some point, you're probably going to use window.focus() in order to bring the new window to the front.
In Internet Explorer, this isn't the problem. Take the following code as an example:
<html>
<head>
<title>Untitled</title>
<script language="JavaScript" type="text/javascript">
<!--
function windowFocus(){
var wnd = window.open('','','width=200,height=100')
window.onfocus = function(){ wnd.focus(); };
}
//-->
</script>
</head>
<body>
<a href="javascript: windowFocus();">Launch Window</a>
</body>
</html>
The above code is pretty simple. When you click on the link, a new window should open. Should you try and navigate back to the original window then the new window should re-focus and be put back on top.This can be a handy function, if you absolutely need your user to respond to an event in the popup window, then you can force them too (or the user closes the window, which is responding in a way...).
The problem is this doesn't work in Chrome. And it's not a bug. It's by design. I should add it does work in Safari so it's not a WebKit issue. Essentially, Google argue that you, the developer, should not be able to play around with windows on the desktop. That's something that should only be performed by a user. Personally, I don't agree. To see the actual bug report, check here and here.
If anyone does find a way of getting this to work on Chrome, then it'd be great to hear from you. I unfortunately wasn't able to find a way.
window.open() and resizable
As it goes, the application that I'm working on does open new windows. These windows act as data entry screens and all of these windows are set to be a specific width and height. The reason for this is that we use absolute positioning on all the form controls in order to display them on screen. If we let the browser set the size of the window then it's more than likely that it'll set the size to something that'll either be too small, so scroll bars will be needed to see all of the controls, or, the window will be too large and there will be massive amounts of blank space shown. So, we set the width and height specifically to avoid these issues and then we disable the users ability to re-size the window.
To do this, when we call window.open, we use specific features that set up the window as describe, specifically we set the width, height and set the resizeable attribute to false. (See W3Schools for the window.open definition).
Here is a good example:
window.open('http://www.google.com','','resizable=0,width=200,height=100');
Again, in Internet Explorer, this all behaves exactly as you'd expect. However, in Chrome, Safari and Firefox, we have a different story. And again, it's not a bug, it's by design.
In Chrome, Safari and Firefox it's impossible to make a window non-resizeable. There's no way round this, it's just not possible. The argument is that by making a window non-resizeable, it's possible that the developer has some how messed up their screen layout, making it impossible for the user to see things that aren't on the screen. If you make the screen resizeable then you avoid this possible complication and if everything does render correctly then the user just doesn't have to resize the window and then it's no skin off off of anyone's nose. So, these browsers just ignore the resizable attribute.
I can see where the browser vendors are coming from, their argument does make sense, but, I also think it looks unprofessional if the content of a screen doesn't resize accordingly with a window resize. This then means this functionality needs to be built in to the application to maintain a professional looking user interface.
For more on this issue, check out Firefox's bug report on it found here: https://bugzilla.mozilla.org/show_bug.cgi?id=177838
Window Height
As I said before, this web application opens up windows of a specific width and height. This is achieved by using the width and height attributes of the window.open e.g.
window.open('http://www.google.com','','width=1000,height=700');
In Internet Explorer, the window opens at the specified width and height. In Chrome and Firefox, the same is true but in Safari, it's a different story. For some unknown reason, when the window opens, it opens with a height of 780px. Odd. No other browser behaves like this.
If you try to use window.resizeTo to fix the size, e.g.
window.resizeTo(1000, 700);
Once this is run, the window changes to a height of 620px. So it still doesn't behave as it should. This only seems to occur on Safari 5.1 (I haven't tested on any earlier versions). After a bit of research, I found that this is a bug, check here for more info: https://discussions.apple.com/thread/3341535?start=0&tstart=0
I find it absolutely amazing that a browser that is so recognized and so widely used suffers from such a simple bug. Again, annoyingly, there's nothing we can really do to solve this. In theory, you could loop over different parameters to window.resizeTo until the window is set to the height you require but it's far from an ideal solution. Hopefully, Apple will address this issue shortly and this problem will go away. But I wouldn't like to put money on it.
Anyway, those are a few of the experiences I've had with window management for web applications across differing web browsers. If I come across any more then I'll be sure to post them.
Enjoy.
Wednesday, 1 August 2012
ExtJS - A Review
Around nine months ago, I was looking into a potential project for work. In it's simplest form, this project involved building a web application that would mostly be built using JavaScript and that worked on all the major browsers and in particular, it must be viewable on an iPad. So, I set about searching for a JavaScript framework that would support this.
Now I class myself as quite the geek and I like to think that I know of most of the major JavaScript frameworks. JQuery, Dojo, Prototype, etc. On top of that there's a few control libraries such as ComponentArt and Obout which I'm also quite familiar with. I looked into all of these but their functionality and look and feel didn't really jump out at me. I thought I'd do a bit of research and came across a framework that I'd never come across before... Sencha's ExtJS Framework. After spending the past couple of months working nearly exclusively with the framework, I thought it'd be a good idea to share my experience with you people so that if you're in a similar position to me, trying to decide whether or not to use an unfamiliar framework, you have a bit more extra information to go on.
It's worth mentioning that I'm in no way affiliated with Sencha so this is a completely independent review.
So, what do I look for in a good framework? Well, I think there's six categories to look at:
- Functionality - Unsurprisingly, a good framework needs to do what you need it to do. If it doesn't fit your requirements then there's no point in using it.
- Performance - There's not a whole lot of use in having a framework that does everything you need it to if it takes days to do it. How well does it perform?
- Ease of use - I would say I'm proficient in JavaScript. I'm certainly no expert. I expect a framework/library to be understandable and usable by someone with my level of understanding of the language. I do not want to have to take a two month extensive course in the inner workings of JavaScript in order to use the thing.
- Documentation - Any and every good framework/library needs to have good documentation. You don't want to be stepping through code to work out how to render something. It's much more effective to look up the documentation, have a quick read and then away you go.
- Extensibility - The chances are that at some point during your development cycle, you're going to need to add to the framework in order to achieve your desired functionality. How easy is this to do?
- Support - Sometimes you just can't work something out, is the support out there to help you through these difficult times?
Functionality
ExtJS has the most extensive functionality of any JavaScript framework I've ever come across. It has the ability to create some great user interfaces with some great special effects. Want pictures flying across the screen? No problem. Want something to fade in or out? Easy. And that's just for starters. It has a whole charting module: bar, line, graph, area, scatter, radar charts can all be created with minimal fuss. Along side that you've got grids which automatically support sorting, paging, editing and grouping.
![]() |
| Charts and graphs is only a small piece of ExtJS functionality |
On top of all the controls, there's the functionality that the controls themselves bring to the table. Bar charts can just be rendered, or, you can animate them so they bounce in to position. Want to show a legend? No problem, that's in there too. Just about every time I've thought "I wonder if I can do x, y and z", I have a look and low and behold the framework supports it. It really is a very impressive framework.
Performance
With the amount of functionality that ExtJS does provide, performance is always going to be a talking point, especially when so much relies on manipulating the DOM which we all know can be slow. Now I've used ExtJS 4.0 extensively and I must say that the performance is very good. Like any programming library, there's way in which you can optimize your code so that you get the most out of it and I believe that if you do optimize then you'll be very impressed with its performance.
![]() |
| Performance of ExtJS4.0 is impressive! |
Ease of Use
ExtJS is exactly what I'd expect a good JavaScript framework to be in terms of ease of use. I simply picked it up and started to play around with it and soon got to grips with its functionality and how it can be used. Sencha provide loads of good examples ranging from the basic to the more advanced. All of their examples have their source code attached, you can simply look at the source code and work out what's going on. All of the objects and functions are logically named so the code is easy to follow. Put that together with a modern browsers JavaScript debugging capabilities and you can work out exactly how everything works and from there you can work out how to adjust the code to suit your needs.
If that isn't good enough, Sencha also provide well written tutorials on how to use the framework and how to deploy it, making it as simple as possible. If you want to check those out then have a look here.
Documentation
![]() |
| Documentation is a must for any framework |
You'd think this is one area that all frameworks would do well in, after all, documenting is just a case of writing down what everything does. You'd expect framework providers, especially ones that charge for use, would devote time to this area. However, you'll be surprised how poor the documentation is out there. jQuery is a framework that I've had a fair amount of experience with and they're pretty good with documentation, in contrast, I've also had a lot of experience with ComponentArt and they're documentation is absolutely shocking. I've wasted hours of my life trying to figure out how to use ComponentArt controls or trying to find out exactly what a certain property/method does because the documentation just simply doesn't tell you. Nine times out of ten, it's either non-existent or incomplete. You have no idea how much of a difference comprehensive documentation makes when you're trying to use a new framework.
Extensibility
Almost every time I've had to use a framework, it never quite works as I need it to so I end up modifying the source code or ideally, I build on top of the framework to add a bit of functionality to it. ExtJS recognises this and provide ways for you to override and extend objects. The framework heavily relies upon inheritance so extending and overriding controls is a very familiar concept for programmers that use object oriented concepts on a day to day basis.
Support
No matter how easy a framework is to use and no matter how good their documentation is I can guarantee at some point or the other you will come across a problem that you're struggling to solve. At this point you'll want to ask the wider world for a bit of help. Sencha have specific forums for this and for a fee you can access specific forums that are monitored by Sencha developers. ExtJS is fast becoming a widely used framework so, if you post a problem on a well known forum (say StackOverflow for example) then you'll be almost guaranteed a reply.
So... In Conclusion....
I think it's pretty fair to say that I'm a massive fan of the framework. This has blown frameworks that I have previously used out of the water. Some of the things I've managed to build in a day would have taken me months without the use of the framework. The documentation and general ease of use make developing applications with the framework a simple and effective task and because of the sheer quality of documentation, you feel your productivity increases just by using it. The thing I like the most... and this sounds kind of odd but, it just works. The quality of coding is very high. I've been using the framework on and off now for about nine months and I can count the number of problems I've come across on one hand and even then, I've been able to solve them with minimal effort.
It's not all good though, as I've stated previously, there is one big downside... upgrading and backwards compatibility. I upgraded from 4.0 to 4.1 and everything, and I do mean everything, broke. When I eventually got things working again the performance was so bad that I had to revert everything and stick with 4.0. I don't seem to be the only person that's had problems either. If you want to have a look for yourself, then you can check out the comments to Sencha's blog post about the 4.1 release here. Here's one comment that jumped out and me and summed up my frustration after a couple of days of trying to get things working after the upgrade:
"What a shocking release. An app that works without fault in 4.0.7 doesn't even show up properly in 4.1. We just got Sencha'd ... again!"
But that's the only fault I can find. If you're not worried about backwards compatibility and if the framework in its current state does what you need then I couldn't recommend it higher. It truly is a fantastic framework to work with. Just don't try upgrading.
Subscribe to:
Posts (Atom)










