1 /* 2 * Naos Framework 3 * 4 * LICENSE 5 * http://www.naos-framework.com/website.naos.framework/en/license 6 * 7 * Copyright (c) 2008 Jupiter GmbH 8 */ 9 10 /** 11 * Creates a new NaosAjax request object. This object allows 12 * you to communicate with the PHP part of the Naos Framework. 13 * 14 * @constructor 15 * 16 * @param requests Defines the actual request. Format {view1: {node: ..., module: ..., controller: ..., action: ..., parameter: {p1: ..., ...}}, ...} 17 * @param domForms An array of HTML form objects, which should be send with this request. 18 * @param callbackCreateData When defined this function will be called with the dom tree which will be send as request. This allows you to modify the dom tree before it gets send if necessary. 19 */ 20 function NaosAjax(/**Object|Array*/ requests, /**Array*/ domForms, /**function*/ callbackCreateData) 21 { 22 NaosDebug.debug("[NaosAjax]: Preparing request."); 23 24 // transform to vanilla object 25 requests = NaosTools.toVanillaObject(requests); 26 27 // generate url from requests and status... 28 var url = naosConfig.application.base_url+'.ajax/'+naosStatus.application.locale+'/' 29 +naosStatus.application.menuItem; 30 31 // ... and generate xml request 32 var xml = zXmlDom.createDocument(); 33 34 var xml_request_ajax = xml.createElement('ajax'); 35 36 var xml_request = xml.createElement('request'); 37 xml_request.appendChild(xml_request_ajax); 38 39 xml.appendChild(xml_request); 40 41 // update url and xml request with current status 42 var views = naosConfig.layout.views.split(','); 43 for(var i=0; i<views.length; ++i) 44 { 45 var viewStatus = null; 46 47 // get current status and update with request 48 if(naosStatus.layout[views[i]] != undefined) 49 viewStatus = naosStatus.layout[views[i]]; 50 51 if(requests[views[i]] != undefined) 52 viewStatus = requests[views[i]]; 53 54 if(viewStatus == null) 55 continue; 56 57 // update url 58 url += '//'+views[i]+'/'+viewStatus.node+'/'+viewStatus.module+'/'+viewStatus.controller+'/'+ 59 viewStatus.action; 60 61 for(var j in viewStatus.parameter) { 62 url += '/'+j+'/'+viewStatus.parameter[j]; 63 } 64 } 65 66 for(var i in requests) 67 { 68 // update xml request 69 var xml_request_ajax_view = xml.createElement('view'); 70 xml_request_ajax_view.setAttribute('id', i); 71 xml_request_ajax.appendChild(xml_request_ajax_view); 72 } 73 74 // append form data to xml request 75 for(var i=0; i < domForms.length; ++i) 76 { 77 var xml_request_ajax_form = xml.createElement('form'); 78 xml_request_ajax_form.setAttribute('id', domForms[i].name); 79 xml_request_ajax_form.setAttribute('items', domForms[i].elements[domForms[i].name+':items'].value); 80 xml_request_ajax_form.setAttribute('titles', domForms[i].elements[domForms[i].name+':titles'].value); 81 82 for(var j=0; j < domForms[i].elements.length; ++j) 83 { 84 if(domForms[i].elements[j].name == domForms[i].name+':items' || domForms[i].elements[j].name == domForms[i].name+':titles') 85 continue; 86 87 if((domForms[i].elements[j].type == 'checkbox' || domForms[i].elements[j].type == 'radio') && domForms[i].elements[j].checked == false) 88 continue; 89 90 var xml_request_ajax_form_item = xml.createElement('item'); 91 xml_request_ajax_form_item.setAttribute('id', domForms[i].elements[j].name); 92 xml_request_ajax_form_item.appendChild(xml.createTextNode(domForms[i].elements[j].value)); 93 94 xml_request_ajax_form.appendChild(xml_request_ajax_form_item); 95 } 96 97 xml_request_ajax.appendChild(xml_request_ajax_form); 98 } 99 100 // append additional data to xml request 101 if(callbackCreateData != null) 102 callbackCreateData(xml, xml_request); 103 104 // set member variables 105 this.requests = requests; 106 this.url = url; 107 this.xmlrequest = xml; 108 109 // create ajax callback functions 110 /** 111 * This function processes a successful AJAX request. It gets called by 112 * the Prototype Ajax.Request object. 113 * @param ajax Contains the response data. 114 * @private 115 */ 116 this.callbackOk = function(/**Ajax.Response*/ ajax) { 117 118 // display debug message 119 NaosDebug.debug("[NaosAjax]: Response received.\nXML: "+ 120 new zXMLSerializer().serializeToString(ajax.responseXML)); 121 122 // update application state 123 var xml_state = zXPath.selectSingleNode(ajax.responseXML, '/response/ajax/state'); 124 naosStatus = NaosTools.fromJSON(xml_state.textContent?xml_state.textContent:xml_state.text); 125 126 // update view output 127 var xml_views = zXPath.selectNodes(ajax.responseXML, '/response/ajax/view'); 128 for(var k=0; k < xml_views.length; ++k) 129 { 130 Naos.updateViewContent(xml_views[k].getAttribute('id'), xml_views[k].textContent?xml_views[k].textContent:xml_views[k].text); 131 NaosHandler.viewUpdateNotifier(xml_views[k].getAttribute('id'), xml_views[k].textContent?xml_views[k].textContent:xml_views[k].text); 132 } 133 134 // perform queued operations 135 var xml_queuedOperations = zXPath.selectSingleNode(ajax.responseXML, '/response/ajax/queuedOperations'); 136 var queuedOperations = NaosTools.fromJSON(xml_queuedOperations.textContent?xml_queuedOperations.textContent:xml_queuedOperations.text); 137 138 // dialog operations 139 for(qopsModule in queuedOperations['dialog']) 140 { 141 for(qopsDialog in queuedOperations['dialog'][qopsModule]) 142 { 143 if(queuedOperations['dialog'][qopsModule][qopsDialog]['operation'] == 'open') 144 { 145 NaosDialog.openDialog(qopsModule, qopsDialog, 146 queuedOperations['dialog'][qopsModule][qopsDialog]['data']['type'], 147 queuedOperations['dialog'][qopsModule][qopsDialog]['data']['position'], 148 queuedOperations['dialog'][qopsModule][qopsDialog]['data']['output']); 149 } 150 else if(queuedOperations['dialog'][qopsModule][qopsDialog]['operation'] == 'close') 151 { 152 NaosDialog.closeDialog(qopsModule, qopsDialog); 153 } 154 } 155 } 156 157 // custom operations 158 for(qopsCustomKey in queuedOperations['custom']) 159 { 160 161 NaosHandler.customOperation(queuedOperations['custom'][qopsCustomKey]['module'], queuedOperations['custom'][qopsCustomKey]['type'], queuedOperations['custom'][qopsCustomKey]['data']); 162 163 } 164 165 NaosAjax.finishRequest(this); 166 167 }.bind(this); 168 169 /** 170 * This function processes an unsuccessful AJAX request. It gets called by 171 * the Prototype Ajax.Request object. 172 * @param ajax Contains the response data. 173 * @private 174 */ 175 this.callbackError = function(/**Ajax.Response*/ ajax) { 176 177 // display debug message 178 NaosDebug.debug("[NaosAjax]: Request failed.\nText: "+ 179 ajax.responseText); 180 181 // remove request from queue 182 NaosAjax.finishRequest(this); 183 184 }.bind(this); 185 186 /** 187 * This function gets called by the Prototype Ajax.Request object for debugging. 188 * @param ajax Contains the response data. 189 * @private 190 */ 191 this.callbackDebug = function(/**Ajax.Response*/ ajax) { 192 193 // display debug message 194 NaosDebug.debug("[NaosAjax]: Request completed.\nText: "+ 195 ajax.responseText); 196 197 }.bind(this); 198 199 /** 200 * Schedules the created NaosAjax object for sending. 201 */ 202 this.send = function () { 203 204 NaosDebug.debug("[NaosAjax]: Queuing request."); 205 206 NaosAjax.activateRequest(this); 207 }.bind(this); 208 209 /** 210 * An internal function which actually sends the NaosAjax request. It 211 * utilizes the Prototype Ajax.Request class. 212 * @private 213 */ 214 this._send = function () { 215 // display hour glass 216 // '<img src="'+naosConfig.application.base_url+'.resources/naos/images/spinner.gif"/>' 217 218 // display debug message 219 NaosDebug.debug("[NaosAjax]: Send request.\nURL: "+this.url+"\nXML: "+ 220 new zXMLSerializer().serializeToString(this.xmlrequest)); 221 222 // send request 223 new Ajax.Request(this.url, {method: 'post', onSuccess: this.callbackOk, 224 onFailure: this.callbackError, postBody: this.xmlrequest, contentType: 'text/xml', 225 encoding: 'UTF-8', evalJSON: false, evalJS: false, asynchronous: true, 226 parameters: '', onComplete: this.callbackDebug 227 }); 228 }.bind(this); 229 } 230 231 /** 232 * The request queue with schedules NaosAjax request objects. 233 * @type Array 234 * @private 235 */ 236 NaosAjax.requestQueue = new Array(); 237 238 /** 239 * Pointer to the last executed UI effect. 240 * @type null|Effect 241 * @private 242 */ 243 NaosAjax.lastGuiEffect = null; 244 245 /** 246 * Cancels the currently activated UI effect. 247 * @private 248 */ 249 NaosAjax.cancelLastGuiEffect = function() 250 { 251 if(NaosAjax.lastGuiEffect) 252 { 253 if(NaosAjax.lastGuiEffect.state == 'running') 254 NaosAjax.lastGuiEffect.cancel(); 255 NaosAjax.lastGuiEffect = null; 256 } 257 } 258 259 /** 260 * Schedules a NaosAjax object by pushing it to the request queue. Activates 261 * the request at once when no pending request is available. Takes care of the 262 * UI notification stuff. 263 * @param naosajax The NaosAjax object which should be scheduled. 264 * @private 265 */ 266 NaosAjax.activateRequest = function (/**NaosAjax*/ naosajax) { 267 NaosAjax.requestQueue.push(naosajax); 268 269 NaosDebug.debug("[NaosAjax]: Request queue count is: "+NaosAjax.requestQueue.length); 270 271 if(NaosAjax.requestQueue.length == 1) 272 { 273 // display hour glass 274 if(!document.getElementById('naos_hourglass')) 275 { 276 var blockingElement = document.createElement('div'); 277 blockingElement.setAttribute('id', 'naos_hourglass'); 278 blockingElement.style.display = 'none'; 279 blockingElement.style.position = 'absolute'; 280 blockingElement.style.left = 0; 281 blockingElement.style.top = 0; 282 blockingElement.style.width = ''+document.viewport.getDimensions().width+'px'; 283 blockingElement.style.height = ''+document.viewport.getDimensions().height+'px'; 284 //blockingElement.style.background = 'white'; 285 286 blockingElement.innerHTML = '<table style="width: '+blockingElement.style.width+'; height: '+blockingElement.style.height+';"><tr><td style="vertical-align: middle; text-align: center;"><img src="'+naosConfig.application.base_url+'.resources/naos/images/spinner.gif"/></td></tr></table>'; 287 288 document.getElementsByTagName("body")[0].appendChild(blockingElement); 289 } 290 291 NaosAjax.cancelLastGuiEffect(); 292 NaosAjax.lastGuiEffect = $('naos_hourglass').appear({ duration: 0.5 }); 293 294 NaosAjax.requestQueue[0]._send(); 295 } 296 } 297 298 /** 299 * Takes care of processed NaosAjax requests. Activates the next scheduled request 300 * if available. Takes care of the UI notification stuff. 301 * @param naosajax The NaosAjax object which is processed already. 302 * @private 303 */ 304 NaosAjax.finishRequest = function (/**NaosAjax*/ naosajax) { 305 for(var i=0; i<NaosAjax.requestQueue.length; ++i) 306 { 307 if(NaosAjax.requestQueue[i] == naosajax) 308 { 309 NaosAjax.requestQueue.splice(i, 1); 310 break; 311 } 312 } 313 314 if(NaosAjax.requestQueue.length >= 1) 315 { 316 NaosAjax.requestQueue[0]._send(); 317 } 318 else 319 { 320 // hide hour glass 321 NaosAjax.cancelLastGuiEffect(); 322 NaosAjax.lastGuiEffect = $('naos_hourglass').fade({ duration: 0.1 }); 323 } 324 } 325