+ Start a Discussion
patskepatske 

Drag and Drop using javascript

Hi guys,

I'm trying to get a pretty standard Scriptaculous drag and drop functionality using javascript to work in a visual force page. Am not having any great deal of luck right now. Can anyone help or point me in the right direction

below is the source for the drag and drop page I have done in HTML it works fine I want to try and port it to visual force, ultimately being able to use the output from the 'debug log button there' to use in a Controller Extension and create some relationships between objects.

I'm guessing the problem is with the way visual force pages reference ID's?? But I can't be completely sure. Any help would be great. Thanks :)


Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
 <title>Drag Drop</title>
  <script src="http://script.aculo.us/prototype.js" type="text/javascript"></script>
  <script src="http://script.aculo.us/scriptaculous.js" type="text/javascript"></script>
  

 <script language="JavaScript">
 sections = ['group1','group2','group3'];

 function createNewSection(name) {
  var name = $F('sectionName');
  if (name != '') {
   var newDiv = Builder.node('div', {id: 'group' + (sections.length + 1), className: 'section', style: 'display:none;' }, [
    Builder.node('h3', {className: 'handle'}, name)
   ]);

   sections.push(newDiv.id);
   $('page').appendChild(newDiv);
   Effect.Appear(newDiv.id);
   destroyLineItemSortables();
   createLineItemSortables();
   createGroupSortable();
  }
 }

 function createLineItemSortables() {
  for(var i = 0; i < sections.length; i++) {
   Sortable.create(sections[i],{tag:'div',dropOnEmpty: true, containment: sections,only:'lineitem'});
  }
 }

 function destroyLineItemSortables() {
  for(var i = 0; i < sections.length; i++) {
   Sortable.destroy(sections[i]);
  }
 }

 function createGroupSortable() {
  Sortable.create('page',{tag:'div',only:'section',handle:'handle'});
 }

 /*
 Debug Functions for checking the group and item order
 */
 function getGroupOrder() {
  var sections = document.getElementsByClassName('section');
  var alerttext = '';
  sections.each(function(section) {
   var sectionID = section.id;
   var order = Sortable.serialize(sectionID);
   alerttext += sectionID + ': ' + Sortable.sequence(section) + '\n';
  });
  alert(alerttext);
  return false;
 }
 </script>

<style>
 body, div {
  font-family: Arial, Helvetica;
  font-size: 11px;
 }

 div.section,div#createNew {
  border: 1px solid #CCCCCC;
  margin: 30px 5px;
  padding: 0px 0px 10px 0px;
  background-color: #EFEFEF;
 }

 div#createNew input { margin-left: 5px; }

 div#createNew h3, div.section h3{
  font-size: 14px;
  padding: 2px 5px;
  margin: 0 0 10px 0;
  background-color: #CCCCCC;
  display: block;
 }

 div.section h3 {
  cursor: move;
 }

 div.lineitem {
  margin: 3px 10px;
  padding: 2px;
  background-color: #FFFFFF;
  cursor: move;
 }

 h1 {
  margin-bottom: 0;
  font-size: 18px;
 }
</style>
</head>
<body>
<div id="page">

 <div id="createNew">

  <h3>Add New Sales Contact</h3>
  <input type="text" id="sectionName" size="25">
  <input type="button" onClick="createNewSection();" value="Create Sales Contact">
 </div>

 <div id="group1" class="section">
  <h3 class="handle">Tickets</h3>
  <div id="item_1" class="lineitem">DWD2008 VIP</div>

  <div id="item_2" class="lineitem">DWD2008 GOLD</div>
  <div id="item_3" class="lineitem">DWD2008 SILVER</div>
  <div id="item_4" class="lineitem">DWD2008 BRONZE</div>
 </div>

 <div id="group2" class="section">
  <h3 class="handle">Sales Contact 1</h3>

 </div>

 <div id="group3" class="section">
  <h3 class="handle">Sales Contact 2</h3>
 </div>

</div>

<fieldset>
 <legend>group order debug</legend>

 <input type="button" onClick="getGroupOrder()" value="output group order">
 <br>
</fieldset>

<script type="text/javascript">
 // <![CDATA[
 Sortable.create('group1',{tag:'div',dropOnEmpty: true, containment: sections,only:'lineitem'});
 Sortable.create('group2',{tag:'div',dropOnEmpty: true, containment: sections,only:'lineitem'});
 Sortable.create('group3',{tag:'div',dropOnEmpty: true, containment: sections,only:'lineitem'});
 Sortable.create('page',{tag:'div',only:'section',handle:'handle'});
 // ]]>
 </script>
</body>
</html>

 


