Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Visualforce Object Hierarchy Editor

By: a guest on Dec 5th, 2010  |  syntax: JavaScript  |  size: 7.08 KB  |  views: 324  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. <apex:component controller="HierarchyController" allowDML="true">
  2.     <!-- a VF component for modifying the hierarchy of an SObject (Campaign,
  3.     Account, etc.) using an ExtJS TreePanel -->
  4.     <!-- Jeff Trull jetrull@sbcglobal.net 2010-12-01 -->
  5.     <apex:attribute name="object" type="Object" description="sObject to edit hierarchy on"
  6.     default="Campaign" />
  7.     <apex:attribute name="fn" type="String" description="name of a Javascript function to call with ID once a Campaign is selected."
  8.     required="false" default="" />
  9.     <!-- load ExtJS -->
  10.     <apex:stylesheet value="{!$Resource.ExtJS}/resources/css/ext-all.css"
  11.     />
  12.     <apex:includeScript value="{!$Resource.ExtJS}/adapter/ext/ext-base.js"
  13.     />
  14.     <apex:includeScript value="{!$Resource.ExtJS}/ext-all.js" />
  15.     <script type="text/javascript">
  16.         Ext.BLANK_IMAGE_URL = "{!$Resource.ExtJS}/resources/images/default/s.gif"
  17.     </script>
  18.     <!-- Create a JS function that calls the child object finding Apex method,
  19.     -->
  20.     <!-- then loads the results when the AJAX request returns -->
  21.     <apex:actionFunction name="fetchObjects" action="{!findChildObjects}"
  22.     rerender="unrollpanel" oncomplete="fetchCallback.call();">
  23.         <apex:param name="sobjname" assignTo="{!fetchObject}" value="" />
  24.         <apex:param name="parentid" assignTo="{!fetchParentId}" value="" />
  25.     </apex:actionFunction>
  26.     <!-- Define function returning child data. Function definition changes
  27.     after reach AJAX response -->
  28.     <!-- to contain the result of our child record search -->
  29.     <apex:outputPanel id="unrollpanel">
  30.         <!-- if not in an outputPanel, the rerender fails! -->
  31.         <!-- A function that just takes the results from a single tree query and
  32.         returns it -->
  33.         <!-- regenerated after every tree node expansion and then called from
  34.         the actionFunction's oncomplete -->
  35.         <script type="text/javascript">
  36.             function nodeResults(forceLeaf) {
  37.                 var loadData = new Array();
  38.                 // unroll child nodes list with apex:repeat
  39.                 // node properties: if level 5, a leaf (cannot have children)
  40.                 //                                      if no children, show as folder, but without "expand" button
  41.                 //                                      if has children, folder with expand button
  42.                 < apex: repeat value = "{!fetchResults}"
  43.                 var = "obj" > loadData.push({
  44.                     id: "{!obj.id}",
  45.                     text: "{!obj.name}",
  46.                     expanded: { !! obj.hasChildren
  47.                     },
  48.                     loaded: { !! obj.hasChildren
  49.                     },
  50.                     leaf: forceLeaf
  51.                 }); < /apex:repeat>
  52.                 return loadData;
  53.         }
  54.        
  55.         </script>
  56.     </apex:outputPanel>
  57.     <!-- Create a JS function to call the Apex method that reassigns a record
  58.     parent -->
  59.     <apex:actionFunction name="updateParent" action="{!setParent}" rerender="setstatuspanel">
  60.         <apex:param name="parent" assignTo="{!parentIdToSet}" value="" />
  61.         <apex:param name="child" assignTo="{!childIdToSet}" value="" />
  62.     </apex:actionFunction>
  63.     <!-- a function regenerated by the parent ID set result after server completes
  64.     -->
  65.     <apex:outputPanel id="setstatuspanel">
  66.         <script type="text/javascript">
  67.             function getSetStatus() {
  68.                 return {
  69.                     !idSetSuccess
  70.                 };
  71.             }
  72.         </script>
  73.     </apex:outputPanel>
  74.     <script type="text/javascript">
  75.         Ext.onReady(function() {
  76.             var tree = new Ext.tree.TreePanel({
  77.                 renderTo: 'treediv',
  78.                 useArrows: true,
  79.                 autoScroll: true,
  80.                 animate: true,
  81.                 containerScroll: true,
  82.                 border: false,
  83.                 enableDD: true,
  84.                 loader: new Ext.tree.TreeLoader({
  85.                     directFn: function(loadid, callback) {
  86.                         // determine if we are expanding a level 4 record (current limit is 5 -> leaf)
  87.                         var lvl4 = (tree.getNodeById(loadid).getDepth() >= 4);
  88.                         // establish callback for when AJAX request completes
  89.                         fetchCallback = function() {
  90.                             callback.apply(window, [nodeResults(lvl4),
  91.                             {
  92.                                 status: true
  93.                             }]);
  94.                         }.createDelegate(this);
  95.                         // call actionFunction created for loading
  96.                         fetchObjects('{!object}', loadid);
  97.                     }
  98.                 }),
  99.                 root: new Ext.tree.AsyncTreeNode({
  100.                     text: 'All {!object}s',
  101.                     expanded: false,
  102.                     draggable: false,
  103.                     id: 'root' // because you cannot use a blank id (Ext would create one)
  104.                 }),
  105.                 listeners: {
  106.                     beforemovenode: function(tree, node, oldParent, newParent) {
  107.                         if (oldParent.id == newParent.id) {
  108.                             // just a change to ordering; no need for server request
  109.                             return true;
  110.                         }
  111.                         var parent = newParent.id;
  112.                         if (parent == 'root') {
  113.                             parent = ''; // translate back into Apex world
  114.                         }
  115.                         // this is, unfortunately, a synchronous approach
  116.                         updateParent(parent, node.id);
  117.                         // if level has changed to/from L5, adjust "leaf" property
  118.                         if ((oldParent.getDepth() == 4) || (newParent.getDepth() == 4)) {
  119.                             node.leaf = (newParent.getDepth() == 4);
  120.                         }
  121.                         return true;
  122.                     },
  123.                     movenode: function(tree, node, oldParent, newParent) {
  124.                         // TreePanel automatically shows nodes without children as leafs
  125.                         // it will also automatically change those leafs into folders when another
  126.                         // node is dropped on them.  However, it will not change the folders back
  127.                         // into leaf icons when the last child is removed.  This is a workaround.
  128.                         if (!oldParent.hasChildNodes()) {
  129.                             oldParent.getUI().removeClass("x-tree-node-collapsed");
  130.                             oldParent.getUI().addClass("x-tree-node-leaf");
  131.                         }
  132.                     },
  133.                     beforedblclick: function(node) {
  134.                         if (('{!fn}' != '') && (node.id != 'root')) {
  135.                             {
  136.                                 !fn
  137.                             }(node.id);
  138.                         }
  139.                     }
  140.                 }
  141.  
  142.             });
  143.  
  144.             tree.getRootNode().expand(); // trigger load of top level objects
  145.         });
  146.     </script>
  147.     <div id="treediv" />
  148. </apex:component>