/** * @version $ Id; cjtserverqueue.js 21-03-2012 03:22:10 Ahmed Said $ * * CJTServerQueue class. */ /* * Put CJTServerQueue class at global scope. * * @var CJTServerQueue */ var CJTServerQueue; /* * JQuery wrapper for the CJTServerQueue object. */ ( function ( $ ) { /* * Abstract base class for Ajax Queue classes. * * This is a prototype and cannot be used without a derivided class. * There is two abstract method must be implemented in the child class. * * Abstracts: * - getData() : This method get called when this.send method is called right before * sending the request to the server. The purpose of the method is to Encapsulate the * queues data and prepare it for sending. * - getResponseParameters(response, data): This method called when server response. The method will be called * for every added queue. The purpose of the method is to de-encapsulate response object * to pass for every queue. * * @author Ahmed Said * @version 6 */ CJTServerQueue = function () { /* * Operation Action. * * @var string */ this.action = null /* * Controller map name. * * @var string */ this.controller = null /* * Queue object unique identifier. * * @internal * @var string */ this.key = '' /* * Lock or Unlock queue object allow and disallow sending * the request to the server when .send() method is called. * * @var boolean */ this.locked = false /* * Operations queue. * * All queued operations are stored here waiting * for sending. * * @var object */ this.queue = [] this.errors = [] /* * Derived classed constructor. * * Call this from child classes for initialize objects. * * @param string Controller map name. * @param string Action name. * @param string Queue key. * @return void */ this._init = function ( controller, action, key ) { this.controller = controller this.action = action this.key = key // Reset prototype copy vars. this.queue = [] this.locked = false } /* * Add request to the queue. * * The method push the new data to the queue list. * * The returned object is jQuery Ajax-Like object that has .success and .error * methods implemented. You can add callbacks to the returned object as like as you * need. When the queue is sent to the server and the response received, * all these methods will be called with the context parameter as "this" pointer. * * Possible values for queue type is 'queue' and endpoint. * * endpoint is extension to send method when the object is locked. * This allow dispatch method to call deferred methods added through send method * when the object was locked. * * @param object Data to add to queue. * @param mixed context to be used for deferred callbacks (e.g success, error). * @param string Queue type. * @return CJTServer.getDeferredObject.promise() */ this.add = function ( data, context, type ) { // Check for special characters in block name. if ( data.property === 'name' ) { if ( !data.value.match( /^[A-Za-z0-9\!\#\@\$\&\*\(\)\[\]\x20\-\_\+\?\:\;\.]{1,50}$/ ) ) { alert( 'The block name cannot contain special characters. Please use A-Z, 0-9, -, _ and space characters only.' ) this.errors = data.value } else { this.errors = [] } } if ( this.errors.length <= 0 ) { var queue = { deferred: CJTServer.getDeferredObject(), data: data, context: context, type: ( ( type == undefined ) ? 'queue' : type ) } var promise = queue.deferred.promise() // Add queue object to the queue. this.queue.push( queue ) return promise } else { return CJTServer.getDeferredObject().promise() } } /* * Clear queues list. * * The method quietly clear queue list. * * No callbacks called when queue is cleared. * * @return void */ this.clear = function () { this.queue = [] } /* * Dispatch callbacks associated for the all the available queues. * * @internal * * state parameter possible values are: * - resolve * - reject * * @param string jQuery.Deferred states. * @param object Response Object to pass to the callbacks. * @return void */ this.dispatch = function ( state, response ) { var method = state + 'With' var serverQueue = this // To use inside .each(). var queueParams = null $( this.queue ).each( function ( index, queue ) { // If rejected don't call getResponseParameters() to avoid error // This is a temporary solution for version 6.0 to be releases! // Get queue parameters based on queue type. if ( ( state == 'reject' ) || ( queue.type == 'endpoint' ) ) { // endpoint type queue is queue to handle the typical/native // ajax response without setting up response parameters. queueParams = [ response ] } else if ( queue.type == 'queue' ) { // Customize response data based on derivded class. queueParams = serverQueue.getResponseParameters( response, queue.data ) } queue.deferred[ method ]( queue.context, queueParams ) // Always call completed callbacks. queue.deferred.completeDeferred.resolveWith( queue.context, queueParams ) } ) // Clear queue. this.clear() } /* * Don't send the queue when send method is called. * * This method is great when an operation need to control the behavior of * another operation. An operation may prevent the queue from sending the request * and do that in alternative ways. * * @return void */ this.lock = function () { this.locked = true } /* * Merge queue object to current queue. * * @param CJTServerQueue Queue object to merge to this queue. * @return void */ this.merge = function ( serverQueue ) { this.queue = $.merge( this.queue, serverQueue.queue ) } /* * Send queue data to server. * * If the object is locked nothing will happen at all. * If the object is unlocked a call to CJTServer.send method will be * processed with the data returned from the abstract method .getData(). * * @param string Http Request Method @see CJTServer.send for more details. * @param object Data to pass along with the queue data. * @return CJTServer.getDeferredObject.promise() */ this.send = function ( method, data ) { var ajaxPromise = null // Process only of not locked. if ( !this.locked && this.errors.length <= 0 ) { var queue = this // To be used inside .each(). // Merge data param with derived class data for the final request. // But first mask usre data param is passed. data = ( data != undefined ) ? data : {} data = $.extend( data, this.getData() ) // Send request to CJTServer object. ajaxPromise = CJTServer.send( this.controller, this.action, data, method ) .success( function ( response ) { queue.dispatch( 'resolve', response ) } ) .error( function ( response ) { queue.dispatch( 'reject', response ) } ) } else { // Use Dummy Deferred object in case the object is locked. ajaxPromise = this.add( data, undefined, 'endpoint' ) } return ajaxPromise } /* * Unlock queue object. * * @return void */ this.unlock = function () { this.locked = false } } // End class. } )( jQuery )