function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
brooksbrooks 

getting into sControls . . .

Hi. Is it theoretically possible to convert data for an object (say, Opportunities) into an XML format with an sControl?

More broadly, can anyone point me to the best uses of sControls so far. (If several were listed and described on one document that would be great.) I mean, why sControls? What makes them an essential part of a developer's toolkit?

Thanks,
Brooks
adamgadamg
S-controls are useful because they 1) let you occupy part of the Salesforce UI with your own and 2) optionally let you build that UI/logic in Javascript/AJAX which doesn't require any additional infrastructure (as it runs client side) or build that UI/logic via standard web dev  (JSP, ASP, PHP, etc).
brooksbrooks
> S-controls are useful because they 1) let you occupy part of the Salesforce UI with your own and 2) optionally let you build that UI/logic in Javascript/AJAX which doesn't require > any additional infrastructure (as it runs client side) or build that UI/logic via standard web dev  (JSP, ASP, PHP, etc).

adamg,

Hi. Yes, but in addition to the UI, sControls allow you to get PAST the UI, right?, the the data in the object itself. Again, I'd like to convert my data to XML using an sControl. Any reason why that wouldn't work?

Thanks,
Brooks
DevAngelDevAngel
No, there is no reason why that would not work.  As a matter of fact the ajax toolkit does that in both directions.  The xml just happens to be SOAP.
Ron HessRon Hess
this is an early / rough version of an scontrol which reads tables, and writes the records into documents in the documents tab ( in a folder called "DataPackage"), it also has code to unpack the documents and re-create the data records.  currently works on single tables.
Joining 2 or more tables back up again is WIP. 

there are some tips / lessons learned burried in here if you are going to capture Dynabeans as XML

basicaly I do this

sforceClient.Query() get the data
Serialize the beans into the soap/xml (over the wire) format
save that string into a document

then to unpack

open the document, get the body
b64 decode the body into the soap string
desearialize the string into beans ( xmlparse)
sforceClient.Create() with the array of beans.

If i get this working to re-join the references i will post the entire thing as an appexchange package, however since you asked, here it is, a work in progress Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> <head> 
<title>Upload Data</title> 
<link  href="/dCSS/Theme2/default/common.css" type="text/css" rel="stylesheet" > <!-- New skin -->

<script src="https://www.salesforce.com/services/lib/ajax/beta3.3/sforceclient.js" type="text/javascript"></script> 
<script language="JavaScript1.2" src="/js/functions.js"></script>
<script type="text/javascript"> 
<!-- 
/* 
 * we limit the number of records to 200 from each table this utility, if a table has more than 200
 * then the results will be random as the related ID's may or may not be present, and the data may 
 * not construct a valid, cross referenced set of related tables
 * 
 * TODO check for missing folder DataPackage
 */             var debug = true;
var data_folder_name = "DataPackage";
var msg ; var dg;
var updateObjects = []; 
var todo =[]; 
var folderid ;
var maxBeans = 24;
var sapp = new Sforce.Application(); // to get browser version
//var cross_ref_tables = [];
var idCache = new Sforce.Hashtable();  // all cross refs are here...

function startup() { 
 // get session id and initialize the sforceClient object 
 sforceClient.init("{!API_Session_ID}", "{!API_Partner_Server_URL_70}"); 
 var uInfo = sforceClient.GetUserInfo(); // check for no API at this org
 if ( uInfo && uInfo.faultcode && uInfo.faultcode.indexOf("API_DISABLED_FOR_ORG")>0) {
  alert( uInfo.faultstring +  
  "\nThis custom link utilizes the AppExchange API.\n" +
  "It appears that the Salesforce.com edition you are using does not have this feature enabled.");
  return;
 } 
 msg = document.getElementById('msg');
 folderid = get_folder(data_folder_name); // create or find a folder where our data is / will live
 try { 
  var existingSel = document.getElementById('select_0');
  dg = sforceClient.describeGlobal(); // query API objects in this org
  // build a check box list   
  //drawList(document.getElementById('divTableHeader'),dg.types); 

  for (var i=0; i<dg.types.length; i++) {   // draw dg.types into avail select menu  
   existingSel.options[existingSel.options.length] = new Option(dg.types[i], dg.types[i]);
  }
  } catch(e) { 
   msg.style.visibility = 'visible'; 
   msg.innerHTML = e;
   //alert(e);
  }
}

