+ Start a Discussion
ShinShin 

prototype.js and AJAX Toolkit causes error

While creating AJAX Toolkit apps I encountered an unexpected error, saying
uncaught exception: {faultcode:'soapenv:Client', faultstring:'Attribute "xmlns" bound to namespace "http://www.w3.org/2000/xmlns/" was already specified for element "query".', }
After long time debugging I finally found out following two libraries are conflicting, prototype.js and AJAX Toolkit. This simple S-Control would raise same error message.

Code:
<html>
  <head>
    <script type="text/javascript" src="/soap/ajax/8.0/connection.js"></script>
    <script type="text/javascript" src="http://prototypejs.org/assets/2007/1/18/prototype.js"></script>
    <script type="text/javascript">    
window.onload = function() {
  var res = sforce.connection.query('SELECT count() FROM Account', function(res) { alert(res.size) })
}
    </script>
  </head>
  <body>
  </body>
</html>
It appears that some array prototype overiding in prototype.js causes this problem. Now prototype.js is one of the most major JavaScript library, do you have any workaround from AJAX Toolkit side?
cheenathcheenath
You can replace the Connection._invoke() method and make this to work.


Code:
<html>
<head>
<script type="text/javascript"
src="/soap/ajax/8.0/connection.js"></script>
<script type="text/javascript" src="http://prototypejs.org/assets/2007/1/18/prototype.js"></script>
<script type="text/javascript">


sforce.Connection.prototype._invoke = function(method, args, isArray, callback, namespaces, url, headerNs, sobjectNs) {
if (callback) {
if (typeof(callback) == "function") {
} else {
if (!callback.onSuccess) {
throw "onSuccess not defined in the callback";
}
if (!callback.onFailure) {
throw "onFailure not defined in the callback";
}
}
}

var writer = new sforce.XmlWriter();
writer.startEnvelope();
this.writeHeader(writer, headerNs);
writer.startBody();
writer.writeStartElement(method);

for (var i = 0; i<namespaces.length; i++) {
var namespace = namespaces[i];
writer.writeNamespace(namespace.ns, namespace.prefix);
}

for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (!arg.value) {
throw "arg " + i + " '" + arg.name + "' not specified";
}
if (arg.isArray && !arg.value.push) {
throw "arg " + i + " '" + arg.name + "' is an array. But passed in value is not an array";
}
if (!arg.isArray && arg.value.push) {
throw "arg " + i + " '" + arg.name + "' is not an array. But passed in value is an array";
}
if (arg.value.push) { //this is an array
for (var j = 0; j < arg.value.length; j++) {
var obj = arg.value[j];
if (!obj) {
throw "Array element at " + j + " is null.";
}
this.writeOne(writer, arg.name, obj, sobjectNs);
}
} else {
this.writeOne(writer, arg.name, arg.value, sobjectNs);
}
}
writer.writeEndElement(method);
writer.endBody();
writer.endEnvelope();
if (sforce.debug.trace) {
sforce.debug.log("Connecting to server: " + url);
sforce.debug.logXml(writer.toString());
}
var transport = new sforce.SoapTransport();
return transport.send(url, writer, isArray, callback);
};




window.onload = function() {
var res = sforce.connection.query('SELECT count() FROM Account', function(res) { alert(res.size) })
}

</script>
</head>
<body>
</body>
</html>

 

ShinShin
Cheenath,
Thank you for your workaround suggestion.

It seems like overriding entire method in AJAX Toolkit.
I'd like to wait some official update to be supplied from salesforce.

Shinichi.
cheenathcheenath
Yes, you have to replace the whole method. I cant think
of any other workaround, sorry.

I have made this change to the next version of the toolkit (9.0).
But it will be a while (2 or 3 months) for this to be released.




DevAngelDevAngel
Ever wonder why we don't ever talk about using prototype?  It's not because we have never heard of it.  From a philosophical point of view, prototype "breaks" javascript.  This is not a good thing and locks you into using prototype once you have started.

Creating workarounds for various browser differences is one thing, workarounds to support frameworks that change the behavior of javascript as a language is another.  I'm glad to see that it's a minor change to the invoke call, but beware, as extensions and bolt-ons for the Apex AJAX toolkit emerge, you could end up with similar problems.

It's too bad too because prototype is a fair-dinkum library from the functional aspect, it's just the implementation that I take issue with.

FWIW  :smileywink:
JashuganJashugan
In what way does prototype.js break javascript?
Mouse.liuMouse.liu

Guys ,Do you see that:

 

<script type="text/javascript"
src="/soap/ajax/8.0/connection.js"></script>

Just change the version to higher,i.e. 20.0 or higher.