If you follow my blog, you’ve noticed that I constantly talk about ExtJS. I use it extensively at my office, and I know the API (for version 2.2.1) about as well as anyone not working for their company.
I recently came across a situation that has me frustrated because ExtJS doesn’t seem to have a built-in utility to solve my problem. Obviously, I can code something custom. . . but I’m frustrated because it’s more work than necessary and far from elegant.
The story begins about a year ago. My company (GFX International) has been working on an enterprise software solution for some time, and the developers wrote a method using jQuery (v1.2.6) to parse an XHTML server response returned during 500 errors. The idea is to create a popup window with the error message (one line of code), which is parsed from a rather long XHTML document (the default 500 error page returned by .NET).
The jQuery method is actually quite elegant and works perfectly.
getErrorText: function (response) {
var errorCode = response.status;
if (errorCode == 401 || errorCode == 403) {
return 'You are not permitted to perform this action.';
}
//the custom error page has a DIV tag with this ID
var errorMessage = $(response.responseText).find("div#errortext").html();
if (!errorMessage) {
//in DEBUG mode, we don't use custom error page.
errorMessage = $(response.responseText).find("h2").html();
}
return errorMessage;
}
Over the past 9 months since I was hired as our Web Developer, I’ve redesigned the UI of this application so that it is built almost entirely on ExtJS widgets and extensions. The problem with the above method is that this now is the only place in the application where we use jQuery – meaning we have to include the jQuery library for only 2 lines of code.
My initial thought was: “I’ll just re-write this method using ExtJS and remove our dependency on jQuery!” Sounds easy enough, but in reality it’s actually a pain in the ass for several reasons.
First, the response variable returned during the 500 error is not a valid XML document. . . it’s not even valid HTML. The .NET framework generates a detailed error message contained within HTML tags, but after closing the final HTML tag is appends a stack of executed code lines leading up to the error. This section of appended data breaks the XML/HTML validity, essentially making it impossible for me to just throw the response variable into an DOMparser() object.
Second, ExtJS has no built-in utility for parsing a generic XML string for a specified value. In jQuery, every variable called by $(someVariable) is checked (1) to see if it’s a string, and if so (2) to see if it is HTML code (using a regular expression match). If jQuery believes your variable to be an HTML chunk, it runs it through a clean() method to convert the HTML string into DOM nodes (getting rid of any junk. . . *cough* .NET stack trace).
ExtJS does have a similar utility: Ext.query(selector, root). Unfortunately for me, this means that I can only parse an exisiting DOM node. Since my response variable isn’t part of the DOM (or even formatted as a proper DOM element) this method doesn’t really help me until I solve the first problem.
After posting this problem on the ExtJS message board, a member of their support team suggested that I simply build a regular expression to parse my response object. Obviously, this would solve my problem. However, it’s not an elegant solution; regular expressions are ugly at best (they are in fact my nemesis), and this solution fails to solve similar problems faced by other ExtJS users (I assume others have encountered this problem). The bottom line is that this type of utility would make a reasonable and very useful addition to the ExtJS library. . . so why isn’t one available?
Doesn’t it seem obvious?
var d = document.createElement(“div”);
d.innerHTML = response.responseText;
errorMessage = Ext.DomQuery.selectValue(“div#errortext”, d);
And if it is valid XML, then you can use responseXML and DomQuery will understand it!
I’ve faced similar problems. My solution was to actually put the response into DOM.
Something like:
Ext.get(‘proxy-element’).update(the-response);
And then I am able to use: Ext.DomQuery. I did not think about elegance of my solution… perhaps I should?
@extidiot: That is a nice solution, but the problem is that (1) I’m not returned valid XML code, and (2) the responseText attribute has an HTML tag, which can’t be a child of DIV. Thus Ext.DomQuery.selectValue() doesn’t seem to work – it actually sets the value to “undefined”.
@wregen: Also a nice solution. Same problem though…
The problem lies in the fact that my response.responseText value isn’t valid XML and needs to be cleaned.
I’m looking into forcing .NET to return the error differently, so I’ll let you know what happens.
I solved this by using simple regular expressions, though I’m still unhappy ExtJS doesn’t have a built-in utility to clean my DOM string (the cause of the problem).
*edit: I can’t post the regular expression because WordPress interprets it as HTML. Check the link in the post to the ExtJS forum and you’ll see my solution.
http://support.microsoft.com/kb/306355
Now your error page can have valid HTML, XHTML or whatever you want in it. You can even make a nice user-friendly message instead of an error dump.