function loadData2(form,element_name) {  // main create() routine

 var tables = []; // build a list of tables to load, describe each one
 for (var i = 0; i < form.elements.length; i++) { var e = form.elements[i];
  if ((e.name == element_name) && (e.checked)) {  e.checked = false; 
   var sd = sforceClient.DescribeSObject(e.value.replace(/\.xml/,""));
   sd.xmlFileName = e.value; 
   tables.push(sd);
  }
 }  
 
 // now re-order the describe list so that master objects are before child...
 tableCrossRef(tables);  // mark tables as master or detail
 tables.sort(isMaster);  // put the master tables before detail
 for (var k in tables) { process_load(tables[k]); } // load records into one table at a time 
 fixLookups(tables); // what about look up objects—
}

function process_load ( describe ) { /* open the document, get the contents */
 var docname = describe.xmlFileName;
 var qr = sforceClient.query("select name,body from document where folderid = '"+folderid+"' and name = '"+docname+"'")
 if (qr.className != "QueryResult" || qr.size <1) throw( "could not query document "+qr.toString);
 if (qr.size != 1) { alert("document not found "+docname); return } 

 var body_str = qr.records[0].getBody("body"); 
 try {  // convert this body to XML dom
 var dom = Sforce.DOM.CreateXmlDoc(body_str);
 var table = dom.childNodes[0]; // table.tagName == "Account" or ...
 var sbeans = table.childNodes; // array of xml elements each containing data for one record / bean
 
 var records = []; // walk thru sbeans creating dynabeans
 for(var i=0; i<sbeans.length; i++) { 
  records.push( Sforce.Serialization.DeserializeBean(sbeans[i]));
 }  // alert("have records"+ records.length);

 // before creating records, see if any fixups can be done, for master-detail relations
 fixup(records); // uses idCache;
 describe.records = records; // save the data so we can do fixups later
 var sr = sforceClient.create(records); // do the load for this table
 for(var i=0; i<sr.length; i++) { 
  if ( ! sr[i].success) { 
   throw("failed to create record " + sr[i].errors[0].toString() ); 
  } else { // now have the ID we will need for fixups, save it into a hash   
   // have sr[i].id and records[i].id 
   // save twice –˜
   assert(sr[i].id != null); 
   var rid = records[i].get("Id"); assert(rid != null);
   //idCache.addItem(sr[i].id,rid);  // probably only need one of these..
   //sr[i].used = false; // flag so we can see if this id gets used later...
   sr[i].table = table; // so we can use retrieve™
   sr[i].record = records[i]; // so we can fix lookups?
   idCache.addItem(rid, sr[i]);  // old id , new save result with table name...
  }  
 }
  
 // report number of loaded records
 var dd = document.getElementById('num_'+table.tagName+".xml");
 if (dd) { dd.innerHTML = "<b>"+records.length+" records loaded from "+
  table.tagName+".xml into the "+table.tagName+ " table</b>"; 
 } else { message("could not find doc element "+'num_'+table.tagName+".xml") }
 
 } catch (e) { alert("error "+e)}
}

function fixLookups(tables) {  /* perform updates for several types of id's,
 * account->account for parent id,  contct -> contact for reports to
 * all case contacts and objects... etc
 * problem is, the records are already inserted, so we will have to update some records
 * for each old ID in our data tables, ( which has not been fixed yet)
 * find the new ID, 
 * create a dynabean to be updated with that id , ref field name, new REF ID
 * update the record
 * and batch this process 
 * do this once for each table if possible, however
 * this could lead to updates in every table we have loaded
 */
 for (var tk in tables) { var ta = tables[tk];
  var records = ta.records; // all the old records from this table, 
  // each oldid entry in idCache may be found in multiple places in the xml files
  // sweep this table , look at all refs, see if that id is in the cache and therefore needs 
  // to be replaced
  for(var i =0;i<records.length;i++) {  // for each record
    // for each field, see if it's a ref field, 
    var rec = records[i];
    for( k in rec.map) { var fl = rec.getItem(k); 
     if ( fl.type != "reference") continue;
     var sr = idCache.getItem(fl.value); 
     if ( sr != null && sr.id != null ) {  // found an id we want to fix.
      //fl.value = sr.id; 
      // construct a dynabean with this field and it's poper new value
      // we already have rec, which is a bean
      rec.set(k,sr.id);
      alert(" set record "+k+ " to "+ sr.id);
     } 
   }
  }
 }
}

