At some point I was given the task to build a working filter for our Violations Tables and it had to work for Firefox as well as IE. The filter needs to transform before the main three tables because it determines what can be shown in them. I experienced a number of difficulties with synchronizing the different xml transforms since there are several going on on this page, and some needed to be done before others. I succeeded but my solution was not as nice (code wise) as I would have liked. Later on, Firefox finally started supporting asynchronous xml and xsl downloads so I could tell better when things would finish instead of polling the ready state. Click on the image to the right to see my end result better.
Here's a snippet of my filter code so you'll be able to do that same: (new way)
function setXML(sourceURL) {
this.xmlSource = sourceURL;
if(window.ActiveXObject)
{
treeXml = new ActiveXObject('Microsoft.XMLDOM');
treeXml.async = false;
treeXml.load(sourceURL);
this.XML = treeXml;
}else{
xmlhttp=new XMLHttpRequest();
//xmlhttp.onreadystatechange=xml_Change;old way
xmlhttp.open("GET",this.xmlSource,true);//"sourceURL"
xmlhttp.overrideMimeType("text/xml");
xmlhttp.send(null);
setXML();//new way
}
}
ViolationsFilterTable.prototype.setXML = setXML;
function setXML(){
var xmlTree = xmlhttp.responseXML;
lookupObject('filterTable').setMyXML(xmlTree);
lookupObject('filterTable').setXmlLoaded(true);
lookupObject('filterTable').initFilterTableFinal();//now transform in Firefox
call loadXSL(); (now with less waiting and polling) }
(old way) function xml_Change()//function for finished loading XSL
{
if (xmlhttp.readyState==4)//loaded = 4
{
if (xmlhttp.status==200)//status ok = 200
{
var xmlTree = xmlhttp.responseXML;
lookupObject('filterTable').setMyXML(xmlTree);
lookupObject('filterTable').setXmlLoaded(true);
lookupObject('filterTable').initFilterTableFinal();//now transform in Firefox
//call loadXSL(); (old way)
}
}
}
Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts
Friday, June 11, 2010
Thursday, June 10, 2010
Tutorial: Special Concerns With CSS and JavaScript
If you want to edit existing CSS and JavaScript, I wish you the best. Here are some guidelines I have come up with for myself to try and minimize collateral damage. You see every css entry or JavaScript class might only be used in one place or it could be used in a thousand places. Sometimes if you change the padding or the position the tiniest bit it will throw something off someplace else.
My best suggestion is to build a class that will stand the test of time and then don't touch it. sometimes its even better to make a new specialized class rather than alter existing ones that could break countless pages. Also feel free to comment in the css if you need to to remember which class that is or which classes it goes with to match baselines.
If it is impossible to avoid editing your existing CSS or JavaScript classes, due to one reason or another(as is too frequently the case), I recommend doing a search over the app to see where it is used. If possible, test each and every one of the unique looking cases after you change whatever it is you need to change.
Some of the more benign (meaning they usually don't mess up where things are) things to change are:
background styles
color
cursor
font-family, font-size, other font-stuff
text-shadow
most white-space ones overflow:hidden
The moderately powerful (or dangerous) ones are:
border(border affects the width in Firefox)
left
text-align
text-indent
overflow:visible
padding
position:relative
top
white-space:nowrap(this can cause it to overflow
The very powerful ones are:
display:block,table-row, or none
float(necessary to line up divs or give spans widths in Firefox)
height
line-height
margin(in IE it can cascade)
position:absolute
width
vertical-align
Internet Explorer does not interpret everything in JavaScript the same way as other browsers. It has unique methods that the others do not have, and it lacks some things that the others DO have. Most of the time, you can fortunately put code in just two groups: IE and non IE.
In order to specify that you want code to execute in IE only or not there is an easy shortcut.
We just attempt to make a proprietary IE JavaScript object, also known as an ActiveXObject?
if(window.ActiveXObject)//IE code
{
}else{//Other browsers code
}
Now you might be wondering which things are IE only and which are Firefox. Most normal methods are supported in both. But here's a link to a nice list of the DOM methods
If you stick to the the DOM to do your work you should be ok in most cases but the following are some incompatible differences between browsers.
My best suggestion is to build a class that will stand the test of time and then don't touch it. sometimes its even better to make a new specialized class rather than alter existing ones that could break countless pages. Also feel free to comment in the css if you need to to remember which class that is or which classes it goes with to match baselines.
If it is impossible to avoid editing your existing CSS or JavaScript classes, due to one reason or another(as is too frequently the case), I recommend doing a search over the app to see where it is used. If possible, test each and every one of the unique looking cases after you change whatever it is you need to change.
Some of the more benign (meaning they usually don't mess up where things are) things to change are:
background styles
color
cursor
font-family, font-size, other font-stuff
text-shadow
most white-space ones
The moderately powerful (or dangerous) ones are:
border(border affects the width in Firefox)
left
text-align
text-indent
overflow:visible
padding
position:relative
top
white-space:nowrap(this can cause it to overflow
The very powerful ones are:
display:block,table-row, or none
float(necessary to line up divs or give spans widths in Firefox)
height
line-height
margin(in IE it can cascade)
position:absolute
width
vertical-align
Internet Explorer does not interpret everything in JavaScript the same way as other browsers. It has unique methods that the others do not have, and it lacks some things that the others DO have. Most of the time, you can fortunately put code in just two groups: IE and non IE.
In order to specify that you want code to execute in IE only or not there is an easy shortcut.
We just attempt to make a proprietary IE JavaScript object, also known as an ActiveXObject?
if(window.ActiveXObject)//IE code
{
}else{//Other browsers code
}
Now you might be wondering which things are IE only and which are Firefox. Most normal methods are supported in both. But here's a link to a nice list of the DOM methods
If you stick to the the DOM to do your work you should be ok in most cases but the following are some incompatible differences between browsers.
- myObject.getAttribute("className"); for IE, myObject.getAttribute("class"); for Firefox
- Getting the Size of the Viewport, or Browser Window: document.documentElement.clientWidth;(or Height) for IE, window.innerWidth; for Firefox
- Event codes! All event codes are differently handled and event is global automatically in IE and not in any other browsers. event.srcElement versus event.target for Firefox to get the thing that started the event. In order to pass event along for firefox to use you must include it in the root method. I.e.
Run like the Wind - To get keyCodes from events use our allEve(event).key; method in Utils.js which works in all browsers
- After you do a var someNodes = selectNodes(yourXML or XSL) you must use someNodes.item(x); for IE and someNodes[x] for Firefox
- When you create a DOM element Firefox now requires you to declare its name-space: document.createElementNS("",'div'); but no other browser supports this.(yet) use document.createElement("div"); for most
- In IE you can easily make a node from a String like this openNode = '
false '; using our handy dandy createNewXmlNode(openNode) function. In Firefox you must build it from scratch with lots more code. - instead of using .text .innerText, or .textcontent, instead use .firstChild.nodeValue which will work for both browsers
- appendchild works in both but it will not overwrite things so you must remove child first
- Using appendChild in Firefox on data that has been inserted via innerHTML will give you dead HTML that you cannot interact with. Use a floating/modal div to display form inputs instead if you can.
- font webdings only works in IE. The chars for arrows are 4 and 6. For Firefox you must use the actual HTML char values: '►' and '▼'
Wednesday, June 9, 2010
Exporting to Excel in Multiple Windows
In this article I'm going to talk about how to export to excel using Java, JavaScript and XML to multiple windows. I'll also show how this can be done from Adobe Flex pages. At the end I'll provide some code examples of my own of how to do the same thing using mainly Java
My company needed a way to export tables of varying sizes (and complexity) to excel. I did some research and found that the best way to do this is to group the XML value in HSSF rows and then write it out to an excel file. The added problem came up that even if you do this, sometimes users like to edit excel files they see, and without closing them they then go and open a new one on a different page. Obviously we didn't want their information to be lost, so we had to come up with a way to open multiple pages, or the same page again and again in multiple windows. Additionally, our clients wanted to be warned prior to waiting forever, if the download was too large and to have the option of only seeing the first 2000 entries or so.
So I came up with the following solution in JavaScript and the following solution: Example of Excel Export in JavaScript
And in the following jsp/java part, prior to invoking it we create a random number and append it to the file name, thus creating a unique window. Another option if you prefer is using the time stamp or a counter of some sort. Random number generation and Function Call Example
Lastly, for your use, this is how to export to excel in java: Java Example of "Table to Excel"
or with the Java on a JSP file: JSP Example of "Table to Excel"
and if you have only wish to display the certain items from the xml, you can package an array and send it like this: Javascript Prep for Excel
Lastly, like I promised, I'll show you how to accomplish this from Adobe Flex:
Firstly, the call looks something like this in the mxml: click="Utils.loadDGInExcel(orderBatches,'Order Batch',0,8);"
Firstly in our Flex you need to prepare the information into an HTML table format
private static var urlExcelExport:String = "openExcelTable";
public static function loadDGInExcel(dg:DataGrid,documentName:String,startPos:Number,colNum:Number):void {
var arrayToExport:Array = convertDGToHTMLTable(dg,startPos,colNum);
ExternalInterface.call(urlExcelExport,documentName,arrayToExport);
}
How to convert a Datagrid's Data to HTML format
It might look complicated but it is a good example of how to get information from ItemRenderers inside of a DataGrid with normal cells and Item Renderer cells. you will obviously have to adapt it to your own needs as your DataGrid will be shaped different. We had to do one other one where we also had to convert specialized components but I'll omit that here unless someone asks for it. I found that the key is to do this differently:
else if(dg.dataProvider.getItemAt(j) is OrderBatchTO && dg.dataProvider.getItemAt(j).status is OrderBatchStatusTO) {
str2[m] = dg.dataProvider.getItemAt(j).status.longName;
}
you need to use the "is" function which is similar to the "as" function in other languages.
My company needed a way to export tables of varying sizes (and complexity) to excel. I did some research and found that the best way to do this is to group the XML value in HSSF rows and then write it out to an excel file. The added problem came up that even if you do this, sometimes users like to edit excel files they see, and without closing them they then go and open a new one on a different page. Obviously we didn't want their information to be lost, so we had to come up with a way to open multiple pages, or the same page again and again in multiple windows. Additionally, our clients wanted to be warned prior to waiting forever, if the download was too large and to have the option of only seeing the first 2000 entries or so.
So I came up with the following solution in JavaScript and the following solution: Example of Excel Export in JavaScript
And in the following jsp/java part, prior to invoking it we create a random number and append it to the file name, thus creating a unique window. Another option if you prefer is using the time stamp or a counter of some sort. Random number generation and Function Call Example
Lastly, for your use, this is how to export to excel in java: Java Example of "Table to Excel"
or with the Java on a JSP file: JSP Example of "Table to Excel"
and if you have only wish to display the certain items from the xml, you can package an array and send it like this: Javascript Prep for Excel
Lastly, like I promised, I'll show you how to accomplish this from Adobe Flex:
Firstly, the call looks something like this in the mxml: click="Utils.loadDGInExcel(orderBatches,'Order Batch',0,8);"
Firstly in our Flex you need to prepare the information into an HTML table format
private static var urlExcelExport:String = "openExcelTable";
public static function loadDGInExcel(dg:DataGrid,documentName:String,startPos:Number,colNum:Number):void {
var arrayToExport:Array = convertDGToHTMLTable(dg,startPos,colNum);
ExternalInterface.call(urlExcelExport,documentName,arrayToExport);
}
How to convert a Datagrid's Data to HTML format
It might look complicated but it is a good example of how to get information from ItemRenderers inside of a DataGrid with normal cells and Item Renderer cells. you will obviously have to adapt it to your own needs as your DataGrid will be shaped different. We had to do one other one where we also had to convert specialized components but I'll omit that here unless someone asks for it. I found that the key is to do this differently:
else if(dg.dataProvider.getItemAt(j) is OrderBatchTO && dg.dataProvider.getItemAt(j).status is OrderBatchStatusTO) {
str2[m] = dg.dataProvider.getItemAt(j).status.longName;
}
you need to use the "is" function which is similar to the "as" function in other languages.
Alpha Search Tree for Large Amounts of Data
To start out, I'd like to share how to make an Alpha Search Tree in XSLT and do it for Firefox and IE. At my work I was given a problem. We had a table with a thousand or more records that was taking around 42 seconds to load on average on IE6. It wasn't much better in IE7. Our customers only use those browsers so I researched the problem and found a way to get it to load in 2.
First off, I examined the load times using the excellent Firebug plug-in and the Charles web debugging proxy and I found that the xml, while large, was not taking more than half a second to load. Also the page and other parts were likewise loading quickly so I knew that the problem lay on the front end. I originally suspected that the XML transform was at fault so I cut out pieces and found that the XML transform was being completed in one second or less. Therefore, the only thing left was the browser's display time for large amounts of HTML data. In order to get it to display less, we either had to add a search filter, or some other kind of filter.
As a preliminary step, since we had built an Alpha Search Tree, I proceeded to make it only load onto the page the items who matched the first letter (or number) detected. By only loading to the page one letter at a time, we cut load times to a 20th of their original size.
Here are some of the code examples of how this is accomplished: http://graphix.bizland.com/js/CheckLetters.txt
http://graphix.bizland.com/js/SetLetter.txt
Firstly we need to build a list of indexed letters corresponding to the first letters of the Items to be displayed in our list so that we can build the menu:
You'll notice in here that we use the LETTER_DIV to store the list of letters we have encountered so far and we have built a group of them with the id being the same on the elements as the letters themselves.
The showLetter function is called when we click on a letter and it adds the current letter to the xml and removes the previous one selected.
Now once we have this list from the XML, we can run the transform using some XSL and JavaScript combined.
Here's a link to the XSL since its too large to display here conveniently: http://graphix.bizland.com/xsl/AlphaSearchTree.txt
The crucial parts are at the beginning with the letter selected by the user part and later on this filtering line:
xsl:when test="mv:toUpper(substring(Name,1,1))=mv:toUpper(substring($firstLetter,1,1)) or mv:toUpper(substring(../Name,1,1))=mv:toUpper(substring($firstLetter,1,1)) or /ClientSummarySet/selectAll or mv:isNum(substring(Name,1,1),substring($firstLetter,1,1)) "
Which makes sure we only transform rows where the name starts with the same letter and we end up with something like this:
First off, I examined the load times using the excellent Firebug plug-in and the Charles web debugging proxy and I found that the xml, while large, was not taking more than half a second to load. Also the page and other parts were likewise loading quickly so I knew that the problem lay on the front end. I originally suspected that the XML transform was at fault so I cut out pieces and found that the XML transform was being completed in one second or less. Therefore, the only thing left was the browser's display time for large amounts of HTML data. In order to get it to display less, we either had to add a search filter, or some other kind of filter.
As a preliminary step, since we had built an Alpha Search Tree, I proceeded to make it only load onto the page the items who matched the first letter (or number) detected. By only loading to the page one letter at a time, we cut load times to a 20th of their original size.
Here are some of the code examples of how this is accomplished: http://graphix.bizland.com/js/CheckLetters.txt
http://graphix.bizland.com/js/SetLetter.txt
Firstly we need to build a list of indexed letters corresponding to the first letters of the Items to be displayed in our list so that we can build the menu:
The showLetter function is called when we click on a letter and it adds the current letter to the xml and removes the previous one selected.
Which makes sure we only transform rows where the name starts with the same letter and we end up with something like this:
Subscribe to:
Posts (Atom)


