Drag and drop graph : Graph « Ajax Layer « JavaScript DHTML

JavaScript DHTML
1. Ajax Layer
2. Data Type
3. Date Time
4. Development
5. Document
6. Dojo toolkit
7. Event
8. Event onMethod
9. Ext JS
10. Form Control
11. GUI Components
12. HTML
13. Javascript Collections
14. Javascript Objects
15. Javascript Properties
16. jQuery
17. Language Basics
18. Mochkit
19. Mootools
20. Node Operation
21. Object Oriented
22. Page Components
23. Rico
24. Scriptaculous
25. Security
26. SmartClient
27. Style Layout
28. Table
29. Utilities
30. Window Browser
31. YUI Library
Java
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
JavaScript DHTML » Ajax Layer » Graph 
Drag and drop graph




// http://js-graph-it.sf.net 

// License: GNU Library or Lesser General Public License (LGPL)









<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>js-graph.it homepage</title>
<script type="text/javascript">
/*********************
 * browser detection *
 *********************/

var ie=document.all;
var nn6=document.getElementById&&!document.all;

/*****************
 * drag and drop *
 *****************/
 
var isdrag=false;
var mouseStartX, mouseStartY;    // mouse position when drag starts
var elementStartX, elementStartY;  // element position when drag starts
var elementToMove;
var blockToMove;

// an array containing bounds to be respected while dragging elements,
// these bounds are left, top, left + width, top + height of the parent element.
var bounds = new Array(4);