function fixup(records) { 
 /* go thru all records in this table, fix up any pointers that we know about
  * from our ID cache, and then remove them from the cache so we don't use 
  * them twice or fail to make a fixup.  at the end the idcache should be empty?
  */
  for(var i =0;i<records.length;i++) {  // for each record
   // for each field, see if it's a ref field, 
   var rec = records[i];
   for( k in rec.map) { 
    // if so, look in the id Cache and pull an id to stuff into this record
    var fl = rec.getItem(k);
    if ( fl.type != "reference") continue;
    var sr = idCache.getItem(fl.value); 
    if ( sr != null && sr.id != null ) {  // found an id we want to fix.
     fl.value = sr.id;    // the fix is in..
    } 
   }
 }
} 

/* because accout is related to account and contact is related to contact
// we cant just re-order this or any load order, instead we need to insert all records
 then go back thru the tables ( each one) and fix up any and all references, that way 
  reportsTo on contacts AND Parent Account on account both will work.
  
  we could fixup master detail relations because they are one way, but 
  would still have to fixup lookup relations later...
  
  this just tries to put the master before the child, that's all
*/
function tableCrossRef(des) { 
 // need to go thru the des and pull child objects
 var aa = []; var newdes = [];
 for (var i=0; i < des.length; i++) { des[i].isMaster = false;
  var table = des[i].name;  // name of table we are looking at now
  for(var k in des[i].childRelationships.keys) { 
   var mm = des[i].childRelationships.getItem(k);
   // see if there is a child of table in the list we have
   if ( isIn(mm.childSObject.toLowerCase(),des) ) { 
    mm.parentSObject = table;
    aa.push(mm);
    if(mm.cascadeDelete && mm.childSObject.toLowerCase() != table.toLowerCase()) 
     des[i].isMaster = true; // only think used from this routine
   } 
  }
 } 
 
// if (debug) alert(aa.toString());
 return aa; // ret value not used
} 

function isMaster(a,b) { if (a.isMaster == true) return -1; return 1; }

function isIn(element,array) { // is the element in the array, like grep()
 for(var i =0 ; i<array.length; i++) { 
  if (element.toLowerCase() == array[i].name.toLowerCase() 
  //|| element.toLowerCase() == array[i].toLowerCase().replace(/\.xml/,"")
  ) {
   return true;
  }
 } 
 return false;
}
function grep(element,array) { // return element in the array like grep in perl
 for(var i =0 ; i<array.length; i++) { 
  if (element.toLowerCase() == array[i].toLowerCase()) return array[i];
 } 
 return null;
}
// this only finds tables with relations to themself
function self_ref(list,des) {  // unused
 // need to go thru the des and pull child objects
 for (var i=0; i < des.length; i++) { 
  var table = des[i].name;  // name of table we are looking at
  var childs = des[i].childRelationships;
  for(var k in childs.keys) { 
   for (var l=0;l<list.length;l++) { 
    var ctab = list[i].toLowerCase().replace(/\.xml/,"");
    if (ctab == k) { 
     var mm = childs.getItem(k); // get the relationship details
     alert("found a match "+ table + " is related to " + k + " by \n"+mm.toString()) 
    }
   } 
  }
 } 
} 

