$ -> window.paper = Raphael('erd', $('#erd').css('width'), $('#erd').css('height')) # $('#erd').on 'click', (ev) -> # console.log 'click' $('div.model_name_text, span.column_name_text, span.column_type_text').on('click', (ev) -> $(this).hide() .next('form').show().find('input[name=to]').val($(this).text()).focus() ) $('div.model a.add_column').on 'click', (ev) -> ev.preventDefault() $(this).hide() .next('form').show().find('input[name=type]').val('string').end().find('input[name=name]').val('').focus() $('div.model a.close').on 'click', (ev) -> ev.preventDefault() if confirm('remove this table?') [model_id, model_name] = [$(this).parent().attr('id'), $(this).parent().data('model_name')] upsert_change 'remove_model', model_name, '', '', '' $(this).parent().hide() $.each window.edges, (i, edge) -> window.edges.splice i, 1 if (edge.from == model_id) || (edge.to == model_id) window.paper.clear() connect_arrows(window.edges) $('div.model').draggable drag: (_event, _ui) -> model = $(this).data('model_name') from = $(this).data('original_position') to = [$(this).css('left').replace(/px$/, ''), $(this).css('top').replace(/px$/, '')].join() upsert_change 'move', model, '', '', to window.paper.clear() connect_arrows(window.edges) $('form.rename_model_form').on('submit', (ev) -> ev.preventDefault() to = $(this).find('input[name=to]').val() if to != '' model = $(this).find('input[name=model]').val() if to != model upsert_change 'rename_model', model, '', model, to $(this).hide().siblings('.model_name_text').text(to).show() ) $('form.rename_column_form').on('submit', (ev) -> ev.preventDefault() to = $(this).find('input[name=to]').val() if to != '' model = $(this).find('input[name=model]').val() column = $(this).find('input[name=column]').val() if to != column upsert_change 'rename_column', model, column, column, to $(this).hide().siblings('.column_name_text').text(to).show() ) $('form.alter_column_form').on('submit', (ev) -> ev.preventDefault() to = $(this).find('input[name=to]').val() if to != '' model = $(this).find('input[name=model]').val() column = $(this).find('input[name=column]').val() type = $(this).find('input[name=type]').val() if to != type upsert_change 'alter_column', model, column, type, to $(this).hide().siblings('.column_type_text').text(to).show() ) $('form.add_column_form').on('submit', (ev) -> ev.preventDefault() name = $(this).find('input[name=name]').val() if name != '' model = $(this).find('input[name=model]').val() type = $(this).find('input[name=type]').val() upsert_change 'add_column', model, "#{name}(#{type})", '', '' $(this).hide().parent().siblings('.columns').find('ul').append("
  • #{name} #{type}
  • ").end().end() .find('a.add_column').show() ) $('#changes_form').on 'submit', (ev) -> j = '[' rows = ($(tr).find('td') for tr in $('#changes > tbody > tr')) $(rows).each (i, row) -> j += "{\"action\": \"#{$(row[0]).html()}\", \"model\": \"#{$(row[1]).html()}\", \"column\": \"#{$(row[2]).html()}\", \"from\": \"#{$(row[3]).html()}\", \"to\": \"#{$(row[4]).html()}\"}" j += ',' if i < rows.length - 1 j += ']' $('#changes_form').find('input[name=changes]').val(j) upsert_change = (action, model, column, from, to) -> rows = ($(tr).find('td') for tr in $('#changes > tbody > tr')) existing = null $(rows).each (i, row) -> existing = row if (action == $(row[0]).html()) && (model == $(row[1]).html()) && (column == $(row[2]).html()) if existing == null $('#changes > tbody').append("#{action}#{model}#{column}#{from}#{to}") else $(existing[3]).text(from) $(existing[4]).text(to) $('#changes').show() positions = (div) -> [left, width, top, height] = [parseInt(div.css('left')), parseInt(div.css('width')), parseInt(div.css('top')), parseInt(div.css('height'))] {left: left, right: left + width, top: top, bottom: top + height, center: {x: (left + left + width) / 2, y: (top + top + height) / 2}, vertex: {}} window.connect_arrows = (edges) -> $.each(edges, (i, edge) -> window.connect_arrow $("##{edge.from}"), $("##{edge.to}") ) window.connect_arrow = (from_elem, to_elem) -> #TODO handle self referential associations return if from_elem.attr('id') == to_elem.attr('id') from = positions(from_elem) to = positions(to_elem) #FIXME terrible code a = (to.center.y - from.center.y) / (to.center.x - from.center.x) b = from.center.y - from.center.x * a x2y = (x) -> ( a * x + b ) y2x = (y) -> ( (y - b) / a ) if from.center.x > to.center.x [from.vertex.x, from.vertex.y] = [from.left, x2y(from.left)] [to.vertex.x, to.vertex.y] = [to.right, x2y(to.right)] else [from.vertex.x, from.vertex.y] = [from.right, x2y(from.right)] [to.vertex.x, to.vertex.y] = [to.left, x2y(to.left)] for rect in [from, to] if rect.vertex.y < rect.top [rect.vertex.x, rect.vertex.y, rect.vertex.direction] = [y2x(rect.top), rect.top, 'v'] else if rect.vertex.y > rect.bottom [rect.vertex.x, rect.vertex.y, rect.vertex.direction] = [y2x(rect.bottom), rect.bottom, 'v'] else from.vertex.direction = 'h' if from.vertex.direction == 'h' 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)}" else 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)}" window.paper.path(path).attr({'stroke-width': 2, opacity: 0.5, 'arrow-end': 'classic-wide-long'})