JavaScript fetch

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,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
 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

This entry was posted in xRM Development and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>