dchasmandchasman
I suspect this should get you moving again Developer Doc: Component IDs. BTW we are working on visualforce native drag and drop support - no release date just yet - and I did want to mention that we will be leveraging Ext.js in our implementation. My team has extensive experience with Scriptaculous/Prototype.js and Dojo and we've made the decision to switch to use Ext.js in our own work going forward.


Message Edited by dchasman on 06-23-2008 07:48 AM
kmccollkmccoll
Exciting news re: ext.js.  I've been holding off using extjs as it meant giving up too much of the pre-built visualforce components.  This could be a huge win for visualforce as it can help expose very rich UI components.

Will we all have to purchase Ext.js licenses?
dchasmandchasman
No additional cost will be applied to use salesforce provided components implemented in terms of Ext.js but we're still working out the licensing details w.r.t. customers and partners that want to build their own pages/components using ext.js functionality directly.
patskepatske
*Bump


Hey guys still having a bit of trouble on this one. Main thing being that I want to pass my output string from the javascript function "GroupOrder();" to my controller or extension.... Is there anyway to do it?

I've seen something similar on the forums but couldn't quite get it working. Really would appreciate any help on this one it's driving me nuts!

In dreamweaver I can get this "groupOrder();" function to execute and give me a string of what elements have what children. But in Visual force everything seems to work fine except for this one **bleep** function :(.

Below is my code for my controller and my visual force page Thanks in advance to anyone that can crack this one. Right now I'm pulling values from SF and using <apex:repeater" tags to format them.. then I want to get the value that gets spat out from "groupOrder()" in the javascript and parse it to upsert some objects in salesforce. Obviously any other ideas on how to solve this would be great also.

Cheers,

Code:
VISUAL FORCE PAGE

<apex:page id="p" standardController="Account" extensions="allocateticketExt" tabstyle="Ticket_Allocation__c" standardStylesheets="false">
  <apex:sectionHeader title="Allocate Tickets"/>
  <apex:form id="f">
   <script src="http://script.aculo.us/prototype.js" type="text/javascript"></script>
   <script src="http://script.aculo.us/scriptaculous.js" type="text/javascript"></script>
  

    <script language="JavaScript">
    sections = ['Tickets'];
    <apex:repeat value="{!salescontacts}" var="scCS">
    sections.push('{!scCS.id}');
    </apex:repeat>

    function createNewSection(name) {
        var name = $F('sectionName');
        if (name != '') {
            var newDiv = Builder.node('div', {id: 'group' + (sections.length + 1), className: 'section', style: 'display:none;' }, [
                Builder.node('h3', {className: 'handle'}, name)
            ]);

            sections.push(newDiv.id);
            $('page').appendChild(newDiv);
            Effect.Appear(newDiv.id);
            destroyLineItemSortables();
            createLineItemSortables();
            createGroupSortable();
        }
    }

    function createLineItemSortables() {
        for(var i = 0; i < sections.length; i++) {
            Sortable.create(sections[i],{tag:'div',dropOnEmpty: true, containment: sections,only:'lineitem'});
        }
    }

    function destroyLineItemSortables() {
        for(var i = 0; i < sections.length; i++) {
            Sortable.destroy(sections[i]);
        }
    }

    function createGroupSortable() {
        Sortable.create('page',{tag:'div',only:'section',handle:'handle'});
    }

    </script>
<style>
    body, div {
        font-family: Arial, Helvetica;
        font-size: 11px;
    }

    div.section,div#createNew {
        border: 1px solid #CCCCCC;
        margin: 30px 5px;
        padding: 0px 0px 10px 0px;
        background-color: #EFEFEF;
    }
      
    div#createNew input { margin-left: 5px; }

    div#createNew h3, div.section h3{
        font-size: 14px;
        padding: 2px 5px;
        margin: 0 0 10px 0;
        background-color: #CCCCCC;
        display: block;
    }

    div.section h3 {
        cursor: move;
    }

    div.lineitem {
        margin: 3px 10px;
        padding: 2px;
        background-color: #FFFFFF;
        cursor: move;
    }

    h1 {
        margin-bottom: 0;
        font-size: 18px;
    }
</style>
<div id="page">
    <div id="createNew">
        <h3>Add New Sales Contact</h3>
        <input type="text" id="sectionName" size="25" />
        <input type="button" onClick="createNewSection();" value="Create Sales Contact" />
    </div>
    
    <div id="Tickets" class="section">
        <h3 class="handle">Tickets</h3>
        <apex:repeat value="{!ticket}" var="t" id="AllTickets">
         <div id="{!t.id}" class="lineitem">{!t.Product_Full_Name__c}</div>
        </apex:repeat>
    </div>
        
    <apex:repeat value="{!salescontacts}" var="sc" id="Allocations">
    <div id="{!sc.id}" class="section">
        <h3 class="handle">{!sc.Name__c}  ({!sc.Role__c})</h3>
        <apex:repeat value="{!allocated}" var="aoi">
            <script type="text/javascript">
              if({!CONTAINS(sc.id,aoi.Sales_Contact__c)}){
                document.write('<div id="{!aoi.Order_Item__c}" class="lineitem">{!aoi.Order_Item__r.Product_Full_Name__c}</div>');
              }
            </script>
        </apex:repeat>
    </div>
    </apex:repeat>
