1 (function(global){ // BEGIN CLOSURE 2 3 var Joint = global.Joint, 4 Element = Joint.dia.Element, 5 point = Joint.point; 6 7 /** 8 * @name Joint.dia.erd 9 * @namespace Holds functionality related to Entity-relationship diagrams. 10 */ 11 var erd = Joint.dia.erd = {}; 12 13 /** 14 * Predefined arrow. You are free to use this arrow as the option parameter to joint method. 15 * Implements Chen-style cardinality notation. 16 * @name Joint.dia.erd.arrow 17 * @memberOf Joint.dia.erd 18 * @example 19 * var arrow = Joint.dia.erd.arrow; 20 */ 21 erd.arrow = { 22 startArrow: {type: 'none'}, 23 endArrow: {type: 'none'}, 24 attrs: {"stroke-dasharray": "none"} 25 }; 26 27 erd.toMany = { 28 startArrow: {type: 'none'}, 29 endArrow: {type: 'none'}, 30 attrs: {"stroke-dasharray": "none"}, 31 label: 'n', 32 labelAttrs: { position: -10, offset: -10 } 33 }; 34 35 erd.manyTo = { 36 startArrow: {type: 'none'}, 37 endArrow: {type: 'none'}, 38 attrs: {"stroke-dasharray": "none"}, 39 label: 'n', 40 labelAttrs: { position: 10, offset: -10 } 41 }; 42 43 erd.toOne = { 44 startArrow: {type: 'none'}, 45 endArrow: {type: 'none'}, 46 attrs: {"stroke-dasharray": "none"}, 47 label: '1', 48 labelAttrs: { position: -10, offset: -10 } 49 }; 50 51 erd.oneTo = { 52 startArrow: {type: 'none'}, 53 endArrow: {type: 'none'}, 54 attrs: {"stroke-dasharray": "none"}, 55 label: '1', 56 labelAttrs: { position: 10, offset: -10 } 57 }; 58 59 erd.oneToMany = { 60 startArrow: {type: 'none'}, 61 endArrow: {type: 'none'}, 62 attrs: {"stroke-dasharray": "none"}, 63 label: ['1', 'n'], 64 labelAttrs: [ { position: 10, offset: -10 }, { position: -10, offset: -10 } ] 65 }; 66 67 erd.manyToOne = { 68 startArrow: {type: 'none'}, 69 endArrow: {type: 'none'}, 70 attrs: {"stroke-dasharray": "none"}, 71 label: ['n', '1'], 72 labelAttrs: [ { position: 10, offset: -10 }, { position: -10, offset: -10 } ] 73 }; 74 75 76 /** 77 * ERD Entity and Weak Entity. 78 * @methodOf Joint.dia.erd 79 */ 80 erd.Entity = Element.extend({ 81 object: 'Entity', 82 module: 'erd', 83 init: function(properties) { 84 var p = Joint.DeepSupplement(this.properties, properties, { 85 attrs: { fill: 'lightgreen', stroke: '#008e09', 'stroke-width': 2 }, 86 label: '', 87 labelAttrs: { 'font-weight': 'bold' }, 88 shadow: true, 89 weak: false, // Weak Entity? 90 padding: 5 91 }); 92 this.setWrapper(this.paper.rect(p.rect.x, p.rect.y, p.rect.width, p.rect.height).attr(p.attrs)); 93 94 if (p.weak) { 95 this.addInner(this.paper.rect(p.rect.x + p.padding, p.rect.y + p.padding, p.rect.width - 2*p.padding, p.rect.height - 2*p.padding).attr(p.attrs)); 96 } 97 this.addInner(this.getLabelElement()); 98 }, 99 getLabelElement: function() { 100 var p = this.properties, 101 bb = this.wrapper.getBBox(), 102 t = this.paper.text(bb.x + bb.width/2, bb.y + bb.height/2, p.label).attr(p.labelAttrs || {}), 103 tbb = t.getBBox(); 104 t.translate(bb.x - tbb.x + p.labelOffsetX, 105 bb.y - tbb.y + p.labelOffsetY); 106 return t; 107 } 108 }); 109 110 /** 111 * ERD Relationship. 112 * @methodOf Joint.dia.erd 113 */ 114 erd.Relationship = Element.extend({ 115 object: 'Relationship', 116 module: 'erd', 117 init: function(properties) { 118 var p = Joint.DeepSupplement(this.properties, properties, { 119 attrs: { rotation: 45, fill: 'lightblue', stroke: '#000d5b', 'stroke-width': 2 }, 120 label: '', 121 labelAttrs: { 'font-weight': 'bold' } 122 }); 123 this.setWrapper(this.paper.rect(p.rect.x, p.rect.y, p.rect.width, p.rect.height).attr(p.attrs)); 124 this.addInner(this.getLabelElement()); 125 }, 126 getLabelElement: function() { 127 var p = this.properties, 128 bb = this.wrapper.getBBox(), 129 t = this.paper.text(bb.x + bb.width/2, bb.y + bb.height/2, p.label).attr(p.labelAttrs || {}), 130 tbb = t.getBBox(); 131 t.translate(bb.x - tbb.x + p.labelOffsetX, 132 bb.y - tbb.y + p.labelOffsetY); 133 return t; 134 } 135 }); 136 137 /** 138 * ERD Attribute, Key Attribute, Multivalued Attribute and Derived Attribute. 139 * @methodOf Joint.dia.erd 140 */ 141 erd.Attribute = Element.extend({ 142 object: 'Attribute', 143 module: 'erd', 144 init: function(properties) { 145 var p = Joint.DeepSupplement(this.properties, properties, { 146 attrs: { fill: 'red', opacity: (properties.primaryKey ? 0.8 : 0.5), 147 stroke: '#5b0001', 'stroke-width': 2, 148 'stroke-dasharray': (properties.derived ? '.' : 'none') }, 149 label: '', 150 labelAttrs: { 'font-weight': 'bold' }, 151 multivalued: false, 152 derived: false, 153 padding: 5 154 }); 155 this.setWrapper(this.paper.ellipse(p.ellipse.x, p.ellipse.y, p.ellipse.rx, p.ellipse.ry).attr(p.attrs)); 156 if (p.multivalued) { 157 this.addInner(this.paper.ellipse(p.ellipse.x, p.ellipse.y, p.ellipse.rx - p.padding, p.ellipse.ry - p.padding).attr(p.attrs)); 158 } 159 this.addInner(this.getLabelElement()); 160 }, 161 getLabelElement: function() { 162 var p = this.properties, 163 bb = this.wrapper.getBBox(), 164 t = this.paper.text(bb.x + bb.width/2, bb.y + bb.height/2, p.label).attr(p.labelAttrs || {}), 165 tbb = t.getBBox(); 166 t.translate(bb.x - tbb.x + p.labelOffsetX, 167 bb.y - tbb.y + p.labelOffsetY); 168 return t; 169 } 170 }); 171 172 })(this); // END CLOSURE 173