NOTE I inserted more code than just ajax calls in time for the code (part) to cause the problem. I donβt think so, so itβs probably best for you to focus on the ajax and jAjax bit further.
Also note that since there is a comment (with upvote) on this subject saying that my code is difficult to decrypt, I would be happy to clarify what needs to be clarified if this may turn out to be the key to finding the problem.
Thanks.
Here is the thing. I am trying to cut jQuery since the only thing I use is the $.ajax() method, and including the whole library like jQuery for only 1 function, this is IMO crazy. I donβt need the full functionality of the $.ajax method at $.ajax , so I wrote my own ajax function.
The problem is that it does not work, and I cannot understand why. I am trying to send objects to the server (in particular: ajaxAction in the controller - using Zend FW). Below is the javascript code and a brief description of what the firebug console tells me.
if (!String.prototype.trim) { String.prototype.trim = function() { "use strict"; return this.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); }; } function getUrl(action,controller) { var base,uri; base = window.location.href.replace('http://'+window.location.host,''); if (base.length > 1) { base = base.substring(1,base.length).split('/'); controller = controller || base[0]; base[0] = controller || base[0]; base[1] = action || base[1]; return '/'+base.join('/'); } controller = controller || 'index'; action = action || 'ajax'; return base+controller+'/'+action; } function formalizeObject(obj,recursion) { recursion = recursion || false; if (typeof obj !== 'object') { throw new Error('no object provided'); } var ret = ''; for (var i in obj) { if (!obj.hasOwnProperty(i) || typeof obj[i] === 'function') { continue; } if (recursion) { ret +='['+i+']'; } else { ret += (ret.length > 0 ? '&' : '') + i.toString(); } if (typeof obj[i] === 'object') { ret += formalizeObject(obj[i],true); continue; } ret += '='+obj[i].toString(); } if (recursion) { return ret; } return encodeURI(ret); } function success() { if (this.readyState===4 && this.status===200) { console.log(this.responseText); } } function ajax(str,url,method,json) { var ret; json = json || false; str = str || {}; method = method || 'POST'; url = url || getUrl(); str = str = (typeof str === 'object' ? str : {data:str}); try { ret = new XMLHttpRequest(); } catch (error) { try { ret= new ActiveXObject('Msxml2.XMLHTTP'); } catch(error) { try { ret= new ActiveXObject('Microsoft.XMLHTTP'); } catch(error) { throw new Error('no Ajax support?'); } } } if (typeof ret !== 'object') { throw new Error('No Ajax, FFS'); } ret.open(method, url, true); ret.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); ret.setRequestHeader('Content-type', (json ? 'application/json' : 'application/x-www-form-urlencode')); ret.onreadystatechange = success; ret.send((json ? JSON.stringify(str) : formalizeObject(str))); return true; } function jAjax(str,url) { $.ajax( { url : url, data: str, type: 'POST', success: function(res) { console.log(res); } }); }
Four ways I tried to execute an Ajax request:
jAjax({data:{foo:'bar'}},getUrl());//1 jAjax({data:{foo:'bar'}},getUrl(),true);//2 ajax({data:{foo:'bar'}},getUrl());//3 ajax({data:{foo:'bar'}},getUrl(),true);//4
jAjax({data:{foo:'bar'}},getUrl()); : This works fine:
[] {"Ajax": true, "controller": "index", "action": "Ajax", "module": "default", "identity": {}, "data": {"Foo": "Bar"}} Parameters: data [foo] 'bar' And Source: data% 5Bfoo% 5D = Bar (from the POST tab on the FB console) Title: application / x -www-form-urlencoded; encoding = UTF-8
All of this was sent to the following URL: http://www.foo.bar/index/ajax?data%5Bfoo%5D=bar
This does not work, however:
[] {"ajax": true, "controller": "index", "action": "ajax", "module": "default", "identity": {}} - response POST tab in FB: JSON data: {foo: 'Bar'} source: {"data": {"Foo": "Bar"}} (but the same URL - case 1) Title: json; encoding = UTF-8
This is big : the full URL of the request is identical to the URL from example 1, as are the headers, but when I look at the POST tab in the FB console (check the request) This is the only difference I can find:
case 1: Parameters: data [foo] 'bar' Source: data% 5Bfoo% 5D = Bar
In this case, I do not see the "Parameters" section, only: Source: data% 5Bfoo% 5D = Bar
Case2 is identical except for the URL, which I think forgot to go through encodeURI . This case is less important now. I think / hope that I will get this job the moment I find out what happened to case 3.
In all 4 cases, the request is sent and received. The action of the controller is as follows:
public function ajaxAction() { $this->_helper->layout->disableLayout(); $this->getHelper('viewRenderer')->setNoRender(); $this->_helper->getHelper('AjaxContext')->addActionContext( 'ajax' , 'json' ) ->initContext('json'); if($this->getRequest()->isPost() && $this->getRequest()->isXmlHttpRequest()) { echo json_encode(array_merge(array('ajax'=>true),$this->_getAllParams())); } else { throw new Exception('no ajax call made??'); } }
Since I get a JSON string, I'm sure the request has been sent and it has the correct XMLHttpRequest header. Why can't I post JSON objects? More importantly: why is case 3 not working? What is jQuery I don't know about? What is it that makes case 1 work, but not case 3?
PS: This may not be appropriate, but at the time of insanity I tried to add this: ret.setRequestHeader('Connection','close'); to the ajax function, but I noticed that the value sent in the Connection header was set to anyway. Perhaps this gives someone a hint about what went wrong?
Thank you in advance