function loadData() {  /* switch modes, put up a pick list of the tables we know exist as xml files 
          * in the exports folder, allow the user to pick one or more 
       */ 
 document.getElementById('divTableHeader').innerHTML = ""; 
 msg.style.visibility = 'hidden'; msg.innerHTML = "";
 
 drawList(document.getElementById('divTableHeader'), listDocs(folderid) ); 
 document.getElementById('loadbutton').innerHTML = 
  "<input value=\" Load Packed Data \" class=\"btn\" type=\"button\" onclick=\"loadData2(document.forms['editPage'],'ids')\" >";
 // would be nice to list how many records are in each of these tables
}

function listDocs(id) { // for folder , list the document names in this folder
 var qr = sforceClient.query("select name from document where folderid = '"+id+"'")
 if (qr.className != "QueryResult" || qr.size <1) throw( "could not query table "+qr.toString);
 var ret = [];for (var i =0;i<qr.records.length; i++) { ret.push(qr.records[i].get("name")) }
 return ret;
}

function create_doc(name,body) { 
 var docname = name+".xml";
 var docid = doc_exists(folderid,docname) ;
 if ( docid != null  ) { 
  if (!confirm("overwrite existing document? :"+docname)) {
   return; 
  } else { // remove the existing doc... 
   sforceClient._delete([docid]);
  } 
 }
 
 var newDoc = new Sforce.Dynabean("Document"); 
 newDoc.set("Body", "<"+name+">"+body+"</"+name+">");
 newDoc.set("FolderId", folderid);  // Need to replace this with your folder ID
 newDoc.set("name", docname); 
 var nq = sforceClient.Create(newDoc)[0]; 
 if (nq.success != true) { throw( "Fault in document create"+ nq.errors[0].message) }

} 
 
function xmlTable(table) {  
 var soql = "Select " + sforceClient.DescribeSObject(table).getCloneFields() + " From " + table;
 var qr = sforceClient.query(soql); // gives 200 records, minimum batch size
 // for now we limit the number of records to 200 from this utility
 if (qr.className != "QueryResult" || qr.size <1) throw( "could not query table "+qr.toString);
 if (qr.records.length >= 200) { 
  if( !confirm("only 200 random records from this table will be included\nProceed ?")) return; 
 }
 var body = ''; var beans = []; // trim down this array while we are debugging
 for (var i=0; i < qr.records.length; i++) { 
  if (i > maxBeans) break; // while debugging , limiit the list
  beans.push(qr.records[i]); 
 }
 
 body += Sforce.Serialization.SerializeBean (beans,"forupdate");
 
 create_doc(table,body); // write the body to a document file.
 return true;
 
} 

function packData() { // create xml doc with ID and all columns
 todo = []; // first stop all currently running queries
 document.getElementById('divTableHeader').innerHTML = "<b>Please wait... </b>"; 
 setTimeout("packData2();",30);
}

function packData2() { // create xml doc with ID and all columns
 try {  
  for (var i=0; i<updateObjects.length; i++) { xmlTable(updateObjects[i]); }
  window.parent.parent.location.href = '/015?fcf='+folderid.substr(0,15);
  
 } catch(e) { msg.style.visibility = 'visible';  msg.innerHTML = e; return false;}
}

function IsChecked(form, element_name) { 
 updateObjects = [];
/* for (i = 0; i < form.elements.length; i++) { 
  if ((form.elements[i].name == element_name) && (form.elements[i].checked)) { 
   updateObjects.push(form.elements[i].value); 
  }
 } */
 var selected = document.getElementById('select_1');
 for (var i= 0; i < selected.options.length; i++) { updateObjects.push(selected.options[i].value); }

 if (updateObjects.length < 1) { 
  msg.style.visibility = 'visible';
  msg.innerHTML = "Error: You must select one or more tables";
  err = 1;
  return;
 } else { msg.style.visibility = 'hidden'; msg.innerHTML = ""; }
 
 packData(); 
} 

