4
<script type="text/javascript" src="jquery.js"></script>
6
<script lang='Javascript'>
12
// Clickstate 0 == No Click Clickstate 1 == Click Clickstate 2 == Drag !!??
13
// Startx/Starty contain coordinate for drag start
14
// Deltax/Deltay contain current distance from start
17
var startx=0,starty=0;
18
var deltax=0,deltay=0;
22
// Multi-select move offset
26
// Drawing Globals -- For while in transit drawing
27
var drawlinesx,drawlinesy;
28
var drawlinedx,drawlinedy;
32
// List of identifiers
33
// List of selected object identifiers
36
var Objects = new Array();
37
var Selected = new Array();
38
var Identifiers = new Array();
44
// User Interface Mode Variables
46
var dragsensitivity=12;
52
User interface callbacks
57
function handler_mouseup()
60
// Either select on/off for multi or single select
62
if(Selected[downRes.objid]){
63
Selected[downRes.objid]=false;
65
Selected[downRes.objid]=true;
68
if(ContextObj==downRes.objid){
71
ContextObj=downRes.objid;
74
}else if(clickstate==8){
76
// Draw Attribute Line
78
upRes=mouseover(gridx,gridy);
80
if(upRes.code!="None"){
82
obj=Objects[downRes.objid];
84
if(upRes.typ=="ERAttribute"||upRes.typ=="Entity"||upRes.typ=="ERRel"){
86
obj.DrawtoID=upRes.objid;
87
obj.DrawfromSide = downRes.side;
89
if(upRes.side!="None"){
90
obj.DrawtoSide = upRes.side;
91
obj.DrawtoPerc = upRes.sideperc;
93
upobj=Objects[downRes.objid];
98
var x1g=Math.abs(upRes.x1-gridx);
99
var x2g=Math.abs(upRes.x2-gridx);
100
var y1g=Math.abs(upRes.y1-gridy);
101
var y2g=Math.abs(upRes.y2-gridy);
103
if(x1g<=x2g&&x1g<=y1g&&x1g<=y2g){
105
perco=makesideperc(gridy,upRes.y1,upRes.y2);
106
}else if(x2g<=x1g&&x2g<=y1g&&x2g<=y2g){
108
perco=makesideperc(gridy,upRes.y1,upRes.y2);
109
}else if(y1g<=x1g&&y1g<=x2g&&y1g<=y2g){
111
perco=makesideperc(gridx,upRes.x1,upRes.x2);
112
}else if(y2g<=x1g&&y2g<=x2g&&y2g<=y1g){
114
perco=makesideperc(gridx,upRes.x1,upRes.x2);
117
obj.DrawtoSide = sid;
118
obj.DrawtoPerc = perco;
121
if(upRes.typ=="ERAttribute"||upRes.typ=="ERRel") obj.DrawtoPerc=0.5;
126
}else if(clickstate==9){
128
// Draw Relationship line
130
upRes=mouseover(gridx,gridy);
132
if(upRes.code!="None"){
134
obj=Objects[downRes.objid];
136
if(upRes.side!="None"){
137
if(obj.DrawtoID=="None"){
138
obj.DrawtoID=upRes.objid;
139
obj.DrawtoSide = upRes.side;
140
obj.DrawtoPerc = upRes.sideperc;
141
obj.DrawfromSide = downRes.side;
143
obj.DrawtoIDDest=upRes.objid;
144
obj.DrawtoSideDest = upRes.side;
145
obj.DrawtoPercDest = upRes.sideperc;
146
obj.DrawfromSideDest = downRes.side;
149
upobj=Objects[downRes.objid];
154
var x1g=Math.abs(upRes.x1-gridx);
155
var x2g=Math.abs(upRes.x2-gridx);
156
var y1g=Math.abs(upRes.y1-gridy);
157
var y2g=Math.abs(upRes.y2-gridy);
159
if(x1g<=x2g&&x1g<=y1g&&x1g<=y2g){
161
perco=makesideperc(gridy,upRes.y1,upRes.y2);
162
}else if(x2g<=x1g&&x2g<=y1g&&x2g<=y2g){
164
perco=makesideperc(gridy,upRes.y1,upRes.y2);
165
}else if(y1g<=x1g&&y1g<=x2g&&y1g<=y2g){
167
perco=makesideperc(gridx,upRes.x1,upRes.x2);
168
}else if(y2g<=x1g&&y2g<=x2g&&y2g<=y1g){
170
perco=makesideperc(gridx,upRes.x1,upRes.x2);
173
if(obj.DrawtoID=="None"){
174
obj.DrawtoID=upRes.objid;
175
obj.DrawtoSide = sid;
176
obj.DrawtoPerc = perco;
177
obj.DrawfromSide = downRes.side;
179
obj.DrawtoIDDest=upRes.objid;
180
obj.DrawtoSideDest = sid;
181
obj.DrawtoPercDest = perco;
182
obj.DrawfromSideDest = downRes.side;
196
function handler_mousedown()
200
downRes=mouseover(gridx,gridy);
207
function handler_mousemove(cx,cy)
210
// gridx=Math.round((cx-(gridsize/2.0))/gridsize)*gridsize;
211
// gridy=Math.round((cy-(gridsize/2.0))/gridsize)*gridsize;
219
// We start drag mode
220
if((distance(gridx,gridy,startx,starty)>dragsensitivity)&&clickstate==1){
224
// We are in drag mode
227
// Single Object Move - If Not Selected, Or if Selected and Center Area Is Dragged
228
if((downRes.typ=="Entity"||downRes.typ=="ERAttribute"||downRes.typ=="ERRel")&&(downRes.code=="NonSel"||(downRes.code=="Cont"&&downRes.side=="None")||(downRes.code=="ContDraw"&&downRes.side=="None"))){
232
if((downRes.typ=="Entity"||downRes.typ=="ERAttribute")&&(downRes.code=="Cont"&&downRes.side=="1")) clickstate=4; // Single Object Scale Left
233
if((downRes.typ=="Entity"||downRes.typ=="ERAttribute")&&(downRes.code=="Cont"&&downRes.side=="2")) clickstate=5; // Single Object Scale Bottom
234
if((downRes.typ=="Entity"||downRes.typ=="ERAttribute")&&(downRes.code=="Cont"&&downRes.side=="3")) clickstate=6; // Single Object Scale Right
235
if((downRes.typ=="Entity"||downRes.typ=="ERAttribute")&&(downRes.code=="Cont"&&downRes.side=="4")) clickstate=7; // Single Object Scale Top
237
if(downRes.typ=="ERAttribute"&&downRes.code=="ContDraw"&&downRes.side!="None"){
239
clickstate=8; // Attribute Connection Draw
240
drawlinekind=1; // Tell drawing engine to draw attribute line symbol
242
if(downRes.side=="1"){
243
drawlinesx=downRes.x1; // Initiate start parameters for line drawing left side
244
drawlinesy=downRes.y1+((downRes.y2-downRes.y1)*0.5);
245
}else if(downRes.side=="2"){
246
drawlinesx=downRes.x1+((downRes.x2-downRes.x1)*0.5); // Initiate start parameters for line drawing bottom side
247
drawlinesy=downRes.y2;
248
}else if(downRes.side=="3"){
249
drawlinesx=downRes.x2; // Initiate start parameters for line drawing left side
250
drawlinesy=downRes.y1+((downRes.y2-downRes.y1)*0.5);
251
}else if(downRes.side=="4"){
252
drawlinesx=downRes.x1+((downRes.x2-downRes.x1)*0.5); // Initiate start parameters for line drawing bottom side
253
drawlinesy=downRes.y1;
256
drawlinedx=drawlinesx;
257
drawlinedy=drawlinesy;
261
if(downRes.typ=="ERRel"&&downRes.code=="ContDraw"&&downRes.side!="None"){
263
var obj=Objects[downRes.objid];
265
if(downRes.side!=obj.DrawfromSide&&downRes.side!=obj.DrawfromSideDest){
267
clickstate=9; // Attribute Connection Draw
268
drawlinekind=1; // Tell drawing engine to draw relation line symbol
270
if(downRes.side=="1"){
271
drawlinesx=downRes.x1; // Initiate start parameters for line drawing left side
272
drawlinesy=downRes.y1+((downRes.y2-downRes.y1)*0.5);
273
}else if(downRes.side=="2"){
274
drawlinesx=downRes.x1+((downRes.x2-downRes.x1)*0.5); // Initiate start parameters for line drawing bottom side
275
drawlinesy=downRes.y2;
276
}else if(downRes.side=="3"){
277
drawlinesx=downRes.x2; // Initiate start parameters for line drawing left side
278
drawlinesy=downRes.y1+((downRes.y2-downRes.y1)*0.5);
279
}else if(downRes.side=="4"){
280
drawlinesx=downRes.x1+((downRes.x2-downRes.x1)*0.5); // Initiate start parameters for line drawing bottom side
281
drawlinesy=downRes.y1;
284
drawlinedx=drawlinesx;
285
drawlinedy=drawlinesy;
295
var obj=Objects[downRes.objid];
298
if(clickstate==3){ // We are in single rectangular object move
299
obj.x1=downRes.x1-deltax;
300
obj.y1=downRes.y1-deltay;
301
obj.x2=downRes.x2-deltax;
302
obj.y2=downRes.y2-deltay;
303
}else if(clickstate==4){ // We are in single rectangular object scale left
304
if((obj.x2-downRes.x1+deltax)>60) obj.x1=downRes.x1-deltax;
305
}else if(clickstate==5){ // We are in single rectangular object scale bottom
306
if((downRes.y2-obj.y1-deltay)>40) obj.y2=downRes.y2-deltay;
307
}else if(clickstate==6){ // We are in single rectangular object scale right
308
if((downRes.x2-obj.x1-deltax)>60) obj.x2=downRes.x2-deltax;
309
}else if(clickstate==7){ // We are in single rectangular object scale top
310
if((obj.y2-downRes.y1+deltay)>40) obj.y1=downRes.y1-deltay;
311
}else if(clickstate==8||clickstate==9){ // We are in straight connective line drawing mode
318
// Call-forward for mouse-over event
320
function mouseover(x,y)
323
// Code of touch, and if available object id and id of side of object that was touched
324
// Tolerances included as constant
330
var obj_sidentifier="None";
332
var obj_centerdist=0;
334
var obj_x1=0; var obj_y1=0; var obj_x2=0; var obj_y2=0;
341
for(j=0;j<Identifiers.length;j++){
343
var objid=Identifiers[j];
344
var obj=Objects[objid];
345
var Sel=Selected[objid];
346
if(ContextObj==objid) Cont=1
349
// Compute coordinates including offset
350
if(obj.type=="Entity"||obj.type=="ERAttribute"||obj.type=="ERRel"){
364
// For each kind of clickable object, check if we are inside object and if so assign variables
365
// Any general properties for all object types are set when "found" is true
367
if(obj.type=="Entity"){
368
if(x>(x1-sidetol)&&y>(y1-sidetol)&&x<(x2+sidetol)&&y<(y2+sidetol)){
371
if(Sel) obj_code="Sel";
372
if(Cont) obj_code="Cont";
374
side=computeside(x,y,x1,y1,x2,y2,sidetol);
375
obj_sidentifier=side.side;
376
obj_sideperc=side.perc;
377
obj_centerdist=side.dist;
381
}else if(obj.type=="ERAttribute"){
382
if(x>(x1-sidetol)&&y>(y1-sidetol)&&x<(x2+sidetol)&&y<(y2+sidetol)){
384
if(Sel) obj_code="Sel";
387
if(obj.DrawtoID=="None"){
394
side=computeside(x,y,x1,y1,x2,y2,sidetol);
395
obj_sidentifier=side.side;
396
obj_sideperc=side.perc;
397
obj_centerdist=side.dist;
402
}else if(obj.type=="ERRel"){
403
if(x>(x1-sidetol)&&y>(y1-sidetol)&&x<(x2+sidetol)&&y<(y2+sidetol)){
407
// Colision detection against diamond
410
if(y>(y1+ry-xk-sidetol)&&y<(y1+ry+xk+sidetol)) inside=1;
412
if(y>(y1-rx+xk-sidetol)&&y<(y2+rx-xk+sidetol)) inside=1;
417
if((x>(x1-sidetol))&&(x<(x1+sidetol))&&(y>(y1+ry-sidetol))&&(y<(y1+ry+sidetol))) obj_sidentifier=1;
418
if((x>(x1+rx-sidetol))&&(x<(x1+rx+sidetol))&&(y>(y2-sidetol))&&(y<(y2+sidetol))) obj_sidentifier=2;
419
if((x>(x2-sidetol))&&(x<(x2+sidetol))&&(y>(y1+ry-sidetol))&&(y<(y1+ry+sidetol))) obj_sidentifier=3;
420
if((x>(x1+rx-sidetol))&&(x<(x1+rx+sidetol))&&(y>(y1-sidetol))&&(y<(y1+sidetol))) obj_sidentifier=4;
424
if(Sel) obj_code="Sel";
427
if(obj.DrawtoID=="None"){
429
}else if(obj.DrawtoIDDest=="None"){
447
// Save coordinates at time of click
456
printstr=obj_id+" "+obj_sidentifier+" "+obj_sideperc;
466
side:obj_sidentifier,
467
sideperc:obj_sideperc,
468
centerdist:obj_centerdist,
478
function importdata()
482
if(i==0) obj = jQuery.parseJSON('{"type":"ERAttribute","id":"ATT1","kind":"Multiple","name":"Address","x1":220,"y1":100,"x2":300,"y2":140, "DrawtoID":"None", "DrawfromSide":"None","DrawtoSide":"None", "DrawtoPerc":"None", "DrawX1":"", "DrawY1":"", "DrawX2":"","DrawY2":""}');
483
if(i==1) obj = jQuery.parseJSON('{"type":"Entity","id":"ENT2","kind":"Weak","name":"Car","x1":100,"y1":160,"x2":220,"y2":220}');
484
if(i==2) obj = jQuery.parseJSON('{"type":"ERAttribute","id":"ATT3","kind":"Key","name":"SSN","x1":160,"y1":260,"x2":260,"y2":300, "DrawtoID":"None", "DrawfromSide":"None","DrawtoSide":"None", "DrawtoPerc":"None", "DrawX1":"", "DrawY1":"", "DrawX2":"","DrawY2":""}');
485
if(i==3) obj = jQuery.parseJSON('{"type":"Entity","id":"ENT4","kind":"Strong","name":"Trailer","x1":320,"y1":260,"x2":420,"y2":320}');
486
if(i==4) obj = jQuery.parseJSON('{"type":"Entity","id":"ENT5","kind":"Strong","name":"Grail","x1":120,"y1":440,"x2":220,"y2":480}');
487
if(i==5) obj = jQuery.parseJSON('{"type":"ERRel","id":"REL6","kind":"Strong","name":"Fool","x1":460,"y1":160,"x2":520,"y2":220, "DrawtoID":"None", "DrawfromSide":"None","DrawtoSide":"None", "DrawtoPerc":"0", "DrawtoIDDest":"None", "DrawfromSideDest":"None","DrawtoSideDest":"None", "DrawtoPercDest":"0", "DrawX1":"", "DrawY1":"", "DrawX2":"","DrawY2":"","DrawX3":"", "DrawY3":"", "DrawX4":"","DrawY4":""}');
488
if(i==6) obj = jQuery.parseJSON('{"type":"ERRel","id":"REL7","kind":"Weak","name":"Drool","x1":360,"y1":360,"x2":420,"y2":420, "DrawtoID":"None", "DrawfromSide":"None","DrawtoSide":"None", "DrawtoPerc":"0", "DrawtoIDDest":"None", "DrawfromSideDest":"None","DrawtoSideDest":"None", "DrawtoPercDest":"0", "DrawX1":"", "DrawY1":"", "DrawX2":"","DrawY2":"","DrawX3":"", "DrawY3":"", "DrawX4":"","DrawY4":""}');
492
Identifiers.push(objid);
498
// Prepares all kinds of objects, with local movement-offset (scrolling offset is handled with transforms??)
499
// Ofss in prepare are not finished.
501
function prepareobj(obji)
503
var fromobj=Objects[obji];
505
// Attributes are prepared by re-pointing the DrawX1, DrawY1, DrawX2 and DrawY2 variables and Relationships are prepared by re-pointing DrawX1-DrawX4 and DrawY1-DrawY4
507
if((fromobj.type=="ERAttribute"||fromobj.type=="ERRel")&&fromobj.DrawtoID!="None"){
509
var toid=fromobj.DrawtoID;
510
var toobj=Objects[toid];
514
if(fromobj.DrawtoIDDest!="None"&&fromobj.DrawtoIDDest!=undefined){
515
var toiddest=fromobj.DrawtoIDDest;
516
var toobjdest=Objects[toiddest];
518
sidek=makeside(fromobj.DrawfromSideDest,fromobj.x1,fromobj.y1,fromobj.x2,fromobj.y2,0.5);
519
fromobj.DrawX3=sidek.x;
520
fromobj.DrawY3=sidek.y;
522
sidek=makeside(fromobj.DrawtoSideDest,toobjdest.x1,toobjdest.y1,toobjdest.x2,toobjdest.y2,fromobj.DrawtoPercDest);
523
fromobj.DrawX4=sidek.x;
524
fromobj.DrawY4=sidek.y;
528
//printstr=fromobj.DrawfromSide+" "+fromobj.x1+" "+fromobj.y1+" "+fromobj.x2+" "+fromobj.y2+" :: "+fromobj.DrawtoSide+" "+toobj.x1+" "+toobj.y1+" "+toobj.x2+" "+toobj.y2+" "+fromobj.DrawtoPerc;
530
sidek=makeside(fromobj.DrawfromSide,fromobj.x1,fromobj.y1,fromobj.x2,fromobj.y2,0.5);
531
fromobj.DrawX1=sidek.x;
532
fromobj.DrawY1=sidek.y;
535
sidek=makeside(fromobj.DrawtoSide,toobj.x1,toobj.y1,toobj.x2,toobj.y2,fromobj.DrawtoPerc);
536
fromobj.DrawX2=sidek.x;
537
fromobj.DrawY2=sidek.y;
545
// Draws all kinds of objects, with local movement-offset (scrolling offset is handled with transforms??)
547
function drawobj(obji)
550
var obj=Objects[obji];
552
var Sel=Selected[obji];
554
if(ContextObj==obji) Cont=1
557
context.strokeStyle = '#000';
558
context.lineWidth = 2.0;
560
// Compute coordinates including offset
561
if(obj.type=="Entity"||obj.type=="ERAttribute"||obj.type=="ERRel"){
573
if(obj.type=="Entity"){
576
context.strokeRect(x1,y1,x2-x1,y2-y1);
578
if(obj.kind=="Weak"){
579
context.strokeRect(x1+5,y1+5,x2-x1-10,y2-y1-10);
582
context.font = "20px Calibri";
583
context.textAlign = "center";
584
context.fillStyle = "#000";
585
context.fillText(obj.name, x1+rx, y2-ry+6);
587
// Draw Select Marker
589
fourpoints(x1,y1+ry,x2,y1+ry,x1+rx,y1,x1+rx,y2,"#5f8");
592
}else if(obj.type=="ERAttribute"){
594
drawellipse(x1,y1,x2,y2);
596
context.font = "20px Calibri";
597
context.textAlign = "center";
598
context.fillStyle = "#000";
599
context.fillText(obj.name, x1+rx, y2-ry+6);
601
if(obj.DrawtoID!="None"){
602
drawline(obj.DrawX1,obj.DrawY1,obj.DrawX2,obj.DrawY2,"#000",2.0);
606
var metrics = context.measureText(obj.name);
607
var w = Math.round(metrics.width/2.0);
609
drawline(x1+rx-w,y2-ry+10,x1+rx+w,y2-ry+10,"#000",2.0);
612
// Draw Select Marker
613
if(Cont&&obj.DrawtoID=="None"){
614
fourpoints(x1,y1+ry,x2,y1+ry,x1+rx,y1,x1+rx,y2,"#fa2");
615
}else if(Sel||(Cont&&obj.DrawtoID!="None")){
616
fourpoints(x1,y1+ry,x2,y1+ry,x1+rx,y1,x1+rx,y2,"#5f8");
619
}else if(obj.type=="ERRel"){
621
if(obj.DrawtoID!="None"){
622
drawline(obj.DrawX1,obj.DrawY1,obj.DrawX2,obj.DrawY2,"#000",2.0);
625
if(obj.DrawtoIDDest!="None"){
626
drawline(obj.DrawX3,obj.DrawY3,obj.DrawX4,obj.DrawY4,"#000",2.0);
629
if(obj.kind=="Weak"){
630
drawdiamond(x1,y1,rx,ry,4);
631
drawdiamond(x1,y1,rx,ry,-4);
633
drawdiamond(x1,y1,rx,ry,0);
636
context.font = "20px Calibri";
637
context.textAlign = "center";
638
context.fillStyle = "#000";
639
context.fillText(obj.name, x1+rx, y2-ry+6);
641
if(Sel||(Cont&&obj.DrawtoID!="None"&&obj.DrawtoIDDest!="None")){
642
fourpoints(x1,y1+ry,x2,y1+ry,x1+rx,y1,x1+rx,y2,"#5f8");
644
if(obj.DrawfromSide!=1&&obj.DrawfromSideDest!=1) point("#fa2",x1,y1+ry);
645
if(obj.DrawfromSide!=2&&obj.DrawfromSideDest!=2) point("#fa2",x1+rx,y2);
646
if(obj.DrawfromSide!=3&&obj.DrawfromSideDest!=3) point("#fa2",x2,y1+ry);
647
if(obj.DrawfromSide!=4&&obj.DrawfromSideDest!=4) point("#fa2",x1+rx,y1);
657
context.clearRect(0,0,600,600);
660
context.strokeStyle = '#ddd';
661
context.lineWidth = 0.5;
663
for(i=0;i<600;i+=20){
665
context.lineTo(i,600);
667
context.lineTo(600,i);
673
drawline(drawlinesx,drawlinesy,drawlinedx,drawlinedy,"#000",1.0);
676
// Prepare model objects
677
for(i=0;i<Identifiers.length;i++){
678
var objid=Identifiers[i];
682
// Draw model objects
683
for(i=0;i<Identifiers.length;i++){
684
var objid=Identifiers[i];
690
context.strokeStyle = '#444';
691
context.lineWidth = 1.0;
692
context.moveTo(gridx-gridsize,gridy);
693
context.lineTo(gridx+gridsize,gridy);
694
context.moveTo(gridx,gridy-gridsize);
695
context.lineTo(gridx,gridy+gridsize);
698
context.strokeStyle = '#ddd';
700
context.fillStyle='#000';
701
context.font = "bold 16px Arial";
702
context.textAlign = "left";
703
context.fillText("currop: "+printstr, 20, 576);
705
setTimeout("foo();",100);
711
<script type="text/javascript" src="dugga.js"></script>
714
<body onload="setupcanvas();">
719
<canvas id='a' width='600' height='600' style='border:2px solid black;'>
723
<div style="border:2px solid black;background-color:#fed;width:300;height:450;">
724
<div id="infobox" style="padding:4px;">
726
Change values to update diagram.<br>