PDA

View Full Version : [ext-basex/$JIT 4.0 adapter extensions] Ajax enhancements and more.



Pages : [1] 2

hendricd
26 Dec 2007, 2:00 PM
ext-basex 4.0 available.

ext-basex 3.0 (and above) is now available on Google Code (http://code.google.com/p/ext-basex/) (SVN (http://code.google.com/p/ext-basex/source/browse)).

A demonstration (http://demos.theactivegroup.com/?demo=basex&script=flickr) of ext-basex/$JIT in action.

Ext-Base adapter extensions v2.3 (LGPL), 3.x (GPL).

The attached script file adds:

new lib.Ajax features (some were already available here (http://extjs.com/forum/showthread.php?p=52350#post52350)( in localXHR.js)
cross-Browser Function/Array/String/Object iteration (compatible with Javascript 1.6s' Array.forEach).


Ext.lib.Ajax.
New config options (can be passed down from a higher level (ie. Ext.data.Connection) implementation.):
{
async : true/false, // Synchronous Request support.
userId: 'JohnDoe', // HTTP Authentication available on each request
password:'inTheClear',
queue : {name: 'chat', priority : 1 } //dynamic queue creation
}

Ajax Requests can also be made without a web-server (ie local file systems) via HTTP-Status-200 emulation.

Ext.lib.Ajax joins the Ext Event system (implements util.Observable). The following events added:

request - (cancellable) Raised just before any passed headers, post content have been serialized.
beforesend - (cancellable) Raised just after all headers, parameters, and content have been serialized and just before the XHR.send occurs.
response - (cancellable) Raised after any response is received, but before any of the success/failure callbacks are made. (Use this to intercept each response for debugging, etc)
exception - (cancellable) Raised after any non-successful HTTP status is recieved, but before any of the other internal success/failure callbacks are made.
abort - Raised any time a forceful abort is issued
timeout - Raised any time an asynchronous request times out.
readystatechange - Raised each time the XHR objects' readyState changes
status:n - Raised anytime a specific httpStatus is returned by the requested server

onStatus/unStatus Event methods. Specific HTTP Status codes may be trapped via cancelable eventListeners. Returning false from an onStatus Handler prevents further function calls/events from being made by the Ajax request stack.

Ext.lib.Ajax.onStatus([403,401],sessionTimeoutHandler,myApp)Alternatively, individual handlers may be assigned using the traditional Observable syntax:

Ext.lib.Ajax.on('status:403', sessionTimeoutHandler, myApp); Note: Ext.lib.Ajax is still implemented as a singleton object, thus any event handlers defined at this level are global to all Ajax requests.


For IE7, optionally force the older ActiveX XMLHttpRequest implementation (permits local file access for IE7).
Ext.lib.Ajax.forceActiveX = true; Replaceable Form encoder support. The Form-POST/Parameter encoding function may be changed at runtime to support non-standard (other than the default: encodeURIComponent) character encoding/encryption:

Ext.lib.Ajax.encoder = escape;
or
Ext.lib.Ajax.encoder = myEncoderFn; //function that returns an encoded string
Then, any form serialized by Ext.lib.Ajax.serializeForm can use a custom encoding strategy.


Proper library placement is key. In order for lib.Ajax to get Observable support, ext-basex.js must be placed after the ext-base.js adapter and the Ext javascript module that provides Ext.util.Observable. For most installations, this will be either ext-all[-debug].js or ext-core.js. Including it before these modules (although fully functional) will not permit lib.Ajax to generate the events described above.

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Your Page for ExtJs 2.0</title>
<link rel="stylesheet" type="text/css" href="../resources/css/ext-all.css" />
<script type="text/javascript" src="../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext-all.js"></script>
<script type="text/javascript" src="../ext-basex.js"></script>
</head>
A simple Ajax debugging harness example:


var log = Ext.log;
var AjaxDebugger = {
request: function( connection, method, url, callback, postData, options ){log(['request',url,postData]);}
,response: function( connection, response, callback, isAbort) { log(['response',response.responseText]);}
,exception: function( connection, response, callback, isAbort) { log(['HTTPException', connection.fullStatus.statusText ]);}
,abort : function(){log('Request was aborted');}
,timeout : function(){log('Request timed out');}
,readystatechange : function(connection){ log('readystatechange', connection.conn.readyState);}
};
Ext.lib.Ajax.on(AjaxDebugger );
Ext.lib.Ajax.suspendEvents() / resumeEvents() to suppress/enable events.
Note: In this version, the request method (GET, POST, PUT, DELETE, and other HTTP verbs) specified by the options.method config takes precedence over any method derived by the Ajax stack .

lib.Ajax Request Queues[ new for 2.3 ]. Ajax requests can now be made with named queues; each with specific execution priority. See this post (http://extjs.com/forum/showthread.php?p=140474#post140474)for more details.

Global forEach iterations:


forEach([1,2,3],console.log); or [1,2,3].forEach(console.log); //Gecko already has the later form.
forEach(object,console.log);
"This is a test".forEach(console.log); or forEach("This is a test",console.log); //character enumeration


11/10/2008 -- ext-basex 3.1 now:
-- includes $JIT. Read more about it here (http://extjs.com/forum/showthread.php?p=225658#post225658).
-- adds Ext.clone(deep) method. Clone anything (string, number,date, arrays, even complex objects)!
-- new Array prototypes: atRandom, unique, map, include, filter, compact, flatten, forEach, clone

[Update] 6/3/2009 -- ext-basex 3.4RC1 (for Ext 2.x, 3.x) is now available. See the Ext 3.0 extensions thread (http://extjs.com/forum/showthread.php?p=338524#post338524)for more on new features.

[Update] 10/28/2009 -- ext-basex 4.0 and $JIT 1.2 are now shipped with debug versions, jsb2 build support, and Ext Core 3 compatibility.

Update: A quick Tutorial on how to use $JIT is also available here (http://extjs.com/forum/showthread.php?p=377251#post377251).

Download Note: the current vBulletin config gzips attachments which [U]IE hates. Download this with Firefox (or other browser) instead of IE.

tof
27 Dec 2007, 1:34 AM
Good !
I if can add a suggestion :


Ext.Ajax.addEvents({requestaborted:true});
Ext.override(Ext.data.Connection, {
abort : function(transId){
if(transId || this.isLoading()){
Ext.lib.Ajax.abort(transId || this.transId);
this.fireEvent('requestaborted', this, this.transId);
}
}});

I personnally use this function/event for a "cancel" button.

hendricd
27 Dec 2007, 6:01 AM
@tof - Yes, although that is for (Ext.data.Connection) the next-level up in the stack, it's a useful addition (also found here (http://extjs.com/forum/showthread.php?p=90942#post90942)).

prophet
29 Dec 2007, 1:07 PM
Great stuff! I think this will come in handy.

galdaka
29 Dec 2007, 3:40 PM
Excellent work!!

@Ext team: Part of this features will be included in future versions of Ext?

Thanks for share!!

DigitalSkyline
31 Dec 2007, 9:22 AM
Thanks, this is proving to be both useful and necessary for handling session timeouts... great!

... only problem I foresee is having to recode if this stuff gets in to Ext 2+...
well such is life.


PS Doug - have you always coded with preceding commas? Just a minor annoyance, To each their own!

DigitalSkyline
31 Dec 2007, 1:16 PM
Doug -
I'm trying to override the default behavior on a single request

Doing this doesn't seem to work:
Ext.lib.Ajax.onStatus([403,401],sessionTimeoutHandler,myApp)

later:
Ext.lib.Ajax.unStatus([403,401]) //didn't fix it
Ext.lib.Ajax.onStatus([403,401],anotherTimeoutHandler,myApp)

still calling sessionTimeoutHandler ...

Any idea why?

hendricd
31 Dec 2007, 1:34 PM
You'll need to treat it like any other 'un':



Ext.lib.Ajax.unStatus([403,401],sessionTimeoutHandler,myApp)Ultimately, EventManager needs the same listener signature to unSet it. ;)

DigitalSkyline
31 Dec 2007, 1:41 PM
Thanks, thought it might be something like that.

daemach
7 Jan 2008, 1:32 PM
What a great utility - thanks for making it available. This is exactly what we needed!

radio1
14 Jan 2008, 4:00 PM
Wow -- thanks VERY MUCH from me also hendricd -- your code makes session timeouts a breeze to handle.

In my application, I simply included "ext-basex-min.js" as described above, and then added a single call to Ext.lib.Ajax.onStatus(...) also as described above. This works very great for handling session timeouts reported by my server-side code.

However, please note the following bug and (hopefully sound) fix I implemented. My code is far too large to post here, but I'll describe the problem as best I can.

My application contains a GridPanel populated by a JsonStore. User clicks on other elements on the screen trigger the JsonStore (and therefore the GridPanel) to reload with applicable data from the server. It's very possible for a user to trigger the reloading of the JsonStore before a previous load was completed. This worked fine without the "ext-basex-min.js" in my app, but including that file (without even calling anything in it) caused IE6 & 7 to trigger a JavaScript error in this situation. Firefox still worked fine though.

My fix involves moving a single line of code into an existing try/catch block as indicated in these snippets.

Old:
createResponseObject:function(o, callbackArg){
var obj = {};
var headerObj = {},headerStr='';

try{ //to catch bad encoding problems here
obj.responseText = o.conn.responseText;
}catch(e){obj.responseText ='';}

obj.responseXML = o.conn.responseXML;

try{
headerStr = o.conn.getAllResponseHeaders()||'';
} catch(ex){}

New:
createResponseObject:function(o, callbackArg){
var obj = {};
var headerObj = {},headerStr='';

try{ //to catch bad encoding problems here
obj.responseText = o.conn.responseText;
}catch(e){obj.responseText ='';}

try{
obj.responseXML = o.conn.responseXML;
headerStr = o.conn.getAllResponseHeaders()||'';
} catch(ex){}

This seems to meet the need in my app, but maybe there's a better fix?
Questions and comments are very welcome!

Thanks again,
-radio1

hendricd
14 Jan 2008, 7:16 PM
@radio1 -- Thanks for the feedback!

Could you tell me what the exception raised by IE was?

Further, could you post the handler used to call the store.load? Was it called asynchronously?

Was: Ext.lib.Ajax.forceActiveX == true ??


Thanks.:)

radio1
15 Jan 2008, 10:28 AM
@radio1 -- Thanks for the feedback!

Could you tell me what the exception raised by IE was?

Further, could you post the handler used to call the store.load? Was it called asynchronously?

Was: Ext.lib.Ajax.forceActiveX == true ??

Thanks.:)

The message in IE is the usual "Problems with this Web page might prevent it from being displayed properly....." popup with the following details:

Line: 236
Char: 9
Error: Unspecified error.
Code: 0
URL: 'myurl'

Note that I isolated the cause of the problem to simply including either "ext-basex.js" (or "ext-basex-min.js") via a <script> tag in my source HTML file (even without actually calling Ext.lib.Ajax.onStatus(...) or referencing any other code in your extension), so Ext.lib.Ajax.forceActiveX was untouched.

As for my JsonStore-related code, my code only ever calls JsonStore.reload() (not .load()). Yup, the calls are asynchronous, and the problem occurred when a second ajax request was sent by the JsonStore while a previous request was still outstanding (the first response was not yet fully received).

For posterity, here's a simplified version of my JsonStore instantiation code -- simplified only by shortening the values assigned to the config options (those are all of the config options I use). I also do some screen-only cosmetic stuff in the event handlers shown (no ajax stuff).

jsonDs = new Ext.data.JsonStore({
url:'myurl',
baseParams: {cmd:'get'},
root:'items',
fields:[...aBunchOfFields...]
});
jsonDs.setDefaultSort(...);
jsonDs.on("beforeload", onStoreLoading, this);
jsonDs.on("datachanged", onStoreChanged, this);

Thanks much again -- please let me know if I can be of any further help. Questions and comments are always welcome.
-radio1

radio1
16 Jan 2008, 6:00 AM
A supplementary note to my above post -- I tried a couple more tests with your original version of "ext-basex.js". Explicitly setting Ext.lib.Ajax.forceActiveX to either true or false has no impact on the problem I described -- it still occurs in both cases. Note however that in my real application, I do not change its default value.

-radio1

hendricd
16 Jan 2008, 6:27 AM
Thanks, I'll keep pondering... ;)

hendricd
4 Feb 2008, 9:45 PM
See first post (http://extjs.com/forum/showthread.php?p=102679#post102679)for latest updates.

hendricd
4 Mar 2008, 3:59 PM
This release adds internal module caching, styleSheet helpers, and callback support.

Note: A progressive Ext loader sample (dependency-aware) is just about finished; will advise when packaged.

hendricd
8 Mar 2008, 8:38 AM
The update corrects a problem reported (http://extjs.com/forum/showthread.php?t=28776) with the current ext-base adapter implementation.
When passing postable content (jsonData, xmlData), the Content-Type headers were either duplicated (more than one sent) and/or the default post header value ('application/x-www-form-urlencoded') was being sent in all cases. This update corrects that behaviour when ext-basex is used.

It is now possible to use traditional Observable syntax for setting global httpStatus handlers:


Ext.lib.Ajax.on({
'status:403' : permissionHandler ,
'status:500' : criticalHandler
});

yanick
10 Mar 2008, 1:47 AM
Hi,
this line(ext-basex.js, line 840):

fullModule=(module.indexOf(".")!==-1?module:module+".js").toLowerCase()
don't work in OS, which has case sensitive file system(linux for example), it's probably bug.

hendricd
10 Mar 2008, 4:00 AM
@yanick -- indeed that would be. Fix posted shortly.

Good eye.

hendricd
19 Mar 2008, 10:01 AM
Thanks (in part) to @MindPatterns and this thread (http://extjs.com/forum/showthread.php?t=19171)(and a personal need to have named queues =P~), I've introduced named-queuing (with priorities) to ext-basex.

To use, simply add a 'queue' config or name to any Ext Ajax request and the new QueueManager will manage the request chains (based on priorities defined on each queue) for you.

Request Queues are automatically created when specified in a request as necessary.

Notes:
Requests without queue specifications are not managed by the Ext.lib.Ajax.QueueManager, and are executed normally.
Queued Requests are supported for both synchonous and asynchronous requests.-
QueueManager properties (via Ext.lib.Ajax.queueManager):
quantas : adjustable at runtime, the deferred poll interval used to ensure the maximum allowed sessions are active any time there are pending queued requests. (default:10ms)

New lib.Ajax supporting properties :
.activeRequests : the Current number of lib.Ajax requests in progress. (read-only)
.pendingRequests : the Current number of pending Queued requests. (read-only)
.maxConcurrentRequests : adjustable at runtime to suit your needs (or browser), specifies the maximum concurrent Queued browser (XHR) requests.
(defaults:10 )

Example:

store.load({
params: {start:0, limit : 50},
callback: update_user_fields,
queue : {name:'userlists', priority : 9 } //create (and use) the named queue 'userlist' and assign lowest (0-9) priority
//or just specify a previously created queue by name
queue : 'userlists'
});
Priority Queues.
The queueManager processes queued requests in order of their priority. There are 10 priorities (0 thru 9, 5 is the default), 0 being the highest priority. As soon as a queued request is added (as outlined above), the queueManager evaluates priorities in sequential order, firing AJAX queued requests until the maxConcurrentRequests value has been reached. Then, after quantas (milliseconds), the queues are again re-evaluated in priority order until all queues are exhausted.
Multiple queues may have the same priority.
Each queue has FIFO(default)/LIFO option as well, eg: queue : {name:'userlists', FIFO :false }All-in-all, quite flexible and tunable.

Let me know how things go (especially for those chat clients ;) )

violinista
27 Mar 2008, 2:41 AM
Henri, many thanks to you for this usable extension!

regards
=;

NotChris
1 Apr 2008, 2:26 PM
I would like to be able to use what you have provided to read an xml file from my local client. I have been struggling with this as you can see from the following forum reply but I have made progress:
http://extjs.com/forum/showthread.php?t=31054

I am using the ext-basex.js you have supplied based on a suggestion in that thread and was able to overcome communication errors. But I was wondering if you could provide a simple example of what would be needed to read a local xml file and display the data within a control (in my case, this is a GridPanel). I have not been able to see the data displayed in my actual grid but I do see the file displayed in the Console Response tab. I am unclear on your comment "Ajax Requests can also be made without a web-server (ie local file systems) via HTTP-Status-200 emulation." How would this be accomplished?

Thanks.

hendricd
1 Apr 2008, 3:29 PM
Just include ext-basex.js anywhere after the ext-base adapter in your <head> section, and add this somewhere early in your script:


Ext.lib.Ajax.forceActiveX = true; //for IE
That's it.

Then, use relevant local URLs (relative URLs are fine too) globally (for your store proxy definitions etc) and you can build a complete App without the need for a web-server.

But your main page must also be loaded from a local drive.

And, yes, you will use the same 'data.Readers' as if you were talking to a web-server.

NotChris
1 Apr 2008, 4:03 PM
I added the line of code you suggested at the beginning of my OnReady function. I am using IE6 and Firefox. I am still having the problem. Does this also work in Firefox? Can you explain in more detail what you mean by "use relevant local URLs (relative URLs are fine too) globally (for your store proxy definitions etc)"? I am using the following (and thanks so much for your help):



var sm3 = new Ext.grid.CheckboxSelectionModel();
var InboxGrid = new Ext.data.Record.create( [
{name: 'company'},
{name: 'price'},
{name: 'pctChange',type: 'date', dateFormat: 'n/j h:ia'},
{name: 'industry'},
{name: 'change'}

]);


var readerInbox = new Ext.data.XmlReader( {
totalRecords: 'recCount',
record: 'Inbox',
id:'ID'
}, InboxGrid );

var grid3store = new Ext.data.Store({
// Both of these lines cause the same results in firefox
//url: 'Grids.xml',
proxy: new Ext.data.HttpProxy({url: 'Grids.xml'}),

reader: readerInbox,

listeners: {
'loadexception': {
fn: function(httpProxy, dataObject, arguments, exception) {
console.log('** - Data Store listener fired (loadexception), arguments:', arguments);
console.log('** - Data Store listener fired (loadexception), httpProxy:', httpProxy);
},
scope: this
},
'load':{
fn: function(store, records, options){
console.log('01 - Data Store listener fired (load), arguments:',arguments);
console.log(' this:',this);
},
scope: this
}
//add remaining events for education:
,'add':{
fn: function(store, records, index){
console.log('Data Store listener fired (add), arguments:',arguments);
}
,scope:this
}
,'beforeload':{
fn: function(store, options){
console.log('Data Store listener fired fired (beforeload), arguments:',arguments);
}
,scope:this
}
,'clear':{
fn: function(store){
console.log('Data Store listener fired fired (clear), arguments:',arguments);
}
,scope:this
}
,'datachanged':{
fn: function(store){
console.log('11 - Data Store listener fired fired (datachanged), arguments:',arguments);
console.log(' If you set a breakpoint here the entire grid will be rendered without data');
console.log(' ...about to "refresh" grid body');
}
,scope:this
}
,'remove':{
fn: function(store, record, index){
console.log('Data Store listener fired fired (remove), arguments:',arguments);
}
,scope:this
}
,'update':{
fn: function(store, record, operation){
console.log('Data Store listener fired fired (update), arguments:',arguments);
}
,scope:this
}


}
});

grid3store.load();

SampleGrid3 = function(limitColumns){

var columns3 = [
sm3,
{header: "Title", width: 210, sortable: true, dataIndex: 'company'},
{header: "From", width: 120, sortable: true, dataIndex: 'price'},
{header: "Date", width: 105, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'pctChange'},
{header: "Status", width: 100, sortable: true, dataIndex: 'industry'},
{header: "Type", width: 180, sortable: true, dataIndex: 'change'}
];



SampleGrid3.superclass.constructor.call(this, {
store: grid3store,
sm: sm3,
columns: columns3,
frame:true,
height:60,
width:500,
id:'grid3',


buttonAlign:'left',
buttons: [{text:'New'}, {
text:'Remove',
handler: function() {

var selectedRows = sm3.getSelections();

for (i = 0; i < selectedRows.length; i++) {
grid3store.remove(sm3.selections.items[i]);
i--;
selectedRows.length--;

}
}
}
]
});


}


Ext.extend(SampleGrid3, Ext.grid.GridPanel);

// html file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head>
<meta http-equiv="Content-Type" content="text/xml; charset=iso-8859-1">

<html>
<head>
<title>Custom Layouts and Containers - Portal Sample</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="../../resources/css/xtheme-slate.css" />

<!-- GC -->
<!-- LIBS -->

<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<!-- <script type="text/javascript" src="../../ext-all.js"></script> -->
<script type="text/javascript" src="../../ext-all-debug.js"></script>
<script type="text/javascript" src="../../ext-basex.js"></script>


<!-- ENDLIBS -->

<script type="text/javascript" src="../form/states.js"></script>
<script type="text/javascript" src="create-grid.js"></script>

<script type="text/javascript" src="Toolbar.js"></script>

<style type="text/css">
.x-toolbar {
overflow: hidden;

}
.x-toolbar-left {
float: left;
}

.x-toolbar-right {
float: right;
}

.x-toolbar .ytb-text {
line-height: 1.5em;
}
</style>

<script type="text/javascript" src="Portal.js"></script>
<script type="text/javascript" src="RowExpander.js"></script>

<script type="text/javascript" src="PortalColumn.js"></script>
<script type="text/javascript" src="Portlet.js"></script>
<link rel="stylesheet" type="text/css" href="portal.css" />

<link rel="stylesheet" type="text/css" href="sample.css" />
<script type="text/javascript" src="quickdetail.js"></script>
<script type="text/javascript" src="searchbaraddin.js"></script>
<link rel="stylesheet" type="text/css" href="columnLock.css">
<script type="text/javascript" src="columnLock.js"></script>
<script type="text/javascript" src="grid3.js"></script>

</head>
<body>
<script type="text/javascript" src="../examples.js"></script><!-- EXAMPLES -->
</body>
</html>

// Code line that you specified to include
Ext.onReady(function(){

Ext.state.Manager.clear();
Ext.lib.Ajax.forceActiveX = true; //for IE
.....

hendricd
1 Apr 2008, 4:18 PM
Sorry, I got in late on this game.


I am still having the problem.

the problem?

hendricd
1 Apr 2008, 4:34 PM
@NotChris -- I just reviewed thread 31054.

If you add this to your Ext.onReady block:



Ext.Ajax.request({
url:'grids.xml', //this assumes the file is located in the same path as your main page
success: function(response){
console.log(['Yippee', response.responseText]);
},
failure : function(){
console.log(['failed ', arguments]); //last argument is the exception (if JS error)
}
});
If you see your xml file (with a resounding 'Yippee') in the console.log, ext-basex is doing its job.

The next questions: is the XML "well-formed"? If it is, response.responseXML should show a valid XMLDocument object suitable for use with the XMLReader (ie. will not contain any parseError nodes) .

If that is good, you likely don't have your reader defined properly to parse the xml document.

NotChris
1 Apr 2008, 5:00 PM
OK - I am seeing the following for response.responseText:
"<?xml?>\r\n<list>\r\n<recCount>2</recCount>\r\n\r\n<Inbox>\r\n<ID>1</ID>\r\n<name>Find All requests..."
so it does appear that this is correct and ext-basex is doing its job.

So when you say, "you likely don't have your reader defined properly to parse the xml document", I assume you mean the actual field definitions for XmlReader - correct?

Thanks again. I'm a learnin from folks like you...

hendricd
1 Apr 2008, 5:05 PM
So when you say, "you likely don't have your reader defined properly to parse the xml document", I assume you mean the actual field definitions for XmlReader - correct? Yes, but make sure you've got a good xml doc. Drag that file into a browser and look for complaints. ;)

Your processingInstruction should look like:

<?xml version="1.0"?>

NotChris
1 Apr 2008, 5:48 PM
Thanks so much. I was able to get it to work by dragging the file into the browser and determining the correct syntax which was off. The data in the grids is being displayed!!

hendricd
1 Apr 2008, 5:53 PM
Always, the silly stuff huh. Be sure to mark your other thread SOLVED, eh ?

NotChris
2 Apr 2008, 5:18 AM
I am actually going to refer to this thread for the final solution on this. I really do like the trick of dragging the xml file into firefox for syntax checking!! Thanks.

Makor
2 Apr 2008, 5:34 AM
How add listeners to load method?

myApp.codeLoader.on({'complete':addUserInfo});
myApp.codeLoader.load('StaticTextField.js');

I need to call addUserInfo only once after load? and then listener must be deleted...

NotChris
2 Apr 2008, 1:09 PM
Doug,

I was wondering if it possible to also use this extension and XmlReader to load icons from an XML file? I would think it would but please take a look at the following thread when you get a chance that explains my problem trying to do this:

http://extjs.com/forum/showthread.php?t=31248&highlight=xml+file%2C+icon

I did check the syntax this time and it is OK. Thank you.

hendricd
2 Apr 2008, 1:52 PM
How add listeners to load method?

myApp.codeLoader.on({'complete':addUserInfo});
myApp.codeLoader.load('StaticTextField.js');

I need to call addUserInfo only once after load? and then listener must be deleted...

@makor - I would recommend you set an exception handler as well, in case of problems:
'complete' fires regardless of exceptions and is designed to signal the end of loading multiple resources, use 'load' instead in your case:


myApp.codeLoader.on({
load : {fn:addUserInfo, single:true, scope:??? },
loadexception : alertFailure
});

jerrybrown5
15 Apr 2008, 11:03 PM
ext-basex also includes ux.ModuleManager
...
Demo for that coming shortly....

Doug,
I am anxious to see a demo of this in action. Two quick questions--

1) Are you going to address the debugged version of js library files versus the minified ones? (Of course it is too late to flip the ext-all-min vs ext-all but I mean for all of the ones after this.)

2) Are you going to be able to specify a priority to libraries so that some won't load until after the module is being displayed? (In other words-- put the actual load of a certain priority level and below on a timeout)

For example if I use Google Maps in my module but not on the first page I would want the gmap js file load to not slow down the module load; however, the gmap load should still not wait until the first map page is trying to get displayed.

Thanks in advance.

Best regards,
Jerry Brown

hendricd
16 Apr 2008, 3:51 AM
@jerrybrown5 -- Here's a taste of what it's all about:



(function(){

//Enable local file access for IE
Ext.lib.Ajax.forceActiveX = (document.location.protocol == 'file:');

var L = Ext.Loader = new Ext.ux.ModuleManager({

disableCaching:true,

listeners:{
load :function(manager, module, response, content){
//styleSheet handler
if(module.extension == 'css'){
module.content = content;
this.applyStyle(module);
}
},
loadexception:function(manager, module, ex){

alert(['Failed to Load Module '+ module.url,'\nError: ',ex.error?ex.error.message:ex]);
}
},

depends : {}, //Holder for the Ext dependency table

getMap:function(moduleName){

moduleName = moduleName.toLowerCase();

var map = this.depends[moduleName.replace("@","")]||false;

//if(!map)return map; //not a defined Ext module map

map = Ext.apply({path:'',depends:false}, map);

var result = [];

if(map.depends){
var c=arguments.callee;
forEach(map.depends,function(module){
//chain dependencies
if(module.substr(0,1)=="@"){
result = result.concat( c.call(this,module));
}else{
result.push(module);
}

},this);
}
return result.concat(map.path + moduleName.replace("@",""));
},

styleAdjust : {pattern:/url\(\s*\.\.\//ig, replacement:'url(../../resources/'}

});

/* Define our dependency table for Ext 2.0.2 */

//define the site layout for Ext packages (most are already built for you!)
var p = 'package/';
var l = p + 'layout/';
var d = p + 'dragdrop/';
var w = p + 'widgets/';
var ux= p + 'ux/';

L.depends = {
// JS source file | source location | Dependencies (in required load order)
"borderlayout": {path: l, depends: [ '@container', l+'containerlayout', p +'splitbar'] }
,"button" : {path: p+'button/' , depends: [ '@widget-core', '@qtips' ]}
,"color-palette": {path: p , depends: [ '@widget-core']}
,"container" : {path: w, depends: [ '@widget-core']}
,"data" : {path: p+'data/', depends: [ p + 'util'] }
,"dataview" : {path: w, depends: [ '@widget-core',p + 'util']}
,"date" : {path: p }
,"datepicker" : {path: p+'datepicker/',
depends: [ '@menus']}
,"dialogs" : {path: p+'dialog/' , depends: [ '@window' ]}
,"dragdrop" : {path: d, depends: [ '@widget-core']}
,"edit-grid" : {path: p+'grid/', depends: [ '@grid', '@form' ]}
,"form" : {path: p+'form/', depends: [ '@panel','@dataview']}
,"full-grid" : {path: p+'grid/', depends: [ '@grid', '@toolbar','@loadmask' ]}
,"grid" : {path: p+'grid/', depends: [ '@dragdrop', '@panel' ,'@data']}
,"layouts" : {path: l, depends: [ '@container', l+'containerlayout', p +'splitbar'] }
,"loadmask" : {path: w }
,"menus" : {path: p+'menu/', depends: [ '@widget-core']}
,"messagebox" : {path: w, depends: [ '@window']}
,"panel" : {path: w, depends: [ '@container', l + 'containerlayout' ]}
,"qtips" : {path: p+'qtips/', depends: [ '@panel','@dragdrop' ] }
,"resizable" : {path: p, depends: [ '@container']}
,"state" : {path: p , depends: [ p + 'util',] }
,"tabs" : {path: p+'tabs/', depends: [ '@layouts', '@panel']}
,"toolbar" : {path: p+'toolbar/' ,depends: [ '@widget-core', '@button' ]}
,"tree" : {path: p+'tree/', depends: [ '@dragdrop', '@form']}
,"viewport" : {path: l, depends: [ '@container']}
,"widget-core" : {path: p, depends: [ p + 'util', "@xtemplate", '@date']}
,"window" : {path: w, depends: [ '@dragdrop', '@panel', w + 'windowmanager', w + 'panelDD'] }
,"xtemplate" : {path: p }

/* optionally define your ux dependencies and locations here */
,'miframe' : {path: ux , depends: [ '@panel'] }
,'uxmedia' : {path: ux , depends: [ '@panel'] }
,'uxflash' : {path: ux , depends: [ '@uxmedia'] }
,'uxfusion' : {path: ux , depends: [ '@uxflash'] }
};

Ext.require = function(){
var modules = [],options = {};
Ext.each(arguments , function(module){

if(module){
if(typeof module == 'object'){
Ext.apply(options,module);
}else{
modules = modules.concat( L.getMap(module) );
}
}

});

return L.load.apply(L,[modules,options]);
};

Ext.provide = L.provides.createDelegate(L);
})();
What this means is that you can use the standard Ext-2.0.2/package/* (still have to move a couple of files around) but no custom builds are required unless you prefer it that way. Then, just update the dependency map (see above) to match your Ext distribution/build.

To prepare for a Fusion Chart, for example:

Start out lean:

<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../../ext-core.js"></script>
<script type="text/javascript" src="ext-basex.js"></script>

Ext.onReady(function(){
if(Ext.require('viewport', 'uxfusion'){
var view = new Ext.ViewPort(
{ region:'center',
items:[{xtype:'fusionpanel',....}]
}
....
}
});

then, at your convenience (maybe after page is initialized)

Ext.require('gmap','tree',{async:true});
All depends on your use-case. ;)

jerrybrown5
16 Apr 2008, 5:50 AM
Doug,
I had no idea that you were using this in an attempt load the ext-all distribution faster. This is a whole lot cooler than I expected. Have you YSlow/firebug performance tested a few samples versus the normal ext-all way yet?

Since it will only load modules that are required, this should improve the page load time when files can be cached. However, I imagine the speed will be slower when they can not be cached since it will need to download more files from the server than just a single ext-all file. I am anxious to see the raw numbers.

One other question--since Ext 2 makes it so easy to lazy create components using xtypes [ and layouts with layout types]---would you consider tieing this logic into Ext.ComponentMgr.create[ and Ext.Container.render] (with a mapping of xtypes [and layouts] to requires) to automatically populate the require commands? [layout logic is in brackets]

Best regards,
Jerry Brown

hendricd
16 Apr 2008, 6:21 AM
@jerrybrown5 -- The caching issues only comes into play when ux.ModuleManager determines that a given module has not already been loaded (evaled).



however, I imagine the speed will be slower when they can not be cached since it will need to download more files from the server than just a single ext-all file, but I am anxious to see the numbers.Yes, but the goal here is determine how viable the approach is for deploying Ext on more public-facing sites (with minimal "perceived" startup time).



One other question--since Ext 2 makes it so easy to late create components/layouts---would you consider tieing this logic into Ext.ComponentMgr.create[ and Ext.Container.render] (with a mapping of xtypes [and layouts] to requires) to automatically populate the require commands? [layout logic is in brackets]
Yes, I've already horsed around with linking with ComponentMgr, but many comps (eg. stores) today don't have xtypes (or even usable ctypes), so the gain would only apply to 'renderable' components and add significant confusion to your scripts.

I settled on this approach because it permits the implementation to decide how best to arrange functional packages based on the demands of site(layout).

ux.ModuleManager is just tool, and presented a mechanism for creating your own Ext.require[needs],[provides] capability.

jerrybrown5
16 Apr 2008, 7:03 AM
Doug,
I think you created a great library as is but I think it would take the cake if you did a few relatively minor things.

-----

Yes, I've already horsed around with linking with ComponentMgr, but many comps (eg. stores) today don't have xtypes (or even usable ctypes), so the gain would only apply to 'renderable' components and add significant confusion to your scripts.


* This will not be for stores for which as you mentioned do not have an xtype. However, you could easily embed a require command around any place where you are creating a new object anyway. The same can not be said when you are using lazy creation with child items.

* I agree that in one sense it adds confusion by inserting code at the object creation level, but in the other sense it adds simplicity by requiring less implementation code when you use this with lazy creation.

* This will add a feature at the right place and at the right time. Pages load faster when you lazy create objects which is the same reason of being of this module.

* The need is there. There are plenty of heavy components such as ones for Flash, TinyMCE and GMaps when you absolutely need to load their dependencies at the right time or else you will greatly slow down your page load time.

-----
Couple of other ideas...
* Your sample did not include the module eval logic that it looks like you are building into it. This would be especially useful on the TinyMCE xtype that is available on the forum.
* Is it possible that you can allow a ~ prefix to automatically load a module asynch (or on a timeout)
* (from earlier) Are you going to address the debugged version of js library files versus the minified ones? Ideally, there would be a global tag that would be checked.

Thanks in advance.

Best regards,
Jerry Brown

hendricd
16 Apr 2008, 7:47 AM
Couple of other ideas...
* Your sample did not include the module eval logic that it looks like you are building into it. This would be especially useful on the TinyMCE xtype that is available on the forum.
* Is it possible that you can allow a ~ prefix to automatically load a module asynch (or on a timeout)
ux.ModuleManager is included in ext-basex.js. It handles retrieval (asynch/synch behaviors) during loading as well as eval, callbacks, and native Ext events during those ops.

You can pass in the new queuing options, too:

Ext.require('panel', 'grid',{async: true, queue:{name:'mods',priority:1}});All the glue is there.



* (from earlier) Are you going to address the debugged version of js library files versus the minified ones? Ideally, there would be a global tag that would be checked.
Again, thats a packaging decision based on the implementation. ;) (I am not (nor will be) in the business of building custom packages ;) )

Kid in a candy store you are now ! =P~

Keep in mind: this is all experimental and very part-time.

hendricd
16 Apr 2008, 1:53 PM
@jerryB --

This:

* This will add a feature at the right place and at the right time. Pages load faster when you lazy create objects which is the same reason of being of this module.

* The need is there. There are plenty of heavy components such as ones for Flash, TinyMCE and GMaps when you absolutely need to load their dependencies at the right time or else you will greatly slow down your page load time.
...got me thinking again. With this in place:



Ext.require('widget-core', function(mod,success){
if(success){
var mgr = Ext.ComponentMgr; // a singleton
mgr.create = mgr.create.createInterceptor(
function(config, defaultType){
if(config.require){
Ext.require.apply(Ext,[].concat(config.require));
delete config.require;
}
});
}
});
...this might be possible (lazy rendering):



Ext.require('viewport', 'borderlayout', 'panel', function(mod,success){

Demo.view = new Ext.Viewport({
layout:'border',
items:[
new Ext.BoxComponent({ // raw element
region:'north',
el: 'header',
height:32
}),
{
region:'west',
require: 'tree' ,
id:'demos',
title:'Demos and Notes',
split:true,
width:200,
minSize: 175,
maxSize: 400,
collapsible: true,
cmargins:'5 5 5 5',
layout:'accordion',
layoutConfig:{
animate:false
,activeOnTop : false
,autoWidth: true
,autoHeight: true
,fill:true
},
defaults:{autoScroll:true},
items:[
{
id:'samples',
xtype:'treepanel',
autoScroll:true,
title: 'Media Samples',
loader: new Ext.tree.TreeLoader(),
rootVisible:false,
lines:false,

root: new Ext.tree.AsyncTreeNode({
text:'Online',
expanded:true,
children:sampleNodes
})
} ,
{
title: 'Hit Parade',
require: 'uxmedia' ,
,id : 'hits'
,xtype: 'mediapanel'
,mediaCfg:{
mediaType:'GIF'
,height:30
,url:'speeddial.gif'
,id:'odometer'
,start : true
}
} ,
{
title : 'Clock'
,id : 'clockPanel'
,require: 'uxflash'
,xtype : 'flashpanel'
,autoHeight : true
,autoWidth: true
,mediaCfg : {
mediaType:'SWF'
,url: 'clock.swf'
,id: 'clock'
,start : true
,loop : true
,controls :true
,height:130 //fixed height for aspect ratio
,params: {
wmode :'transparent'
,scale :'exactfit'
,salign :'t'
}
}
}

]
},
{ xtype:'tabpanel',
require: 'tabs' ,
region:'center',
id :'demoTabs',
activeTab: 0,
split:true,

enableTabScroll: true,
monitorResize: true,
autoDestroy:true,

defaults:{

closable :true

}
,items:[{title:'BackGrounder'
,contentEl:'background'
,autoScroll : true
,closable:false
}]

}
]
});
});

:-? Testing that now..

jerrybrown5
17 Apr 2008, 12:40 AM
Doug,
Very, very nice. Candy anyone?! :)

Best regards,
Jerry Brown

maximumcoder
5 May 2008, 4:52 AM
Hi hendrico.. excellent addon to extjs...

Im particularly interested in the Ext.ux.ModuleManager. Though have spent the entire weekend and the whole of monday too with no luck. Can you please please throw me a bone over here. I just need a small working example to get the ball rolling. Right now using the little code excerpt nothing works. No life, no errors, no exceptions no nothing. The app remains silent.. Help the brother out.. thanks

hendricd
5 May 2008, 4:57 AM
@maximumcoder -- Have a look at the adviframe.js included with ux.ManagedIframe (see sig below). It includes a working sample of using ModuleManager for injecting cached JS/CSS into iframes, but should outline the usage.

maximumcoder
5 May 2008, 5:19 AM
thanks that helps a lot...

though just out of curiousity... i had read earlier about the dependancy aware ext module loader. Hows the progress on that??? (translated to... eagerly waiting ;) ) Thats what i really need coz my application is more or less using most of the features of the library and the initial load times are making my potential users crying hoarse :P

thanks anyways..

hendricd
5 May 2008, 5:25 AM
Hows the progress on that???

The Synchro-XHR version is working very well, still working on the Asynch variant and trying to convert one of the /examples to use it. Admittedly, the licensing issues have forced me to re-evaluate priorities. /:)

fangzhouxing
5 May 2008, 7:55 AM
I am confused about the difference between Ext.lib.Ajax.request and Ext.Ajax.request?

When using ext-basex, I must use Ext.lib.Ajax.request instead of Ext.Ajax.request?

hendricd
5 May 2008, 8:02 AM
I am confused about the difference between Ext.lib.Ajax.request and Ext.Ajax.request?

When using ext-basex, I must use Ext.lib.Ajax.request instead of Ext.Ajax.request?
No. You'll continue to use either AJax interface. The ext-basex implementation enhances the standalone Ext adapter to provide new features that are transparent throughout the framework.

With ext-basex in place, you have a few more request options available. Just pass them as you would any other but adding: async:false, queue:'best' etc...

fangzhouxing
5 May 2008, 7:15 PM
hi,hendricd,thank you for reply!

fangzhouxing
6 May 2008, 1:59 AM
hi,hendricd,one more question:

the Ext.lib.Ajax.clearAuthenticationCache method is effective in IE, but seems not effective in FireFox.

How to make it effective in FireFox?

hendricd
6 May 2008, 4:13 AM
@fangzhouxing -- Try this variant:


,clearAuthenticationCache:function(url) {

try{

if (Ext.isIE) {
// IE clear HTTP Authentication (all domains !)
document.execCommand("ClearAuthenticationCache");
}
else {
// create an xmlhttp object
var xmlhttp;
if( xmlhttp = new XMLHttpRequest()){
// prepare invalid credentials
xmlhttp.open("GET", url || '/@@' , true, "logout", "logout");
// send the request to the server
xmlhttp.send("");
// abort the request
xmlhttp.abort.defer(100,xmlhttp);
}
}
} catch(e) { } // There was an error
}
and let me know how it goes. I suspect it may not work on Safari, but it's a crap-shoot with HTTP Basic/NTLM Auth anyway. ;)

fangzhouxing
6 May 2008, 7:36 AM
I have tested the code provided, and the problem still exists.

Maybe we can use different solution like this:
http://userfirstweb.com/23/logouts-form-based-http-basic-authentication/
(Logouts & Form-based HTTP Basic Authentication)

hendricd
6 May 2008, 8:04 AM
Username and password support was added to ext-basex to permit login using an XHR call, but the browsers have not taken the initiative to address the logout for a specific realm.

Thats what makes a unified logout so difficult. (:|

fangzhouxing
6 May 2008, 4:47 PM
New config options (can be passed down from a higher level (ie. Ext.data.Connection) implementation.):
{
async : true/false, // Synchronous Request support.
userId: 'JohnDoe', // HTTP Authentication available on each request
password:'inTheClear',
queue : {name: 'chat', priority : 1 } //dynamic queue creation
}

I have test the 'async ' config item, and it works fine!

I wonder why we need the 'userId' and 'password' config items, because we can use following code instead:


Ext.Ajax.defaultHeaders.Authorization = "Basic " + user:psw;

and if i use the 'userId' and 'password' config items, i cannot find them in server side code.

fangzhouxing
7 May 2008, 4:21 PM
Username and password support was added to ext-basex to permit login using an XHR call,

When I use HTTP Basic Authorization with ExtJS, the 'Username and password support' seems not needed.

sp797
13 May 2008, 12:18 PM
When debugging in Firefox, I cannot debug code in javascript files that were loaded by ModuleManager. Firefox only allows me to select js files that were loaded in the "traditional" way. Has anyone found a way to workound this issue?

hendricd
13 May 2008, 12:25 PM
@sp797 -- Later versions of Firebug (1.2b+ I believe) permit debugging of 'eval'ed scripts, but I doubt it would be of much value if you were loading minified Ext modules anyway.

The next version of ux.ModuleManager will include debug mode support which writes the loaded javascript into <script> tags for debugging. Coming soon. ;)

pompom
20 May 2008, 12:28 AM
Hello Doug,

I think your awesome work will help me in my app but could you tell me if what i want to do is possible ?

Actually, i am interested in the QueueManager.

I have a form and when i clic a button, a MySQL request depending on the form fields is sent and the result is saved in a file on my computer.
The request can be huge and i need to be able to send many requests quickly and continue to use my app.
The last thing is that i would like to display in a frequently refreshed grid the pending requests with some details and to be able to cancel some of them...

Is it possible ? Do you have any examples with your QueueManager ? Any tips ?

Sorry for my poor English !

Thanks and regards
Julien

hendricd
20 May 2008, 3:04 AM
@pompom -- All that sounds doable, except for:


...and the result is saved in a file on my computer.You'll need to come up with a download/save strategy that minimizes the user's browser 'interaction' during all this. Otherwise that fancy grid will be useless with all the "Save As.." dialogs being generated (could use a nice download manager tho ).

The next release adds additional events the queueManager which should make updating a status grid possible and queued-requests abortable.

Sorry, no, I don't have any sample constructed any where near that elaborate. You should work out a simple prototype first to make sure you're going to be happy with Exts' Form protocol and get familiar with the various browsers' download nuances.

pompom
20 May 2008, 5:07 AM
Thanks for the answer.

Actually the file is saved automaticaly on my computer with a random name. The user never interacts after he has clicked on the button.

Do you have any approximative idea of when your next release is coming ? :)

hendricd
20 May 2008, 5:22 AM
Do you have any approximative idea of when your next release is coming ? :)

2-3 weeks.

pompom
20 May 2008, 6:56 AM
Great ! Looking forward to seeing it ! :D

jvanantwerp
3 Jun 2008, 2:42 PM
Has anyone had problems using onStatus to catch errors when using the form.submit method?

I use the following:

// set up Ajax error handlers
Ext.lib.Ajax.onStatus([404], function(statusCode, transaction, response, callback, isAbort)
{
Ext.MessageBox.alert('Sorry Not Found', 'The resource could not be found. If you feel this is an error, please contact Support.');
return(true);
},
this);

// not authorized exception
Ext.lib.Ajax.onStatus([403,401], function(statusCode, transaction, response, callback, isAbort)
{
Ext.MessageBox.alert('Not Allowed', 'Sorry, you are not allowed to perform the action you requested. If you feel this is an error, please contact Support.');
return(true);
},
this);

to set up the handlers. The 404 handler always gets called when a 404 occurs during the submit. However, the 403 error handler does not get called during form submit, although it does get called when a 403 (or 401) is returned for any other Ajax request I make.

Any ideas?

Thanks!
- John

hendricd
5 Jun 2008, 7:20 AM
@John - XHR is not involved in a form.submit. Wouldn't expect it to trap anything.

jvanantwerp
5 Jun 2008, 7:27 AM
Ok, that's what I originally thought... it just confused me when the 404 errors were seemingly caught. :">

Thanks!
- John

wm003
9 Jun 2008, 3:47 AM
Doug, great work. =D> However, it would be nice if you could check future code through jslint (http://www.jslint.com) before posting it.

hendricd
9 Jun 2008, 4:48 AM
Doug, great work. =D> However, it would be nice if you could check future code through jslint (http://www.jslint.com) before posting it.

What's giving you trouble?

wm003
9 Jun 2008, 5:33 AM
What's giving you trouble?

Nothing;) I only forced myself checking all code through jslint to have "cleaner" code.

I found it out while i was studying your code. And now i have a suggestion:
As i was testing the comet-extension from tof i needed ext-basex to support the queued requestobject being available from outside the ajax-functions. So i did a little change of one line to make this possible:


,dispatch : function(){
var lib =Ext.lib.Ajax, qm = this, qmq = qm.queues;
disp = function(qName){
var q = qmq[qName];
while(q && q.pending && lib.pendingRequests && lib.activeRequests < lib.maxConcurrentRequests){

/*
With the Change of the following line its possible by
var ajaxobj = Ext.lib.Ajax.queueManager.getQueue('queueName').requestObj

to gain access to something like
var text = ajaxobj.conn.responseText;

*/
// q.requestNext();
//keep the requestobject accessible from outside
q.requestObj = q.requestNext();


}
return lib.pendingRequests > 0 ? (lib.activeRequests < lib.maxConcurrentRequests) :false;
};

Ext.each(this.priorityQueues ,function(queues){
//queues == array of queue names
if(lib.pendingRequests<1 )return false;
return Ext.each(queues||[],disp,this) == undefined?true:false;
}, this);

lib.pendingRequests > 0 ? this.dispatch.defer(this.quantas,this): this.stop();

}

hendricd
9 Jun 2008, 6:08 AM
@wm003-- Although the next release of ext-basex will add a activeRequest property to the Queue class, it's doubtful that will be usefull in an asynchronous environment, as you'll only have a fraction of a second to use it.


to gain access to something like
var text = ajaxobj.conn.responseText;

The standard Ext.Ajax.request events/callbacks are still the best place (and time) to access the responseText.

stevebla
9 Jun 2008, 7:47 AM
My WinZip will not open these archives .. gives me "End-of-central-directory signature not found"
.. any idea why?
(I really would like to use this code .. it sounds like the perfect solution for handling session timeouts)

Thank you

hendricd
9 Jun 2008, 7:50 AM
What zip-client are you using?

stevebla
9 Jun 2008, 8:08 AM
WinZip 8.1 evaluation

hendricd
9 Jun 2008, 8:09 AM
Try the more current version 11.0. /:)

stevebla
9 Jun 2008, 8:17 AM
OK .. Thank you

stevebla
9 Jun 2008, 8:55 AM
I got the files using Firefox instead of IE.

My corporate IE image seems to be doing some sort of filtering on the .zip 's, probably to thwart some security threat (real or imagined!).

Thanks again!

wm003
9 Jun 2008, 9:06 PM
@wm003-- Although the next release of ext-basex will add a activeRequest property to the Queue class, it's doubtful that will be usefull in an asynchronous environment, as you'll only have a fraction of a second to use it.


Not in the case of the comet code whereas the ajax never returns until the timeout occurs. In the meantime ever 200 milliseconds the responseText is parsed for changings. That was the only reason for the little codechange.

The standard Ext.Ajax.request events/callbacks are only triggered when the ajax call has _finished_. In the comet code the server code loops endless (until timeout) so it will never come back to finish the ajax call. See tof's code (http://extjs.com/forum/showthread.php?p=58156#post58156) here for further information. I modified his code to work "hand in hand" with your basex to always use the lowest priority. This way every new "normal" ajax-code will trigger the cometcode to cancel ifself immediatly. as any normal ajax-call will get priority 5 as default the comet code (with always priority 9) will be automatically called again when the remaining ajax requests are finished.... if your next version of basex will include a possibility to gain access to the "conn" object (as i suggested above) i will post the final solution of the extended comet-code...but i guess this should be further discussed in a separate thread...:)

In "normal" Ajax case you're absolutely right :)

KRavEN
12 Jun 2008, 4:53 AM
When using Ext.lib.Ajax.onStatus([403,401],sessionTimeoutHandler,this); how do I resend the request after I re-authenticate the user?

hendricd
12 Jun 2008, 5:31 AM
I haven't tried this yet, but, in theory:




var A = Ext.lib.Ajax;
A.request = A.request.createInterceptor(
function(method, uri, cb, data, options){
if(!A._locked){
//save the last request arguments
A._lastRequest = Array.prototype.slice.call(arguments,0);
}else if(options && options.loggingIn){
return true; //allow your login only
}
}
return !A._locked; //cancel all future requests during lockout
}, A);

var sessionTimeoutHandler = function( ....) {
A._locked = true;
alert('Session no longer valid, please login again..');

var withCallBack = function(success){
if(success){
A._locked = false;
A._lastRequest ? A.request.apply(A,A._lastRequest): null;
A._lastRequest = null;
}
};
// set your request options.loggingIn = true during your login request to allow it to pass thru.
doYourAsynchLogin( ..., withCallback );
};

A.onStatus([403,401],sessionTimeoutHandler);
A.on('status:403', sessionTimeoutHandler); //alternate form

this SHOULD work globally throughout the framework, but as written it will only execute the last failed request and prevent all other requests until login is succesful.

Let us know what you end up with.

KRavEN
12 Jun 2008, 6:48 AM
That helps a lot Doug. Thank you.


but as written it will only execute the last failed request and prevent all other requests until login is succesful.

There's the rub. I still need to be able to submit the login form and in it's success method call withCallBack(true).

hendricd
12 Jun 2008, 7:06 AM
@KRavEN -- I updated the post while you were probably reading it. See the revised version.

KRavEN
12 Jun 2008, 8:08 AM
Okay, well here's what I came up with. I couldn't figure out how to set options.loggingIn = true when using the form.submit() method but I was able to get it from options.scope.options.loggingIn. There are probably better ways to do the form/window but I needed it to look exactly like the window the user sees when they first open the page.


// not authorized exception
var A = Ext.lib.Ajax;
A.request = A.request.createInterceptor(function(method, uri, cb, data, options) {
if (!A._locked) {
// save the last request arguments
A._lastRequest = Array.prototype.slice.call(arguments, 0);
} else if (options.scope.options && options.scope.options.loggingIn) {
return true; // allow your login only
}
return !A._locked; // cancel all future requests during lockout
}, A);

var sessionTimeoutHandler = function(statusCode, transaction, response, callback, isAbort) {
A._locked = true;

var withCallBack = function(success) {
if (success) {
A._locked = false;
A._lastRequest ? A.request.apply(A, A._lastRequest) : null;
A._lastRequest = null;
}
};

var success = function(f, a) {
if (a && a.result) {
loginWindow.destroy();
withCallBack(true);
}
}

var submitForm = function() {
loginForm.form.submit({
waitMsg : 'Logging in...',
method : 'POST',
clientValidation : true,
loggingIn : true,
success : success
});
}

var loginForm = new Ext.FormPanel({
baseCls : 'x-plain',
labelWidth : 145,
labelAlign : 'right',
url : 'login',
title : '<b>Login Information</b>',
bodyStyle : 'padding:10px 0 0 15px',
defaults : {
anchor : '90%',
allowBlank : false,
xtype : 'textfield',
msgTarget : 'side'
},
items : [{
fieldLabel : 'Enter your ID',
id : 'username',
name : 'username'
}, {
fieldLabel : 'Enter your Password',
name : 'password',
id : 'password',
inputType : 'password'
}]
});

var loginWindow = new Ext.Window({
title : 'Login',
width : 350,
height : 165,
layout : 'fit',
plain : true,
closable : false,
bodyStyle : 'padding:5px;',
buttonAlign : 'center',
items : loginForm
});

loginWindow.addButton('Login', submitForm);

loginWindow.on('show', function() {
var f = loginForm.findById('username');
f.focus.defer(100, f);
});

loginWindow.show();

var usernameMap = new Ext.KeyMap(loginForm.findById('username').getEl(), {
key : Ext.EventObject.ENTER,
fn : function() {
loginForm.findById('password').focus();
}
});

var passwordMap = new Ext.KeyMap(loginForm.findById('password').getEl(), {
key : Ext.EventObject.ENTER,
fn : submitForm
});
};

A.onStatus([401], sessionTimeoutHandler);

KRavEN
12 Jun 2008, 8:31 AM
I guess a more advanced version would start putting requests in a queue and start processing the queue after A._locked = false

hendricd
12 Jun 2008, 9:09 AM
I guess a more advanced version would start putting requests in a queue and start processing the queue after A._locked = false

Yes, that was my thought as well, but the required ability to suspend/resume a queue is not available until v.3.0 of ext-basex. With that in place, it could look something like:



A.request = A.request.createInterceptor(function(method, uri, cb, data, options) {
if (!A._locked) {
// save the last request arguments
A._lastRequest = Array.prototype.slice.call(arguments, 0);
} else if (arguments.callee.target.loggingIn) {
arguments.callee.target.loggingIn = false;
return true; // allow your login only
} else {
// queue (suspended) all future requests during lockout
options || (options = {});
Ext.apply(options,{
queue:{name:'suspense', suspended:true} //add to suspended queue
});

}

}, A);

var sessionTimeoutHandler = function(statusCode, transaction, response, callback, isAbort) {
A._locked = true;

var withCallBack = function(success) {
if (success) {
A._locked = false;
A._lastRequest ? A.request.apply(A, A._lastRequest) : null;
var q;
if(q = A.queueManager.getQueue('suspense')){
q.resume();
A.queueManager.start();
}

}
};
with this mod: (createInterceptor may botch this tho :-? )
var submitForm = function() {
A.request.loggingIn = true; //simple function expando
loginForm.form.submit({
waitMsg : 'Logging in...',
method : 'POST',
clientValidation : true,
loggingIn : true,
success : success
});
}

mlarese
13 Jun 2008, 12:39 AM
I don't know if somebody tried before.
If you add ext-basex in docs/Index.html (ext api) you can navigate without server
:D

brookd
14 Jun 2008, 1:44 PM
I was playing with the ModuleManager and trying to get callbacks to work via the syntax explained here in Hendrics earlier post:
http://extjs.com/forum/showthread.php?t=21681&highlight=this.headers&page=5



Ext.require('panel', 'grid',{async: true, queue:{name:'mods',priority:1}});


But I think that is incorrect. You need to pass the modules as an array if you want to pass additional arguments:




Ext.requires(['panel'],{listeners:{'load':function(){console.log('loaded')},scope:this}})


Otherwise, it will try to load the object as a module and generate an error...

Please correct me if I am wrong here..

hendricd
14 Jun 2008, 7:02 PM
@brookd -- Release 3.0 (soon) of ext-basex and ModuleManager fully implements the theme described in that post. The current release does not.

But the syntax will be quite similar, expanded as well. Callbacks can be defined inline in the request chain and config options can be changed inline as well.

Your entire application shell could be reduced to something like this:




var loadAllYouCan = false;
Ext.require(
{ listeners: { //unique to current request chain
load : function (MM, module, response, content, executable ) { progressSoFarFn();}, //as each is done
complete: function(MM, howDidWeDo, loadedArray, executedArray ){}, //when all are done
loadexception : function (MM, module, errorObj){ //troubles
return complainAboutIt(module.name, errorObj) || loadAllYouCan;
}
},
progressInitFn,
{queue:{name:'ASAP', priority: 1}},
'viewport',
'grid',
'tree',
'state',
'customermap/customerUI',
{queue:{name:'TAKEYOURTIME', priority: 9}},
'customermap/customerUI.css',
{method : 'DOM' , queue:null },
'http://maps.google.com/maps?file=api&v=2&key=' + APP.MAPKEY,
App.buildMap,
//ext-basex script-tag-proxy support:
{params:{ GroupId: 'valued'}, proxied:{ callbackParam:'serviceFuncParam', callbackName : 'App.showCustomersOnTheMapFn' }},
'http://distantUrl.com/app/customerList.php', //xml response
progressDoneFn

);

This is targeted at support for 2.0x at the moment, as 2.1+ no longer distributes /packages/* :(

stever
16 Jun 2008, 5:20 PM
This is targeted at support for 2.0x at the moment, as 2.1+ no longer distributes /packages/* :(

Huh? They build for me... they are defined in the ext.jsb file, etc...

hendricd
16 Jun 2008, 6:29 PM
@stever -- That sounds promising, but /packages are not included in the standard 2.1 zip distribution. Were they in yours?

stever
16 Jun 2008, 6:33 PM
@stever -- That sounds promising, but /packages are not included in the standard 2.1 zip distribution. Were they in yours?

Ahh... never used the standard zip package. Do you? Well, I guess you do if that is what you are testing on...

Eric24
18 Jun 2008, 10:05 AM
@Doug, I love your library--kudos! I was wondering if you had ever gotten around to making a demo of your Ajax queue functionality?

I'd like to get your input on a couple of questions/thoughts:
1) Is it possible to add a max-simultaneous-requests limit to an individual queue? For example, I may want to give a low-priority polling queue only access to one "channel", in order to keep other channel(s) open for upcoming higher-priority requests. The prioritization alone does not address this, since a couple of low-priority requests could use up the available channels, leaving a new higher-priority request to wait.

2) Is it possible to configure a queue to never have more than 'n' queued requests (any additional ones just "replacing" the last one that's waiting)? For example, a request to update a detail panel might get hit dozens of times as the user clicks around on a grid. By setting the max-queued-requests to 1 in this case, each subsequent request would just replace the one that was already waiting, so if 10 requests came in before the first one completed, only the 10th one would actually get executed.


Thanks!
Eric

hendricd
18 Jun 2008, 11:35 AM
@Doug, I love your library--kudos! I was wondering if you had ever gotten around to making a demo of your Ajax queue functionality?

No, but using it live tho! Planning on one for the ext-basex 3.0 release, tho.


I'd like to get your input on a couple of questions/thoughts:
1) Is it possible to add a max-simultaneous-requests limit to an individual queue? For example, I may want to give a low-priority polling queue only access to one "channel", in order to keep other channel(s) open for upcoming higher-priority requests. The prioritization alone does not address this, since a couple of low-priority requests could use up the available channels, leaving a new higher-priority request to wait.

2) Is it possible to configure a queue to never have more than 'n' queued requests (any additional ones just "replacing" the last one that's waiting)? For example, a request to update a detail panel might get hit dozens of times as the user clicks around on a grid. By setting the max-queued-requests to 1 in this case, each subsequent request would just replace the one that was already waiting, so if 10 requests came in before the first one completed, only the 10th one would actually get executed.

Thanks!
Eric
This might sum up things up for you: (again 3.0 stuff)



var A = Ext.lib.Ajax;
var QM = A.queueManager;
var Q;

//create some Queues

//You could control queue size limits yourself,
//just add a limit property for the queue and its event
QM.createQueue({name:'chat', priority:2, FIFO:true});
QM.createQueue({name:'treenodeclicks', priority:9, FIFO:false, limit: 1}); == LIFO, dispatch the latest request first.

/* Dispatch mode: progressive
* false (default) to exhaust each prioritys' queues (sequentialy) during dispatch (left-to-right, top_to-bottom)
* true to dispatch a 'single' request from each priority::queue until all are exhausted.
*/
QM.progressive = true;

A.on('beforequeue', function( Q, requestArgs ){
if(Q.name == 'treenodeclicks' && Q.limit){
return (Q.requests.length < Q.limit); //or false, discard it
or:
if(!!Q.requests.length) Q.clear(); //dump the queue before adding this request
return true;
or:
if(!!Q.requests.length) Q.suspend(); //suspend dispatch on the queue before adding this request
return true;
}
}; //false return value would discard the request altogether.

Control over the dispatch (progressive vs sequential) method and the event handler makes things quite flexible.

pompom
19 Jun 2008, 4:04 AM
2-3 weeks.

Hello there :)

As it has been 4 weeks, do you have a new estimation of when release 3.0 will be available ?

Thanks :)

hendricd
19 Jun 2008, 4:45 AM
Sorry about that. The FF3 release thru a wrench into 'many a schedule'. Testing (for a few more days..)

hendricd
20 Jun 2008, 11:03 AM
3.0 adds:

- Enhanced request-Queue management (suspend, resume, and progressive/sequential queue dispatch).
- Adds script-tag support directly to lib.Ajax stack (so its now tied in with the native Ext.Ajax event system as well.)



Ext.Ajax.request({
url: 'http://www.flickr.com/services/rest/',
params:{ method:'flickr.photos.getRecent', per_page: '12', format:'json', "api_key": YourKey},
proxied: {debug:true,
callbackParam: 'jsoncallback',
callbackName: 'yourResponseHandlerFnName' //optional
},
queue: {name:'flickr', priority: 7},
timeout: 5000,
success: function( response) {
var recentPhotos = response.responseText;
},
failure: function(response, options){

}
});
ext-basex also includes the latest version (1.0beta1) of ux.ModuleManager. This version has been enhanced to support the new event management, queuing, and script proxy support capabilities of ext-basex.

These two new enhanced versions pave the way for something new:

Ext.JIT (Just-in-time). This new Ext addition provides support for loading resource bundles (CSS, JSON,scripts, XML, and markup) as complete packages and represents a significant shift in the way one can now structure RIAs. JIT will also provide a mechanism for progressive loading of Ext (or other) library dependencies based on standard/custom distribution packages (no more ext-all.js if you don't want to, without a complicated build process). More on all that soon...

Array.prototype extensions (beta2+) (using current forEach capabilities, some may look familiar ;) ) These prototype functions are extended if they do not already exist in Array.prototype :

:clear, clone, first, last, grep, filter, include, select, flatten, compact, and unique.

Other news:
- The license for ext-basex 3.0, ux.ModuleManager 1.0, and JIT 1.0 will change to GPL3. Current releases (2.3 and below) will remain GNU-LGPL3 licensed (yes, commercial licenses (http://licensing.theactivegroup.com) are available).
- ext-basex 3.0, and ux.ModuleManager 1.0beta, and Ext.JIT 1.0 alpha1 will all be available shortly via a google-code project/svn.

Browser testing (even FF3) has been good so far on the Windows platform, so Beta Feedback on other configs is appreciated.

Zip Download is available on the first thread post (http://extjs.com/forum/showthread.php?t=21681)as usual.

wm003
21 Jun 2008, 1:30 AM
Very nice. thanks for sharing.

I still suggest adding the current requestobject to the queue within the dispatch-function:


while(q.pending && !q.suspended && A.pendingRequests && A.activeRequests < A.maxConcurrentRequests){
// q.requestNext();
q.requestObj = q.requestNext();
if(q.progressive || qm.progressive){ break;}
}

wm003
21 Jun 2008, 1:41 AM
I also suggest adding some "forceQueue" option to be able to give ajax calls within widgets (like the treepanel) a priority aswell.

I did that in 2.3 like this


request : function(method, uri, cb, data, options) {

...

if(!this.events || this.fireEvent('request', method, uri, cb, data, options) !== false){
if (this.forceQueue && !options.queue) {
options.queue = {
priority: 5
};
}

hendricd
21 Jun 2008, 4:06 AM
I still suggest adding the current requestobject to the queue within the dispatch-function:


while(q.pending && !q.suspended && A.pendingRequests && A.activeRequests < A.maxConcurrentRequests){
// q.requestNext();
q.requestObj = q.requestNext();
if(q.progressive || qm.progressive){ break;}
}


As written in 3.0, your q.requestObj == q.activeRequest. It's set by the requestNext method. It's the same value. ;)


I also suggest adding some "forceQueue" option to be able to give ajax calls within widgets (like the treepanel) a priority aswell.

I did that in 2.3 like this



request : function(method, uri, cb, data, options) {

...

if(!this.events || this.fireEvent('request', method, uri, cb, data, options) !== false){
if (this.forceQueue && !options.queue) {
options.queue = {
priority: 5
};
}

..and, how about this one instead:


if(!this.events || this.fireEvent('request', method, uri, cb, data, options) !== false){
if((options.queue || (options.queue = this.queueAll)) && !options.queued){
var q = options.queue, qname = q.name || q, qm=this.queueManager;
q = qm.getQueue(qname) || qm.createQueue(q);
options.queue = q; //set its Queue object in options for use in response handlers
options.queued = true;

Permitting:
Ext.lib.Ajax.queueAll = {name:'turbo', priority:3}; or just 'true' for the existing default Queue.

wm003
21 Jun 2008, 4:46 AM
As written in 3.0, your q.requestObj == q.activeRequest. It's set by the requestNext method. It's the same value. ;)


:"> oh, i missed that one. Thanks for pointing me in the right direction :)



Permitting:

Ext.lib.Ajax.queueAll = {name:'turbo', priority:3}; or just 'true' for the existing default Queue.



Excellent solution! Exactly what i needed!:D

wm003
21 Jun 2008, 5:20 AM
if((options.queue || (options.queue = this.queueAll)) && !options.queued){

:-?mmh, what if treepanel or gridpanel are calling ajax.request then? options.queue will be false they are going not to be queued.. (or maybe i do not correly understand the if statement here..:-/)

So shouldnt it be
if((!options.queue |

instead of


if((options.queue |

hendricd
21 Jun 2008, 5:50 AM
:-?mmh, what if treepanel or gridpanel are calling ajax.request then? options.queue will be false they are going not to be queued.. (or maybe i do not correly understand the if statement here..:-/)


To clarify:

if((options.queue || (options.queue = Ext.lib.Ajax.queueAll)) && !options.queued){This asserts request.options.queue first (from a higher level component like TreeLoader), else (||) assert options.queue to lib.Ajax default (false, true, or Qconfig{}).

Of course you could still provide a queue configs on either TreeLoader or the Grid's Proxy as well.

wm003
21 Jun 2008, 6:36 AM
B) Ah, i understand now. Thanks. Are you going to implement this into the final 3.0 of basex?

hendricd
22 Jun 2008, 3:59 AM
B) Ah, i understand now. Thanks. Are you going to implement this into the final 3.0 of basex?

You'll see it in beta2. :D

coderobo
24 Jun 2008, 10:02 AM
I setup a redirect handler using -




function redirectHandler(conn, response, options ) {
debugger;
}
...
Ext.lib.Ajax.on('status:302', redirectHandler, this);
However when a JSON store load causes the server to return a 302, the redirectHandler never gets a chance to intercept the call. The browser (FF2) seems to preempt it by following the redirect, fetching the redirected page (login page) and stuffing the final 200 OK login response page to the JSON store loader.

I can see the above behavior using FF LiveHeaders add-on as well as using the std Ext Ajax event handler -



Ext.Ajax.on(
'requestcomplete' , redirectHandler
);
The requestcomplete handler only gets to fire after the browser has followed the 302 and got to the final page with a status of 200.

So the question that comes to the surface - Is this a bug in the ext-basex (I have tried 2.3 and 3.0 beta1) or the basex library can't trap 302 by virtue of any design limitations ?

The JSON store uses an HttpProxy w/o instantiating a new Connection object to allow it to get to the Singleton Ajax object:




function mkHttpProxy(tableid) {
return new Ext.data.HttpProxy({
url: 'itables/'+tableid+'-json.jsp'
});

var store = new Ext.data.Store({
proxy: mkHttpProxy(tableid),
....


Regards

hendricd
24 Jun 2008, 10:07 AM
Yes, 302 will generally be handled by the browser for you, so you'll have rather limited success with that.

If the session has indeed expired, your server should respond with 40x status, and then you can handle recovery/login screen client-side in a controlled fashion.

coderobo
24 Jun 2008, 10:36 AM
Yes, 302 will generally be handled by the browser for you, so you'll have rather limited success with that.

If the session has indeed expired, your server should respond with 40x status, and then you can handle recovery/login screen client-side in a controlled fashion.

Thanks Hendicd - The 40X are trapped so they are fine. Its the initial login that is triggered via a 302 that is the root of the problem. I am using a J2EE app server that uses the standard form-auth mechanism via a 302 redirect to login page. I don't have control over it. I suppose some messy server side programming could be used to trap the redirects and turn them into a 401 or an appropriate JSON response.

The more I use ext and Ext ux I realize it represents a paradigm shift from the Web 1.0 world. Perhaps these pitfalls should be mentioned in a FAQ.

Thanks

hendricd
24 Jun 2008, 10:40 AM
Wonder if you could set a header in the login POST and have the serverside avoid the redirect if it's present.

coderobo
24 Jun 2008, 12:32 PM
Wonder if you could set a header in the login POST and have the serverside avoid the redirect if it's present.

Yeah I am writing a Java Servlet filter that will trap the redirect and convert it into a 401 if it sees the XHR header in a POST.

hendricd
27 Jun 2008, 7:28 AM
See, this (http://extjs.com/forum/showthread.php?p=184817#post184817)for latest changes.

Eric24
27 Jun 2008, 8:24 AM
Doug,

What should I know about the simultaneous requests limit? Your defaults are 2 for IE and 4 for FF. What's behind that? Are there any guidelines or hard limits regarding this?

Thanks!

hendricd
27 Jun 2008, 8:33 AM
The current default for 3.0 is 10. That seems to be a good common denom for today's modern browsers.

lvanderree
29 Jun 2008, 5:09 AM
Hi Doug,

thanks for this great work!
I am using it in the symfony-extjs-theme-plugin (http://www.symfony-project.org/forum/index.php/m/55103/#msg_55103) (if that is OK with you). Together with the work of KRavEN I now can intercept if my session has been timed-out (401) so I can offer the opportunity to re-login and automatically re-request the latest action!

For a demo: http://tejohnston.dynora.eu/ (login: admin:admin) open a new window and logout via: http://tejohnston.dynora.eu/logout and now try to refresh the grid (or sort a column to get a better idea of the result).

I was wondering if it is also possible to implement (async.) lazy-loading of javascript and inject those includes in the header of your html, together with callback methodes? As the "using (http://www.jondavis.net/blog/post/2008/04/Javascript-Introducing-Using-%28js%29.aspx)" script is doing as well.
The using script is working fine for me to accomplish this, but I cannot intercept 401-headers with it when a person has been timed-out. That is why I want to combine it with your script, but maybe you have/had got some ideas for this as well?

hendricd
29 Jun 2008, 8:25 AM
....I was wondering if it is also possible to implement (async.) lazy-loading of javascript and inject those includes in the header of your html, together with callback methodes? As the "using (http://www.jondavis.net/blog/post/2008/04/Javascript-Introducing-Using-%28js%29.aspx)" script is doing as well.
The using script is working fine for me to accomplish this, but I cannot intercept 401-headers with it when a person has been timed-out. That is why I want to combine it with your script, but maybe you have/had got some ideas for this as well?

Wow. You're loading lots of externals, huh? :)

In order to trap HTTP status for resource requests like yours, you need to stick with straight Ajax requests (as <script> tags don't provide the necessary status reporting you would need for session timouts/re-authentication). Marrying "using" with basex will not work as "using" is unaware of the additional event plumbing/request queuing that basex provides. You would need one or the other but, not both.

The 3.0 basex package (containing ux.ModuleManager 1.0) has everything you'll likely need to do all that. To create your own equivalent of "using++", using basex, consider something like this:



(function(){

var L = new Ext.ux.ModuleManager({
disableCaching : false,
method : App.debug ? "DOM" /*<script> tags */: "GET" /* or POST -- pure Ajax */,
styleAdjust : {pattern:/url\(\s*\.\.\//ig, replacement:'url(../../resources/'}
});

var delegate = L.load.createDelegate;

Ext.apply( window, { //adjust to suit your dialect
$iNeed : delegate(L) ,

$iNeedLatest : delegate(L, [{disableCaching : true}], 0) ,

$iProvide : L.provides.createDelegate(L),

$iNeedBlocking : delegate(L, [{async:false}], 0),

$iNeedNoRealHurry : delegate(L, [{async:true, queue:'slow', priority: 9}], 0),

$iNeedForFrame : delegate(L, [{method: 'DOM', target: someFrame.window }], 0),

$iNeedForMIF : delegate(L, [{ target: someMIF }], 0),

$iNeedCSS : delegate(L, [{method: 'DOM'}], 0),

$iNeedCSSForSwapping : delegate(L, [
{ method:'GET',
listeners:{
load :function(ModMan, module, response, content){
ModMan.applyStyle(module, module.content = content);
}
}
} ], 0)
});
})();
Wire up that, with this (http://extjs.com/forum/showthread.php?p=180960#post180960)and this (http://extjs.com/forum/showthread.php?p=181993#post181993), and you've got a complete solution (a subset of what the upcoming Ext.JIT is designed to do).

$iNeed('packages/tinyMCE',function(success){
if(success){ doStuffwithtinyMCE(); }
});Tweak it. ;)

lvanderree
29 Jun 2008, 1:18 PM
Thanks for the fast response.

Yep, I indeed have a lot of includes. Almost every panel has its own file, since I am generating these with my generator. I only have to set some config-files and together with the datamodel this results in these panels. Fortunately KRavEN is working on a combiner to reduce the number of files for production versions to only one, and so the latency to get the panels loaded. (this will also remove my need for lazy-loading, but maybe it will be nice for other people and in development-environments).

I already was thinking of changing one or the other (preferably loose "using" and using basex only (with the ModuleManager)) to get this done. With this info I think I should be able to get some further. At the moment however I am very busy with getting a demo version of my graduation project ready for Wednesday, so till then I won't be working on it.

I'll come back to you whenever I have made some progress on it.

wm003
1 Jul 2008, 9:25 PM
Another Suggestion:
a config item for each ajax.request that will trigger cancelling currently running request with a lower priority than the new requesting one.
Something like


Ext.Ajax.request({
url: 'importantrequest.php',

success: ajax_success,
failure: ajax_failure,
queue: {
name : 'veryimportant',
priority: 1,
freeSlot: true //this will trigger basex to cancel a running request with a prio 2-9
}

});

bt_bruno
7 Jul 2008, 2:58 AM
@hendricd
It seems to be awesome to load js files dinamic. Ext.ux.ModuleManager is excellent. Congratulations. I'm writting a 'one-page-only' app and this is very usefull.

BTW, can I load .js files using autoLoad att from tabPanel? If no, it would be just what is missing.

Cheers!

hendricd
7 Jul 2008, 4:55 AM
BTW, can I load .js files using autoLoad att from tabPanel? If no, it would be just what is missing.

Ext.Panel::autoLoad can already load <script>s and markup. Not sure what you mean I guess.

hendricd
7 Jul 2008, 9:53 AM
Thanks for all the feedback. ;)

I'll begin documenting more here (http://code.google.com/p/ext-basex/)as time permits.

Romantik
7 Jul 2008, 1:27 PM
Hi all and hendricd
big thanks for plugin - it's good one for developer
Explain me simple situation and tell me please where I'm not correct?
I'm using your example adviframes and see something strange
I've replaced in the code of the tree
defaultSrc : 'http://www.google.com/'
to
defaultSrc : 'test.php'

test.php


<?php
echo time();
?>


when I click on this node I see current timestamp (e.g. 1215465924)
then after each action (click again on this node, reload, refresh) I don't see current time - only past time (1215465924)
So when I refresh via browser I see changed time =(

how to fix it?

thanks.

hendricd
7 Jul 2008, 1:34 PM
I think you've posted this in the wrong thread, but I suspect your browser is using a cached response.

Either set appropriate cache-control headers in your PHP response, or mangle the URL to prevent browser caching:


MIFP.setSrc('test.php?bustCache='+new Date().getTime() );

mystix
10 Jul 2008, 6:14 PM
hey @hendricd, just found this in the Examples forum:
jScout - full-featured javascript/css on-demand package loader (http://www.extjs.com/forum/showthread.php?t=40866)

haven't checked it out yet, but since you're working on JIT, thought it might be good to get a heads up on alternatives. :)

hendricd
11 Jul 2008, 4:12 AM
hey @hendricd, just found this in the Examples forum:
jScout - full-featured javascript/css on-demand package loader (http://www.extjs.com/forum/showthread.php?t=40866)

haven't checked it out yet, but since you're working on JIT, thought it might be good to get a heads up on alternatives. :)

Yep. Neat stuff. I saw that last week. Should be releasing JIT soon (Building a demo site that uses all it's goodies). Stay tuned. ;)

jlowe
11 Jul 2008, 10:06 AM
Hi Doug,

I'm refactoring our application to handle many of the repetitive tasks closer to (or within) the framework. One of those repetitive tasks is the decoding of the responseText to JSON.

I'm considering using ext-basex and modifying it (either the code itself or via runtime extension) to handle this task. It seems that adding a responseJson attribute to the response object, and populating it within createResponseObject(), would do the trick.

Have you considered this enhancement? Does this seem like the appropriate place to handle this?

On a related note, is your response object available to Ext.Ajax, or do I need to directly use your Ext.lib.Ajax?

Thanks,
-Jeff

hendricd
11 Jul 2008, 2:08 PM
@jlowe -- I had considered that earlier but was concerned about the potential response 'analysis' overhead. Thinking about more tho, now that you've brought it up again, it's certainly doable if the response's Content-Type contains '*/json'? Short of that, an expensive attempt would have to be made to determine if the response was JSON. :-?


On a related note, is your response object available to Ext.Ajax, or do I need to directly use your Ext.lib.Ajax?

No, all ext-basex enhancements to Ext.lib.Ajax and the responseObject (thus Ext.data.Connection) are transparent, so it would flow throughout the Ext framework.

jlowe
14 Jul 2008, 5:41 AM
... it's certainly doable if the response's Content-Type contains '*/json'? Short of that, an expensive attempt would have to be made to determine if the response was JSON. :-?

I believe that would be consistent with the XHR object, which populates responseXml if the Content-Type specifies XML. No need for further overhead.

stever
14 Jul 2008, 5:45 PM
I believe that would be consistent with the XHR object, which populates responseXml if the Content-Type specifies XML. No need for further overhead.

Prototype does this, adding responseJSON to the object.

Digital God
15 Jul 2008, 10:04 PM
Hi all, i've problem with ModuleManager.
It works fine, great solution for my app. But i have problem with charset.
I've russian text in loaded files, and charset is windows-1252 - it is possible to set utf-8?

mubenchi
15 Jul 2008, 11:59 PM
i want to use Ext.lib.Ajax.onStatus to deal with the situation that the server check session timeout,and give a http 302 or 401 and so on status.could any one give me a help?thanks

ZooKeeper
16 Jul 2008, 3:42 AM
I'm also greatly in favor of responseJson. It'll be a lifesaver, since I have to decode it in EVERY callback.
Relying that much on content type is probably not such a good idea, since not everyone can set it.

hendricd
16 Jul 2008, 11:13 AM
Hi all, i've problem with ModuleManager.
It works fine, great solution for my app. But i have problem with charset.
I've russian text in loaded files, and charset is windows-1252 - it is possible to set utf-8?

@Digital God -- If you are loading a resource via a standard XHR request(GET, POST) the browser always assumes the response is going to be UTF-8. You server should encode the response as UTF-8 prior to sending it (or save your file with UTF-8 encoding before serving it up).

hendricd
16 Jul 2008, 11:23 AM
i want to use Ext.lib.Ajax.onStatus to deal with the situation that the server check session timeout,and give a http 302 or 401 and so on status.could any one give me a help?thanks

@mubenchi -- Have a look at this post (http://extjs.com/forum/showthread.php?p=180960#post180960) (and beyond, on this thread) for some sample usage and other things you may need to consider as well.

hendricd
16 Jul 2008, 12:05 PM
I'm also greatly in favor of responseJson. It'll be a lifesaver, since I have to decode it in EVERY callback.
Relying that much on content type is probably not such a good idea, since not everyone can set it.

@Zookeeper -- While I understand where you're coming from with that, it's somewhat dangerous to be evaling anything that comes along in a response.

Anywho:

I've given all this a bit of thought (during a short vacation :> )...

There are a number of issues that arise when making assumptions about JSON handling, and I thought I would throw out a code frag for review/feedback for sensibility:



Ext.apply(Ext.lib.Ajax, {

decodeJSON : Ext.decode, //optional custom JSON decoder implementation

reCtypeJSON : /\/json/gi ,

createResponseObject : function(o, callbackArg, isAbort){
var obj = {responseXML :null,
responseText :'',
responseStream : null,
responseJSON : null,
getResponseHeader : {},
getAllResponseHeaders : ''
};

// some existing code omitted for clarity......

if(o.options.isJSON || this.reCtypeJSON.test( headerObj['Content-Type'] || "" ){
try{
obj.responseJSON = this.decodeJSON(obj.responseText);
} catch(exJSON){
o.status.isError = true;
o.status.error = exJSON;
//Raise lib.Ajax Exception Event
if(this.events){
this.fireEvent('exception',o ,obj, callback, isAbort, exJSON);
}

}
}
.........
});
Some notes on flexibility:

1) It comes at a price. Content-Type header evaluation could be expensive.
2) Script injection is a risk here, so an optional Ext.lib.Ajax.decodeJSON function permits custom JSON "Crockford-scrutiny" if your implementation demands it (otherwise it falls back to the standard Ext.decode -- a simple eval).
3) The regex Content-Type test pattern (reCtypeJSON ) can be adjusted to suite your needs as well.
4) request.options.isJSON is a request hint that the response will be JSON, thus it would preclude the need to adapt server code to send either text/json or application/json Content-type response headers on each response (altho in practice, the new RFC says you SHOULD).

Food for thought. :-?

mystix
16 Jul 2008, 5:54 PM
might be easier to just set


decodeJSON: Ext.decode, // custom json decoder function -- defaults to Ext.decode
then you could do away with


this.decodeJSON || (this.decodeJSON = Ext.decode);
other than that, it looks good -- as usual ;)

Digital God
16 Jul 2008, 11:41 PM
hendricd
i'm using DOM method, because i use Adobe AIR and i can't use eval function

ZooKeeper
17 Jul 2008, 2:36 AM
might be easier to just set


decodeJSON: Ext.decode, // custom json decoder function -- defaults to Ext.decode
then you could do away with


this.decodeJSON || (this.decodeJSON = Ext.decode);
other than that, it looks good -- as usual ;)

I cann't agree more. If you are expecting Json then if it decode fails then it's either not a 200 code or something else which is an error anyway (there should be a param showing that json was successfully parsed). The other issue is if you want to figure out what error was it, parsing error, timeout or non200 code.

For myself I can say that I'd be happy with decodeJSON param and flag that it was successfully parsed or not.

hendricd
17 Jul 2008, 2:57 AM
See Code sample revised -- Thx Mystix.


I cann't agree more. If you are expecting Json then if it decode fails then it's either not a 200 code or something else which is an error anyway (there should be a param showing that json was successfully parsed). The other issue is if you want to figure out what error was it, parsing error, timeout or non200 code.

For myself I can say that I'd be happy with decodeJSON param and flag that it was successfully parsed or not.

@ZooKeeper -- HTTP status and timeout are already handled elsewhere in the basex stack.
See the revised code that adds the exception event when JSON decoding fails.

Also, if(response.responseJSON !== null) it processed a good JSON response. ;)

hendricd
17 Jul 2008, 6:06 AM
posted to svn/trunk (http://code.google.com/p/ext-basex/source/browse/trunk/source/ext-basex.js).

Lemme know how it goes. ;)

hendricd
17 Jul 2008, 10:30 AM
hendricd
i'm using DOM method, because i use Adobe AIR and i can't use eval function
@Digital God -- I'm not clear on what you are attempting here?

Are you trying to load a text file (what?) with a <script> tag(method:'DOM')? You don't have any control over response character-set from within the browser. The server must comply with your encoding wishes.

ZooKeeper
17 Jul 2008, 11:18 PM
There's a parentesis missing on the line
if(o.options.isJSON || (this.reCtypeJSON && this.reCtypeJSON.test( headerObj['Content-Type'] || "" ) )){

Digital God
18 Jul 2008, 2:02 AM
2hendricd
forget it, i've found my mistake))

hendricd
18 Jul 2008, 3:40 AM
There's a parentesis missing on the line
if(o.options.isJSON || (this.reCtypeJSON && this.reCtypeJSON.test( headerObj['Content-Type'] || "" ) )){

Fixed in trunk (bad paste 8-|)

lvanderree
18 Jul 2008, 5:13 AM
Doug, you are a hero ;)

The module manager.load works like a charm!

I will post a demo soon, KRavEN and I have thought of a real nice way to dynamically load new xtype-definitions, by extending the ComponentMgr.create method.

with the synchronize load-calls we can make with your module manager we can request the js-file on demand if the xtype isn't known yet :O

for the people who haven't figured out how to do so. a small example:



App.CodeLoader = new Ext.ux.ModuleManager({modulePath: baseUrl });

App.CodeLoader.load( {async:false, method:'SCRIPT'}, '/js/' + modulename + '/listAjaxGridPanelJs.pjs');
(similar examples can also be found in the basex-source)

hendricd
18 Jul 2008, 5:34 AM
Good to hear you guys are making progress. ;)

Here is a fragment of what JIT adds for what you are attempting:


Ext.require({method:'GET'}, 'widget-core',function(success){
if(success){
var mgr = Ext.ComponentMgr;

mgr.create = mgr.create.createInterceptor(function(config, defaultType){
var require;
if(require = config.require){
var o = {async:false},
setAsynch = function(rm){
return typeof rm === 'object' ? Ext.apply({},o,rm):
typeof rm ==='function' ? rm : {module:rm,async:false};
};

if(Ext.isArray( require) ){
require = require.map( setAsynch );
} else {
require = setAsynch(require);
}

Ext.require.apply(Ext,[].concat(require) );

}
});
}
});Which permits:


container.add({
xtype:'panel',
require: ['tabs','grid','gmaps'],
items: [.....] ,
.....
});

Slow down guys, you're stealin' my thunder. ;)

lvanderree
19 Jul 2008, 9:35 AM
Thunder and lightning are in the air! :D

I've adjusted the Ext.ComponentMgr.create method to make it request new scripts at the server if it detects the to be instantiated xtype is unknown. That is whay I call Lazy Loading :)

A demo can be found here:
http://tejohnston.dynora.eu/ (admin admin)

all grid-panels and form-panels you see are being requested with the Ext.ux.ModuleManager.load method (at the moment with a GET request, so not injecting the scripts into the header) when a xtype is being instantiated but not known yet.

It even works when you first need to login before you have enough credentials to retrieve the script! After login the request is being repeated automatically to show you the correct panels. (This is where the GET probably is an advantage above injecting scripts, since with injecting you would need to replace the result you got when you didn't had enough credentials, which now is solved automatically).

The only problem with GET is debugging is a little harder.

=D> for Doug! for his great work! and help!

A small example of what now is possible:


var editWindow = new Ext.Window({
items : [
{
xtype : ('Edit' + this.relatedModuleName + 'FormPanel').toLowerCase()
}
]
});
editWindow.show();
I don't need to load a script which defines this formpanel, it is being generated by my Symfony sfExtjsThemePlugin and automatically requested upon first use by my create.createInterceptor from the server!

Eric24
21 Jul 2008, 12:05 PM
@Doug: Is there a way to configure a queue to only handle one request at a time (even if there are other "slots" available)? In other words, a queue so configured would still be processed at its priority level, but only allow one outstanding request at a time, with any other requests in that queue just waiting until the outstanding request was complete.

hendricd
21 Jul 2008, 5:23 PM
@Doug: Is there a way to configure a queue to only handle one request at a time (even if there are other "slots" available)? In other words, a queue so configured would still be processed at its priority level, but only allow one outstanding request at a time, with any other requests in that queue just waiting until the outstanding request was complete.

@Eric24 -- What you are asking for is 'sequential optimism', not queuing. See if this (http://extjs.com/forum/showthread.php?p=120278#post120278) asynch pattern fits your needs (it won't begin the next until the previous has completed).

Eric24
22 Jul 2008, 6:16 AM
@Doug: The 'sequential optimism' (what a strange term) pattern is well understood, but I was hoping to do something like this within the context of the basex queues (so I don't have to manage these requests externally). Essentially, I want to take advantage of the queuing but either allow for a config option that puts a queue into "one at a time" mode (at which point I could trigger the next request--somehow?--in the success handler) or better yet, a "sequential" mode that does this under the covers. Whether each individual request succeeds or fails would still be handled in the respective success/failure handler, the only difference is that a queue in "sequential" mode would hold all but one of its requests (no different than if the max outstanding request limit had been reached). By integrating this with basex queues, you then have the option of controlling the request priority both by queue priority and by "sequential/parallel" mode.

Of course, whether you decide to do this or not is entirely up to you (I'm not quite advanced enough in ExtJS just yet to feel like I could make this mod in a reasonable period of time), but I'm curious to know if you see this as a useful addition?

Thanks
Eric

hendricd
23 Jul 2008, 4:30 AM
.... Essentially, I want to take advantage of the queuing but either allow for a config option that puts a queue into "one at a time" mode (at which point I could trigger the next request--somehow?--in the success handler) or better yet, a "sequential" mode that does this under the covers. Whether each individual request succeeds or fails would still be handled in the respective success/failure handler, the only difference is that a queue in "sequential" mode would hold all but one of its requests (no different than if the max outstanding request limit had been reached). By integrating this with basex queues, you then have the option of controlling the request priority both by queue priority and by "sequential/parallel" mode.


@Eric24 -- I believe a combination of the current progressive (one-at-a-time) queue mode and a single event listener, is all you'll need. Here is an example of how you would create that behavior with a series of queued requests:


var A = Ext.lib.Ajax;
var QM = A.queueManager;
var Q=QM.createQueue({name:'chained', priority: 3, progressive:true, suspended:true }); //one-at-a-time mode

A.on('request', function(method, uri, cb, data, options){
var Q=options.queue;
if(Q && Q.name == 'chained')Q.suspend(); //suspend the queue again until current completes
});

var add = function(){
Ext.Ajax.request({
url:url,
queue: Q.name ,
success: function(response){
var options = response.options;
if(options.queue){
options.queue.resume(); //re-enable for next request
QM.start();
}
//do your thing
},
failure : function( ) { same thing or dump the entire queue ??? },
....
});
};

//fill the Queue with 10 requests
for(var i=0,i<10,i++)add();

Q.resume();
QM.start(); //get things started

I hesitate to introduce internal functionality (as you describe) that might be based on success/failure. IMHO: Each implementation has specific needs in those scenarios and I don't think a sensible series of 'config options' could handle every use-case.

Queue behavior options and EventListeners, as shown above, offer tremendous flexibility for your own way of doing things.

Give that a try.

ClemsonJeeper
24 Jul 2008, 2:17 PM
I keep getting very sporatic errors of:

Ext.lib.Ajax.on is not a function

Noted in Firefox with Firebug.

I'm guessing this is because Ext.lib.Ajax has not fully loaded by the time I start using it?

However I am loading ext-all.js and ext-basex-min.js before I use any of if. (They are in the header).

Is there some synchronization issue or something? Does Ext.lib.Ajax need to be inside or outside of an Ext.onReady() {}?

thanks...

hendricd
25 Jul 2008, 4:30 AM
@ClemsonJeeper -- I suspect you may not have it (basex) loaded in the proper order, or you may not be waiting until onReady to do "something". Can you post your <head> section and describe in more detail what you are attempting when things go nuts?

hendricd
1 Aug 2008, 1:16 PM
requested .responseJSON features available in trunk (http://code.google.com/p/ext-basex/source/browse/#svn/trunk/source)?

I'd like to commit, but could use some feedback... :-?

lvanderree
5 Aug 2008, 5:25 PM
Hi Doug,

I'd like to respond, but don't know what to say ;) I see the responseJSON property, and see it contains the decoded object, which you probably can access directly after loading has succeeded, which seems nice, but need to use it in a real situation I think to give more feedback.

Or what else do you want to hear about it?

I had another question.

I have this code:


var loadMask = new Ext.LoadMask(Ext.getBody(), {msg:"<b>Loading Panel</b><br>&nbsp;<br>please wait..."});
loadMask.show();

Ext.app.CodeLoader.load( {async:false, method:'GET', cacheResponses:true}, '/js/getXtype/' + xtype );

loadMask.hide();


which runs in my componentMgr.create-interceptor but the loadMask only shows up in Firefox3, in FF2 Opera and IE6 (wine) I can't see the loading mask. My guess is, because it is done in a thread which is blocked because of the CodeLoader.load action. When CodeLoader.load is done the loadMask does appear, but immediately gets hidden by the loadMask.hide() call...
I can see that the show() method is good, since it works in FF3 and when I set a breakpoint in FF2 with firebug at the CodeLoader.load-line the mask is shown.

Any tips on how I can give it some time to render the mask?

Thanks again

hendricd
5 Aug 2008, 7:32 PM
...but the loadMask only shows up in Firefox3, in FF2 Opera and IE6 (wine) I can't see the loading mask.
@lvanderree -- Just gotta give the browser(s) time to render things:


var loadMask = new Ext.LoadMask(Ext.getBody(), {msg:"<b>Loading Panel</b><br>&nbsp;<br>please wait..."});
loadMask.show();

Ext.app.CodeLoader.load.defer(100, Ext.app.CodeLoader,[ {async:false, method:'GET', cacheResponses:true}, '/js/getXtype/' + xtype, loadMask.hide ] );


....

lvanderree
6 Aug 2008, 12:50 AM
@lvanderree -- Just gotta give the browser(s) time to render things:


var loadMask = new Ext.LoadMask(Ext.getBody(), {msg:"<b>Loading Panel</b><br>&nbsp;<br>please wait..."});
loadMask.show();

Ext.app.CodeLoader.load.defer(100, Ext.app.CodeLoader,[ {async:false, method:'GET', cacheResponses:true}, '/js/getXtype/' + xtype, loadMask.hide ] );


....


I thought about that as well, but this would make the CodeLoader do his thing in a new thread (async), while I want to make it run synchronous, so defering it will not work.

I have to keep the synchronous call, or else the constructor of the xtype is being called, before it is retrieved from the server.

lvanderree
6 Aug 2008, 4:25 AM
I haven't solved my previous issue, but wanted to know your opinion about the following:

I noticed you override the serializeForm method in basex, and I haven't looked at the differences between the original (2.2? version) and yours, but wanted to know what you think about checkboxes only sending their value when they are checked.

I override it like this:


case 'checkbox':
data += this.encoder(name) + '=' + this.encoder(el.checked ? true : false) + '&';
break;


always sending true OR false, depending on the checked property.

The biggest problem I had with the default functionality was that a checkbox returns 'on' instead of true. (I know you can set this with the inputValue property, but I don't like that default at all)

hendricd
6 Aug 2008, 5:24 AM
I have to keep the synchronous call, or else the constructor of the xtype is being called, before it is retrieved from the server.
This is supported too, ya know:


Ext.app.CodeLoader.load(
loadMask.show , //multiple inline functions
{async:false, method:'GET', cacheResponses:true},
'/js/getXtype/' + xtype,
loadMask.hide);
A progressBar could be implemented using this syntax as well. ;)


I noticed you override the serializeForm method in basex, and I haven't looked at the differences between the original (2.2? version) and yours, but wanted to know what you think about checkboxes only sending their value when they are checked.

I override it like this:


case 'checkbox':
data += this.encoder(name) + '=' + this.encoder(el.checked ? true : false) + '&';
break;
always sending true OR false, depending on the checked property.

The biggest problem I had with the default functionality was that a checkbox returns 'on' instead of true. (I know you can set this with the inputValue property, but I don't like that default at all)
My overrides merely provide an alternate encoding mechanism (base64/encrypted etc) during serialization of values. You might check with the HTTP spec on that. I'm not sure whether the design intent was to mimic that for checkboxes or not, but I see no reason why you couldn't.

lvanderree
6 Aug 2008, 5:51 AM
Ah brilliant,

it looks like this gives me best results:



Ext.app.CodeLoader.load(
Ext.MessageBox.wait("Loading Panel", "Please Wait..."),
{async:false, method:'GET', cacheResponses:true},
'/js/getXtype/' + xtype
);

Ext.MessageBox.hide()


So calling the hide() method outside the load-arguments, else hide was called before loading was finished (or so it seemed).

about the checkbox, I think conform the HTML standards checkboxes aren't supposed to send a value when they aren't checked, but I like to agree with saki about this: http://extjs.com/forum/showthread.php?t=25924 Although this behavior might be useful in early ages of internet now, that web pages are used as database frontends, I'd like to know that value is false.

markpele
17 Aug 2008, 2:03 PM
In my app I need to send scriptTag requests to a remote server.
Each request has an ID that get incremented by 1.
The server demands that the requests arrive in the correct order otherwise it closes the session.

Once in a couple of hours I get an error from the server indicating that requests arrived in the wrong order. Right now I'm using Ext scriptTagProxy but I wonder if basex can help me.

Is it possible that the order of two script requests is mixed in the way to the server?
Will a short timeout, something like 100ms can prevent it.
Does basex use some kind of timeout to address this problem?

Thank you.

hendricd
18 Aug 2008, 4:35 AM
In my app I need to send scriptTag requests to a remote server.
Each request has an ID that get incremented by 1.
The server demands that the requests arrive in the correct order otherwise it closes the session.

Once in a couple of hours I get an error from the server indicating that requests arrived in the wrong order. Right now I'm using Ext scriptTagProxy but I wonder if basex can help me.

Is it possible that the order of two script requests is mixed in the way to the server?
Will a short timeout, something like 100ms can prevent it.
Does basex use some kind of timeout to address this problem?

Thank you.

@markpele -- The load method of the included ux.ModuleManager could manage most of that for you (leveraging the built in ScriptTagProxy support of basex), but it would be useful to see some code showing what you're trying to sequence before I could propose a solution.
How often are you making the requests? is this a Chat protocol?

markpele
18 Aug 2008, 5:42 AM
Yes, it is a chat protocol.
I'm using long polling where you use the two browser slots to enable server push.
It could happen that the app sends automatically an empty 'keep alive' request and immediately afterwords the user will send a request so practically the two requests are being sent right after the other.

I could easily check if the time gap between the requests is not long enough and delay the second request. I just wanted to verify that it's theoretically possible that the request will arrive to the server in the wrong order.

hendricd
18 Aug 2008, 6:31 AM
...It could happen that the app sends automatically an empty 'keep alive' request and immediately afterwords the user will send a request so practically the two requests are being sent right after the other.
.... I just wanted to verify that it's theoretically possible that the request will arrive to the server in the wrong order.
@markpele -- As <script> tags are asynchronously fetched, its highly probable that (on a busy server) one request may take a bit longer than another. In that scenario, you will have to defer the next request until the previous has completed.

ModuleManager behaves in just that fashion, but you'll have to queue up (stack) your chat lines and let the load method handle that for you. Look at some of the recent posts on this thread for some examples.

ClemsonJeeper
27 Aug 2008, 7:23 PM
@ClemsonJeeper -- I suspect you may not have it (basex) loaded in the proper order, or you may not be waiting until onReady to do "something". Can you post your <head> section and describe in more detail what you are attempting when things go nuts?



<link rel="stylesheet" type="text/css" href="/ext/resources/css/ext-all.css"/>
<script type="text/javascript" src="/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="/ext/ext-all-debug.js"></script>
<script type="text/javascript" src="/contrib/ext-basex/ext-basex.js"></script>
<script type="text/javascript" src="/javascript/main.js"></script>


Is contained in <head>. main.js includes:




Ext.onReady(function() {

Ext.lib.Ajax.on('status:402', function () {
Ext.Msg.alert('Timed Out', 'Your session has timed out. Click OK to re-log in.',
function () {
window.location.href='/logout.php';
});
});
....


Before it does anything.

I sporatically get these Ext.lib.Ajax.on() not defined errors in Firebug. Note this ONLY happens when Firebug is enabled.

What am I missing? :-)

hendricd
28 Aug 2008, 3:17 AM
...I sporatically get these Ext.lib.Ajax.on() not defined errors in Firebug. Note this ONLY happens when Firebug is enabled.


Hmm. FF3 and FB (even latest 1.2.0) are still flaky at best together. But, I've never seen what you describe happen.

Tried un/re-install FBug yet?

ClemsonJeeper
28 Aug 2008, 1:23 PM
Hmm. FF3 and FB (even latest 1.2.0) are still flaky at best together. But, I've never seen what you describe happen.

Tried un/re-install FBug yet?

Yep... latest of both versions... happens on multiple computers.

Does it look like I'm calling things correctly and loading things properly?

Is there anything I can do to debug this?

Makor
2 Sep 2008, 1:14 AM
HELP. In IE (IE7 ?) forEach loses scope...

Exemple :


forEach(dataArr,function(item,index,scope){
if (item.get('type_name')=='test') this.Discover++;
else if (item.get('type_name')=='test2') this.Transp++;
},this.shipCounters);


in FF i get this.shipCounters.Discover = 3

in IE - this.Discover is undefined and dont count...

Use last version of basex

hendricd
2 Sep 2008, 3:28 AM
HELP. In IE (IE7 ?) forEach loses scope...

Exemple :


forEach(dataArr,function(item,index,scope){
if (item.get('type_name')=='test') this.Discover++;
else if (item.get('type_name')=='test2') this.Transp++;
},this.shipCounters);
in FF i get this.shipCounters.Discover = 3

in IE - this.Discover is undefined and dont count...

Use last version of basex

@Makor -- Try this simple test on FF and IE:



var c = {a:0, b:0};
var d = [1,2,1,2,1,2,1,1];

forEach(d,function(item, index, collection){
this[item == 1?'a':'b']++;
},c);
alert( Ext.encode(c)); //should equal : {"a":5,"b":3}

Makor
2 Sep 2008, 3:38 AM
Test in FF:
{"a":5,"b":3}

Test in IE:
{"a":0,"b":0}

hendricd
2 Sep 2008, 3:57 AM
@Makor -- What version of basex (and IE) is this?

That test works as expected on all platforms with basex 3.0. :-?

Makor
2 Sep 2008, 11:54 PM
IE 7. basex - 3 Final after upgrade. And previus, dont know version. But error was in both versions...

hendricd
3 Sep 2008, 6:56 AM
IE 7. basex - 3 Final after upgrade. And previus, dont know version. But error was in both versions...

@Makor -- basex uses applyIf in many cases when adding forEach support to the various prototypes. Are you, by chance, using Ext with another JS framework that provides similar forEach functionality on IE?

ZooKeeper
3 Sep 2008, 9:01 AM
Doug! Thanks a lot for your terrific work in keeping all you projects going and so constantly supported.

I've got maybe not exactly basex question here, but what the heck.

I want to implement such a behavior that when I make Ext.Ajax.request it'll always have isJson option turned on, but for Store requests for it to be off.

I want this for:
1) Not writing isJson with every single request i make (which is a lot)
2) Not make a useless and really expensive Ext.decode on the data for stores.

If I override Ext.lib.Ajax and set isJson: true that makes it decode in both cases.
So how do i specifically turn it on only for Ajax.requests?

Thanks

hendricd
3 Sep 2008, 9:46 AM
Doug! Thanks a lot for your terrific work in keeping all you projects going and so constantly supported.

I've got maybe not exactly basex question here, but what the heck.

I want to implement such a behavior that when I make Ext.Ajax.request it'll always have isJson option turned on, but for Store requests for it to be off.

I want this for:
1) Not writing isJson with every single request i make (which is a lot)
2) Not make a useless and really expensive Ext.decode on the data for stores.

If I override Ext.lib.Ajax and set isJson: true that makes it decode in both cases.
So how do i specifically turn it on only for Ajax.requests?

Thanks
@ZooKeeper --
You have a few options.

My personal preference for store-load-efficiency (and error recovery):



//Ext 2.2 shown here.
Ext.override( Ext.data.JsonReader, {
read : function(response){
var o = response.responseJSON || Ext.decode( response.responseText);
if(!o) {
throw {message: "JsonReader.read: Json object not found"};
}
return this.readRecords(o);
}
});
Might as well take advantage of it, right? :-?

So, your JSON responses SHOULD return a suitable Content-Type of "application(/text)/json" or set {isJSON:true} in your load statement. If neither happens, there will be no responseJSON value and regular eval would take place by the reader.

For global flexibility, you have a couple of options:



//without a decoder defined, there is no eval, thus no responseJSON !
var A = Ext.lib.Ajax;
A.setJSON = function(bool){
A.decodeJSON = bool ? Ext.decode : false;
};

or, get silly with:



IwantJSON = true; //global switch

Ext.lib.Ajax.on( 'request' , function(method, uri, cb, data, options){
options || (options = {}); //assert any options
options.isJSON = IwantJSON;
});
Make sure your using the latest 3.1 from SVN (http://code.google.com/p/ext-basex/source/browse/trunk/source/ext-basex.js).

Use some or all. Tweak it! ;)

ZooKeeper
3 Sep 2008, 10:59 PM
Thanks for the a reply!

I've got the same content type for all my JSON coming out so this leaves me to setting isJSON manually for each request i make...


Ext.lib.Ajax.on( 'request' , function(method, uri, cb, data, options){
options || (options = {}); //assert any options
options.isJSON = IwantJSON;
});

again sets isJson for all requests..

Is there a way to make isJson=true globally for all Ext.AJAX.requests and leave it false for all store loads?

hendricd
4 Sep 2008, 2:54 AM
@ZooKeeper -- You may still be confused. basex populates responseJSON automatically when:

(response.content-type == '(application|text)/json' or options.isJSON == true ) and
typeof Ext.lib.Ajax.decodeJSON == function [eg. Ext.decode]


I've got the same content type for all my JSON coming out so this leaves me to setting isJSON manually for each request i make... What content-type are you sending back for JSON responses? One of the above? If not, your server isn't following the RFC for JSON. If it is, your stores are just fine with the JSON.Reader override (any actual JSON response would only get evaled once for data.Stores).


Is there a way to make isJson=true globally for all Ext.AJAX.requests and leave it false for all store loads?
By somehow setting isJSON true for all requests, an attempt will be made thoughout the framework to eval all responses (XML, HTML as well). Any eval failure there would force an exception and your Ajax request would fail even though it got a valid (HTML/XML) responseText. Setting isJSON globally would not be a good idea (unless your App ran on pure JSON alone).

hendricd
17 Sep 2008, 8:32 PM
Well after months of all talk and "no show", the wait is over. :>

With all the required enhancements to ext-basex now completed (v 3.1 required), $JIT arrives sporting a cool flickr photo-browser demo located here (http://freeport.theactivegroup.com/demos/demodesk.html?demo=flickr) (careful, it's addictive to watch :) ). But, the important thing to note is the initial load time.

The demonstration is based upon standard Ext 2.0.2 'packages' (with a few package tweaks) and demonstrates how to load portions of Ext on an "as-needed" basis (rather than ext-all.js).

So, what is $JIT?

Well, "Just in Time" man! And, no, it's not a compiler. /:)

It's a means to deliver external resources to your browser (Text, Markup, JSON, code, CSS, XML) with dependency management options as well.

$JIT sits on top of ext-basex (and the included Ext.ux.ModuleManager) and requires no server-side support, providing a new way of structuring large dynamic RIAs.

The basic philosophy goes like this:

1) Use the standard Ext /package builds (already provided in ext.jsb) or create your own required configuration for deployment (and not just for Ext either).

2) Then, tell $JIT what your packages look like. Here is an example:


$JIT.depends[ "mygrid" ] = {path: "assets/", depends: [ '@layouts', '@panelDD', '@fullgrid' ] }
The following statement would load 'assets/mygrid.js' after the layout, panelDD, and fullgrid packages were (or already) loaded (in the declared order) and optionally execute a callback function when completed:

$JIT('mygrid', buildUI );And, any of those packages may also contain other $JIT commands, loading additional resources they may require as well.

3)Then, load just the core Ext code (ext-base, ext-core, ext-basex, jit, ext-all.css) into your pages' <head> section as usual.

4) Then, $JIT takes over. Here's a simplified example:



$JIT( {method:'GET'}, //Ajax for standard packages
'panel',
'dragdrop',
'grid',
{method:'DOM', modulePath:'assets/'}, //switch to <script> tag mode for debugging.
'custom.css'
'myApp',
function(allLoaded){ //not executed until all dependencies are delivered
if(allLoaded){

buildUI();
}
}
);
And, you don't have code things proceduraly. $JIT is fully asynchronous (naturally, synchronous requests are supported too), so you can wait for a previously requested resource (elsewhere in your scripts) and act on them:


$JIT.onAvailable( 'custom.css', function(ok){
if(ok)
$JIT.applyStyle('custom.css'); //apply the stylesheet as soon as it arrives (removeStyle to clear it)
}, scope, 5000); //5 second timeout
And, you can wait for a specific class to arrive:


var showPurchases = function(toTabPanel){
$JIT('purchasesGrid');
$JIT.onClassAvailable( 'App.Customer.Purchases.Grid', function(ok){
if(ok) {
var G = this.add(new App.Customer.Purchases.Grid( {....}));
this.rendered && this.doLayout();
this.setActiveTab(G);
}
}, toTabPanel, 5000); //5 second timeout

};

And, talk about "lazy-loading"! $JIT adds this feature to the Ext.ComponentMgr:


tabs.add({
xtype: 'panel',
layout : 'fit',
JIT : ['gridFixes', 'gridfilters', 'ux/snapons'],
items:[ .... ]
});

Since $JIT uses ext-basex, you've also got Queuing and proxied (<script> tag) requests built in. See the demos' flikr.js source file for an example of that loading a store/dataview.

WAY too much to document here, but you should get the idea. Documentation (http://code.google.com/p/ext-basex/)and more samples are coming to the demo site (all based on $JIT of course) ;)

The latest 4.0 build can be found in /trunk (http://code.google.com/p/ext-basex/source/browse/#svn/trunk/source).
Enjoy.

kevinwu8
20 Sep 2008, 2:18 AM
Hi.Doug..

I have a login system..
Now i wish user submit this login form can use HTTP authentication via ext-basex..
Here is my submitForm function code..But it not work...


var submitForm = function() {
Ext.lib.Ajax.request({
async:false,
url:submitUrl,
method : 'POST',
userId:'userID',
password:'userPWD'
});
}
Would you please help me??...

very thanks..

Kevin..

hendricd
20 Sep 2008, 5:00 AM
@kevinwu8 -- Review this (http://extjs.com/learn/Manual:RESTful_Web_Services#HTTP_Authentication) and some of the other references included there, and make sure that 'Basic Auth' is something your really want (ie. is your site going to be public-facing without SSL?)

The userID/password submitted in HTTP headers are easily base64-decoded for viewing by the public.

If your talking about an intranet or SSL, try:



var submitLogin = function(userId, password) {

//Auth values passed in the open (base64 encoded)
Ext.Ajax.defaultHeaders.Authorization = "Basic "+ yourEncodebase64Fn(userId + ':' + password);

OR:

Ext.Ajax.request({
async:false,
url:submitUrl,
method : 'POST',
userId:userId,
password:password
});

OR:

Ext.lib.Ajax.request('POST', submitURL, null, data,
{
async:false,
userId:userId,
password:password
});
}
If you choose the generic route, you will need to provide the necessary base64 encoding function (yourEncodebase64Fn) for the header (here (http://extjs.com/forum/showthread.php?t=18222&highlight=base64)is one).

Eric24
26 Sep 2008, 2:09 PM
Doug,

Do you have a simple example of using a proxied cross-domain request with base-x?

Thanks!
Eric

hendricd
26 Sep 2008, 6:36 PM
Doug,

Do you have a simple example of using a proxied cross-domain request with base-x?

Thanks!
Eric
This is the relevant proxied JSONP request for flickr.com browser ( $JIT) demo:

//Make a proxied JSONP request to access the flickr API in JSON mode
Ext.Ajax.request({
url : 'http://www.flickr.com/services/rest'
,isJSON : true //they'll be no responseHeaders so, set the hint


,proxied :{
debug:true, //Preserves the <script> tag for examination
callbackParam: 'jsoncallback'
//callbackName : define callback functions of your own
}
,params:{
page : startPage || 1,
per_page : 50,
method :'flickr.photos.getRecent',
extras : 'tags,views,date_taken',
format :'json',
api_key : this.apiKey
}

,callback : function(options,success,response){

var trouble, photos = response.responseJSON;
//.responseXML,
// .responseText(could be anything presented via JSONP, [careful here])

if(/*transport*/ success && photos){

if(photos.stat == 'ok'){
this.activePage = parseInt(photos.page ,10) || 1;
this.store.loadData(photos);
} else {
trouble = String.format('flikr.com reports a problem:<br />Status: {0}<br />Reason:{1}<br />{2}',photos.stat,photos.code,photos.message );
}
} else {
trouble = String.format('The Remote request to Flikr.com failed:<br />Reason:{0}<br />{1}-{2}<br />{3}'
,response.status
,response.statusText
,response.fullStatus.error?response.fullStatus.error.description : null
,response.fullStatus.text );
}
if(trouble){
this.thumbView.getEl().update(trouble);
}

this.thumbView.hideMask();

}
,scope: this
});

Eric24
27 Sep 2008, 7:27 AM
Perfect--exactly what I was looking for!

On a related note, do you happen to know how to get Firebug to show proxied requests? Under Console or Net, it shows all requests to the origin domain, but even if I enable FB globally, it still doesn't seem to show the proxied transactions. Am I missing something or is it just not possible for FB to show these?

hendricd
27 Sep 2008, 7:34 AM
Perfect--exactly what I was looking for!

On a related note, do you happen to know how to get Firebug to show proxied requests? Under Console or Net, it shows all requests to the origin domain, but even if I enable FB globally, it still doesn't seem to show the proxied transactions. Am I missing something or is it just not possible for FB to show these?

As you may know, proxied requests are accomplished via <script> tags, so they would likely appear somewhere on the 'net' tab.

Note: Some enhancements were made recently for ext-basex and proxied support. Ensure you are using the latest from svn/trunk (http://code.google.com/p/ext-basex/source/browse/#svn/trunk/source).

wm003
8 Oct 2008, 4:20 AM
the latest revision (r33) always returns only 1 element from the responsed JSON Array(whereas all array-elements are objects) ...revision from September 18th (r32) always returns the correct amount of elements....very strange:-/

hendricd
8 Oct 2008, 5:18 AM
the latest revision (r33) always returns only 1 element from the responsed JSON Array(whereas all array-elements are objects) ...revision from September 18th (r32) always returns the correct amount of elements....very strange:-/

@wm003 -- Not sure what you mean. Can you elaborate on that?

mjlecomte
17 Oct 2008, 11:10 AM
Doug,

Do you have any ideas/suggestions how this might be used against a serverside permissions system? If I understand the theory behind $JIT, the client is essentially acting as the manager for the js resources. I'm wondering about situations where you'd want to deliver content depending if a user has access. Is this completely beyond the scope of $JIT?

hendricd
17 Oct 2008, 11:14 AM
Doug,

Do you have any ideas/suggestions how this might be used against a serverside permissions system?...

$JIT could be involved in the solution (as it can load/cache/manage just about anything), but ultimately the problem you mention must be addressed by a server-side ACL implementation.

What did you have in mind?

mjlecomte
17 Oct 2008, 11:31 AM
$JIT could be involved in the solution (as it can load/cache/manage just about anything), but ultimately the problem you mention must be addressed by a server-side ACL implementation.

What did you have in mind?

Hey, you can't answer my question with a question especially when I don't know what I'm even asking.

Ok, more seriously, what I had in mind is these areas of js files:


base/core ext library
classes, widgets, overrides
extensions, plugins
configs


Looking at it from GUI usage:

So Joe Blow hits a page and gets hit with a login script.
So at this point minimal amount of resources has been loaded.
Joe enters credentials and logs in.
At this point I guess we either redirect to new page or destroy some current content and stream in new content.
There's another extension (JScout) that suggests (I think) that you could pick the resources in some fashion to load in a particular order. So that some content might be delivered so the user can start working, while more content can stream in the background, giving the impression of a quicker load.
At this point let's say we have a rather basic page with a menu of some sort and maybe some commonly used widgets.
Hmmm.....I may be answering my own question at this point.
So, the menu, would be built from the serverside, taking into account ACL. So if the menu were constructed according to the ACL then the client would know what modules they have permission to.
Then let's say user wants to load some module ManagerLevelWindow1. ManagerLevelWindow1 I think may be built from a class ManagerLevelWindows and may also get some configuration data and store data from the server.


Are you getting a better picture of what I'm talking about now? I guess the simple creation of the menu may address where I was thinking the client could not really manage the resources.

Maybe it would just be Step 9, where $JIT would get the ManagerLevelWindows Class automatically (permission c/would be assumed granted if the menu was loaded in the first place), and then the backend would be responsible for determining what config and data to send back depending on the users ACL check.

What am I missing? :-?

hendricd
18 Oct 2008, 6:45 AM
@MJ -- What if you started lean:



<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Management</title>
<link rel="stylesheet" type="text/css" href="lib/resources/css/ext-all.css" />
<script type="text/javascript" src="lib/ext-corelib.js"></script>
<script type="text/javascript">
$JIT.setMethod("GET"); //set the default retrieval method: GET == minimal source to snoop
//load the startup script
Ext.onReady( function() { $JIT.script( 'startup'); });
</script>
</head>
<body>
</body>
</html>
startup.js:



//code is simplified for the discussion:

var doLogin = function(){

var howdWeDo = function(success){ //in this case, based on HTTP status (553, etc)
if(!success){
Ext.Msg.show({
msg:'You\'re an excellent typist but, try again.',
title: 'Authentication Failure',
buttons: Ext.Msg.OK});
}else{
loginWin[loginWin.closeAction]();

Ext.getBody().mask('One Moment...');

//preload some alternate themes in the backbground
$JIT({method:"GET", modulePath:'lib/Ext-'+Ext.version+'/resources/css/'}, 'xtheme-gray.css', 'xtheme-slate.css' );
}
};

with(
loginWin = new Ext.Window({
layout : 'fit',
height : 'auto',
width : 'auto',
items : {xtype: 'form', items: [ userid, password ] },
buttons: ['Login', 'Cancel' ]
})
){
buttons[0].handler = function(){
$JIT({method:'POST', params: getForm().getValues() } , 'admin/login.php', howdWeDo ); //returns JS tho
};

show();
}

};

$JIT('dialogs','window','form', doLogin); //load just what's needed for login

then serverside, 'admin/login.php' returns the next series of javascript actions based on Auth success/failure (again, simplified syntax):



<?php
$user = $_POST["userid"];
$ACL = serverSideAuthenticate($user, $_POST["password"]);
if($ACL === false){

http_send_status(553); //pick one
exit();

} else {

header('Content-Type: text/javascript');

setcookie('app_user', $user, time()+3600); //or other session strategy
session_start();
$_SESSION['user'] = $user;
$_SESSION['ACL'] = $ACL;

$buttonAdd = "{text:'Add',handler:function() { App.runtime.ManagerWin.addRecord(); } }";
$buttonEdit = "{text:'Edit',handler:function() { App.runtime.ManagerWin.editRecord(); } }";
$buttonDelete = "{text:'Delete',handler:function() { App.runtime.ManagerWin.deleteRecord(); } }";


//$JIT any dependencies (Ext packages, AppClasses) required to support use of this class.
echo "$JIT({ method:'DOM' /* for FireBugging things */ },'layouts','dialogs','window','classes/ManagerLevelWindows');";

echo "$JIT.onAvailable('ManagerLevelWindows', //wait for the base class for all ACL-based Windows"
echo " function(success){"
echo " Ext.getBody().unmask();";
echo " if(!success){ complainSomehow(); return; }";
echo " Ext.ns('App.runtime');";
echo " App.runtime.ManagerWin = new ??.ManagerLevelWindows({";

echo " layout : 'border',";
echo " height : 500,";
echo " width : 600,";
echo " title : 'Contact Maintenance',";
echo " items: ["
echo " {region:'west', layout:'accordian',items:[...], minWidth:300 },";
echo " {region:'center', xtype:'form', items:[fields....] }";

echo " ],";
echo " buttons: [";
if(true === $ACL['ADD']){ echo $buttonAdd."," ; }
if(true === $ACL['EDIT']){ echo $buttonEdit."," ; }
if(true === $ACL['DELETE']){ echo $buttonDelete."," ; }
echo " { text: 'Close', handler: function() { App.runtime.ManagerWin[App.runtime.ManagerWin.closeAction](); }";
echo " ]"

//Only include visible instance methods your ACL permits
if(true === $ACL['ADD']){
echo " ,addRecord : function(){ ........} ";
}
if(true === $ACL['EDIT']){
echo " ,editRecord : function(){ ........} ";
}
if(true === $ACL['DELETE']){
echo " ,deleteRecord : function(){ ........} ";
}
echo " });"
$theme = $ACL['favTheme'];
echo " $JIT.onAvailable( '".$theme."' , function(){ $JIT.applyStyle('".$theme."');}) ";
echo " App.runtime.ManagerWin.show();"

echo " });"

}
?>
It's an entirely different way of structuring a RIA using Ext, but demonstrates the progressive library loading capabilities of $JIT coupled with one of several ways to address your Application class design in conjunction with ACL.

Just food for thought. :-?

canxss
19 Oct 2008, 3:32 PM
Hi,

While I was trying to implement some general handler for response anomalies that can happen, I came across a problem:

All my responses are in JSON format. So on requestcomplete event I wanted to check if responseJSON is null and then take some action. I didn't set isJSON true but my ContentTypes were correct as "application/json; charset=utf-8". But as I moved along I saw this problem (by the way I'm not using queuing or other features of basex): For the first response responseJSON was correct but for the secong it was null and for the third it was correct and for the later it was null again. So I decided to debug and found out that the test method of RegExp was causing the problem. In the "Java Script - The Definitive Guide" it says:
"If you use exec( ) or test( ) on a pattern that has the g flag set, and you are searching multiple strings, you must either find all the matches in each string so that lastIndex is automatically reset to zero (this happens when the last search fails), or you must explicitly set the lastIndex property to 0 yourself."

Therefore for the first test it matches the application/json correctly (and sets the lastIndex to something bigger than zero) but for the second it doesn't (but sets the lastIndex to ZERO) so for the third it matches again correctly.

Anyway I'm new to Ext, JS and web programming :) but I thought this wasn't the intended behaviour. So I fixed this by setting lastIndex to ZERO after the test and my problem is solved.

hendricd
20 Oct 2008, 2:00 AM
@canxss -- Thanks for the catch on that one. I had left the 'g' in by mistake during testing. (:|
This has been corrected in SVN/trunk (http://code.google.com/p/ext-basex/source/browse/trunk/source/ext-basex.js).

To fix without an SVN download, just set the configurable:


Ext.lib.Ajax.reCtypeJSON = /(application|text)\/json/i ;in your startup code somewhere.

ZooKeeper
28 Oct 2008, 2:38 AM
Can you please hint where should i plug my default callback.
Let me explain a little.
I've got a standart procedure on EVERY ajax.request.
It involves something like this

Ext.Ajax.request({
url: 'someurl',
callback: function(opts,suss,resp){
if (!suss){
Ext.Msg.alert(c.Msg.Error, 'Some Error!');
return
}
var d = resp.responseJSON;
if (!d.success) {
Ext.Msg.alert(c.Msg.Error, d.msg);
} else {
myactualcallback();
}
}
});

I'd like to move all this stuff to some layer between ext-basex and my app.
So every callback will fire the code above and only then the myactualcallback should be fired.

hendricd
28 Oct 2008, 5:46 AM
Can you please hint where should i plug my default callback.
Let me explain a little.
I've got a standart procedure on EVERY ajax.request.
It involves something like this

Ext.Ajax.request({
url: 'someurl',
callback: function(opts,suss,resp){
if (!suss){
Ext.Msg.alert(c.Msg.Error, 'Some Error!');
return
}
var d = resp.responseJSON;
if (!d.success) {
Ext.Msg.alert(c.Msg.Error, d.msg);
} else {
myactualcallback();
}
}
});I'd like to move all this stuff to some layer between ext-basex and my app.
So every callback will fire the code above and only then the myactualcallback should be fired.
@Zookeeper -- For what you're after, I would recommend something like this:



(function(){

var AJAXHook = function(transportSuccess, response ) {
var _continue, rj ;
if( transportSuccess ){

//Now evaluate Application logic errors

if ( (rj = response.responseJSON) && !rj.success) ){
Ext.Msg.alert( rj ... );
_continue = false;
}

} else { //Other problem
var e = response.fullStatus.error;
e = e.message || e.description || e;
Ext.Msg.alert( 'Other Error' , e );
}

return _continue; // 'false' prevents any further callbacks from executing
};

Ext.lib.Ajax.on({
response : function(connObj, response, callback, isAbort ){
return AJAXHook(true, response); //HTTP transport succeeded
},

//handle transport failure or when the JSON was invalid.
exception : function(connObj, response, callback, isAbort){
return AJAXHook(false, response); //HTTP transport(or other failure) failed
}
});

})()

ZooKeeper
29 Oct 2008, 4:17 AM
This is great!
All that I wanted.
The only issue is that it fires with every single Store load. Is there a way to limit this hook only to Ajax.requests that I explicitly call? :-?

Btw, why are you specifying "(function(){"? What's the benefit of it?

Thanks a lot!

P.S.: Am I missing something here? please take a look at the line of ext-basex that states "o.status.proxied = !!o.proxied;". Doesn't look right to me.

hendricd
29 Oct 2008, 4:45 AM
The only issue is that it fires with every single Store load. Is there a way to limit this hook only to Ajax.requests that I explicitly call?One slight change permits that:


myApp.debug.JSONHook = function(transportSuccess, response ) {
var _continue, rj ;
if( transportSuccess ){

//Now evaluate Application logic errors

if ( (rj = response.responseJSON) && !rj.success) ){
Ext.Msg.alert( rj ... );
_continue = false;
}

} else { //Other problem
var e = response.fullStatus.error;
e = e.message || e.description || e;
Ext.Msg.alert( 'Other Error' , e );
}

return _continue; // 'false' prevents any further callbacks from executing
};

Ext.lib.Ajax.on({
response : function(connObj, response, callback, isAbort ){
return response.options.storeHook ?
response.options.storeHook(true, response) : null ; //HTTP transport succeeded
},

//handle transport failure or when the JSON was invalid.
exception : function(connObj, response, callback, isAbort){
return response.options.storeHook ?
response.options.storeHook(false, response) : null ; //HTTP transport(or other failure) failed
}
});
Then, when you want JSON analysis on a request:


store.load({ params: {}, storeHook: myApp.debug.JSONHook });

...Btw, why are you specifying "(function(){"? What's the benefit of it?

In my previous post, that kept the AJAXHook function privately-scoped to the two lib.AJax event handlers.


P.S.: Am I missing something here? please take a look at the line of ext-basex that states "o.status.proxied = !!o.proxied;". Doesn't look right to me.

Since the 'proxied' request option can either be:
true, false, undefined, null, or a config object,
that statement coerces "o.status.proxied" into an simple boolean value. It is correctly structured for that purpose. ;)

ZooKeeper
30 Oct 2008, 7:11 AM
Thanks a lot!
I've noticed another thing that took me like an hour to figure out.
My datepickers all over the app broke.
When i just click the trigger button it chooses the date a month before today's date.
Took me a while to figure that's your code causing this.


forEach([Date, Number, RegExp, Boolean], function(t) {
t.prototype.clone = function(deep) {
return deep ? new t(this) : this;
}
});

Commenting this block solves the issue.

hendricd
30 Oct 2008, 9:31 AM
Thanks a lot!
I've noticed another thing that took me like an hour to figure out.
My datepickers all over the app broke.
When i just click the trigger button it chooses the date a month before today's date.
Took me a while to figure that's your code causing this.


forEach([Date, Number, RegExp, Boolean], function(t) {
t.prototype.clone = function(deep) {
return deep ? new t(this) : this;
}
});Commenting this block solves the issue.

Ha! :">

Sorry about that. Didn't realize Ext already had a clone prototype for the Date object:

Replace with this block instead:



forEach([ Number, RegExp, Boolean], function(t) {
t.prototype.clone = function(deep) {
return deep ? new t(this) : this;
}
});
Ext.applyIf(Date.prototype, {
clone : function(deep){
return deep? new Date(this.getTime()) : this ;
}
});

SVN updated.

Sander_S
9 Nov 2008, 2:16 PM
Cool extension Doug, JIT looks very nice =D>

However I'm having problems using it.

Whatever I try I always get the following exception:


'Array.prototype.forEach' is null or not an object
Even when I make the most basic setup: a html page only loading the files in the right order
I tested it using ext 2.0.2 / 2.2. FF3 and ie7 using the latest jit/basex version from svn

Any clue where this is coming from ? or how this could be fixed ?
The strange thing is I can load the demo normally ... :-? (there must be something different but I can't find it)

Hope someone can help

hendricd
10 Nov 2008, 8:48 AM
Cool extension Doug, JIT looks very nice =D>

However I'm having problems using it.

Whatever I try I always get the following exception:


'Array.prototype.forEach' is null or not an object
Even when I make the most basic setup: a html page only loading the files in the right order
I tested it using ext 2.0.2 / 2.2. FF3 and ie7 using the latest jit/basex version from svn

Any clue where this is coming from ? or how this could be fixed ?
The strange thing is I can load the demo normally ... :-? (there must be something different but I can't find it)

Hope someone can help
@Sander_S -- This issue has been resolved in SVN and the 3.1 release available on the first post.

Sander_S
10 Nov 2008, 2:13 PM
Thanks this solves the problem

However with 2.2 there is no xtemplate included in the builded package, so something missing in the jsb I think :S, had to include it manually otherwise it drops errors

Furthermore you forgot a ; in jit.js @ line 86 ;)

Can you also move the ext lib path config var 'libv' out of the lib, i have the path to ext different and i would like to not modify jit.js so I could just update to the newest version without changing it. (this is btw line 86)

hendricd
10 Nov 2008, 2:29 PM
Thanks this solves the problem

However with 2.2 there is no xtemplate included in the builded package, so something missing in the jsb I think :S, had to include it manually otherwise it drops errors

Furthermore you forgot a ; in jit.js @ line 86 ;)

@Sander -- Before you get too far with $JIT on Ext 2.2, know this: The demo is based on 2.0.2 packages. So, the .dependencies are based upon tweaked packaging that the .JSB's do/may not consider. (XTemplate is not the only unit that requires packaging attention).

I have yet to build a suitable package for Ext 2.2 as there are just too many pending bug fixes to settle on a final package structure for 2.2.

But, $JIT.depends allows you the freedom to declare unit packaging anyway you wish. The demo, likely shows the extreme potential with many smaller units altho 'less and larger'
units are certainly possible (depending on your build strategy).


Can you also move the ext lib path config var 'libv' out of the lib, i have the path to ext different and i would like to not modify jit.js so I could just update to the newest version without changing it. (this is btw line 86)You are meant to define these based upon your site heirarchy, I don't:


/* Define our dependency table for module names */

//define the site layout for Ext packages (most are already built for you!)
//define for DemoSite's lib/Ext-version

var libv = 'lib/Ext-'+Ext.version+'/';
var p = libv + 'package/';
var l = p + 'layout/';
var d = p + 'dragdrop/';
var w = p + 'widgets/';
var ux= p + 'ux/';



That's why the $JIT interface is published seperately from the core engine (ext-basex) so that you can customize the dependency strategy to meet the needs of your site.

Sander_S
10 Nov 2008, 2:43 PM
Btw, like your quick response with the issue above :), almost forgot that.



You are meant to define these based upon your site heirarchy, I don't:


/* Define our dependency table for module names */
...
That's why the $JIT interface is published seperately from the core engine (ext-basex) so that you can customize the dependency strategy to meet the needs of your site.

I know that I am suppose to adjust them. I only thought that this is one of the few things needing adjustments. Since there are also more methods in the file that could get updates the config could be apart from the methods in another file.

On the 2.2: I'm just experimenting with it, maybe I'll just use ext-all as the only one and use JIT for my custom files until it is updates. Unfortunately I'm not that much of an ext expert (yet?) to resolve the dependencies to 2.2 (and I also lack a bit of time...)

I'll let you know my experiences or if I run into something else.

hendricd
10 Nov 2008, 2:56 PM
On the 2.2: I'm just experimenting with it, maybe I'll just use ext-all as the only one and use JIT for my custom files until it is updates. Unfortunately I'm not that much of an ext expert (yet?) to resolve the dependencies to 2.2 (and I also lack a bit of time...)

Ha! You wouldn't believe what it took to get the default 2.0.2 packaging tweaked (moved a few files around). The default JSB for it has a few holes in it.

And, 2.2 doesn't even ship with packages. So you'll have to tweak it's JSB similarly. (time permitting). :>

Ah, the quest for the 'holy grail' of Ext "dynaloading". ;)

Sander_S
11 Nov 2008, 1:16 AM
And, 2.2 doesn't even ship with packages. So you'll have to tweak it's JSB similarly. (time permitting). :>

Ah, the quest for the 'holy grail' of Ext "dynaloading". ;)

The builder has a nice depency list on it, isn't this available for other people ? A nice dependency tree would make it a lot easier ..

*Thinks of the beauty of java (could also be c# or so don't want to mess with people ;) ), with imports in every file that would make dynaloading very easy*

hendricd
11 Nov 2008, 4:23 AM
with imports in every file that would make dynaloading very easy*

Now, you're getting the picture. ;)
That's why $JIT also supports this syntax at the top/bottom of your source files



// CustomerEdit.js
$JIT.require('fullgrid', 'dialogs', 'layouts',....);

$JIT.onAvailable('layouts', function( success ){

//You app code...

});

$JIT.provide('customeredit');

hendricd
11 Nov 2008, 4:29 AM
with imports in every file that would make dynaloading very easy*

Now, you're getting the picture. ;)
That's why $JIT also supports this syntax at the top/bottom of your source files



// CustomerEdit.js
$JIT.require('fullgrid', 'dialogs', 'layouts',....);

$JIT.onAvailable('layouts', function( success ){

//You app code...

});

$JIT.provide('customeredit');


I really need some docs written. (:|

alayasf
25 Nov 2008, 6:20 AM
i tested the async = False with Ext.ux.plugins.RemoteValidator of Saki 's.
( https://extjs.com/forum/showthread.php?t=19112 )

Works perfectly

Does not work with Ext.ux.form.ServerValidator
( https://extjs.com/forum/showthread.php?t=19112&page=8 )

where is the problem?
Thank you

hendricd
25 Nov 2008, 7:47 AM
Does not work with Ext.ux.form.ServerValidator
( https://extjs.com/forum/showthread.php?t=19112&page=8 )

where is the problem?
Thank you

Because the option : async is not passed to the Ajax.request of ux.form.ServerValidator. Amend it to account for that:



,serverValidate:function() {
var options = {
url:this.url + '?#' + (this.field.name || this.name)
,method :this.method
,async : Ext.value(this.async ,true),
,scope:this
,success:this.handleSuccess
,failure:this.handleFailure
,params:this.params || {}
};

Chris in Cambridge
26 Nov 2008, 11:49 AM
Ha! You wouldn't believe what it took to get the default 2.0.2 packaging tweaked (moved a few files around). The default JSB for it has a few holes in it.

And, 2.2 doesn't even ship with packages. So you'll have to tweak it's JSB similarly. (time permitting). :>

Ah, the quest for the 'holy grail' of Ext "dynaloading". ;)

I'm willing to give it a shot for 2.2. Are there any pointers, details, or caveats that you might be able to share? Thanks.

wki01
26 Nov 2008, 11:50 PM
,serverValidate:function() {
var options = {
url:this.url + '?#' + (this.field.name || this.name)
,method :this.method
,async : Ext.value(this.async ,true),
,scope:this
,success:this.handleSuccess
,failure:this.handleFailure
,params:this.params || {}
};


What is the difference between use
async: true
and
Ext.value(this.async ,true)
?

Thank you

mystix
27 Nov 2008, 12:02 AM
Ext.value() was previously undocumented, so i added this description to the SVN docs yesterday:


/**
* Utility method for validating that a value is non-empty (i.e. i) not null, ii) not undefined, and iii) not an empty string),
* returning the specified default value if it is.
* @param {Mixed} value The value to test
* @param {Mixed} defaultValue The value to return if the original value is empty
* @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false)
* @return {Mixed} value, if non-empty, else defaultValue
*/
value : function(v, defaultValue, allowBlank){
return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
}

alayasf
1 Dec 2008, 3:32 AM
,serverValidate:function() {
var options = {
url:this.url + '?#' + (this.field.name || this.name)
,method :this.method
,async : Ext.value(this.async ,true),
,scope:this
,success:this.handleSuccess
,failure:this.handleFailure
,params:this.params || {}
};


Does not work.
I can assume that:
The remote Validator is a singleton and for this work.
The server validator extends observable and this does not work.

Thank you

hendricd
1 Dec 2008, 4:48 AM
@alayasf -- I have not studied Saki's class with significant detail, but the goal is to somehow pass the async options on through to Ext.lib.Ajax portion of the stack.

Have you asked Saki about adding support for that (and possibly headers, etc as well) ?

ludoo
11 Dec 2008, 8:36 AM
Hi,

Is there a chance to see baseX integrate a way to communicate through HTML5 PostMessage (http://ajaxian.com/archives/using-html-5-postmessage) ?

Thanks

canxss
9 Jan 2009, 6:49 PM
Hi,

I'm using FF 3.0.5 and IE 7.06 and when I make an Ext.Ajax.request and get 404 error, my request callback isn't get called in FF but it is called in IE.

Through this thread I confirmed that ext-basex is causing this problem:
https://extjs.com/forum/showthread.php?t=56906

Is there a solution to this?

Thanks in advance

jasonb885
18 Mar 2009, 5:09 PM
I'm willing to give it a shot for 2.2. Are there any pointers, details, or caveats that you might be able to share? Thanks.

It's shaping up to be fun so far. There's no longer a core package that includes ComponentMgr, so util/MixedCollection and widgets/ComponentMgr need to be loaded after ext-core and before jit. Looks like util/JSON needs to be loaded, too, so the Ext.decode fix happens.

Perhaps using the Ext Builder to build Core - Components and Core - Utilities and loading those first might make the most sense instead of trying to use JIT with only the ones that aren't already necessary. (And cat that into the ext-core file maybe.) Demand loading files that are absolutely essential anyway or nearly so probably makes little sense.

The more I look at it, the more useless it seems without feature packages. For example, generally you're going to load all the layout files. There's virtually nothing you'd want to exclude. Loading them all individually is less efficient.

mahesh122
19 Mar 2009, 11:49 AM
I am using ext-basex 3.1 and came across these two issues. I also had an attempt to fix them and it works fine. It would be great if the author confirms the issues & includes proper fix.

Issue 1:

When a queued request is aborted, QueueManager looses the pendingRequests count and QueueManager.dispatch function goes in indefinite loop (once all requests are dispatched)

A.abort simply sets the request.active to false


o.request.active = o.queued = false;


Queue.requestNext reduces A.pendingRequests only on if(req.active) But it pops the request out of queue.


To fix this: I tried moving the A.pendingRequests--; line outside of if(req.active)



requestNext : function(peek) {
var req;
this.activeRequest = null;
if (!this.suspended && (req = this.next(peek))) {
A.pendingRequests--;
if(req.active){ //was it aborted
this.activeRequest = A.request.apply(A,req);

} else {
return this.requestNext(peek);
}
}
return this.activeRequest;
}


Issue 2:
Queue.activeRequest is not released once done with the request. This holds the reference on the request (and its response).

I don't understand the necessity of this property as i find it accessed only within Queue.requestNext

If it is required to be there it has to be released porperly. I just removed the use of this property.

Changed requestNext looks like


requestNext: function(peek) {
var req;
this.activeRequest = null;
var acReq;
if (!this.suspended && (req = this.next(peek))) {
A.pendingRequests--;
if (req.active) { //was it aborted
acReq = A.request.apply(A, req);

} else {
return this.requestNext(peek);
}
}
return acReq;
}


Thank you,
Mahesh

hendricd
19 Mar 2009, 1:04 PM
@Mahesh

Regarding:

Issue 1: I'll have to review the impact of that, test, and get back to you. By chance, was your aborted queued-request the last item in the Q ?


Issue 2: There has been past interest (http://extjs.com/forum/showthread.php?p=179288#post179288) in maintaining the activeRequest property for the benefit of Comet applications (admittedly a narrow use case, as the value would likely change within a fraction of a second, but still accessible for events like queueempty where the ability to abort the the activeRequest might be desirable should queues be used in that decision).

mahesh122
19 Mar 2009, 2:09 PM
@Mahesh

Regarding:

Issue 1: I'll have to review the impact of that, test, and get back to you. By chance, was your aborted queued-request the last item in the Q ?


Issue 2: There has been past interest (http://extjs.com/forum/showthread.php?p=179288#post179288) in maintaining the activeRequest property for the benefit of Comet applications (admittedly a narrow use case, as the value would likely change within a fraction of a second, but still accessible for events like queueempty where the ability to abort the the activeRequest might be desirable should queues be used in that decision).

Issue 1: It was not, I guess. Actually, in my scenario, I had a datastore's load call that put an request. A moment later the same store's load was called with different parameters resulting in aborting the existing request and putting new one which was added as the last item in queue. I guess there were other requests in between these two.

Issue 2: I believe it is fine having activeRequest on Queue; but it has to be released once we are done with the request.

jasonb885
21 Mar 2009, 6:52 PM
Would it be possible to add support for:



- meta packages
- dynamic building of packages by passing the file names or a hash to a specific url


For example, JSLoad (http://www.instructables.com/community/Free-Code-JSLoad/) supports meta packaging as tags that only have other tags and a concacination url that is passed an ordered list of file deps to be handled in a fashion up to the developer.

While I have looked at the code, basex and JIT greatly exceed my skill level.

Thanks.

Hrm, looks like L.getMap is where the relevant magic happens. Ah, apparently none:true is what I was looking for. At least, it seems to offer the behavior I was seeking.

$JIT.onAvailable doesn't recognize none:true packages, though, so you can't act asynchronously on the completed loading of a meta package. Building the meta packages into actual dependency ordered packages on the server would solve that.

wki01
17 Apr 2009, 7:12 AM
Ext-base adapter extensions v2.3 is compatible with ext 3.0?
THANKS

hendricd
17 Apr 2009, 7:14 AM
Ext-base adapter extensions v2.3 is compatible with ext 3.0?
THANKS

Just back from the conference, and I'm evaluating the merits of that now...

Give me a couple days..

sarathy
24 Apr 2009, 11:08 AM
Hi Doug,

Thank you for building and supporting the basex. I am finding the



Ext.lib.Ajax.on('status:302', sessionTimeoutHandler)


very useful to centrailize session time out handling logic. I am using ext-basex2_2.zip with ext/JS 2.2.1 and noticing that the function is not getting triggered in IE6 and IE7. It works just fine in FF3. Is this a known problem or am I missing something?

hendricd
24 Apr 2009, 11:25 AM
Hi Doug,

Thank you for building and supporting the basex. I am finding the



Ext.lib.Ajax.on('status:302', sessionTimeoutHandler)
very useful to centrailize session time out handling logic. I am using ext-basex2_2.zip with ext/JS 2.2.1 and noticing that the function is not getting triggered in IE6 and IE7. It works just fine in FF3. Is this a known problem or am I missing something?

It is likely that IE is handling the 302 redirect internally and you never see the 302 reponse in your ajax request.

EDIT: Not sure much of this applies to your usage, but:

An HTTP redirection, whether executed by the Web browser or XMLHttpRequest, can be executed only if the redirection follows the same origin policy. If a redirection to another domain is attempted with XMLHttpRequest, the results vary. For example, Microsoft Internet Explorer returns a status code of 0 and no further data. Mozilla-based browsers return the status code 302 and the redirected URL.


Although using HTTP redirection can be effective, it can also be problematic from an Ajax perspective. When using the XMLHttpRequest object and calling a URL that generates a redirection, the redirected URL will be loaded automatically. This is bad because the script needs to know what the redirected URL is, but the XMLHttpRequest object doesn’t give that URL.

sarathy
27 Apr 2009, 9:50 AM
Hi Doug,

All my redirects within the same domain. Basically the server sends a redirect to login page when it detects session timeout. Ext/JS based AJAX handling need to detect this condition and let the redirect be effective.

As you suspect, I think IE is not allowing the 302 to bubble up to the ext layer. Since catching 302 is not working, I have devised crude way of looking in the response text for eye catchers to detect if a redirect has occurred.

Thanks for your prompt help.
Regards,
-sarathy

tasman
17 May 2009, 9:40 AM
Hello

I tried use basex with ext 3 and found the error:

this.headers is undefined
line 546: var cType = this.headers['Content-Type'] || null;


the same script with Ext 2.1 works well

very thanks!

hendricd
18 May 2009, 5:52 AM
Hello

I tried use basex with ext 3 and found the error:

this.headers is undefined
line 546: var cType = this.headers['Content-Type'] || null;


the same script with Ext 2.1 works well

very thanks!

@tasman -- Try the latest from google.code: SVN (http://code.google.com/p/ext-basex/source/browse/#svn/trunk/source%3Fstate%3Dclosed).

zombeerose
18 May 2009, 12:50 PM
I grabbed the latest SVN code but I am still getting this error:

this.defaultHeaders is undefined on line 845.

There appear to be several other issues with the new Ext 3.0 library that impact your extension.
* function initHeader is undefined - line 846
* function setHeader is undefined - line 852
* function handleReadyState is undefined - line 857

Are you aware of these?

hendricd
18 May 2009, 1:23 PM
I grabbed the latest SVN code but I am still getting this error:

this.defaultHeaders is undefined on line 845.

There appear to be several other issues with the new Ext 3.0 library that impact your extension.
* function initHeader is undefined - line 846
* function setHeader is undefined - line 852
* function handleReadyState is undefined - line 857

Are you aware of these?

Yes, since 3.0 is essentially a re-write, most of those functions are now private. 8-|

I be giving ext-basex a thorough review shortly..

tasman
18 May 2009, 4:00 PM
@tasman -- Try the latest from google.code: SVN (http://code.google.com/p/ext-basex/source/browse/#svn/trunk/source%3Fstate%3Dclosed).

Hello!

the error gone!

but there are another one:

this.initHeader is not a function

line 692: this.initHeader('Content-Type',cType,false);

thanks!

hendricd
19 May 2009, 7:02 AM
I grabbed the latest SVN code but I am still getting this error:

this.defaultHeaders is undefined on line 845.

There appear to be several other issues with the new Ext 3.0 library that impact your extension.
* function initHeader is undefined - line 846
* function setHeader is undefined - line 852
* function handleReadyState is undefined - line 857

Are you aware of these?


Hello!

the error gone!

but there are another one:

this.initHeader is not a function

line 692: this.initHeader('Content-Type',cType,false);

thanks!

OK, gang. Try the latest v3.3 from SVN (http://code.google.com/p/ext-basex/source/browse/#svn/trunk/source%3Fstate%3Dclosed)again. I [think] its all covered now. ;)

tasman
19 May 2009, 7:19 PM
Ok! now all works!

very thanks!!!!

wki01
21 May 2009, 8:04 AM
Hello
I would like to know if it is planned ext-basex LGPL licensed for ext 3.0.

thanks

hendricd
21 May 2009, 8:15 AM
Hello
I would like to know if it is planned ext-basex LGPL licensed for ext 3.0.

thanks

Sorry, no.

Since ext-basex does not qualify for Extjs's FLOSS exception introduced last year (as it replaces/enhances much of the core features of the ext-base adapter), it will likely remain GPL.

mschwartz
21 May 2009, 8:17 AM
Sorry, no.

Since ext-basex does not qualify for Extjs's FLOSS exception introduced last year (as it replaces/enhances much of the core features of the ext-base adapter), it will likely remain GPL.

Can't you go dual license?

1) If you are Ext licensed, follow that license
2) If you are not Ext licensed, then Ext and this is GPL

hendricd
21 May 2009, 8:23 AM
Can't you go dual license?

1) If you are Ext licensed, follow that license
2) If you are not Ext licensed, then Ext and this is GPL

ext-basex IS dual licensed (GPL/CDL). If you have commercial-use (or other non-GPL) interests in Ext or basex (and you use basex) you'll likely need a CDL (http://licensing.theactivegroup.com) for basex as well. ;)

mschwartz
21 May 2009, 8:26 AM
It's a real headache to keep track of who needs to be paid what anymore.

hendricd
5 Jun 2009, 3:55 AM
For more on the recent additions, see this post (http://extjs.com/forum/showthread.php?t=70396).

mrsunshine
5 Jun 2009, 5:24 AM
Is it possible with ext-basex to handle the case IE6 with activex deactivated?
So if the user has a ie6 with activex deactivated a fallback over iframe will be used for all Ext.Ajax.request()

greetings Nils

hendricd
5 Jun 2009, 5:37 AM
@mrsunshine -- Possible, but what a narrow (and unfortunate) edge-case to have to support. 8-|

Since most all Ext.Ajax requests are handled thru the Ext.data.Connection, why not just override/create a version of that which uses an IFRAME instead. (Performance will be crap tho, and very resource-intensive for a busy app.) You'd have to parse the FRAME document for each response, and you get no header support.

Is all that worth it for an obsolete browser? :-?

mrsunshine
5 Jun 2009, 5:48 AM
@mrsunshine -- Possible, but what a narrow (and unfortunate) edge-case to have to support. 8-|

Since most all Ext.Ajax requests are handled thru the Ext.data.Connection, why not just override/create a version of that which uses an IFRAME instead. (Performance will be crap tho, and very resource-intensive for a busy app.) You'd have to parse the FRAME document for each response, and you get no header support.

Is all that worth it for an obsolete browser? :-?
In my opinion of course NO ;-) but the customer is the king :(

for ext 2.2 i used


/*
* xmlHttpRequest fallback for IE6 with deactivated Active-X
*/

classname.XhrFallback = function() {
return {
init: function(containerId) {
var xhr = Ext.lib.Ajax.getConnectionObject();
if(!xhr){
// add needed emty form to body
Ext.getCmp(containerId).add({
xtype:'panel',
hidden: true,
html:'<form id="ie6xhrFallbackForm" enctype="multipart/form-data" style="display:none;"></form>'
});
Ext.getCmp(containerId).doLayout();

FallbackXmlHttpRequest = function(o) {
Ext.apply(this, o || {});
this.method = this.method || 'POST';
FallbackXmlHttpRequest.superclass.constructor.call(this);

if (this.success) {
this.on('requestcomplete', this.success);
}

if (this.failure) {
this.on('requestfailed', this.failure);
}
};

Ext.extend(FallbackXmlHttpRequest, Ext.data.Connection, {
request : function(o){
if (!o.params) {
o.params = 'ajax=1';
} else if (typeof o.params == 'object') {
o.params.ajax = '1';
} else {
o.params += '&ajax=1';
}

if (!o.form) {
o.form = 'ie6xhrFallbackForm';
}

if (!o.isUpload) {
o.isUpload = true;
}
o.async = o.async || false;
FallbackXmlHttpRequest.superclass.request.call(this, o);
}
});

Ext.Ajax = new FallbackXmlHttpRequest();
}
}
};
}();



in ext 3.0 this dosn't work any more, i suppose that's because

Ext.lib.Ajax.getConnectionObject();
is now a privat function.

is it possible to get my ext 2.2 code work for 3.0?

hendricd
5 Jun 2009, 5:58 AM
No factor really. Simple change:



classname.XhrFallback = function() {
return {
init: function(containerId) {
var xhr = Ext.lib.Ajax.getConnectionObject();
if(Ext.isIE && !window.ActiveXObject){

mrsunshine
5 Jun 2009, 6:12 AM
Thanks for the condition.

Now i have to compare Ext.data.Connection 2.2 and 3.0 to find out what change, because now it breks in my ugly ie6 testcase. i guess i have to rewrite my fallback :-?

mrsunshine
8 Jun 2009, 6:28 AM
Fallback works fine.

only

!window.ActiveXObject
produce a error in the connection class, but i don't need this condition.

Anyway thank you very much

fermo111
9 Jun 2009, 9:08 AM
Hi

I just tried it for the first time using the code from the svn.

I am not quite sure how the sync request work. Can you help me?

This is what I have written:

var rsp = Ext.lib.Ajax.request("POST", url, '', Ext.util.JSON.encode(request), {async: false});
expecting that the rsp object would contain a rsp.conn.responseText that I could read to get the answer from the remote server.

I found that there are cases in which the conn object is undefined, while I can see from Firebug that the server sends back a correct response.

Stepping through the code with Firebug, I could see that at the end of the makeRequest method, when the line that says:

r.send(postData || null);
is executed, there is a callback to the onStateChange method which in turns calls the handleTransactionResponse that does a

this.releaseObject(o);

When the call to the Ext.lib.Ajax.request returns, the conn object has been deleted and I cannot get the answer from the server.

What am I doing wrong? I do not want to use a callback to get the result, since this would defy the purpose of a synchronous call.

Thanks

Luca

hendricd
9 Jun 2009, 9:38 AM
Even though the call is synchronous, ext-basex preserves the async design of the callbacks to maintain maximim compatibility for use with Ext.Ajax (Data.Connection). As a result the reponse object is still passed back in the callbacks.

So, for the 'one-liner' sync request (I suspect) you're after:




var makeSyncRequest = function(method, url, data){
var resp;
Ext.lib.Ajax.request(
method,
url,
{
success : function(response){resp = response; },
failure : function(response) { resp = response; }

},
data,
{async: false}
);
return resp;
);Since the sync request is a blocking call, the function's return will contain your response.

Using Ext.Ajax, it's business as usual:


Ext.Ajax.request({
url : 'something.php',
method : 'POST',
params : {....},
failure : this.onBooBoo,
success : this.onCompleted,
scope : this,
timeout : 15000,
async : false
});

fermo111
9 Jun 2009, 9:40 AM
Just to go on with my work, I've added a config options, so that the last 3 lines of the 'handleTransactionResponse' now read:


if (!o.options.dontReleaseObject) {
!o.isPart && this.releaseObject(o);
}
return responseObject;

fermo111
9 Jun 2009, 10:52 PM
Oops. I wrote the last post before seeing your previous response.

Nice suggestion.

Thanks Doug

zombeerose
11 Jun 2009, 3:21 PM
I am getting this error when an intentionally invalid structure is returned as the response. ReadyState = 4 and mode = 'readystate'



this.createExceptionObject is not a function
http://www/includes/library/extjs/portal/source/core/ext-basex.js
Line 488


I am running FF3 + WinXP Pro. I am running ext-basex 3.4 from the Google Code.

Any ideas?

hendricd
11 Jun 2009, 5:32 PM
I am getting this error when an intentionally invalid structure is returned as the response. ReadyState = 4 and mode = 'readystate'



this.createExceptionObject is not a function
http://www/includes/library/extjs/portal/source/core/ext-basex.js
Line 488
I am running FF3 + WinXP Pro. I am running ext-basex 3.4 from the Google Code.

Any ideas?

@zombeerose -- What does the request look like and what is the responseText ?
Do you have a Firebug callstack available ?

zombeerose
15 Jun 2009, 2:14 PM
Not sure what you want from the Request. I'm posting some data like...


article: 100
data: [{"id":"1"}]
id: xnode-324
Response text ... Obviously it's a php error that is invalidating the response - but I think the function "createExceptionObject" should still be defined at this point.


Notice: Undefined variable: unknown in /srv/www/site/app/modules/modules/controllers/MyController.php on line 90
{"success":true}
Firebug callstack...


handleTran...Response()
onStateChange()
defer()


Variable states at the point of the error...


o.status.isError is true
isAbort is undefined
isTimeout is undefined
contentType is "application/json"
status is 200
statusText is "OK"
Anything else I can provide?

hendricd
15 Jun 2009, 2:30 PM
@zombeerose -- Can you post the actual Ext.Ajax.request (or Treeloader config for the request.) and the Content-Type header(s) your server returned.

If you set 'Break on All Errors' in Firebug, what is 'this' in the debugger when it starts? What Ext version is this?
Tuff, without a working example. ;)