function drawList(div,list) { 
 var ta = createTag(div,"table",{'class':"list" ,'width':'100%','border':'0','cellspacing':'0','cellpadding':'0'} );
 var tb = createTag(ta,"tbody");
 var tr = createTag(tb,"tr",{'class':"headerRow"});
 createTag(createTag(tr,"th",{'width':'5%'}), "input",
  {'type':'checkbox','id':'topcheck',
  'onClick':"javascript:SelectChecked(document.forms['editPage'],'ids',this.checked)"})
 createTag(tr,"th",{'nowrap':'nowrap','width':'15%'}).innerHTML="Table";
 createTag(tr,"th",{'nowrap':'nowrap', 'width':'45%' }).innerHTML="Records"; 
 for (var i=0;i<list.length;i++) {
  tr = createTag(tb,"tr");
  td = createTag(tr,"td") 
  createTag(td,"input",{'type':'checkbox','name':'ids','id':'ids','value':list[i] });
  createTag(tr,"td").innerHTML = "&nbsp;" + list[i]; 
  createTag(tr,"td").innerHTML = "<span id=num_"+ list[i] + ">&nbsp;</span>"; 
 } 
}

function handleKeyDown_select_0(evt) {
    evt = getEvent(evt);
 // var errGeneral = document.getElementById('error_General');
 //errGeneral.innerHTML = 'keycode :'+evt.keyCode;
 //errGeneral.style.visibility = 'visible';
    
 // Enter key
    if (evt.keyCode == 13 || evt.which == 13) {
        queueSearch_select_0();
        return false;
    }
 queueSearch_select_0(); // queue a search so that we search on each new char
    return true;
}

function  queryRecordCounts(list) { 
 todo = list.sort(); 
 // start a process of running a query to count records in each table...
 setTimeout("countrecords()",100);
} 

function countrecords() {  // not used
 var so = todo.shift(); 
 if (!so) return;
 sforceClient.setBatchSize(2); // for now
 var qr = sforceClient.query("select id from "+so,drawcount);
}

function drawcount(qr) {  // not used
 if (qr.size < 1) { // put up a zero?
  var ss= qr.SOQL.split(" ");
  var name = ss.pop();
  var dd = document.getElementById('num_'+name);
  if (dd) { dd.innerHTML = 0+"";}
 } else { 
  // find the row which has this table name
//  msg.style.visibility = 'visible';
//  msg.innerHTML = "table :"+qr.records[0].definition.name + " has " + qr.size ; 
  var dd = document.getElementById('num_'+qr.records[0].definition.name);
  if (dd) { dd.innerHTML = qr.size+""; } 
 }
 setTimeout("countrecords()",10); // see if there are more todo
}
function doc_exists( f,n) { 
 var qr = sforceClient.query("select id from Document where folderid = '"+f+"' and name = '"+n+"'");
 if (qr.className != "QueryResult" ) throw("could not query documents folder :"+qr.toString()); 
 if ( qr.size > 0 && qr.records[0] ) return qr.records[0].get("Id");
 return null;
} 
function get_folder(name) { 
// TODO should create folder if it's missing ?
 var qr = sforceClient.query("select id from Folder where name = '"+name+"'");
 if (qr.className == 'Fault') { throw( "Fault in document find"+ qr[0].errors[0].message)}
 if (qr.size < 1) { throw("could not find folder "+name); }
 return qr.records[0].get("Id");
}

function makeTable(p) {
 var table = createTag(p,"table",{ 'class':'list','width':'100%','border':'0','cellspacing':'0','cellpadding':'0'} );
 table.tbody = createTag(table,'tbody');
 return table
}

function makeRow(atts) { return createTag(null,'TR',atts); }
function createTag(parent, name, keyvalPairs) {
 var ret; 
 if (sapp.get_type() == Sforce.Application.Type.InternetExplorer) {
  var trTag = "<"+name+" ";
  for (key in keyvalPairs) {
    trTag += key + "=\"" + keyvalPairs[key] + "\"";
  }
  trTag += ">";
  ret = document.createElement(trTag);
 } else { 
  ret = document.createElement(name);
  for (key in keyvalPairs) {
   ret.setAttribute(key, keyvalPairs[key]);
  }
 } 
 if (parent) parent.appendChild(ret);
 ret.active = false;
 return ret;
}
function SelectChecked(form, element_name, value) { 
 var i = 0; for (i = 0; i < form.elements.length; i++) { 
  if (form.elements[i].name == element_name) { 
   form.elements[i].checked = value; 
  } 
 } 
} 

