PDA

View Full Version : [Solved] IE7 Throws "Invalid Argument" on 4th Grid Call via Prototype.js



cluettr
27 Jun 2007, 7:54 PM
I tested this under Firefox in the hopes of being able to troubleshoot it on my own but the error does not appear in Firefox, only IE. If I make 4 successive calls to load a grid via an Ajax.Updater the 4th call throws a javascript error Invalid Argument. This happens every time on the 4th call and on any grid in the page. This is not a publicly available website (Behind a Verizon firewell) so I can't provide a link to it. I can however provide code if that helps but the fact that it works in Firefox and not in IE tells me it is likely a bug of sorts. Possibly an issue with prototype.js.

I'm not an expert so I'll leave it to those who are to either clue me in or ask for my help in providing them info that may help them eradicate the bug.

- Rob Cluett

mystix
28 Jun 2007, 3:15 AM
which version of Ext are you on?

if you're on 1.0.1a or earlier, have you tried the yui adapter instead?
if you're on 1.1b1, have you tried ext-base.js instead?

cluettr
28 Jun 2007, 5:25 AM
Hi, Thank you for the response. The version I am running is ext-1.0.1. I haven't tried any other adapters besides the prototype.js adapter. The reason for this is because my site is built upon the prototype.js library in it's entirety. By switching to the YUI adapter I would assume I would need to rewrite much of the site so it no longer rides the prototype.js framework. It's an endeavor that I'd be hesistant to take on. I'd be quicker to forgo the extjs grid and go with something else than have to do a rewrite.

I feel the key here is that it works in Firefox and not in IE so it's not a matter of changing the adapter but a matter of determining what is happening inside the code geared to IE.

Any feedback would be appreciated.

mystix
28 Jun 2007, 6:08 AM
hmmm... you'll have to put up some sample code illustrating what you're trying to do then.

perhaps you could post a simplified test case using prototype which replicates the problem?
(remember to wrap the test code in [ code] [ /code] tags)

tryanDLS
28 Jun 2007, 7:37 AM
Starting with 1.1beta1, you should be able to use ext-base as the adapter and use your existing prototype includes (rather than the Ext adapter versions) to support your old prototype-based code.

cluettr
28 Jun 2007, 7:44 AM
Excellent! Thank you for the follow up! I did use Microsofts javascript Debugger which pointed to the following in prototype.js. I am a javascript novice, but I think the code below is merely the error handling function.