function movemouse(e)
{
  if (isdrag)
  {
    var currentMouseX = nn6 ? e.clientX : event.clientX;
    var currentMouseY = nn6 ? e.clientY : event.clientY;
    var newElementX = elementStartX + currentMouseX - mouseStartX;
    var newElementY = elementStartY + currentMouseY - mouseStartY;

    // check bounds
    // note: the "-1" and "+1" is to avoid borders overlap
    if(newElementX < bounds[0])
      newElementX = bounds[01;
    if(newElementX + elementToMove.offsetWidth > bounds[2])
      newElementX = bounds[2- elementToMove.offsetWidth - 1;
    if(newElementY < bounds[1])
      newElementY = bounds[11;
    if(newElementY + elementToMove.offsetHeight > bounds[3])
      newElementY = bounds[3- elementToMove.offsetHeight - 1;
    
    // move element
    elementToMove.style.left = newElementX + 'px';
    elementToMove.style.top  = newElementY + 'px';

//    elementToMove.style.left = newElementX / elementToMove.parentNode.offsetWidth * 100 + '%';
//    elementToMove.style.top  = newElementY / elementToMove.parentNode.offsetHeight * 100 + '%';
  
    elementToMove.style.right = null;
    elementToMove.style.bottom = null;
    
    if(blockToMove)
      blockToMove.onMove();
    return false;
  }
}

/**
 * finds the innermost draggable element starting from the one that generated the event "e"
 * (i.e.: the html element under mouse pointer), then setup the document's onmousemove function to
 * move the element around.
 */
function selectmouse(e
{
  
  var eventSource = nn6 ? e.target : event.srcElement;
  
  while (eventSource != document.body && !hasClass(eventSource, "draggable"))
  {    
    eventSource = nn6 ? eventSource.parentNode : eventSource.parentElement;
  }

  // if a draggable element was found, calculate its actual position
  if (hasClass(eventSource, "draggable"))
  {
    isdrag = true;
    elementToMove = eventSource;
    
    // calculate start point
    //elementStartX = calculateOffsetLeft(elementToMove);
    //elementStartY = calculateOffsetTop(elementToMove);
    elementStartX = elementToMove.offsetLeft;
    elementStartY = elementToMove.offsetTop;
    
    // calculate mouse start point
    mouseStartX = nn6 ? e.clientX : event.clientX;
    mouseStartY = nn6 ? e.clientY : event.clientY;
    
    // calculate bounds as left, top, width, height of the parent element
    if(elementToMove.parentNode.style.position == 'absolute')
    {
      bounds[00;
      bounds[10;
    }
    else
    {
      bounds[0= calculateOffsetLeft(elementToMove.parentNode);
      bounds[1= calculateOffsetTop(elementToMove.parentNode);
    }
    bounds[2= bounds[0+ elementToMove.parentNode.offsetWidth;
    bounds[3= bounds[1+ elementToMove.parentNode.offsetHeight;
    
    
    // either find the block related to the dragging element to call its onMove method
    blockToMove = findBlock(eventSource.id);
    document.onmousemove = movemouse;
    
    return false;
  }
}

document.onmousedown=selectmouse;
document.onmouseup=new Function("isdrag=false");



/*************
 * Constants *
 *************/
var AUTO = 0;
var HORIZONTAL = 1;
var VERTICAL = 2;

/**************
 * Inspectors *
 **************/

var inspectors = new Array();

/**
 * The canvas class.
 * This class is built on a div html element.
 */
function Canvas(htmlElement)
{
  /*
   * initialization
   */
  this.id = htmlElement.id;
  this.htmlElement = htmlElement;
  this.blocks = new Array();
  this.connectors = new Array();
  
  this.initCanvas = function()
  {
    // inspect canvas children to identify first level blocks
    this.findNestedBlocksAndConnectors(this.htmlElement);
    
    // init connectors
    var i;
    for(i = 0; i < this.connectors.length; i++)
    {
      this.connectors[i].initConnector();
    }
  }
  
  this.findNestedBlocksAndConnectors = function(node)
  {
    var children = node.childNodes;
    var i;
    var offsetLeft = calculateOffsetLeft(this.htmlElement);
    var offsetTop = calculateOffsetTop(this.htmlElement);
    
    for(i = 0; i < children.length; i++)
    {
      // move element in a "correct relative" position and set it size as fixed
      if(getStyle(children[i]"position"== 'absolute')
      {
        children[i].style.left = children[i].offsetLeft + offsetLeft + "px";
        children[i].style.top = children[i].offsetTop + offsetTop + "px";
        children[i].style.width = children[i].offsetWidth;
        children[i].style.height = children[i].offsetHeight;
      }
    
      if(isBlock(children[i]))
      {
        // block found initialize it
        var newBlock = new Block(children[i]this);
        newBlock.initBlock();
        this.blocks.push(newBlock);
      }
      else if(isConnector(children[i]))
      {
        // connector found, just create it, source or destination blocks may not 
        // have been initialized yet
        var newConnector = new Connector(children[i]this);
        this.connectors.push(newConnector);
      }
      else
      {
        // continue searching nested elements
        this.findNestedBlocksAndConnectors(children[i]);
      }
    }    
  }
  
  /*
   * methods
   */  
  this.print = function()
  {
    var output = '<ul><legend>canvas: ' + this.id + '</legend>';
    var i;
    for(i = 0; i < this.blocks.length; i++)
    {
      output += '<li>';
      output += this.blocks[i].print();
      output += '</li>';
    }
    output += '</ul>';
    return output;
  }
  
  /*
   * This function searches for a nested block with a given id
   */
  this.findBlock = function(blockId)
  {
    var result;
    var i;
    for(i = 0; i < this.blocks.length && !result; i++)
    {
      result = this.blocks[i].findBlock(blockId);
    }
    
    return result;
  }
  
  this.toString = function()
  {
    return 'canvas: ' + this.id;
  }
}

/*
 * Block class
 */
function Block(htmlElement, canvas)
{  
  /*
   * initialization
   */
   
  this.canvas = canvas;
  this.htmlElement = htmlElement;
  this.id = htmlElement.id;
  this.blocks = new Array();
  this.moveListeners = new Array();  
  
  
  this.initBlock = function()
  {
    // inspect block children to identify nested blocks
    var children = this.htmlElement.childNodes;
    var i;    
    for(i = 0; i < children.length; i++)
    {
      if(isBlock(children[i]))
      {
        var innerBlock = new Block(children[i]this.canvas);
        innerBlock.initBlock();
        this.blocks.push(innerBlock);
        this.moveListeners.push(innerBlock);
      }
    }
    
    //this.htmlElement.onmousemove = new Function('if(isdrag) findBlock(\'' + this.id + '\').onMove();');
  }
  
  this.top = function()
  {
    return calculateOffsetTop(this.htmlElement);
  }
  
  this.left = function()
  {
    return calculateOffsetLeft(this.htmlElement);
  }
  
  this.width = function()
  {
    return this.htmlElement.offsetWidth;
  }
  
  this.height = function()
  {
    return this.htmlElement.offsetHeight;
  }
  
  /*
   * methods
   */  
  this.print = function()
  {
    var output = 'block: ' + this.id;
    if(this.blocks.length > 0)
    {
      output += '<ul>';
      var i;
      for(i = 0; i < this.blocks.length; i++)
      {
        output += '<li>';
        output += this.blocks[i].print();
        output += '</li>';
      }
      output += '</ul>';
    }
    return output;
  }
  
  /*
   * This function searches for a nested block (or the block itself) with a given id
   */
  this.findBlock = function(blockId)
  {
    if(this.id == blockId)
      return this;
      
    var result;
    var i;
    for(i = 0; i < this.blocks.length && !result; i++)
    {
      result = this.blocks[i].findBlock(blockId);
    }
    
    return result;
  }
  
  this.move = function(left, top)
  {    
    this.htmlElement.style.left = left;
    this.htmlElement.style.top = top;
    this.onMove();
  }
    
  this.onMove = function()
  {
    var i;
    
    // notify listeners
    for(i = 0; i < this.moveListeners.length; i++)
    {
      this.moveListeners[i].onMove();
    }
  }
  
  this.toString = function()
  {
    return 'block: ' + this.id;
  }
}

/*
 * Connector class.
 * The init function takes two Block objects as arguments representing 
 * the source and destination of the connector
 */
function Connector(htmlElement, canvas)
{
  this.htmlElement = htmlElement;
  this.canvas = canvas;
  this.source = null;
  this.destination = null;
  this.startX = null;
  this.startY = null;
  this.destX = null;
  this.destY = null;
  this.segment1 = null;
  this.segment2 = null;
  this.segment3 = null;
  this.preferredOrientation = AUTO;
  this.orientation = HORIZONTAL;
  this.size = 1;
  this.color = 'black';
  this.moveListeners = new Array();
  
  this.initConnector = function()
  {
    // detect the connector id
    if(this.htmlElement.id)
      this.id = this.htmlElement.id;
    else
      this.id = this.htmlElement.className;
      
    // split the class name to get the ids of the source and destination blocks
    var splitted = htmlElement.className.split(' ');
    if(splitted.length < 3)
    {
      alert('Unable to create connector \'' + id + '\', class is not in the correct format: connector <sourceBlockId>, <destBlockId>');
      return;
    }
    
    var connectorClass = splitted[0' ' + splitted[1' ' + splitted[2];
    
    this.source = this.canvas.findBlock(splitted[1]);
    if(!this.source)
    {
      alert('cannot find source block with id \'' + splitted[1'\'');
      return;
    }
    
    this.destination = this.canvas.findBlock(splitted[2]);
    if(!this.destination)
    {
      alert('cannot find destination block with id \'' + splitted[2'\'');
      return;
    }
    
    // check preferred orientation
    if(hasClass(this.htmlElement, 'vertical'))
      this.preferredOrientation = VERTICAL;
    else if(hasClass(this.htmlElement, 'horizontal'))
      this.preferredOrientation = HORIZONTAL;
    else
      this.preferredOrientation = AUTO;
    
    // build the segments
    this.segment1 = document.createElement('div');
    this.segment1.id = this.id + "_1";    
    this.canvas.htmlElement.appendChild(this.segment1);

    this.segment1.style.position = 'absolute';
    this.segment1.style.overflow = 'hidden';
    
    if(!getStyle(this.segment1, 'background-color'))
      this.segment1.style.backgroundColor = this.color;
    this.segment1.className = connectorClass;
    
    this.segment2 = document.createElement('div');
    this.segment2.id = this.id + "_2";
    this.canvas.htmlElement.appendChild(this.segment2);

    this.segment2.className = connectorClass;    
    this.segment2.style.position = 'absolute';
    this.segment2.style.overflow = 'hidden';
    
    if(!getStyle(this.segment2, 'background-color'))
      this.segment2.style.backgroundColor = this.color;
    
    this.segment3 = document.createElement('div');
    this.segment3.id = this.id + "_3";
    this.canvas.htmlElement.appendChild(this.segment3);

    this.segment3.style.position = 'absolute';
    this.segment3.style.overflow = 'hidden';
    
    if(!getStyle(this.segment3, 'background-color'))
      this.segment3.style.backgroundColor = this.color;      
    this.segment3.className = connectorClass;
    
    this.repaint();
    
    this.source.moveListeners.push(this);
    this.destination.moveListeners.push(this);
    
    // call inspectors for this connector
    var i;
    for(i = 0; i < inspectors.length; i++)
    {
      inspectors[i].inspect(this);
    }
    
    // remove old html element
    this.htmlElement.parentNode.removeChild(this.htmlElement);
  }
  
  /**
   * Repaints the connector
   */
  this.repaint = function()
  {
    var sourceLeft = this.source.left();
    var sourceTop = this.source.top();
    var sourceWidth = this.source.width();
    var sourceHeight = this.source.height();
    
    var destinationLeft = this.destination.left();
    var destinationTop = this.destination.top();
    var destinationWidth = this.destination.width();
    var destinationHeight = this.destination.height();
    
    if(this.preferredOrientation == HORIZONTAL)
    {
      // use horizontal orientation except if it is impossible
      if((destinationLeft - sourceLeft - sourceWidth*
        (sourceLeft - destinationLeft - destinationWidth0)
        this.orientation = VERTICAL;
      else
        this.orientation = HORIZONTAL;
    }
    else if(this.preferredOrientation == VERTICAL)
    {
      // use vertical orientation except if it is impossible
      if((destinationTop - sourceTop - sourceHeight*
        (sourceTop - destinationTop - destinationHeight0)
        this.orientation = HORIZONTAL;
      else
        this.orientation = VERTICAL;
    }
    else
    {
      // auto orientation: change current orientation if it is impossible to maintain
      if(this.orientation == HORIZONTAL &&
        (destinationLeft - sourceLeft - sourceWidth*
        (sourceLeft - destinationLeft - destinationWidth0)
      {
        this.orientation = VERTICAL;
      }
      else if(this.orientation == VERTICAL &&
        (destinationTop - sourceTop - sourceHeight*
        (sourceTop - destinationTop - destinationHeight0)
      {
        this.orientation = HORIZONTAL;
      }
    }
    
    if(this.orientation == HORIZONTAL)
    {
      // deduce which face to use on source and destination blocks
      if(sourceLeft + sourceWidth / < destinationLeft + destinationWidth / 2)
      {
        // use left side of the source block and right side of the destination block
        this.startX = sourceLeft + sourceWidth;
        this.destX = destinationLeft;
      }
      else
      {
        // use right side of the source block and left side of the destination block
        this.startX = sourceLeft;
        this.destX = destinationLeft + destinationWidth;
      }

      this.startY = sourceTop + sourceHeight / 2;
      this.destY = destinationTop + destinationHeight /2;
      
      // first horizontal segment positioning
      this.segment1.style.left = Math.min(this.startX, (this.destX + this.startX2'px';
      this.segment1.style.top = this.startY + 'px';
      this.segment1.style.width = Math.abs((this.startX - this.destX2this.size + 'px';
      this.segment1.style.height = this.size + 'px';
      
      // vertical segment positioning
      this.segment2.style.left = ((this.startX + this.destX/2'px';
      this.segment2.style.top = Math.min(this.startY, this.destY'px';
      this.segment2.style.width = this.size + 'px';
      this.segment2.style.height = Math.abs(this.destY - this.startY'px';
      
      // second horizontal segment positioning
      this.segment3.style.left = Math.min((this.startX + this.destX/2this.destX'px';
      this.segment3.style.top = this.destY + 'px';
      this.segment3.style.width = Math.abs((this.destX - this.startX2'px';
      this.segment3.style.height = this.size + 'px';
      
      // label positioning
      //this.htmlElement.style.left = this.startX + 'px';
      //this.htmlElement.style.top = this.startY + this.size + 'px';
    }
    else
    {
      // deduce which face to use on source and destination blocks
      if(sourceTop + sourceHeight / < destinationTop + destinationHeight / 2)
      {
        // use bottom side of the sheightblock and top side of thtopestination block
        this.startY = sourceTop + sourceHeight;
        this.destY = destinationTop;
      }
      else
      {
        // use top side of the source block and bottom side of the destination block
        this.startY = sourceTop;
        this.destY = destinationTop + destinationHeight;
      }
      
      this.startX = sourceLeft + sourceWidth / 2;
      this.destX = destinationLeft + destinationWidth / 2;
      
      // first vertical segment positioning
      this.segment1.style.left = this.startX + 'px';
      this.segment1.style.top = Math.min(this.startY, (this.destY + this.startY)/2'px';
      this.segment1.style.width = this.size + 'px';
      this.segment1.style.height = Math.abs((this.startY - this.destY2this.size + 'px';
      
      // horizontal segment positioning
      this.segment2.style.left = Math.min(this.startX, this.destX'px';
      this.segment2.style.top = ((this.startY + this.destY/2'px';
      this.segment2.style.width = Math.abs(this.destX - this.startX'px';
      this.segment2.style.height = this.size + 'px';
      
      // second vertical segment positioning
      this.segment3.style.left = this.destX + 'px';
      this.segment3.style.top = Math.min(this.destY, (this.destY + this.startY2'px';
      this.segment3.style.width = this.size + 'px';
      this.segment3.style.height = Math.abs((this.destY - this.startY2'px';
      
      // label positioning
      //this.htmlElement.style.left = this.startX + 'px';
      //this.htmlElement.style.top = this.startY + this.size + 'px';
    }
  }
  
  this.onMove = function()
  {
    this.repaint();
    
    // notify listeners
    var i;
    for(i = 0; i < this.moveListeners.length; i++)
      this.moveListeners[i].onMove();
  }
}

function ConnectorEnd(connector, htmlElement, segment)
{
  this.connector = connector;
  this.htmlElement = htmlElement;
  this.connector.segment1.parentNode.appendChild(htmlElement);
  // strip extension
  this.src = this.htmlElement.src.substring(0this.htmlElement.src.lastIndexOf('.'));
  this.srcExtension = this.htmlElement.src.substring(this.htmlElement.src.lastIndexOf('.'));
  
  this.orientation;
  
  this.repaint = function()
  {
    this.htmlElement.style.position = 'absolute';
    
    var orientation;
    var left;
    var top;
    
    if(connector.orientation == HORIZONTAL)
    {
      left = segment.offsetLeft;
      orientation = "l";
      if(segment.offsetLeft == connector.segment2.offsetLeft)
      {
        left += segment.offsetWidth - this.htmlElement.offsetWidth;
        var orientation = "r";
      }
  
      top = segment.offsetTop - (this.htmlElement.offsetHeight / 2);
    }
    else
    {
      top = segment.offsetTop;
      orientation = "u";
      if(segment.offsetTop == connector.segment2.offsetTop)
      {
        top += segment.offsetHeight - this.htmlElement.offsetHeight;
        var orientation = "d";
      }
  
      left = segment.offsetLeft - (this.htmlElement.offsetWidth / 2);
    }
    
    this.htmlElement.style.left = Math.ceil(left"px";
    this.htmlElement.style.top = Math.ceil(top"px";
    
    if(this.htmlElement.tagName.toLowerCase() == "img" && this.orientation != orientation)
    {        
      this.htmlElement.src = this.src + "_" + orientation + this.srcExtension;
    }
    this.orientation = orientation;
  }
  
  this.onMove = function()
  {
    this.repaint();
  }
}

function SideConnectorLabel(connector, htmlElement, side)
{
  this.connector = connector;
  this.htmlElement = htmlElement;
  this.connector.segment1.parentNode.appendChild(htmlElement);
  if(side == 'source')
    this.segment = connector.segment1;
  else
    this.segment = connector.segment3;
  this.side = side;
    
  this.repaint = function()
  {
    this.htmlElement.style.position = 'absolute';
    
    var segmentOrientation;
    if(this.segment.offsetWidth < this.segment.offsetHeight)
      segmentOrientation = VERTICAL;
    else
      segmentOrientation = HORIZONTAL;
      
    var left = this.segment.offsetLeft;
    var top = this.segment.offsetTop;

    if(segmentOrientation == VERTICAL)
    {
      if(this.segment.offsetTop == connector.segment2.offsetTop)
      {
        // put label on the bottom of the connector (segment goes downward)
        top += this.segment.offsetHeight - this.htmlElement.offsetHeight;
      }
    }
    else
    {
      if(this.segment.offsetLeft == connector.segment2.offsetLeft)
      {
        // anchor the label on its right side to avoid overlap with the block
        left += this.segment.offsetWidth - this.htmlElement.offsetWidth;
      }
      if(this.segment.offsetTop < (this.side == 'source' ? connector.segment3.offsetTop : connector.segment1.offsetTop))
      {
        // put label over the connector rather than below
        top -= this.htmlElement.offsetHeight;
      }      
    }
    
    this.htmlElement.style.left = Math.ceil(left"px";
    this.htmlElement.style.top = Math.ceil(top"px";
  }
  
  this.onMove = function()
  {
    this.repaint();
  }
}

function MiddleConnectorLabel(connector, htmlElement)
{
  this.connector = connector;
  this.htmlElement = htmlElement;
  this.connector.segment2.parentNode.appendChild(htmlElement);
  
  this.repaint = function()
  {
    this.htmlElement.style.position = 'absolute';
    
    var segmentOrientation;
    if(connector.segment2.offsetWidth < connector.segment2.offsetHeight)
      segmentOrientation = VERTICAL;
    else
      segmentOrientation = HORIZONTAL;
      
    var left;
    var top;

    if(segmentOrientation == VERTICAL)
    {
      // put label at middle height on right side of the connector
      top = connector.segment2.offsetTop + (connector.segment2.offsetHeight - this.htmlElement.offsetHeight2;
      left = connector.segment2.offsetLeft;
    }
    else
    {
      // put connector below the connector at middle widths
      top = connector.segment2.offsetTop;
      left = connector.segment2.offsetLeft + (connector.segment2.offsetWidth - this.htmlElement.offsetWidth2;;
    }
    
    this.htmlElement.style.left = Math.ceil(left"px";
    this.htmlElement.style.top = Math.ceil(top"px";
  }
  
  this.onMove = function()
  {
    this.repaint();
  }
}

/*
 * Inspector classes
 */

function ConnectorEndsInspector()
{
  this.inspect = function(connector)
  {
    var children = connector.htmlElement.childNodes;
    var i;
    for(i = 0; i < children.length; i++)
    {
      if(hasClass(children[i]"connector-end"))
      {
        var newElement = new ConnectorEnd(connector, children[i], connector.segment3);
        newElement.repaint();
        connector.moveListeners.push(newElement);
      }
      else if(hasClass(children[i]"connector-start"))
      {
        var newElement = new ConnectorEnd(connector, children[i], connector.segment1);
        newElement.repaint();
        connector.moveListeners.push(newElement);
      }
    }
  }
}

function ConnectorLabelsInspector()
{
  this.inspect = function(connector)
  {
    var children = connector.htmlElement.childNodes;
    var i;
    for(i = 0; i < children.length; i++)
    {
      if(hasClass(children[i]"source-label"))
      {
        var newElement = new SideConnectorLabel(connector, children[i]"source");
        newElement.repaint();
        connector.moveListeners.push(newElement);
      }
      else if(hasClass(children[i]"middle-label"))
      {
        var newElement = new MiddleConnectorLabel(connector, children[i]);
        newElement.repaint();
        connector.moveListeners.push(newElement);
      }
      else if(hasClass(children[i]"destination-label"))
      {
        var newElement = new SideConnectorLabel(connector, children[i]"destination");
        newElement.repaint();
        connector.moveListeners.push(newElement);
      }
    }
  }
}

/*
 * Inspector registration
 */

inspectors.push(new ConnectorEndsInspector());
inspectors.push(new ConnectorLabelsInspector());

/*
 * an array containing all the canvases in document
 */
var canvases = new Array();

/*
 * This function initializes the js_graph objects inspecting the html document
 */
function initPageObjects()
{
  if(isCanvas(document.body))
  {
    var newCanvas = new Canvas(document.body);
    newCanvas.initCanvas();
    canvases.push(newCanvas);
  }
  else
  {
  
  var divs = document.getElementsByTagName('div');
  var i;
  for(i = 0; i < divs.length; i++)
  {
    if(isCanvas(divs[i]))
    {
      var newCanvas = new Canvas(divs[i]);
      newCanvas.initCanvas();
      canvases.push(newCanvas);
    }
  }
  }
}


/*
 * Utility functions
 */


function findCanvas(canvasId)
{  
  var i;
  for(i = 0; i < canvases.length; i++)
    if(canvases[i].id == canvasId)
      return canvases[i];
  return null;
}

function findBlock(blockId)
{
  var i;
  for(i = 0; i < canvases.length; i++)
  {
    var block = canvases[i].findBlock(blockId);
    if(block)
      return block;
  }
  return null;
}
 
/*
 * This function determines whether a html element is to be considered a canvas
 */
function isBlock(htmlElement)
{
  return hasClass(htmlElement, 'block');
}

/*
 * This function determines whether a html element is to be considered a block
 */
function isCanvas(htmlElement)
{
  return hasClass(htmlElement, 'canvas');
}

/*
 * This function determines whether a html element is to be considered a connector
 */
function isConnector(htmlElement)
{
  return htmlElement.className && htmlElement.className.match(new RegExp('connector .*'));
}

/*
 * This function calculates the absolute 'top' value for a html node
 */
function calculateOffsetTop(obj)
{
  var curtop = 0;
  if (obj.offsetParent)
  {
    while (obj.offsetParent)
    {
      curtop += obj.offsetTop;
      obj = obj.offsetParent;
    }
  }
  else if (obj.y)
    curtop += obj.y;
  return curtop;  
}

/*
 * This function calculates the absolute 'left' value for a html node
 */
function calculateOffsetLeft(obj)
{
  var curleft = 0;
  if (obj.offsetParent)
  {
    while (obj.offsetParent)
    {
      curleft += obj.offsetLeft;
      obj = obj.offsetParent;
    }
  }
  else if (obj.x)
    curleft += obj.x;
  return curleft;              
}


function hasClass(element, className)
{
  if(!element.className)
    return false;
    
  var classes = element.className.split(' ');
  var i;
  for(i = 0; i < classes.length; i++)
    if(classes[i== className)
      return true;
  return false;
}

/**
 * This function retrieves the actual value of a style property even if it is set via css.
 */
function getStyle(node, styleProp)
{
  // if not an element
  ifnode.nodeType != 1)
    return;
    
  var value;
  if (node.currentStyle)
  {
    // ie case
    styleProp = replaceDashWithCamelNotation(styleProp);
    value = node.currentStyle[styleProp];
  }
  else if (window.getComputedStyle)
  {
    // mozilla case
    value = document.defaultView.getComputedStyle(node, null).getPropertyValue(styleProp);
  }
  
  return value;
}

function replaceDashWithCamelNotation(value)
{
  var pos = value.indexOf('-');
  while(pos > && value.length > pos + 1)
  {
    value = value.substring(0, pos+ value.substring(pos + 1, pos + 2).toUpperCase() + value.substring(pos + 2);
    pos = value.indexOf('-');
  }
  return value;
}

</script>


<style rel="stylesheet" type="text/css">
.draggable
{
  position: absolute;
  cursor: move;
}

.connector
{
  background-color: black;
}

.dock_point
{
  height: 1px;
  width: 1px;
  overflow: hidden;
  padding: 0px !important;
  border: none !important;
  margin: 0px;
  position: absolute;
  font-size: 1px;
  visibility: hidden;
}

div.block
{
  border: 1px solid #262A37;
  background-color: #E0E8FF;
  padding: 5px;
  font-size: 11px;
}

html
{
  padding: 0px;
  margin: 0px;
}

body
{
  font-family: verdana;
  color: #33333F;
  padding: 3px;
  margin: 0px;
  background-color: white;
}

h1
{
  color: #FF7521;
  margin: 0px;
}

h2
{
  font-size: 15px;
  margin: 0px;
}

.middle-label, .source-label, .destination-label
{
  font-size: 11px;
  font-weight: bold;
  padding: 5px;
}

div.connector
{
  background-color: #FF9900;
}

table.main_table 
{
  width: 100%; 
  border-collapse: separate;
}
  
td.menu
{
  padding: 5px;
}

.menu ul
{
  margin: 0px;
  padding: 0px;
  list-style-type: none;
  list-style-position: outside;
}

.menu li
{
  border: none;
  padding: 0px;
  font-size: 12px;
  margin-bottom: 3px;
}

.menu li a
{
  display: block;
  border: 1px solid #262A37;
  width: 100px;
  color: #262A37;
  text-decoration: none;
  padding: 1px;
  background-color: #E0E8FF;
}

.menu li a#active_menu
{
  color: #FF9900;
  border-color: #FF9900;
}

.menu li a:hover
{
  color: #FF9900;
  border-color: #FF9900;
}
</style>


</head>
<body onload="initPageObjects();">
  <table class="main_table">
    <tr>
      <td style="vertical-align: top; padding: 0px;">
      <div id="mainCanvas" class="canvas block" style="width: 100%; height: 400px; background-color: white; padding: 0px;">
        <div id="title_block" class="block draggable" style="left: 30px; top: 30px;">
          <h1>js-graph.it</h1>
        </div>
        <div id="subtitle_block" class="block draggable" style="left: 130px; top: 130px;">
          <h2>a javascript library for graphs representation</h2>
        </div>
        <div class="connector title_block subtitle_block">
          <img class="connector-end" src="arrow.gif"/>
        </div>
        
        <table class="block draggable" style="left: 550px; top: 50px; border-collapse: collapse; cursor: default;" id="sf_logo" cellpadding="0" cellspacing="0">
          <tr>
            <td style="border: 1px solid #262A37; cursor: pointer;">
              <a href="http://www.java2java.com"><img src="http://www.java2java.com/style/logo.png" width="125" height="37" border="0" alt="SourceForge.net Logo" /></a></td>
            <td></td>
          </tr>
          <tr>
            <td></td>
            <td style="border: 1px solid #262A37; cursor: move;">        
            <img src="move.gif"/></td>
          </tr>
        </table>
    
        <div class="connector title_block sf_logo">
          <label class="middle-label">hosted on</label>
          <img class="connector-end" src="arrow.gif"/>
        </div>
        
        <div class="connector subtitle_block description1_block">
          <img class="connector-end" src="arrow.gif"/>
          <label class="middle-label">that</label>
        </div>
        
        <div id="description1_block" class="block draggable" style="left: 100px; top: 250px;">
          allows you
        </div>
        
        <div class="connector description1_block description2_block">
          <img class="connector-end" src="arrow.gif"/>
          <label class="source-label">to</label>
          <label class="middle-label">connect</label>
          <label class="destination-label">your</label>
        </div>    
        
        <div id="description2_block" class="block draggable" style="left: 350px; top: 300px;">
          html elements
          <div id="description2_out1" class="block dock_point" style="right: -2px; top: 20%; background-color: black;"></div>
          <div id="description2_out2" class="block dock_point" style="right: -2px; top: 80%; background-color: black;"></div>
        </div>
        
        <div id="no_js_code_block" class="block draggable" style="left: 590px; top: 200px; width: 200px;">
          using css classes to declare blocks, connectors, labels...<br/>
          no JavaScript code required.
        </div>
        
        <div class="connector description2_out1 no_js_code_block horizontal">
          <img class="connector-end" src="arrow.gif"/>
          <label class="middle-label">how?</label>
        </div>
        
        <div id="drag_and_drop_block" class="block draggable" style="left: 600px; top: 340px; width: 250px;">
          you can drag and drop anything around!<br/>
          (but you already noticed, didn't you?)
        </div>
        
        <div class="connector description2_out2 drag_and_drop_block horizontal">
          <img class="connector-end" src="arrow.gif"/>
          <label class="middle-label">and...</label>
          <label class="destination-label">...oh!</label>
        </div>
      </div>
      </td>
    </tr>
  </table>
  <div class="connector active_menu mainCanvas">
  </div>
  </body>
</html>
           
       
dragdrop.zip( 15 k)
Related examples in the same category
1. Quadratic Curve Test
2. Line Width
3. Drawing arches
4. JavaScript Graphics
5. JavaScript Graphics 2
6. JavaScript Graphics 3
7. JavaScript Graphics 4
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.