Sforce.DescribeSObjectResult.prototype.getCloneFields = function() {
 var out = ['id'];
 for (key in this.fieldMap.getKeys()) {
  if (this.fieldMap.getItem(key).updateable  == true ||
   this.fieldMap.getItem(key).createable   == true )  { 
   out.push( this.fieldMap.getItem(key).name );
  }
 }
 return out.join(",");
}

function message(str,div) {  // draw or clear a message
 if (!div) div = document.getElementById('msg');
 if (!str || str == "")  {  msg.style.visibility = 'hidden'; msg.innerHTML = ""; } 
 else {  msg.style.visibility = 'visible'; msg.innerHTML = str;}
} 

Sforce.Dynabean.prototype.getBody = function(propName) { // like get(), but will decode b64 document body elements
 var body=''; 
 try { 
  if (propName.toLowerCase() != 'body') { 
   throw( "ERROR: getBody() only returns a base64 body element");
  }
  var tmp = this.getItem(propName).value; 
  
  if ( Sforce.Util.dltypeof(tmp) == "domelement" ) {  // see what type of object tmp is...
   for (var i=0; i < tmp.childNodes.length; i++) { 
    body += tmp.childNodes[i].textContent; 
   } 
  } else { // normal string if body is < 4096 bytes 
   body = tmp; 
  } 
 } catch (e) { throw(e); }
  
 var b64 = new Sforce.Util.Base64();
 return b64.decode( body); // and decode it 
};

function assert(fact,msg) { 
// if ( ! debug ) return ; // only execute if we are in debug mode
 if ( fact ) { return true } 
 msg = "Assert failure \n" + msg;
 if (arguments.callee.caller != null) { 
  msg = msg + " in function "+ arguments.callee.caller.toString().match(/function\s+(\w+)/)[1];
 } 
 if(debug) {alert(msg)} else {throw(msg);}
 return false
}

--> 
</script>  

</head> 
<body onload="startup()"  class="home  editPage">
<a name="skiplink">
<img src="/s.gif" height='1' width='1' alt="Content Starts Here" class="skiplink"></a>
<form name="editPage" id="editPage">
<div class="bPageTitle">
<div class="ptBody secondaryPalette">
 <div class="content">
 <img src="/s.gif" alt="Home"  class="pageTitleIcon">
 <h1 class="pageType noSecondHeader">
 Package Data<span  class="titleSeparatingColon">:</span></h1>
 <!-- <h2 class="pageDescription"></h2> <div class="blank">&nbsp;</div>-->
 </div>
 <div class="ptBreadcrumb"></div>
</div>
 
more instructions, read me... <br>select one or more tables to package

<div class="bPageBlock bEditBlock secondaryPalette" id="ep">
 
<div class="pbHeader">
 <TABLE  cellpadding="0" cellspacing="0" border="0">
 <TR> 
 <TD class=""> </TD>
 <TD class="pbButton"><center>
  <span id="loadbutton">
  <input name="save1" value=" Pack Data " class="btn" type="button" onclick="IsChecked(document.forms['editPage'],'ids')" > 
  <input name="load" value=" List Packed Data " class="btn" type="button" onclick="loadData()" >
  </span>
  <div class=errorMsg id="msg"></div>
  </center>
  </TD>
  </TR>
 </TABLE>
</DIV>
 
