function _(str) { /* getText */ if (!(str in window.LOCALE)) { return str; } return window.LOCALE[str]; } var DATATYPES = false; var LOCALE = {}; var SQL = {}; /* -------------------- base visual element -------------------- */ SQL.Visual = OZ.Class(); /* abstract parent */ SQL.Visual.prototype.init = function() { this._init(); this._build(); } SQL.Visual.prototype._init = function() { this.dom = { container:OZ.DOM.elm("div"), content:OZ.DOM.elm("div"), title:OZ.DOM.elm("div",{className:"title"}) }; this.data = { title:"" } } SQL.Visual.prototype._build = function() {} SQL.Visual.prototype.toXML = function() {} SQL.Visual.prototype.fromXML = function(node) {} SQL.Visual.prototype.destroy = function() { /* "destructor" */ var p = this.dom.container.parentNode; if (p && p.nodeType == 1) { p.removeChild(this.dom.container); } } SQL.Visual.prototype.setTitle = function(text) { if (!text) { return; } this.data.title = text; this.dom.title.innerHTML = text; } SQL.Visual.prototype.getTitle = function() { return this.data.title; } SQL.Visual.prototype.redraw = function() {} /* --------------------- table row ( = db column) ------------ */ SQL.Row = OZ.Class().extend(SQL.Visual); SQL.Row.prototype.init = function(owner, title, data) { this.owner = owner; this.relations = []; this.keys = []; this.selected = false; this.expanded = false; SQL.Visual.prototype.init.apply(this); this.data.type = 0; this.data.size = ""; this.data.def = null; this.data.nll = true; this.data.ai = false; this.data.comment = ""; if (data) { this.update(data); } this.setTitle(title); } SQL.Row.prototype._build = function() { this.dom.container.className = "row"; this.dom.content.style.display = "none"; this.enter = this.bind(this.enter); this.changeComment = this.bind(this.changeComment); this.dom.selected = OZ.DOM.elm("span",{className:"row_selected"}); this.dom.selected.innerHTML = "» "; OZ.DOM.append([this.dom.container,this.dom.selected,this.dom.title,this.dom.content]); OZ.Event.add(this.dom.container,"click",this.bind(this.click)); OZ.Event.add(this.dom.container,"dblclick",this.bind(this.dblclick)); OZ.Event.add(this.dom.container,"mousedown",this.bind(this.mousedown)); } SQL.Row.prototype.select = function() { if (this.selected) { return; } this.selected = true; this.redraw(); } SQL.Row.prototype.deselect = function() { if (!this.selected) { return; } this.selected = false; this.redraw(); this.collapse(); } SQL.Row.prototype.setTitle = function(t) { var old = this.getTitle(); for (var i=0;i\n'; var elm = this.getDataType(); var t = elm.getAttribute("sql"); if (this.data.size.length) { t += "("+this.data.size+")"; } xml += ""+t+"\n"; if (this.data.def || this.data.def === null) { var q = elm.getAttribute("quote"); var d = this.data.def; if (d === null) { d = "NULL"; } else if (d != "CURRENT_TIMESTAMP") { d = q+d+q; } xml += ""+d+""; } for (var i=0;i\n'; } if (this.data.comment) { var escaped = this.data.comment.replace(/&/g, "&").replace(/>/g, ">").replace(/\n"; } xml += "\n"; return xml; } SQL.Row.prototype.fromXML = function(node) { var name = node.getAttribute("name"); this.setTitle(name); var obj = { type:0, size:"" }; obj.nll = (node.getAttribute("null") == "1"); obj.ai = (node.getAttribute("autoincrement") == "1"); var cs = node.getElementsByTagName("comment"); if (cs.length && cs[0].firstChild) { obj.comment = cs[0].firstChild.nodeValue; } var d = node.getElementsByTagName("datatype"); if (d.length && d[0].firstChild) { var s = d[0].firstChild.nodeValue; var r = s.match(/^([^\(]+)(\((.*)\))?.*$/); var type = r[1]; if (r[3]) { obj.size = r[3]; } var types = window.DATATYPES.getElementsByTagName("type"); for (var i=0;i 0; } SQL.Row.prototype.enter = function(e) { if (e.keyCode == 13) { this.collapse(); } } /* --------------------------- relation (connector) ----------- */ SQL.Relation = OZ.Class().extend(SQL.Visual); SQL.Relation._counter = 0; SQL.Relation.prototype.init = function(owner, row1, row2) { this.constructor._counter++; this.owner = owner; this.row1 = row1; this.row2 = row2; this.hidden = false; SQL.Visual.prototype.init.apply(this); this.row1.addRelation(this); this.row2.addRelation(this); this.dom = []; if (CONFIG.RELATION_COLORS) { var colorIndex = this.constructor._counter - 1; var color = CONFIG.RELATION_COLORS[colorIndex % CONFIG.RELATION_COLORS.length]; } else { var color = "#000"; } if (this.owner.vector == "svg") { var path = document.createElementNS(this.owner.svgNS, "path"); path.setAttribute("stroke", color); path.setAttribute("stroke-width", CONFIG.RELATION_THICKNESS); path.setAttribute("fill", "none"); this.owner.dom.svg.appendChild(path); this.dom.push(path); } else if (this.owner.vector == "vml") { var curve = OZ.DOM.elm("v:curve"); curve.strokeweight = CONFIG.RELATION_THICKNESS+"px"; curve.from = "0 0"; curve.to = "0 0"; curve.control1 = "10 10"; curve.control2 = "100 300"; curve.strokecolor = color; curve.filled = false; this.owner.dom.content.appendChild(curve); this.dom.push(curve); } else { for (var i=0;i<3;i++) { var div = OZ.DOM.elm("div",{position:"absolute",className:"relation"}); this.dom.push(div); if (i & 1) { /* middle */ OZ.Style.set(div,{width:CONFIG.RELATION_THICKNESS+"px"}); } else { /* first & last */ OZ.Style.set(div,{height:CONFIG.RELATION_THICKNESS+"px"}); } this.owner.dom.content.appendChild(div); } } this.redraw(); } SQL.Relation.prototype.show = function() { this.hidden = false; for (var i=0;i\n'; for (var i=0;i/g, ">").replace(/\n"; } xml += "\n"; return xml; } SQL.Table.prototype.fromXML = function(node) { var name = node.getAttribute("name"); this.setTitle(name); var x = parseInt(node.getAttribute("x")) || 0; var y = parseInt(node.getAttribute("y")) || 0; this.moveTo(x, y); var rows = node.getElementsByTagName("row"); for (var i=0;i 1) { return; } var event = e.touches[0]; } else { var event = e; } for (var i=0;i\n'; for (var i=0;i\n'; } xml += '\n'; return xml; } SQL.Key.prototype.fromXML = function(node) { this.setType(node.getAttribute("type")); this.setName(node.getAttribute("name")); var parts = node.getElementsByTagName("part"); for (var i=0;i 1) { return; } var event = e.touches[0]; } else { var event = e; } var dx = event.clientX - this.x; var dy = event.clientY - this.y; if (this.l + dx < 0) { dx = -this.l; } if (this.t + dy < 0) { dy = -this.t; } if (this.l + this.w + 4 + dx > this.width) { dx = this.width - 4 - this.l - this.w; } if (this.t + this.h + 4 + dy > this.height) { dy = this.height - 4 - this.t - this.h; } this.x += dx; this.y += dy; this.l += dx; this.t += dy; var coefX = this.width / this.owner.width; var coefY = this.height / this.owner.height; var left = this.l / coefX; var top = this.t / coefY; if (OZ.webkit) { document.body.scrollLeft = Math.round(left); document.body.scrollTop = Math.round(top); } else { document.documentElement.scrollLeft = Math.round(left); document.documentElement.scrollTop = Math.round(top); } this.redraw(); } SQL.Map.prototype.up = function(e) { /* mouseup */ this.flag = false; this.dom.container.style.cursor = ""; OZ.Event.remove(this.documentMove); OZ.Event.remove(this.documentUp); } SQL.Map.prototype.sync = function() { /* when window changes, adjust map */ var dims = OZ.DOM.win(); var scroll = OZ.DOM.scroll(); var scaleX = this.width / this.owner.width; var scaleY = this.height / this.owner.height; var w = dims[0] * scaleX - 4 - 0; var h = dims[1] * scaleY - 4 - 0; var x = scroll[0] * scaleX; var y = scroll[1] * scaleY; this.w = Math.round(w); this.h = Math.round(h); this.l = Math.round(x); this.t = Math.round(y); this.redraw(); } SQL.Map.prototype.redraw = function() { this.dom.port.style.width = this.w+"px"; this.dom.port.style.height = this.h+"px"; this.dom.port.style.left = this.l+"px"; this.dom.port.style.top = this.t+"px"; } /* --------------------- io ------------ */ SQL.IO = OZ.Class(); SQL.IO.prototype.init = function(owner) { this.owner = owner; this._name = ""; /* last used keyword */ this.dom = { container:OZ.$("io") }; var ids = ["saveload", "clientsave", "clientload", "clientsql", "quicksave", "serversave", "serverload", "serverlist", "serverimport"]; for (var i=0;i 1) { this.dom.removetable.value = _("removetables"); } } else { this.dom.removetable.disabled = true; this.dom.removetable.value = _("removetable"); } for (var i=0;i=x && tx=x && tx1x1)) && ((ty>=y && ty=y && ty1y1))) { this.selection.push(t); } } this.processSelection(); } SQL.TableManager.prototype.click = function(e) { /* finish adding new table */ var newtable = false; if (this.adding) { this.adding = false; OZ.DOM.removeClass("area","adding"); this.dom.addtable.value = this.oldvalue; var scroll = OZ.DOM.scroll(); var x = e.clientX + scroll[0]; var y = e.clientY + scroll[1]; newtable = this.owner.addTable(_("newtable"),x,y); var r = newtable.addRow("id",{ai:true}); var k = newtable.addKey("PRIMARY",""); k.addRow(r); } this.select(newtable); this.owner.rowManager.select(false); if (this.selection.length == 1) { this.edit(e); } } SQL.TableManager.prototype.preAdd = function(e) { /* click add new table */ if (this.adding) { this.adding = false; OZ.DOM.removeClass("area","adding"); this.dom.addtable.value = this.oldvalue; } else { this.adding = true; OZ.DOM.addClass("area","adding"); this.oldvalue = this.dom.addtable.value; this.dom.addtable.value = "["+_("addpending")+"]"; } } SQL.TableManager.prototype.clear = function(e) { /* remove all tables */ if (!this.owner.tables.length) { return; } var result = confirm(_("confirmall")+" ?"); if (!result) { return; } this.owner.clearTables(); } SQL.TableManager.prototype.remove = function(e) { var titles = this.selection.slice(0); for (var i=0;i=0;i--) { var r = rels[i]; if (r.row2 == this.selected) { this.owner.removeRelation(r); } } this.redraw(); } SQL.RowManager.prototype.endCreate = function() { this.creating = false; this.dom.foreigncreate.value = _("foreigncreate"); } SQL.RowManager.prototype.endConnect = function() { this.connecting = false; this.dom.foreignconnect.value = _("foreignconnect"); } SQL.RowManager.prototype.up = function(e) { this.selected.up(); this.redraw(); } SQL.RowManager.prototype.down = function(e) { this.selected.down(); this.redraw(); } SQL.RowManager.prototype.remove = function(e) { var result = confirm(_("confirmrow")+" '"+this.selected.getTitle()+"' ?"); if (!result) { return; } var t = this.selected.owner; this.selected.owner.removeRow(this.selected); var next = false; if (t.rows) { next = t.rows[t.rows.length-1]; } this.select(next); } SQL.RowManager.prototype.redraw = function() { this.endCreate(); this.endConnect(); if (this.selected) { var table = this.selected.owner; var rows = table.rows; this.dom.uprow.disabled = (rows[0] == this.selected); this.dom.downrow.disabled = (rows[rows.length-1] == this.selected); this.dom.removerow.disabled = false; this.dom.editrow.disabled = false; this.dom.foreigncreate.disabled = !(this.selected.isUnique()); this.dom.foreignconnect.disabled = !(this.selected.isUnique()); this.dom.foreigndisconnect.disabled = true; var rels = this.selected.relations; for (var i=0;i=0;i--) { var k = this.table.keys[i]; if (!k.rows.length) { this.table.removeKey(k); } } } SQL.KeyManager.prototype.sync = function(table) { /* sync content with given table */ this.table = table; this.dom.listlabel.innerHTML = _("keyslistlabel").replace(/%s/,table.getTitle()); OZ.DOM.clear(this.dom.list); for (var i=0;i 1) { this.dom.title.removeChild(this.dom.title.childNodes[1]); } var txt = OZ.DOM.text(title); this.dom.title.appendChild(txt); this.dom.background.style.visibility = "visible"; OZ.DOM.clear(this.dom.content); this.dom.content.appendChild(content); var win = OZ.DOM.win(); var scroll = OZ.DOM.scroll(); this.dom.container.style.left = Math.round(scroll[0] + (win[0] - this.dom.container.offsetWidth)/2)+"px"; this.dom.container.style.top = Math.round(scroll[1] + (win[1] - this.dom.container.offsetHeight)/2)+"px"; this.dom.cancel.style.visibility = (this.callback ? "" : "hidden"); this.dom.container.style.visibility = "visible"; var formElements = ["input","select","textarea"]; var all = this.dom.container.getElementsByTagName("*"); for (var i=0;i max) { max = z; } } OZ.$("controls").style.zIndex = max+5; return max; } SQL.Designer.prototype.addTable = function(name, x, y) { var max = this.getMaxZ(); var t = new SQL.Table(this, name, x, y, max+1); this.tables.push(t); this.dom.content.appendChild(t.dom.container); t.redraw(); return t; } SQL.Designer.prototype.removeTable = function(t) { this.tableManager.select(false); this.rowManager.select(false); var idx = this.tables.indexOf(t); if (idx == -1) { return; } t.destroy(); this.tables.splice(idx,1); } SQL.Designer.prototype.addRelation = function(row1, row2) { var r = new SQL.Relation(this, row1, row2); this.relations.push(r); return r; } SQL.Designer.prototype.removeRelation = function(r) { var idx = this.relations.indexOf(r); if (idx == -1) { return; } r.destroy(); this.relations.splice(idx,1); } SQL.Designer.prototype.getCookie = function() { var c = document.cookie; var obj = {}; var parts = c.split(";"); for (var i=0;i old) { t.setZ(t.getZ()-1); } } var m = table.dom.mini; m.parentNode.appendChild(m); } SQL.Designer.prototype.clearTables = function() { while (this.tables.length) { this.removeTable(this.tables[0]); } this.setTitle(false); } SQL.Designer.prototype.alignTables = function() { var win = OZ.DOM.win(); var avail = win[0] - OZ.$("bar").offsetWidth; var x = 10; var y = 10; var max = 0; this.tables.sort(function(a,b){ return b.getRelations().length - a.getRelations().length; }); for (var i=0;i avail) { x = 10; y += 10 + max; max = 0; } t.moveTo(x,y); x += 10 + w; if (h > max) { max = h; } } this.sync(); } SQL.Designer.prototype.findNamedTable = function(name) { /* find row specified as table(row) */ for (var i=0;i\n'; xml += '\n'; /* serialize datatypes */ if (window.XMLSerializer) { var s = new XMLSerializer(); xml += s.serializeToString(window.DATATYPES); } else if (window.DATATYPES.xml) { xml += window.DATATYPES.xml; } else { alert(_("errorxml")+': '+e.message); } for (var i=0;i