erd 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,152 +1,241 @@
1
- $ ->
2
- window.paper = Raphael('erd', $('#erd').css('width'), $('#erd').css('height'))
1
+ class ERD
2
+ constructor: (@name, @elem, @edges) ->
3
+ @paper = Raphael(name, @elem.css('width'), @elem.css('height'))
4
+ @setup_handlers()
5
+ @connect_arrows()
3
6
 
4
- # $('#erd').on 'click', (ev) ->
5
- # console.log 'click'
6
- $('div.model_name_text, span.column_name_text, span.column_type_text').on('click', (ev) ->
7
- $(this).hide()
8
- .next('form').show().find('input[name=to]').val($(this).text()).focus()
9
- )
7
+ upsert_change: (action, model, column, from, to) ->
8
+ rows = ($(tr).find('td') for tr in $('#changes > tbody > tr'))
9
+ existing = null
10
+ $(rows).each (i, row) ->
11
+ existing = row if (action == $(row[0]).html()) && (model == $(row[1]).html()) && (column == $(row[2]).html())
12
+ if existing == null
13
+ $('#changes > tbody').append("<tr><td>#{action}</td><td>#{model}</td><td>#{column}</td><td>#{from}</td><td>#{to}</td></tr>")
14
+ else
15
+ $(existing[3]).text(from)
16
+ $(existing[4]).text(to)
17
+ $('#changes').show()
18
+
19
+ positions: (div) ->
20
+ [left, width, top, height] = [parseInt(div.css('left')), parseInt(div.css('width')), parseInt(div.css('top')), parseInt(div.css('height'))]
21
+ {left: left, right: left + width, top: top, bottom: top + height, center: {x: (left + left + width) / 2, y: (top + top + height) / 2}, vertex: {}}
22
+
23
+ connect_arrows: ->
24
+ $.each @edges, (i, edge) =>
25
+ @connect_arrow $("##{edge.from}"), $("##{edge.to}")
26
+
27
+ connect_arrow: (from_elem, to_elem) ->
28
+ #TODO handle self referential associations
29
+ return if from_elem.attr('id') == to_elem.attr('id')
30
+
31
+ from = @positions(from_elem)
32
+ to = @positions(to_elem)
33
+ #FIXME terrible code
34
+ a = (to.center.y - from.center.y) / (to.center.x - from.center.x)
35
+ b = from.center.y - from.center.x * a
36
+
37
+ x2y = (x) -> ( a * x + b )
38
+ y2x = (y) -> ( (y - b) / a )
39
+
40
+ if from.center.x > to.center.x
41
+ [from.vertex.x, from.vertex.y] = [from.left, x2y(from.left)]
42
+ [to.vertex.x, to.vertex.y] = [to.right, x2y(to.right)]
43
+ else
44
+ [from.vertex.x, from.vertex.y] = [from.right, x2y(from.right)]
45
+ [to.vertex.x, to.vertex.y] = [to.left, x2y(to.left)]
46
+ for rect in [from, to]
47
+ if rect.vertex.y < rect.top
48
+ [rect.vertex.x, rect.vertex.y, rect.vertex.direction] = [y2x(rect.top), rect.top, 'v']
49
+ else if rect.vertex.y > rect.bottom
50
+ [rect.vertex.x, rect.vertex.y, rect.vertex.direction] = [y2x(rect.bottom), rect.bottom, 'v']
51
+ else
52
+ from.vertex.direction = 'h'
53
+
54
+ if from.vertex.direction == 'h'
55
+ path = "M#{parseInt(from.vertex.x)} #{parseInt(from.vertex.y)}H#{parseInt((from.vertex.x + to.vertex.x) / 2)} V#{parseInt(to.vertex.y)} H#{parseInt(to.vertex.x)}"
56
+ else
57
+ path = "M#{parseInt(from.vertex.x)} #{parseInt(from.vertex.y)}V#{parseInt((from.vertex.y + to.vertex.y) / 2)} H#{parseInt(to.vertex.x)} V#{parseInt(to.vertex.y)}"
58
+
59
+ @paper.path(path).attr({'stroke-width': 2, opacity: 0.5, 'arrow-end': 'classic-wide-long'})
60
+
61
+ setup_handlers: ->
62
+ @setup_click_handlers()
63
+ @setup_submit_handlers()
64
+ $('div.model').draggable(drag: @handle_drag)
65
+
66
+ handle_drag: (ev, ui) =>
67
+ target = $(ev.target)
68
+ target.addClass('noclick')
69
+ model = target.data('model_name')
70
+ from = target.data('original_position')
71
+ to = [target.css('left').replace(/px$/, ''), target.css('top').replace(/px$/, '')].join()
72
+ @upsert_change 'move', model, '', '', to
73
+ @paper.clear()
74
+ @connect_arrows(@edges)
75
+
76
+ setup_click_handlers: ->
77
+ text_elems = [
78
+ 'div.model_name_text',
79
+ 'span.column_name_text',
80
+ 'span.column_type_text'
81
+ ].join()
82
+
83
+ $(text_elems).on 'click', @handle_text_elem_click
84
+ $('div.model a.add_column').on 'click', @handle_add_column_click
85
+ $('div.model a.close').on 'click', @handle_remove_model_click
86
+
87
+ setup_submit_handlers: ->
88
+ $('form.rename_model_form').on 'submit', @handle_rename_model
89
+ $('form.rename_column_form').on 'submit', @handle_rename_column
90
+ $('form.alter_column_form').on 'submit', @handle_change_column_type
91
+ $('form.add_column_form').on 'submit', @handle_add_column
92
+ $('#changes_form').on 'submit', @handle_save
93
+
94
+ handle_save: ->
95
+ j = '['
96
+ rows = ($(tr).find('td') for tr in $('#changes > tbody > tr'))
97
+ $(rows).each (i, row) ->
98
+ j += "{\"action\": \"#{$(row[0]).html()}\", \"model\": \"#{$(row[1]).html()}\", \"column\": \"#{$(row[2]).html()}\", \"from\": \"#{$(row[3]).html()}\", \"to\": \"#{$(row[4]).html()}\"}"
99
+ j += ',' if i < rows.length - 1
100
+ j += ']'
101
+ $('#changes_form').find('input[name=changes]').val(j)
10
102
 