<div id="divTableHeader" class="pbBody">  
  <table border=0 cellspacing=1 cellpadding=0 id="seluser" > 
     <TR> 
       <TD COLSPAN=5 ><table cellpadding=1 cellspacing=1 border=0> 
          <tr> 
             <td height=5 colspan=100%></td> 
           </tr> 
           <tr> 
             <td valign=bottom class=bodyBold>Available Tables</td> 
             <td width=3 rowSpan=2><IMG src="/s.gif" width=3 border=0></td> 
             <td>&nbsp;</td> 
             <td width=3 rowSpan=2><IMG src="/s.gif" width=3 border=0></td> 
             <td valign=bottom class=bodyBold>Selected Tables</td> 
           </tr> 
           <tr> 
       <td valign="top" class="dataCol"><div class="requiredInput"> 
   <div class="requiredBlock"></div>
  <select name="select_0" id="select_0" MULTIPLE  width="200" size="10" tabindex="4" ondblclick="javascript:moveOption(document.editPage.select_0, document.editPage.select_1,'--None--', [], null,'--None--');"> 
        </select></div></td> 
             <td valign=center class=bodySmall> <table cellpadding=0 cellspacing=0 border=0> 
                 <tr> 
                   <td valign=bottom align=center class=bodySmall>Add</td> 
                 </tr> 
                 <tr> 
                   <td align=center><a tabindex="4" href="javascript:moveOption(document.editPage.select_0, document.editPage.select_1,'--None--', [], null,'--None--');"><img src="/s.gif" alt="Add" class="rightArrowIcon"></a></td> 
                 </tr> 
                 <tr> 
                   <td><IMG src="/s.gif" height=3> 
                 <tr> 
                   <td align=center><a tabindex="5" href="javascript:moveOption(document.editPage.select_1, document.editPage.select_0,'--None--', [], null,'--None--');"><img src="/s.gif" alt="Remove" class="leftArrowIcon"></a></td> 
                 </tr> 
                 <tr> 
                   <td align=center valign=top class=bodySmall>Remove</td> 
                 </tr> 
             </table></td> 
             <td valign="top" class="dataCol"><div class="requiredInput"> 
       <div class="requiredBlock"></div>
        <select name="select_1" id="select_1" MULTIPLE  width="200" size="10" tabindex="6" 
         ondblclick="javascript:moveOption(document.editPage.select_1, document.editPage.select_0,'--None--', [], null,'--None--');" > 
                <option value="">--None--
                </select></div>
             </td> 
           </tr> 
           <tr> 
             <td colspan="5"><div class=errorMsg id="error_select_1"></div></td> 
           </tr> 
         </table></TD> 
     </TR> 
   </table>
</div>
 
<div class="pbFooter secondaryPalette"> <div class="bg"></div></div> 

</div>
</div>
</form>  
</body> 
</html>

 
...


Carl_VCarl_V
Im sorry, but could someone please explain how the following excerpts of code work?

Im particular interested to know what the keyvalpairs refers to in first function, and in the second, the relevance of the
form.elements[i].name == element_name.  Im trying to build a form for use in new s-control and having a little trouble...

Regards,
Carl



function createTag(parent, name, keyvalPairs) {
var ret;
if (sapp.get_type() == Sforce.Application.Type.InternetExplorer) {
var trTag = "<"+name+" ";
for (key in keyvalPairs) {
trTag += key + "=\"" + keyvalPairs[key] + "\"";
}
trTag += ">";
ret = document.createElement(trTag);
} else {
ret = document.createElement(name);
for (key in keyvalPairs) {
ret.setAttribute(key, keyvalPairs[key]);
}
}
if (parent) parent.appendChild(ret);
ret.active = false;
return ret;
}


function SelectChecked(form, element_name, value) {
var i = 0; for (i = 0; i < form.elements.length; i++) {
if (form.elements[i].name == element_name) {
form.elements[i].checked = value;
}
}
}

The_FoxThe_Fox
Hi Carl:smileyhappy:,

In fact you are running throught all elements of the form the the form.elements[i].name and the element-name is the name of the element you are interested in.


That's all

Regards
DevAngelDevAngel
The Fox, as usual, is correct.

I don't know why you would do that when you can use ids and request the element directly using document.getElementById([elementid]).

While it may not impact your particular implementation, iterating all the elements of a form is a bad practice that will lead to poor performance.  Even if you didn't have ids on all your elements, you should still try to minimize the number of form elements to consider by using document.getElementsByTagName("input") or some other create mechanism.

Cheers
The_FoxThe_Fox
Hi Dave,

You 'll make me blush:smileywink:

I think that may be by the force of the habit (not sure it is proper english) tell me the proper expression

Of course Dave is quite right on this. I will add this on my list to modify my s-controls

Regards