</div>
<br/><br/>
<p>
 <apex:outputText value="Clicked— {!state}" id="showstate" />
</p>

<apex:outputPanel onclick="methodOneInJavascript(GroupOrder();)" styleClass="btn"> 
  Click Me 
</apex:outputPanel>

<apex:actionFunction action="{!methodOne}" name="methodOneInJavascript" rerender="showstate">
   <apex:param name="firstParam" assignTo="{!state}" value="" />
</apex:actionFunction>

<script type="text/javascript">
    // <![CDATA[
    Sortable.create('Tickets',{tag:'div',dropOnEmpty: true, containment: sections,only:'lineitem'});
    <apex:repeat value="{!salescontacts}" var="scs">
      Sortable.create('{!scs.id}',{tag:'div',dropOnEmpty: true, containment: sections,only:'lineitem'});
    </apex:repeat>
    Sortable.create('page',{tag:'div',only:'section',handle:'handle'});
    // ]]>
 </script>
 <script type="text/javascript">
         function SortIt(order){
           var trueorder = '';
           if(order.length==null){return trueorder;}
           else{
           for(x=0;x<order.length;x++){
             if(x==(order.length-1)){
              trueorder = trueorder + order[x].id;
             }
             else{
              trueorder = trueorder + order[x].id + ',';
             }
           }
           return trueorder;
           }
          }
        
         /*
         Debug Functions for checking the group and item order
         */
         function GroupOrder() {
          var sections = document.form['p:f'].getElementsByClassName('section');
          var alerttext = '';
          for(var i=0;i<sections.length;i++){
           var sectionID = sections[i].id;
           var lineitems = document.form['p:f'].getElementById(sectionID).getElementsByClassName('lineitem');
           var realorder = SortIt(lineitems);
           alerttext += sectionID + ': ' + realorder + '\n';
          }
          return alerttext;
         }
</script>
</apex:form>
</apex:page>


CONTROLLER

public class allocateticketExt {

    String aId;
    String pId;
    List<Order_Item__c> tickets;
    List<Order_Item__c> ticketsB = new List<Order_Item__c>();
    List<Sales_Contact__c> salescontacts;
    List<Ticket_Allocation__c> allocations = new List<Ticket_Allocation__c>(); // list of allocations
    List<Ticket_Allocation__c> allocated;
    
    public allocateticketExt(ApexPages.StandardController controller) {
      aId = ApexPages.currentPage().getParameters().get('aId');
      pId = ApexPages.currentPage().getParameters().get('pId');
    }
    
    public PageReference redirect(){
     PageReference pageRef = new PageReference('/'+pId);
     pageRef.setRedirect(true);
     return pageRef;
    }
    
    public void Tickets() {
      tickets = [select Product_Full_Name__c, Product_new__c, Product_new__r.RecordTypeId, Product_new__r.Ticket_Class__c, Quantity__c, Sales_Prospect__c from Order_Item__c where Sales_Prospect__c = :pId and Product_new__r.RecordTypeId='012T00000000EONIA2' order by Quantity__c DESC];
      for(integer i=0;i<tickets.size();i++){
        if(tickets[i].Quantity__c == 1){
          ticketsB.add(tickets[i]);
        }
        else{
          for(integer j=0;j<tickets[i].Quantity__c;j++){
            ticketsB.add(tickets[i]);
          }
        }
      }
    }
    
    public List<Ticket_Allocation__c> getAllocated(){
      allocated = [select Id, Order_Item__r.Product_Full_Name__c, Order_Item__c, Sales_Contact__c, Sales_Contact__r.Name__c, Sales_Contact__r.Role__c from Ticket_Allocation__c where Sales_Contact__r.Sales_Prospect__c = :pId];
      return allocated;
    }
    
    public List<Order_Item__c> getTicket() {
      Tickets();
      return ticketsB;
    }

    public List<Sales_Contact__c> getSalesContacts(){
      salescontacts = [select Id, Name__c, Contact__r.Name, Contact__c, Role__c, Sales_Prospect__c, Number_Of_Tickets_Allocated__c from Sales_Contact__c where Sales_Prospect__c = :pId];
      return salescontacts;
    }
    
    public void setState(String n) {
  state = n;
}

public String getState() {
  return state;
}

public PageReference methodOne() {
  return null;
}

private String state = 'no';
}