11
- $('div.model a.add_column').on 'click', (ev) ->
103
+ handle_add_column: (ev) ->
12
104
  ev.preventDefault()
13
- $(this).hide()
14
- .next('form').show().find('input[name=type]').val('string').end().find('input[name=name]').val('').focus()
15
-
16
- $('div.model a.close').on 'click', (ev) ->
105
+ target = $(ev.target)
106
+ name = target.find('input[name=name]').val()
107
+ return if name == ''
108
+
109
+ model = target.find('input[name=model]').val()
110
+ type = target.find('input[name=type]').val()
111
+ upsert_change 'add_column', model, "#{name}(#{type})", '', ''
112
+
113
+ name_span = $("<span/>", class: 'column_name_text')
114
+ .append(name)
115
+
116
+ type_span = $("<span/>", class: 'column_type_text')
117
+ .append(type)
118
+
119
+ li_node = $("<li/>", class: 'column')
120
+ .append(name_span)
121
+ .append("&nbsp;")
122
+ .append(type_span)
123
+
124
+ target.hide()
125
+ .parent()
126
+ .siblings('.columns')
127
+ .find('ul')
128
+ .append(li_node)
129
+ .end()
130
+ .end()
131
+ .find('a.add_column')
132
+ .show()
133
+
134
+ handle_change_column_type: (ev) ->
17
135
  ev.preventDefault()
18
- if confirm('remove this table?')
19
- [model_id, model_name] = [$(this).parent().attr('id'), $(this).parent().data('model_name')]
20
- upsert_change 'remove_model', model_name, '', '', ''
21
- $(this).parent().hide()
22
-
23
- $.each window.edges, (i, edge) ->
24
- window.edges.splice i, 1 if (edge.from == model_id) || (edge.to == model_id)
25
- window.paper.clear()
26
- connect_arrows(window.edges)
27
-
28
- $('div.model').draggable
29
- drag: (_event, _ui) ->
30
- model = $(this).data('model_name')
31
- from = $(this).data('original_position')
32
- to = [$(this).css('left').replace(/px$/, ''), $(this).css('top').replace(/px$/, '')].join()
33
- upsert_change 'move', model, '', '', to
34
- window.paper.clear()
35
- connect_arrows(window.edges)
36
-
37
- $('form.rename_model_form').on('submit', (ev) ->
136
+ target = $(ev.target)
137
+ to = target.find('input[name=to]').val()
138
+ return if to == ''
139
+
140
+ model = target.find('input[name=model]').val()
141
+ column = target.find('input[name=column]').val()
142
+ type = target.find('input[name=type]').val()
143
+ if to != type
144
+ upsert_change 'alter_column', model, column, type, to
145
+
146
+ target.hide()
147
+ .siblings('.column_type_text')
148
+ .text(to)
149
+ .show()
150
+
151
+ handle_rename_column: (ev) ->
38
152
  ev.preventDefault()
39
- to = $(this).find('input[name=to]').val()
153
+ target = $(ev.target)
154
+ to = target.find('input[name=to]').val()
155
+ return if to == ''
40
156
 
41
- if to != ''
42
- model = $(this).find('input[name=model]').val()
43
- if to != model
44
- upsert_change 'rename_model', model, '', model, to
157
+ model = target.find('input[name=model]').val()
158
+ column = target.find('input[name=column]').val()
159
+ if to != column
160
+ upsert_change 'rename_column', model, column, column, to
45
161
 
46
- $(this).hide().siblings('.model_name_text').text(to).show()
47
- )
162
+ target.hide()
163
+ .siblings('.column_name_text')
164
+ .text(to)
165
+ .show()
48
166
 