var Enumerable = {
each: function(iterator) {
var index = 0;
try {
this._each(function(value) {
iterator(value, index++);
});
} catch (e) {
if (e != $break) throw e;
}
return this;
},

I'm uploading ext-1.1-beta1 now and will see if this resolves the issue. I assume I only need to remove the js include for the adapter file and replace it with the ext-base.js?

tryanDLS
28 Jun 2007, 7:58 AM
I'm uploading ext-1.1-beta1 now and will see if this resolves the issue. I assume I only need to remove the js include for the adapter file and replace it with the ext-base.js?
Yes, and you might want to include your own (more current) versions of the base prototype/scriptaculous files. I'm not sure if the Ext versions of the files were tweaked to deal with any issues - you might want to do file compares between them and the real versions.

cluettr
28 Jun 2007, 8:47 AM
Thank you TryanDLS...

So that I am clear... The "Adapters" contain a copy of the prototype.js and sriptaculous.js files? My inlcudes were set up such that I had the prototype.js and sriptaculous.js files included independently and then the adapter. I hope that made sense.

Regarding the issue I am experiencing, do you feel the ext-base.js will clear the condition or are we taking a shot at it?

cluettr
28 Jun 2007, 9:05 AM
I modified my code so it uses 1.1-beta1 and the problem still exists.


<script type="text/javascript" src="../_javascript/ext-1.1-beta1/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../_javascript/ext-1.1-beta1/ext-all.js"></script>

cluettr
28 Jun 2007, 10:39 AM
Could this be some sort of memory leak? Odd that on every 4th call it happens...

tryanDLS
28 Jun 2007, 3:10 PM
Have you tried downloading 1.1beta? At this point, I think we need to seem some sample code that illustrates the problem.

cluettr
28 Jun 2007, 4:10 PM
Hi TryanDLS. I agree. I'm sorry I didn't post code sooner.

I in fact modified my code to use the Ext specific functions as opposed to prototype.js. I wanted to be sure I was not running into an issue with prototype.js. Having done so I still have the issue. Here is the code I am using...

This function basically sets a div's visibility to true (aka displays the pop up menu):


function showMenuRight()
{
var myelement = Ext.get(selector_menu_right)
myelement.setVisible(true, true);
}

This function is used so that when the user clicks on a menu option in the above mentioned div that it loads my grid:


function changeMenuRight(option)
{
var um = Ext.get('selector_menu_right_contents').getUpdateManager();
um.loadScripts=true;
um.update('contents_selector_right_' + option + '.php');

}

This is the page containing the grid that is called in ChangeMenuRight. Again I click the link that fires this 4 times and then I get the error and can no longer click it again:



<script>
var GridUI = function() {

var ds; //hold our data
var grid; //component
var columnModel; // definition of the columns
var dsContext;
var gridForm;


function setupDataSource() {
ds = new Ext.data.Store({

proxy: new Ext.data.HttpProxy({url: '_xml/xml_grid_contacts.php'}),

reader: new Ext.data.XmlReader({
record: 'Item',
totalRecords: 'TotalResults',
id: 'BAID'
}, [
'newname', 'phoneoffice','phonemobile','phonehome'
])
});



ds.load({params:{start:0, limit:22}});
}

function getColumnModel() {
if(!columnModel) {
columnModel = new Ext.grid.ColumnModel(
[
{
header: 'Name',
width: 250,
sortable: true,
dataIndex: 'newname'
},

{
header: 'Office',
width:100,
sortable: true,
dataIndex: 'phoneoffice'
},
{
header: 'Mobile',
width:100,
sortable:true,
dataIndex: 'phonemobile'
},
{
header: 'Home',
width:100,
sortable: true,
dataIndex: 'phonehome'
}
]
);
}
return columnModel;
}

function buildGrid() {
gridForm = new Ext.BasicForm(
Ext.get("updategrid"),
{

}
);

grid = new Ext.grid.EditorGrid(
'contactsgrid',
{
ds: ds,
cm: getColumnModel(),
autoSizeColumns: true,
selModel: new Ext.grid.RowSelectionModel({singleSelect:true})
}
);


grid.render();

var gridFoot = grid.getView().getFooterPanel(true);

// add a paging toolbar to the grid's footer
var paging = new Ext.PagingToolbar(gridFoot, ds, {
pageSize: 22,
displayInfo: true,
displayMsg: 'Displaying contacts {0} - {1} of {2}',
emptyMsg: "No contacts to display"});

var gridHeaderPanel = grid.getView().getHeaderPanel(true);
var tb = new Ext.Toolbar(
gridHeaderPanel,
[
{
text: 'Add Row',
handler: function() {
ds.add(
new Ext.data.Record(
{
description:'new task',
completed: false,
duedate: new Date(),
priority:'B',
context:'2',
newRecord:true
}
)
)
}
},
{
text: 'Delete Row',
handler: function() {
selectedRow = grid.getSelectionModel().getSelected();
if(selectedRow) {
gridForm.submit(
{
waitMsg: 'Deleting row, please wait...',
url:'http://0.0.0.0:3000/admin/deleterow',
params:{rowid:selectedRow.data.description},
success:function(form, action) {
ds.remove(selectedRow);
},
failure: function(form, action) {
alert('Oops the delete did not work out too well!');
}
}
);
}
}
} ,
{
text: 'Save Changes',
handler: function() {
jsonData = "[";

for(i=0;i<ds.getCount();i++) {
record = ds.getAt(i);
if(record.data.newRecord || record.dirty) {
jsonData += Ext.util.JSON.encode(record.data) + ",";
}
}

jsonData = jsonData.substring(0,jsonData.length-1) + "]";

console.info(jsonData);

gridForm.submit(
{
waitMsg: 'Saving changes, please wait...',
url:'http://0.0.0.0:3000/admin/updategrid',
params:{data:jsonData},
success:function(form, action) {
alert('Congrats! Your changes were saved!!!!');
},
failure: function(form, action) {
alert('Oops the delete did not work out too well!');
}
}
);
}
}
]
)
}

function destroyGrid() {
grid.destroy(true);
}

return {
init : function() {
setupDataSource();
buildGrid();
},

getDataSource: function() {
return ds;
}
}
}();

Ext.BLANK_IMAGE_URL = 'https://enss.verizon.com/index.php';
Ext.onReady(GridUI.init, GridUI, true);

</script>

<?php require_once ("_includes/variables.inc"); ?>
<?php require_once ("_classes/user.class.php"); // class: user ?>

<?

$user = new user($baid);
$screen_width = $user->getValue('screen_width_avail'); // used to adjust panels to width of users screen
$screen_height = $user->getValue('screen_height_avail'); // used to adjust panels to height of users screen

?>

<form id="updategrid"></form>

<table cellspacing=0 cellpadding=5>
<tr>
<td>
<table width="450px" cellspacing=0 cellpadding=0>
<tr>
<td colspan=2>
<? include_once ('contents_selector_right_menu_global.php'); ?>
</td>
</tr>
<tr>
<td colspan=2 bgcolor=#FFFFFF width="2" valign="top">
<img SRC="/images/spacer_transparent.gif" width="2" height="12"></td>
</tr>

<tr>
<td colspan=2>
<div id="contactsgrid" style="width:464px; height:<?= $screen_height - 241 ?>px; border: 1px solid #CCCCCC; overflow:hidden;" class="ygrid-mso"></div>
</td>
</tr>
<tr>
<td colspan=2 height="1" valign="top">
<img SRC="/images/spacer_transparent.gif" width="1" height="1">
</td>
</tr>

<tr>
<td>
Retired/Former Employees
</td>
<td>
Manage Access Rights
</td>
</tr>
<tr>
<td>
Retired/Former Employees
</td>
<td>
Manage Access Rights
</td>
</tr>
<tr>
<td>
Retired/Former Employees
</td>
<td>
Manage Access Rights

</td>
</tr>
</table>
</td>
</tr>
</table>

cluettr
28 Jun 2007, 4:27 PM
Here is what it is choking on since moving to Ext and off of prototype.js:

Invalid Argument on ss=_2.createStyleSheet() in ext-all.js
'cell' is null or not an object on ct=ts.cell in ext-all.js

tryanDLS
28 Jun 2007, 4:45 PM
I would suggest stripping that down to a simpler example and also using ext-all-debug.js so you get a better idea of where the error is. You're not rebuilding that structure on every click are you? - that would cause duplicate elements - and maybe run into an IE issue related to too many dynamic stylesheets.

Also, why is your BLANK_IMAGE_URL pointing to a php page, rather than a local copy of s.gif?

cluettr
28 Jun 2007, 5:41 PM
I would suggest stripping that down to a simpler example and also using ext-all-debug.js so you get a better idea of where the error is.

OK, I will give this a whirl.


You're not rebuilding that structure on every click are you? - that would cause duplicate elements - and maybe run into an IE issue related to too many dynamic stylesheets.

I am and I agree that it's the wrong way but I honestly am not sure what the right way would be. Am I to place this code in the header of the hosting page and then build the grid with each call? I guess I am a little confused on the best approach here.


Also, why is your BLANK_IMAGE_URL pointing to a php page, rather than a local copy of s.gif?

I'm not sure. I read somehere to point it to a page which worked so I assumed it was an acceptable method. I'll revise.

cluettr
28 Jun 2007, 5:47 PM
using ext-all-debug it points to:


createStyleSheet : function(cssText){
var ss;
if(Ext.isIE){
ss = doc.createStyleSheet();
ss.cssText = cssText;
}else{

Looks like you might be on to it with the stylesheet reference...

tryanDLS
28 Jun 2007, 6:45 PM
If you can, you should build the grid once and just reload on subsequent clicks. It would probably make more sense to have the grid building code in your main page, rather than making a request to load the grid building script, which then has to make another request to load the data.

If you're going to run all that code again, you need to destroy the previous objects - there are threads discussing this.

cluettr
28 Jun 2007, 7:03 PM
I'm with you on this. My inexperience is showing : )

Please help me understand. If I were to build the grid once using the Ext.onReady(GridUI.init, GridUI, true); statement how would I then call upon it to display when and where I need it? Is it a matter of something like setting the innerhtml of a div to the grid that's already built and in memory? At the moment I call a function which populates the div with the code above. As you can tell I'm missing something here on good practices.