SCION Drag-and-drop Demo

by jbeard4

HTML

<script src="https://raw.github.com/jbeard4/scxml-viz/master/ScxmlViz.js"></script>
<script src="http://d3js.org/d3.v2.js"></script>
<script src="http://jbeard4.github.com/SCION/builds/latest/scion.js"></script>
<div id="rect"></div>

<textarea id="scxmlDoc" style="display:none;">
    <scxml 
        xmlns="http://www.w3.org/2005/07/scxml"
        version="1.0"
        profile="ecmascript">

        <datamodel>
            <data id="firstEvent"/>
            <data id="eventStamp"/>
            <data id="rectNode"/>
            <data id="rectX"/>
            <data id="rectY"/>
        </datamodel>

        <state id="initial-default">
            <transition event="init" target="idle">
                <assign location="rectNode" expr="_event.data"/>
                <assign location="rectX" expr="0"/>
                <assign location="rectY" expr="0"/>
            </transition>
        </state>

        <state id="idle">
            <onentry>
                <script>
                    $(rectNode).text('idle');
                </script>
            </onentry>

            <transition event="mousedown" target="dragging">
                <assign location="firstEvent" expr="_event.data"/>
                <assign location="eventStamp" expr="_event.data"/>
            </transition>
        </state>

        <state id="dragging">
            <onentry>
                <script>
                    $(rectNode).text('dragging');
                </script>
            </onentry>

            <transition event="mouseup" target="idle"/>

            <transition event="mousemove" target="dragging">
                <script>
                    var dx = eventStamp.clientX - _event.data.clientX;
                    var dy = eventStamp.clientY - _event.data.clientY;

                    //note that rectNode, rectX and rectY are all exposed
                    //from the datamodel as local variables
                    
                    rectNode.style.left = (rectX -= dx) + 'px';
...

CSS

html, body {
    height:100%;
    width:100%;
    margin: 0;
    padding: 0;
}

div#viz{
    width:100%;
    height:100%;
}

div#rect{ 
    width:100px;
    height:100px;
    background-color:red;
    border:2px solid black;
    position:absolute;
    left:0px;
    top:0px;
}

g.cell rect {
  fill: white;
  stroke: black;
}

text {
  font: 10px sans-serif;
}

path.transition,path.reverseTransition {
  fill: none;
  stroke: black;
  stroke-width: 1.5px;
}

g.orthogonalComponent rect {
    stroke-dasharray : 0.25em 0.25em; 
}

g.history rect {
    fill : #3399FF; 
}

g.initial rect {
    stroke : #CC0099;
}

g.highlighted rect {
    stroke : #66FF33;
}

JavaScript

var scion = require('scion');

var rect = document.getElementById("rect");

var scxmlDocString = document.getElementById('scxmlDoc').textContent;

var scxmlDoc = (new DOMParser()).parseFromString(scxmlDocString, "application/xml");

console.log(scxmlDoc,scxmlDocString);

//visualize
var vizAttachPoint = document.getElementById('viz');

ScxmlViz(vizAttachPoint,scxmlDoc,400,400);

function toggleHighlight(highlight,stateId){
    if(stateId[0] === '$') return;
    
    d3.select('#' + stateId).classed('highlighted',highlight);
}


var listener = {
    onEntry : toggleHighlight.bind(null,true),
    onExit : toggleHighlight.bind(null,false)       
};

scion.documentStringToModel(scxmlDocString,function(err,model){

    if(err) throw err;

    //instantiate the interpreter
    var interpreter = new scion.SCXML(model);

    interpreter.registerListener(listener);
    
    //start the interpreter
    interpreter.start();

    //send the init event
    interpreter.gen({name:"init",data:rect});

    function handleEvent(e){
        e.preventDefault();
        interpreter.gen({name : e.type,data: e});
    }

    //connect all relevant event listeners
    $(rect).mousedown(handleEvent);
    $(document.documentElement).bind("mouseup mousemove",handleEvent);
});