49
- $('form.rename_column_form').on('submit', (ev) ->
167
+ handle_rename_model: (ev) ->
50
168
  ev.preventDefault()
51
- to = $(this).find('input[name=to]').val()
169
+ target = $(ev.target)
170
+ to = target.find('input[name=to]').val()
171
+ return if to == ''
52
172
 
53
- if to != ''
54
- model = $(this).find('input[name=model]').val()
55
- column = $(this).find('input[name=column]').val()
56
- if to != column
57
- upsert_change 'rename_column', model, column, column, to
173
+ model = target.find('input[name=model]').val()
174
+ if to != model
175
+ upsert_change 'rename_model', model, '', model, to
58
176
 
59
- $(this).hide().siblings('.column_name_text').text(to).show()
60
- )
177
+ target.hide()
178
+ .siblings('.model_name_text')
179
+ .text(to)
180
+ .show()
61
181
 
62
- $('form.alter_column_form').on('submit', (ev) ->
182
+ handle_add_column_click: (ev) ->
63
183
  ev.preventDefault()
64
- to = $(this).find('input[name=to]').val()
65
-
66
- if to != ''
67
- model = $(this).find('input[name=model]').val()
68
- column = $(this).find('input[name=column]').val()
69
- type = $(this).find('input[name=type]').val()
70
- if to != type
71
- upsert_change 'alter_column', model, column, type, to
72
-
73
- $(this).hide().siblings('.column_type_text').text(to).show()
74
- )
75
-
76
- $('form.add_column_form').on('submit', (ev) ->
184
+ target = $(@)
185
+
186
+ m = target.parents('div.model')
187
+ if m.hasClass('noclick')
188
+ m.removeClass('noclick')
189
+ return false
190
+
191
+ target.hide()
192
+ .next('form')
193
+ .show()
194
+ .find('input[name=type]')
195
+ .val('string')
196
+ .end()
197
+ .find('input[name=name]')
198
+ .val('')
199
+ .focus()
200
+
201
+ handle_text_elem_click: (ev) ->
202
+ target = $(@)
203
+ text = target.text()
204
+
205
+ m = target.parents('div.model')
206
+ if m.hasClass('noclick')
207
+ m.removeClass('noclick')
208
+ return false
209
+
210
+ target.hide()
211
+ .next('form')
212
+ .show()
213
+ .find('input[name=to]')
214
+ .val(text)
215
+ .focus()
216
+
217
+ handle_remove_model_click: (ev) =>
77
218
  ev.preventDefault()
78
- name = $(this).find('input[name=name]').val()
79
219
 
80
- if name != ''
81
- model = $(this).find('input[name=model]').val()
82
- type = $(this).find('input[name=type]').val()
83
- upsert_change 'add_column', model, "#{name}(#{type})", '', ''
220
+ target = $(ev.target)
221
+ parent = target.parent()
84
222
 
85
- $(this).hide().parent().siblings('.columns').find('ul').append("<li class=\"column\"><span class=\"column_name_text\">#{name}</span>&nbsp;<span class=\"column_type_text\">#{type}</span></li>").end().end()
86
- .find('a.add_column').show()
87
- )
223
+ m = target.parents('div.model')
224
+ if m.hasClass('noclick')
225
+ m.removeClass('noclick')
226
+ return false
88
227
 
89
- $('#changes_form').on 'submit', (ev) ->
90
- j = '['
91
- rows = ($(tr).find('td') for tr in $('#changes > tbody > tr'))
92
- $(rows).each (i, row) ->
93
- j += "{\"action\": \"#{$(row[0]).html()}\", \"model\": \"#{$(row[1]).html()}\", \"column\": \"#{$(row[2]).html()}\", \"from\": \"#{$(row[3]).html()}\", \"to\": \"#{$(row[4]).html()}\"}"
94
- j += ',' if i < rows.length - 1
95
- j += ']'
96
- $('#changes_form').find('input[name=changes]').val(j)
228
+ return unless confirm('remove this table?')
97
229
 
