| 1 |
/** |
| 2 |
* @version $ Id; cjtserverqueue.js 21-03-2012 03:22:10 Ahmed Said $ |
| 3 |
* |
| 4 |
* CJTServerQueue class. |
| 5 |
*/ |
| 6 |
|
| 7 |
/* |
| 8 |
* Put CJTServerQueue class at global scope. |
| 9 |
* |
| 10 |
* @var CJTServerQueue |
| 11 |
*/ |
| 12 |
var CJTServerQueue; |
| 13 |
|
| 14 |
/* |
| 15 |
* JQuery wrapper for the CJTServerQueue object. |
| 16 |
*/ |
| 17 |
( function ( $ ) { |
| 18 |
|
| 19 |
/* |
| 20 |
* Abstract base class for Ajax Queue classes. |
| 21 |
* |
| 22 |
* This is a prototype and cannot be used without a derivided class. |
| 23 |
* There is two abstract method must be implemented in the child class. |
| 24 |
* |
| 25 |
* Abstracts: |
| 26 |
* - getData() : This method get called when this.send method is called right before |
| 27 |
* sending the request to the server. The purpose of the method is to Encapsulate the |
| 28 |
* queues data and prepare it for sending. |
| 29 |
* - getResponseParameters(response, data): This method called when server response. The method will be called |
| 30 |
* for every added queue. The purpose of the method is to de-encapsulate response object |
| 31 |
* to pass for every queue. |
| 32 |
* |
| 33 |
* @author Ahmed Said |
| 34 |
* @version 6 |
| 35 |
*/ |
| 36 |
CJTServerQueue = function () { |
| 37 |
|
| 38 |
/* |
| 39 |
* Operation Action. |
| 40 |
* |
| 41 |
* @var string |
| 42 |
*/ |
| 43 |
this.action = null |
| 44 |
|
| 45 |
/* |
| 46 |
* Controller map name. |
| 47 |
* |
| 48 |
* @var string |
| 49 |
*/ |
| 50 |
this.controller = null |
| 51 |
|
| 52 |
/* |
| 53 |
* Queue object unique identifier. |
| 54 |
* |
| 55 |
* @internal |
| 56 |
* @var string |
| 57 |
*/ |
| 58 |
this.key = '' |
| 59 |
|
| 60 |
/* |
| 61 |
* Lock or Unlock queue object allow and disallow sending |
| 62 |
* the request to the server when .send() method is called. |
| 63 |
* |
| 64 |
* @var boolean |
| 65 |
*/ |
| 66 |
this.locked = false |
| 67 |
|
| 68 |
/* |
| 69 |
* Operations queue. |
| 70 |
* |
| 71 |
* All queued operations are stored here waiting |
| 72 |
* for sending. |
| 73 |
* |
| 74 |
* @var object |
| 75 |
*/ |
| 76 |
this.queue = [] |
| 77 |
|
| 78 |
this.errors = [] |
| 79 |
|
| 80 |
/* |
| 81 |
* Derived classed constructor. |
| 82 |
* |
| 83 |
* Call this from child classes for initialize objects. |
| 84 |
* |
| 85 |
* @param string Controller map name. |
| 86 |
* @param string Action name. |
| 87 |
* @param string Queue key. |
| 88 |
* @return void |
| 89 |
*/ |
| 90 |
this._init = function ( controller, action, key ) { |
| 91 |
this.controller = controller |
| 92 |
this.action = action |
| 93 |
this.key = key |
| 94 |
// Reset prototype copy vars. |
| 95 |
this.queue = [] |
| 96 |
this.locked = false |
| 97 |
} |
| 98 |
|
| 99 |
/* |
| 100 |
* Add request to the queue. |
| 101 |
* |
| 102 |
* The method push the new data to the queue list. |
| 103 |
* |
| 104 |
* The returned object is jQuery Ajax-Like object that has .success and .error |
| 105 |
* methods implemented. You can add callbacks to the returned object as like as you |
| 106 |
* need. When the queue is sent to the server and the response received, |
| 107 |
* all these methods will be called with the context parameter as "this" pointer. |
| 108 |
* |
| 109 |
* Possible values for queue type is 'queue' and endpoint. |
| 110 |
* |
| 111 |
* endpoint is extension to send method when the object is locked. |
| 112 |
* This allow dispatch method to call deferred methods added through send method |
| 113 |
* when the object was locked. |
| 114 |
* |
| 115 |
* @param object Data to add to queue. |
| 116 |
* @param mixed context to be used for deferred callbacks (e.g success, error). |
| 117 |
* @param string Queue type. |
| 118 |
* @return CJTServer.getDeferredObject.promise() |
| 119 |
*/ |
| 120 |
this.add = function ( data, context, type ) { |
| 121 |
// Check for special characters in block name. |
| 122 |
if ( data.property === 'name' ) { |
| 123 |
if ( !data.value.match( /^[A-Za-z0-9\!\#\@\$\&\*\(\)\[\]\x20\-\_\+\?\:\;\.]{1,50}$/ ) ) { |
| 124 |
alert( 'The block name cannot contain special characters. Please use A-Z, 0-9, -, _ and space characters only.' ) |
| 125 |
|
| 126 |
this.errors = data.value |
| 127 |
} else { |
| 128 |
this.errors = [] |
| 129 |
} |
| 130 |
} |
| 131 |
|
| 132 |
if ( this.errors.length <= 0 ) { |
| 133 |
var queue = { |
| 134 |
deferred: CJTServer.getDeferredObject(), |
| 135 |
data: data, |
| 136 |
context: context, |
| 137 |
type: ( ( type == undefined ) ? 'queue' : type ) |
| 138 |
} |
| 139 |
var promise = queue.deferred.promise() |
| 140 |
// Add queue object to the queue. |
| 141 |
this.queue.push( queue ) |
| 142 |
return promise |
| 143 |
} else { |
| 144 |
return CJTServer.getDeferredObject().promise() |
| 145 |
} |
| 146 |
} |
| 147 |
|
| 148 |
/* |
| 149 |
* Clear queues list. |
| 150 |
* |
| 151 |
* The method quietly clear queue list. |
| 152 |
* |
| 153 |
* No callbacks called when queue is cleared. |
| 154 |
* |
| 155 |
* @return void |
| 156 |
*/ |
| 157 |
this.clear = function () { |
| 158 |
this.queue = [] |
| 159 |
} |
| 160 |
|
| 161 |
/* |
| 162 |
* Dispatch callbacks associated for the all the available queues. |
| 163 |
* |
| 164 |
* @internal |
| 165 |
* |
| 166 |
* state parameter possible values are: |
| 167 |
* - resolve |
| 168 |
* - reject |
| 169 |
* |
| 170 |
* @param string jQuery.Deferred states. |
| 171 |
* @param object Response Object to pass to the callbacks. |
| 172 |
* @return void |
| 173 |
*/ |
| 174 |
this.dispatch = function ( state, response ) { |
| 175 |
var method = state + 'With' |
| 176 |
var serverQueue = this // To use inside .each(). |
| 177 |
var queueParams = null |
| 178 |
$( this.queue ).each( function ( index, queue ) { |
| 179 |
// If rejected don't call getResponseParameters() to avoid error |
| 180 |
// This is a temporary solution for version 6.0 to be releases! |
| 181 |
// Get queue parameters based on queue type. |
| 182 |
if ( ( state == 'reject' ) || ( queue.type == 'endpoint' ) ) { |
| 183 |
// endpoint type queue is queue to handle the typical/native |
| 184 |
// ajax response without setting up response parameters. |
| 185 |
queueParams = [ response ] |
| 186 |
} |
| 187 |
else if ( queue.type == 'queue' ) { |
| 188 |
// Customize response data based on derivded class. |
| 189 |
queueParams = serverQueue.getResponseParameters( response, queue.data ) |
| 190 |
} |
| 191 |
queue.deferred[ method ]( queue.context, queueParams ) |
| 192 |
// Always call completed callbacks. |
| 193 |
queue.deferred.completeDeferred.resolveWith( queue.context, queueParams ) |
| 194 |
} ) |
| 195 |
// Clear queue. |
| 196 |
this.clear() |
| 197 |
} |
| 198 |
|
| 199 |
/* |
| 200 |
* Don't send the queue when send method is called. |
| 201 |
* |
| 202 |
* This method is great when an operation need to control the behavior of |
| 203 |
* another operation. An operation may prevent the queue from sending the request |
| 204 |
* and do that in alternative ways. |
| 205 |
* |
| 206 |
* @return void |
| 207 |
*/ |
| 208 |
this.lock = function () { |
| 209 |
this.locked = true |
| 210 |
} |
| 211 |
|
| 212 |
/* |
| 213 |
* Merge queue object to current queue. |
| 214 |
* |
| 215 |
* @param CJTServerQueue Queue object to merge to this queue. |
| 216 |
* @return void |
| 217 |
*/ |
| 218 |
this.merge = function ( serverQueue ) { |
| 219 |
this.queue = $.merge( this.queue, serverQueue.queue ) |
| 220 |
} |
| 221 |
|
| 222 |
/* |
| 223 |
* Send queue data to server. |
| 224 |
* |
| 225 |
* If the object is locked nothing will happen at all. |
| 226 |
* If the object is unlocked a call to CJTServer.send method will be |
| 227 |
* processed with the data returned from the abstract method .getData(). |
| 228 |
* |
| 229 |
* @param string Http Request Method @see CJTServer.send for more details. |
| 230 |
* @param object Data to pass along with the queue data. |
| 231 |
* @return CJTServer.getDeferredObject.promise() |
| 232 |
*/ |
| 233 |
this.send = function ( method, data ) { |
| 234 |
var ajaxPromise = null |
| 235 |
// Process only of not locked. |
| 236 |
|
| 237 |
if ( !this.locked && this.errors.length <= 0 ) { |
| 238 |
var queue = this // To be used inside .each(). |
| 239 |
// Merge data param with derived class data for the final request. |
| 240 |
// But first mask usre data param is passed. |
| 241 |
data = ( data != undefined ) ? data : {} |
| 242 |
data = $.extend( data, this.getData() ) |
| 243 |
// Send request to CJTServer object. |
| 244 |
ajaxPromise = CJTServer.send( this.controller, this.action, data, method ) |
| 245 |
.success( |
| 246 |
function ( response ) { |
| 247 |
queue.dispatch( 'resolve', response ) |
| 248 |
} |
| 249 |
) |
| 250 |
.error( |
| 251 |
function ( response ) { |
| 252 |
queue.dispatch( 'reject', response ) |
| 253 |
} |
| 254 |
) |
| 255 |
} |
| 256 |
else { |
| 257 |
// Use Dummy Deferred object in case the object is locked. |
| 258 |
ajaxPromise = this.add( data, undefined, 'endpoint' ) |
| 259 |
} |
| 260 |
return ajaxPromise |
| 261 |
} |
| 262 |
|
| 263 |
/* |
| 264 |
* Unlock queue object. |
| 265 |
* |
| 266 |
* @return void |
| 267 |
*/ |
| 268 |
this.unlock = function () { |
| 269 |
this.locked = false |
| 270 |
} |
| 271 |
|
| 272 |
} // End class. |
| 273 |
|
| 274 |
} )( jQuery ) |