<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The source code</title>
- <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
- <script type="text/javascript" src="../prettify/prettify.js"></script>
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
<style type="text/css">
.highlight { display: block; background-color: #ddd; }
</style>
</script>
</head>
<body onload="prettyPrint(); highlight();">
- <pre class="prettyprint lang-js"><span id='Ext-fx-Manager'>/**
-</span> * @class Ext.fx.Manager
- * Animation Manager which keeps track of all current animations and manages them on a frame by frame basis.
- * @private
+ <pre class="prettyprint lang-js"><span id='Ext-direct-Manager'>/**
+</span> * Ext.Direct aims to streamline communication between the client and server by providing a single interface that
+ * reduces the amount of common code typically required to validate data and handle returned data packets (reading data,
+ * error conditions, etc).
+ *
+ * The Ext.direct namespace includes several classes for a closer integration with the server-side. The Ext.data
+ * namespace also includes classes for working with Ext.data.Stores which are backed by data from an Ext.Direct method.
+ *
+ * # Specification
+ *
+ * For additional information consult the [Ext.Direct Specification][1].
+ *
+ * # Providers
+ *
+ * Ext.Direct uses a provider architecture, where one or more providers are used to transport data to and from the
+ * server. There are several providers that exist in the core at the moment:
+ *
+ * - {@link Ext.direct.JsonProvider JsonProvider} for simple JSON operations
+ * - {@link Ext.direct.PollingProvider PollingProvider} for repeated requests
+ * - {@link Ext.direct.RemotingProvider RemotingProvider} exposes server side on the client.
+ *
+ * A provider does not need to be invoked directly, providers are added via {@link Ext.direct.Manager}.{@link #addProvider}.
+ *
+ * # Router
+ *
+ * Ext.Direct utilizes a "router" on the server to direct requests from the client to the appropriate server-side
+ * method. Because the Ext.Direct API is completely platform-agnostic, you could completely swap out a Java based server
+ * solution and replace it with one that uses C# without changing the client side JavaScript at all.
+ *
+ * # Server side events
+ *
+ * Custom events from the server may be handled by the client by adding listeners, for example:
+ *
+ * {"type":"event","name":"message","data":"Successfully polled at: 11:19:30 am"}
+ *
+ * // add a handler for a 'message' event sent by the server
+ * Ext.direct.Manager.on('message', function(e){
+ * out.append(String.format('<p><i>{0}</i></p>', e.data));
+ * out.el.scrollTo('t', 100000, true);
+ * });
+ *
+ * [1]: http://sencha.com/products/extjs/extdirect
+ *
* @singleton
+ * @alternateClassName Ext.Direct
*/
-
-Ext.define('Ext.fx.Manager', {
+Ext.define('Ext.direct.Manager', {
/* Begin Definitions */
-
singleton: true,
- requires: ['Ext.util.MixedCollection',
- 'Ext.fx.target.Element',
- 'Ext.fx.target.CompositeElement',
- 'Ext.fx.target.Sprite',
- 'Ext.fx.target.CompositeSprite',
- 'Ext.fx.target.Component'],
-
mixins: {
- queue: 'Ext.fx.Queue'
+ observable: 'Ext.util.Observable'
},
- /* End Definitions */
+ requires: ['Ext.util.MixedCollection'],
- constructor: function() {
- this.items = Ext.create('Ext.util.MixedCollection');
- this.mixins.queue.constructor.call(this);
-
- // this.requestAnimFrame = (function() {
- // var raf = window.requestAnimationFrame ||
- // window.webkitRequestAnimationFrame ||
- // window.mozRequestAnimationFrame ||
- // window.oRequestAnimationFrame ||
- // window.msRequestAnimationFrame;
- // if (raf) {
- // return function(callback, element) {
- // raf(callback);
- // };
- // }
- // else {
- // return function(callback, element) {
- // window.setTimeout(callback, Ext.fx.Manager.interval);
- // };
- // }
- // })();
+ statics: {
+ exceptions: {
+ TRANSPORT: 'xhr',
+ PARSE: 'parse',
+ LOGIN: 'login',
+ SERVER: 'exception'
+ }
},
-<span id='Ext-fx-Manager-cfg-interval'> /**
-</span> * @cfg {Number} interval Default interval in miliseconds to calculate each frame. Defaults to 16ms (~60fps)
- */
- interval: 16,
+ /* End Definitions */
-<span id='Ext-fx-Manager-cfg-forceJS'> /**
-</span> * @cfg {Boolean} forceJS Turn off to not use CSS3 transitions when they are available
- */
- forceJS: true,
+ constructor: function(){
+ var me = this;
+
+ me.addEvents(
+<span id='Ext-direct-Manager-event-event'> /**
+</span> * @event event
+ * Fires after an event.
+ * @param {Ext.direct.Event} e The Ext.direct.Event type that occurred.
+ * @param {Ext.direct.Provider} provider The {@link Ext.direct.Provider Provider}.
+ */
+ 'event',
+<span id='Ext-direct-Manager-event-exception'> /**
+</span> * @event exception
+ * Fires after an event exception.
+ * @param {Ext.direct.Event} e The event type that occurred.
+ */
+ 'exception'
+ );
+ me.transactions = Ext.create('Ext.util.MixedCollection');
+ me.providers = Ext.create('Ext.util.MixedCollection');
+
+ me.mixins.observable.constructor.call(me);
+ },
- // @private Target factory
- createTarget: function(target) {
+<span id='Ext-direct-Manager-method-addProvider'> /**
+</span> * Adds an Ext.Direct Provider and creates the proxy or stub methods to execute server-side methods. If the provider
+ * is not already connected, it will auto-connect.
+ *
+ * var pollProv = new Ext.direct.PollingProvider({
+ * url: 'php/poll2.php'
+ * });
+ *
+ * Ext.direct.Manager.addProvider({
+ * "type":"remoting", // create a {@link Ext.direct.RemotingProvider}
+ * "url":"php\/router.php", // url to connect to the Ext.Direct server-side router.
+ * "actions":{ // each property within the actions object represents a Class
+ * "TestAction":[ // array of methods within each server side Class
+ * {
+ * "name":"doEcho", // name of method
+ * "len":1
+ * },{
+ * "name":"multiply",
+ * "len":1
+ * },{
+ * "name":"doForm",
+ * "formHandler":true, // handle form on server with Ext.Direct.Transaction
+ * "len":1
+ * }]
+ * },
+ * "namespace":"myApplication",// namespace to create the Remoting Provider in
+ * },{
+ * type: 'polling', // create a {@link Ext.direct.PollingProvider}
+ * url: 'php/poll.php'
+ * }, pollProv); // reference to previously created instance
+ *
+ * @param {Ext.direct.Provider/Object...} provider
+ * Accepts any number of Provider descriptions (an instance or config object for
+ * a Provider). Each Provider description instructs Ext.Directhow to create
+ * client-side stub methods.
+ */
+ addProvider : function(provider){
var me = this,
- useCSS3 = !me.forceJS && Ext.supports.Transitions,
- targetObj;
+ args = arguments,
+ i = 0,
+ len;
- me.useCSS3 = useCSS3;
-
- // dom id
- if (Ext.isString(target)) {
- target = Ext.get(target);
- }
- // dom element
- if (target && target.tagName) {
- target = Ext.get(target);
- targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
- me.targets.add(targetObj);
- return targetObj;
- }
- if (Ext.isObject(target)) {
- // Element
- if (target.dom) {
- targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
+ if (args.length > 1) {
+ for (len = args.length; i < len; ++i) {
+ me.addProvider(args[i]);
}
- // Element Composite
- else if (target.isComposite) {
- targetObj = Ext.create('Ext.fx.target.' + 'CompositeElement' + (useCSS3 ? 'CSS' : ''), target);
- }
- // Draw Sprite
- else if (target.isSprite) {
- targetObj = Ext.create('Ext.fx.target.Sprite', target);
- }
- // Draw Sprite Composite
- else if (target.isCompositeSprite) {
- targetObj = Ext.create('Ext.fx.target.CompositeSprite', target);
- }
- // Component
- else if (target.isComponent) {
- targetObj = Ext.create('Ext.fx.target.Component', target);
- }
- else if (target.isAnimTarget) {
- return target;
- }
- else {
- return null;
- }
- me.targets.add(targetObj);
- return targetObj;
- }
- else {
- return null;
+ return;
}
- },
-
-<span id='Ext-fx-Manager-method-addAnim'> /**
-</span> * Add an Anim to the manager. This is done automatically when an Anim instance is created.
- * @param {Ext.fx.Anim} anim
- */
- addAnim: function(anim) {
- var items = this.items,
- task = this.task;
- // var me = this,
- // items = me.items,
- // cb = function() {
- // if (items.length) {
- // me.task = true;
- // me.runner();
- // me.requestAnimFrame(cb);
- // }
- // else {
- // me.task = false;
- // }
- // };
-
- items.add(anim);
- // Start the timer if not already running
- if (!task && items.length) {
- task = this.task = {
- run: this.runner,
- interval: this.interval,
- scope: this
- };
- Ext.TaskManager.start(task);
+ // if provider has not already been instantiated
+ if (!provider.isProvider) {
+ provider = Ext.create('direct.' + provider.type + 'provider', provider);
}
+ me.providers.add(provider);
+ provider.on('data', me.onProviderData, me);
- // //Start the timer if not already running
- // if (!me.task && items.length) {
- // me.requestAnimFrame(cb);
- // }
- },
-<span id='Ext-fx-Manager-method-removeAnim'> /**
-</span> * Remove an Anim from the manager. This is done automatically when an Anim ends.
- * @param {Ext.fx.Anim} anim
- */
- removeAnim: function(anim) {
- // this.items.remove(anim);
- var items = this.items,
- task = this.task;
- items.remove(anim);
- // Stop the timer if there are no more managed Anims
- if (task && !items.length) {
- Ext.TaskManager.stop(task);
- delete this.task;
+ if (!provider.isConnected()) {
+ provider.connect();
}
- },
-<span id='Ext-fx-Manager-method-startingFilter'> /**
-</span> * @private
- * Filter function to determine which animations need to be started
- */
- startingFilter: function(o) {
- return o.paused === false && o.running === false && o.iterations > 0;
+ return provider;
},
-<span id='Ext-fx-Manager-method-runningFilter'> /**
-</span> * @private
- * Filter function to determine which animations are still running
+<span id='Ext-direct-Manager-method-getProvider'> /**
+</span> * Retrieves a {@link Ext.direct.Provider provider} by the **{@link Ext.direct.Provider#id id}** specified when the
+ * provider is {@link #addProvider added}.
+ * @param {String/Ext.direct.Provider} id The id of the provider, or the provider instance.
*/
- runningFilter: function(o) {
- return o.paused === false && o.running === true && o.isAnimator !== true;
+ getProvider : function(id){
+ return id.isProvider ? id : this.providers.get(id);
},
-<span id='Ext-fx-Manager-method-runner'> /**
-</span> * @private
- * Runner function being called each frame
+<span id='Ext-direct-Manager-method-removeProvider'> /**
+</span> * Removes the provider.
+ * @param {String/Ext.direct.Provider} provider The provider instance or the id of the provider.
+ * @return {Ext.direct.Provider} The provider, null if not found.
*/
- runner: function() {
+ removeProvider : function(provider){
var me = this,
- items = me.items;
-
- me.targetData = {};
- me.targetArr = {};
+ providers = me.providers;
- // Single timestamp for all animations this interval
- me.timestamp = new Date();
+ provider = provider.isProvider ? provider : providers.get(provider);
- // Start any items not current running
- items.filterBy(me.startingFilter).each(me.startAnim, me);
-
- // Build the new attributes to be applied for all targets in this frame
- items.filterBy(me.runningFilter).each(me.runAnim, me);
-
- // Apply all the pending changes to their targets
- me.applyPendingAttrs();
+ if (provider) {
+ provider.un('data', me.onProviderData, me);
+ providers.remove(provider);
+ return provider;
+ }
+ return null;
},
-<span id='Ext-fx-Manager-method-startAnim'> /**
-</span> * @private
- * Start the individual animation (initialization)
+<span id='Ext-direct-Manager-method-addTransaction'> /**
+</span> * Adds a transaction to the manager.
+ * @private
+ * @param {Ext.direct.Transaction} transaction The transaction to add
+ * @return {Ext.direct.Transaction} transaction
*/
- startAnim: function(anim) {
- anim.start(this.timestamp);
+ addTransaction: function(transaction){
+ this.transactions.add(transaction);
+ return transaction;
},
-<span id='Ext-fx-Manager-method-runAnim'> /**
-</span> * @private
- * Run the individual animation for this frame
+<span id='Ext-direct-Manager-method-removeTransaction'> /**
+</span> * Removes a transaction from the manager.
+ * @private
+ * @param {String/Ext.direct.Transaction} transaction The transaction/id of transaction to remove
+ * @return {Ext.direct.Transaction} transaction
*/
- runAnim: function(anim) {
- if (!anim) {
- return;
- }
- var me = this,
- targetId = anim.target.getId(),
- useCSS3 = me.useCSS3 && anim.target.type == 'element',
- elapsedTime = me.timestamp - anim.startTime,
- target, o;
-
- this.collectTargetData(anim, elapsedTime, useCSS3);
-
- // For CSS3 animation, we need to immediately set the first frame's attributes without any transition
- // to get a good initial state, then add the transition properties and set the final attributes.
- if (useCSS3) {
- // Flush the collected attributes, without transition
- anim.target.setAttr(me.targetData[targetId], true);
-
- // Add the end frame data
- me.targetData[targetId] = [];
- me.collectTargetData(anim, anim.duration, useCSS3);
-
- // Pause the animation so runAnim doesn't keep getting called
- anim.paused = true;
-
- target = anim.target.target;
- // We only want to attach an event on the last element in a composite
- if (anim.target.isComposite) {
- target = anim.target.target.last();
- }
-
- // Listen for the transitionend event
- o = {};
- o[Ext.supports.CSS3TransitionEnd] = anim.lastFrame;
- o.scope = anim;
- o.single = true;
- target.on(o);
- }
- // For JS animation, trigger the lastFrame handler if this is the final frame
- else if (elapsedTime >= anim.duration) {
- me.applyPendingAttrs(true);
- delete me.targetData[targetId];
- delete me.targetArr[targetId];
- anim.lastFrame();
- }
+ removeTransaction: function(transaction){
+ transaction = this.getTransaction(transaction);
+ this.transactions.remove(transaction);
+ return transaction;
},
-<span id='Ext-fx-Manager-method-collectTargetData'> /**
-</span> * Collect target attributes for the given Anim object at the given timestamp
- * @param {Ext.fx.Anim} anim The Anim instance
- * @param {Number} timestamp Time after the anim's start time
+<span id='Ext-direct-Manager-method-getTransaction'> /**
+</span> * Gets a transaction
+ * @private
+ * @param {String/Ext.direct.Transaction} transaction The transaction/id of transaction to get
+ * @return {Ext.direct.Transaction}
*/
- collectTargetData: function(anim, elapsedTime, useCSS3) {
- var targetId = anim.target.getId(),
- targetData = this.targetData[targetId],
- data;
-
- if (!targetData) {
- targetData = this.targetData[targetId] = [];
- this.targetArr[targetId] = anim.target;
- }
-
- data = {
- duration: anim.duration,
- easing: (useCSS3 && anim.reverse) ? anim.easingFn.reverse().toCSS3() : anim.easing,
- attrs: {}
- };
- Ext.apply(data.attrs, anim.runAnim(elapsedTime));
- targetData.push(data);
+ getTransaction: function(transaction){
+ return transaction.isTransaction ? transaction : this.transactions.get(transaction);
},
-<span id='Ext-fx-Manager-method-applyPendingAttrs'> /**
-</span> * @private
- * Apply all pending attribute changes to their targets
- */
- applyPendingAttrs: function(isLastFrame) {
- var targetData = this.targetData,
- targetArr = this.targetArr,
- targetId;
- for (targetId in targetData) {
- if (targetData.hasOwnProperty(targetId)) {
- targetArr[targetId].setAttr(targetData[targetId], false, isLastFrame);
+ onProviderData : function(provider, event){
+ var me = this,
+ i = 0,
+ len;
+
+ if (Ext.isArray(event)) {
+ for (len = event.length; i < len; ++i) {
+ me.onProviderData(provider, event[i]);
}
+ return;
+ }
+ if (event.name && event.name != 'event' && event.name != 'exception') {
+ me.fireEvent(event.name, event);
+ } else if (event.status === false) {
+ me.fireEvent('exception', event);
}
+ me.fireEvent('event', event, provider);
}
+}, function(){
+ // Backwards compatibility
+ Ext.Direct = Ext.direct.Manager;
});
</pre>
</body>