When working on partner hosted Dynamics CRM deployments it is not possible to deploy assemblies on the server – so the solution does often involve JavaScript.
This solution is based on elements found round and about on different blogs and some ideas of my own.
This solution displays a picture on the account form saved attached to a note (annotation).
First the Fetch sentence to retrieve the annotationid
1: function getAccountLogoAnnotationId() {
2: var fetchXml = '';
3: fetchXml += '<fetch mapping="logical" count="50" version="1.0">';
4: fetchXml += '<entity name="annotation">';
5: fetchXml += '<attribute name="annotationid" />';
6: fetchXml += '<filter>';
7: fetchXml += '<condition attribute="filename" operator="eq" value="logo.png" />';
8: fetchXml += '<condition attribute="isdocument" operator="eq" value="1" />';
9: fetchXml += '<condition attribute="objecttypecode" operator="eq" value="1" />';
10: fetchXml += '<condition attribute="objectid" operator="eq" value="'+crmForm.ObjectId+'" />';
11: fetchXml += '</filter>';
12: fetchXml += '</entity>';
13: fetchXml += '</fetch>';
14: fetchXml += '';
15:
16: /* Make the fetch and retrieve xml result */
17: var resxml = Fetch(fetchXml);
18: /* Create an ObjTree Object */
19: var xotree = new XML.ObjTree();
20: /* Objectize xml result */
21: var tree = xotree.parseXML(resxml);
22: return (tree.resultset.result.annotationid);
23:
24: }
Notice the xotree object – it’s a method to kind of create a JS object in this case a annotation object, but it could be any CRM entity – for more information have a look here: Objectizing Ajax (XML) results.
My code is copy pasted from Adi Katz blog post – i’ll repost it here:
1: if ( typeof(XML) == 'undefined' ) XML = function() {};
2:
3: // constructor
4:
5: XML.ObjTree = function () {
6: return this;
7: };
8:
9: // object prototype
10: XML.ObjTree.prototype.xmlDecl = '<?xml version="1.0" encoding="UTF-8" ?>\n';
11: XML.ObjTree.prototype.attr_prefix = '';
12:
13: // method: parseXML( xmlsource )
14: XML.ObjTree.prototype.parseXML = function ( xml ) {
15: var root;
16: if ( window.ActiveXObject ) {
17: xmldom = new ActiveXObject('Microsoft.XMLDOM');
18: xmldom.async = false;
19: xmldom.loadXML( xml );
20: root = xmldom.documentElement;
21: }
22: if ( ! root ) return;
23: return this.parseDOM( root );
24: };
25:
26: // method: parseDOM( documentroot )
27: XML.ObjTree.prototype.parseDOM = function ( root ) {
28: if ( ! root ) return;
29:
30: this.__force_array = {};
31: if ( this.force_array ) {
32: for( var i=0; i<this.force_array.length; i++ ) {
33: this.__force_array[this.force_array[i]] = 1;
34: }
35: }
36:
37: var json = this.parseElement( root ); // parse root node
38: if ( this.__force_array[root.nodeName] ) {
39: json = [ json ];
40: }
41: if ( root.nodeType != 11 ) { // DOCUMENT_FRAGMENT_NODE
42: var tmp = {};
43: tmp[root.nodeName] = json; // root nodeName
44: json = tmp;
45: }
46: return json;
47: };
48:
49: // method: parseElement( element )
50: XML.ObjTree.prototype.parseElement = function ( elem ) {
51: // COMMENT_NODE
52: if ( elem.nodeType == 7 ) {
53: return;
54: }
55:
56: // TEXT_NODE CDATA_SECTION_NODE
57: if ( elem.nodeType == 3 || elem.nodeType == 4 ) {
58: var bool = elem.nodeValue.match( /[^\x00-\x20]/ );
59: if ( bool == null ) return; // ignore white spaces
60: return elem.nodeValue;
61: }
62:
63: var retval;
64: var cnt = {};
65:
66: // parse attributes
67: if ( elem.attributes && elem.attributes.length ) {
68: retval = {};
69: for ( var i=0; i<elem.attributes.length; i++ ) {
70: var key = elem.attributes[i].nodeName;
71: if ( typeof(key) != "string" ) continue;
72: var val = elem.attributes[i].nodeValue;
73: if ( ! val ) continue;
74: key = this.attr_prefix + key;
75: if ( typeof(cnt[key]) == "undefined" ) cnt[key] = 0;
76: cnt[key] ++;
77: this.addNode( retval, key, cnt[key], val );
78: }
79: }
80:
81: // parse child nodes (recursive)
82: if ( elem.childNodes && elem.childNodes.length ) {
83: var textonly = true;
84: if ( retval ) textonly = false; // some attributes exists
85: for ( var i=0; i<elem.childNodes.length && textonly; i++ ) {
86: var ntype = elem.childNodes[i].nodeType;
87: if ( ntype == 3 || ntype == 4 ) continue;
88: textonly = false;
89: }
90: if ( textonly ) {
91: if ( ! retval ) retval = "";
92: for ( var i=0; i<elem.childNodes.length; i++ ) {
93: retval += elem.childNodes[i].nodeValue;
94: }
95: } else {
96: if ( ! retval ) retval = {};
97: for ( var i=0; i<elem.childNodes.length; i++ ) {
98: var key = elem.childNodes[i].nodeName.replace("#","");
99: if ( typeof(key) != "string" ) continue;
100: var val = this.parseElement( elem.childNodes[i] );
101: if ( ! val ) continue;
102: if ( typeof(cnt[key]) == "undefined" ) cnt[key] = 0;
103: cnt[key] ++;
104: this.addNode( retval, key, cnt[key], val );
105: }
106: }
107: }
108: return retval;
109: };
110:
111: // method: addNode( hash, key, count, value )
112: XML.ObjTree.prototype.addNode = function ( hash, key, cnts, val ) {
113: key = this.key_qualify(key);
114: if ( this.__force_array[key] ) {
115: if ( cnts == 1 ) hash[key] = [];
116: hash[key][hash[key].length] = val; // push
117: } else if ( cnts == 1 ) { // 1st sibling
118: hash[key] = val;
119: } else if ( cnts == 2 ) { // 2nd sibling
120: hash[key] = [ hash[key], val ];
121: } else { // 3rd sibling and more
122: hash[key][hash[key].length] = val;
123: }
124: };
125:
126: XML.ObjTree.prototype.key_qualify = function( key ){
127: return key.replace(/\W/gi,"");
128: }
129: // method: xml_escape( text )
130: XML.ObjTree.prototype.xml_escape = function ( text ) {
131: return String(text).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
132: };
133:
134: /*
135: Copyright (c) 2005-2006 Yusuke Kawasaki. All rights reserved.
136: This program is free software; you can redistribute it and/or
137: modify it under the Artistic license. Or whatever license I choose,
138: which I will do instead of keeping this documentation like it is.
139: */
140:
So there you have it – it’s actually pretty easy – and using Stunnware Javascript Factory it’s manageable in spite of the many lines of code.
Take care