98
- upsert_change = (action, model, column, from, to) ->
99
- rows = ($(tr).find('td') for tr in $('#changes > tbody > tr'))
100
- existing = null
101
- $(rows).each (i, row) ->
102
- existing = row if (action == $(row[0]).html()) && (model == $(row[1]).html()) && (column == $(row[2]).html())
103
- if existing == null
104
- $('#changes > tbody').append("<tr><td>#{action}</td><td>#{model}</td><td>#{column}</td><td>#{from}</td><td>#{to}</td></tr>")
105
- else
106
- $(existing[3]).text(from)
107
- $(existing[4]).text(to)
108
- $('#changes').show()
109
-
110
- positions = (div) ->
111
- [left, width, top, height] = [parseInt(div.css('left')), parseInt(div.css('width')), parseInt(div.css('top')), parseInt(div.css('height'))]
112
- {left: left, right: left + width, top: top, bottom: top + height, center: {x: (left + left + width) / 2, y: (top + top + height) / 2}, vertex: {}}
113
-
114
-
115
- window.connect_arrows = (edges) ->
116
- $.each(edges, (i, edge) ->
117
- window.connect_arrow $("##{edge.from}"), $("##{edge.to}")
118
- )
119
-
120
- window.connect_arrow = (from_elem, to_elem) ->
121
- #TODO handle self referential associations
122
- return if from_elem.attr('id') == to_elem.attr('id')
123
-
124
- from = positions(from_elem)
125
- to = positions(to_elem)
126
- #FIXME terrible code
127
- a = (to.center.y - from.center.y) / (to.center.x - from.center.x)
128
- b = from.center.y - from.center.x * a
129
-
130
- x2y = (x) -> ( a * x + b )
131
- y2x = (y) -> ( (y - b) / a )
132
-
133
- if from.center.x > to.center.x
134
- [from.vertex.x, from.vertex.y] = [from.left, x2y(from.left)]
135
- [to.vertex.x, to.vertex.y] = [to.right, x2y(to.right)]
136
- else
137
- [from.vertex.x, from.vertex.y] = [from.right, x2y(from.right)]
138
- [to.vertex.x, to.vertex.y] = [to.left, x2y(to.left)]
139
- for rect in [from, to]
140
- if rect.vertex.y < rect.top
141
- [rect.vertex.x, rect.vertex.y, rect.vertex.direction] = [y2x(rect.top), rect.top, 'v']
142
- else if rect.vertex.y > rect.bottom
143
- [rect.vertex.x, rect.vertex.y, rect.vertex.direction] = [y2x(rect.bottom), rect.bottom, 'v']
144
- else
145
- from.vertex.direction = 'h'
230
+ [model_id, model_name] = [parent.attr('id'), parent.data('model_name')]
231
+ upsert_change 'remove_model', model_name, '', '', ''
232
+ parent.hide()
233
+
234
+ $.each @edges, (i, edge) =>
235
+ @edges.splice i, 1 if (edge.from == model_id) || (edge.to == model_id)
236
+ @paper.clear()
237
+ @connect_arrows(@edges)
146
238
 
147
- if from.vertex.direction == 'h'
148
- path = "M#{parseInt(from.vertex.x)} #{parseInt(from.vertex.y)}H#{parseInt((from.vertex.x + to.vertex.x) / 2)} V#{parseInt(to.vertex.y)} H#{parseInt(to.vertex.x)}"
149
- else
150
- path = "M#{parseInt(from.vertex.x)} #{parseInt(from.vertex.y)}V#{parseInt((from.vertex.y + to.vertex.y) / 2)} H#{parseInt(to.vertex.x)} V#{parseInt(to.vertex.y)}"
239
+ $ ->
240
+ window.erd = new ERD('erd', $('#erd'), window.raw_edges)
151
241
 
152
- window.paper.path(path).attr({'stroke-width': 2, opacity: 0.5, 'arrow-end': 'classic-wide-long'})
@@ -2,5 +2,5 @@
2
2
  <%= render :partial => 'erd/erd/model', :collection => models -%>
3
3
  <svg width="<%= width %>pt" height="<%= height %>pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
4
4
  </svg>
5
- <script>$(function() { window.edges = <%= edges.to_json.html_safe %>; connect_arrows(window.edges)})</script>
5
+ <script>window.raw_edges = <%= edges.to_json.html_safe %>;</script>
6
6
  </div>
data/lib/erd/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Erd
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-28 00:00:00.000000000 Z
12
+ date: 2012-04-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails-erd
16
- requirement: &70264677495520 !ruby/object:Gem::Requirement
16
+ requirement: &70208383601640 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.4.5
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70264677495520
24
+ version_requirements: *70208383601640
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: nokogiri
27
- requirement: &70264677495100 !ruby/object:Gem::Requirement
27
+ requirement: &70208383631860 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70264677495100
35
+ version_requirements: *70208383631860
36
36
  description: erd engine on Rails
37
37
  email:
38
38
  - ronnie@dio.jp